From a43cdf46752ffb0f5c5ec9d989096e5b619a8a93 Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Thu, 13 Nov 2014 13:47:37 +0100 Subject: [PATCH 1/7] move LOG_LEVELS --- dragonlib/utils/logging_utils.py | 16 ++++++++++++++++ dragonpy/core/base_cli.py | 17 +---------------- 2 files changed, 17 insertions(+), 16 deletions(-) mode change 100644 => 100755 dragonlib/utils/logging_utils.py mode change 100644 => 100755 dragonpy/core/base_cli.py diff --git a/dragonlib/utils/logging_utils.py b/dragonlib/utils/logging_utils.py old mode 100644 new mode 100755 index a11d6c69..9c9103a4 --- a/dragonlib/utils/logging_utils.py +++ b/dragonlib/utils/logging_utils.py @@ -26,6 +26,22 @@ # log.critical("Fixed Log handlers: %s", repr(log.handlers)) +def get_log_levels(additional_levels=[100,99]): + levels = additional_levels[:] + try: + # Python 3 + levels += logging._nameToLevel.values() + except AttributeError: + # Python 2 + levels += [level for level in logging._levelNames if isinstance(level, int)] + + levels.sort() + return levels + +LOG_LEVELS = get_log_levels() + + + def setup_logging(level, logger_name=None, handler=None, log_formatter=None): """ levels: diff --git a/dragonpy/core/base_cli.py b/dragonpy/core/base_cli.py old mode 100644 new mode 100755 index f9f86cb4..2f81c473 --- a/dragonpy/core/base_cli.py +++ b/dragonpy/core/base_cli.py @@ -16,26 +16,11 @@ import argparse import sys import logging -from dragonlib.utils.logging_utils import setup_logging +from dragonlib.utils.logging_utils import setup_logging, LOG_LEVELS log = logging.getLogger(__name__) -def get_log_levels(): - levels = [100, 99] # FIXME - try: - # Python 3 - levels += logging._nameToLevel.values() - except AttributeError: - # Python 2 - levels += [level for level in logging._levelNames if isinstance(level, int)] - - levels.sort() - return levels - -LOG_LEVELS = get_log_levels() - - class ActionLogList(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): print("A list of all loggers:") From d7637e44f3087a1bb1f19a77fa331cb9865872b9 Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Thu, 13 Nov 2014 15:26:27 +0100 Subject: [PATCH 2/7] outsource dragonlib: https://github.com/6809/dragonlib --- PyDC/PyDC/CassetteObjects.py | 2 +- PyDC/PyDC/__init__.py | 2 - PyDC/PyDC/bitstream_handler.py | 3 +- PyDC/PyDC/configs.py | 2 +- PyDC/PyDC/wave2bitstream.py | 3 +- dragonlib/CoCo/__init__.py | 0 dragonlib/CoCo/basic_tokens.py | 196 ----- dragonlib/__init__.py | 0 dragonlib/api.py | 170 ---- dragonlib/core/__init__.py | 0 dragonlib/core/basic.py | 565 ------------- dragonlib/core/basic_parser.py | 239 ------ dragonlib/dragon32/__init__.py | 0 dragonlib/dragon32/basic_tokens.py | 131 --- dragonlib/tests/__init__.py | 0 dragonlib/tests/run_all_dragonlib_tests.py | 28 - dragonlib/tests/test_api.py | 572 ------------- dragonlib/tests/test_base.py | 61 -- dragonlib/tests/test_basic_parser.py | 311 ------- dragonlib/utils/__init__.py | 0 dragonlib/utils/auto_shift.py | 43 - dragonlib/utils/get_six.sh | 20 - dragonlib/utils/iter_utils.py | 72 -- dragonlib/utils/logging_utils.py | 180 ----- dragonlib/utils/six.py | 762 ------------------ dragonpy/components/cpu6809.py | 2 +- dragonpy/tests/test_6809_StoreLoad.py | 4 +- dragonpy/tests/test_6809_address_modes.py | 5 +- dragonpy/tests/test_6809_arithmetic.py | 6 +- dragonpy/tests/test_6809_arithmetic_shift.py | 4 +- .../tests/test_6809_branch_instructions.py | 6 +- dragonpy/tests/test_6809_program.py | 4 +- dragonpy/tests/test_6809_register_changes.py | 5 +- dragonpy/tests/test_BASIC_Dragon32.py | 6 +- dragonpy/tests/test_BASIC_simple09.py | 3 +- dragonpy/tests/test_all.py | 3 - dragonpy/tests/test_base.py | 17 +- .../tests/test_condition_code_register.py | 6 +- dragonpy/tests/test_cpu6809.py | 4 +- dragonpy/tests/test_sbc09.py | 5 +- dragonpy/utils/BASIC09_floating_point.py | 2 +- dragonpy/utils/byte_word_values.py | 73 -- setup.py | 2 +- 43 files changed, 35 insertions(+), 3484 deletions(-) delete mode 100644 dragonlib/CoCo/__init__.py delete mode 100644 dragonlib/CoCo/basic_tokens.py delete mode 100644 dragonlib/__init__.py delete mode 100644 dragonlib/api.py delete mode 100644 dragonlib/core/__init__.py delete mode 100644 dragonlib/core/basic.py delete mode 100644 dragonlib/core/basic_parser.py delete mode 100644 dragonlib/dragon32/__init__.py delete mode 100644 dragonlib/dragon32/basic_tokens.py delete mode 100644 dragonlib/tests/__init__.py delete mode 100644 dragonlib/tests/run_all_dragonlib_tests.py delete mode 100644 dragonlib/tests/test_api.py delete mode 100644 dragonlib/tests/test_base.py delete mode 100644 dragonlib/tests/test_basic_parser.py delete mode 100644 dragonlib/utils/__init__.py delete mode 100644 dragonlib/utils/auto_shift.py delete mode 100755 dragonlib/utils/get_six.sh delete mode 100644 dragonlib/utils/iter_utils.py delete mode 100755 dragonlib/utils/logging_utils.py delete mode 100644 dragonlib/utils/six.py delete mode 100644 dragonpy/utils/byte_word_values.py diff --git a/PyDC/PyDC/CassetteObjects.py b/PyDC/PyDC/CassetteObjects.py index 93be509e..cfea4176 100644 --- a/PyDC/PyDC/CassetteObjects.py +++ b/PyDC/PyDC/CassetteObjects.py @@ -18,7 +18,7 @@ # own modules from basic_tokens import bytes2codeline -from utils import get_word, codepoints2string, string2codepoint, LOG_LEVEL_DICT, \ +from dragonlib.utils import get_word, codepoints2string, string2codepoint, LOG_LEVEL_DICT, \ LOG_FORMATTER, pformat_codepoints from wave2bitstream import Wave2Bitstream, Bitstream2Wave from bitstream_handler import BitstreamHandler, CasStream, BytestreamHandler diff --git a/PyDC/PyDC/__init__.py b/PyDC/PyDC/__init__.py index 2d4ef7db..e64cadd7 100644 --- a/PyDC/PyDC/__init__.py +++ b/PyDC/PyDC/__init__.py @@ -13,8 +13,6 @@ import sys from CassetteObjects import Cassette -from utils import print_bitlist -from wave2bitstream import Wave2Bitstream, Bitstream2Wave __version__ = (0, 1, 0, 'dev') diff --git a/PyDC/PyDC/bitstream_handler.py b/PyDC/PyDC/bitstream_handler.py index 91caedd4..5fadccd3 100755 --- a/PyDC/PyDC/bitstream_handler.py +++ b/PyDC/PyDC/bitstream_handler.py @@ -18,12 +18,11 @@ import itertools import logging import os -import sys log = logging.getLogger("PyDC") # own modules -from utils import find_iter_window, iter_steps, MaxPosArraived, \ +from dragonlib.utils import find_iter_window, iter_steps, MaxPosArraived, \ print_bitlist, bits2codepoint, list2str, bitstream2codepoints, \ PatternNotFound, count_the_same, codepoints2bitstream, pformat_codepoints diff --git a/PyDC/PyDC/configs.py b/PyDC/PyDC/configs.py index 924b44a4..bf4870b3 100644 --- a/PyDC/PyDC/configs.py +++ b/PyDC/PyDC/configs.py @@ -21,7 +21,7 @@ class BaseConfig(object): VOLUME_RATIO = 90 # "Loundness" in percent of the created wave file def print_debug_info(self): - from utils import byte2bit_string + from dragonlib.utils import byte2bit_string print "Config: '%s'" % self.__class__.__name__ diff --git a/PyDC/PyDC/wave2bitstream.py b/PyDC/PyDC/wave2bitstream.py index b957d874..594b30d6 100644 --- a/PyDC/PyDC/wave2bitstream.py +++ b/PyDC/PyDC/wave2bitstream.py @@ -6,7 +6,6 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -import sys import wave import functools import array @@ -25,7 +24,7 @@ # own modules -from utils import average, diff_info, TextLevelMeter, iter_window, \ +from dragonlib.utils import average, diff_info, TextLevelMeter, iter_window, \ human_duration, ProcessInfo, count_sign, iter_steps, sinus_values_by_hz, \ hz2duration, duration2hz, codepoints2bitstream, bits2codepoint diff --git a/dragonlib/CoCo/__init__.py b/dragonlib/CoCo/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/CoCo/basic_tokens.py b/dragonlib/CoCo/basic_tokens.py deleted file mode 100644 index ea79f4d4..00000000 --- a/dragonlib/CoCo/basic_tokens.py +++ /dev/null @@ -1,196 +0,0 @@ -# encoding:utf8 - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - informations from: - - * Color BASIC 1.3: - http://sourceforge.net/p/toolshed/code/ci/default/tree/cocoroms/bas.asm - - * Extended Color BASIC 1.1: - http://sourceforge.net/p/toolshed/code/ci/default/tree/cocoroms/extbas.asm - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - - -# Revesed word tokens from Color BASIC 1.3: -COCO_COLOR_BASIC_TOKENS = { - 0x80: "FOR", - 0x81: "GO", - 0x82: "REM", - 0x83: "'", - 0x84: "ELSE", - 0x85: "IF", - 0x86: "DATA", - 0x87: "PRINT", - 0x88: "ON", - 0x89: "INPUT", - 0x8a: "END", - 0x8b: "NEXT", - 0x8c: "DIM", - 0x8d: "READ", - 0x8e: "RUN", - 0x8f: "RESTORE", - 0x90: "RETURN", - 0x91: "STOP", - 0x92: "POKE", - 0x93: "CONT", - 0x94: "LIST", - 0x95: "CLEAR", - 0x96: "NEW", - 0x97: "CLOAD", - 0x98: "CSAVE", - 0x99: "OPEN", - 0x9a: "CLOSE", - 0x9b: "LLIST", - 0x9c: "SET", - 0x9d: "RESET", - 0x9e: "CLS", - 0x9f: "MOTOR", - 0xa0: "SOUND", - 0xa1: "AUDIO", - 0xa2: "EXEC", - 0xa3: "SKIPF", - 0xa4: "TAB(", - 0xa5: "TO", - 0xa6: "SUB", - 0xa7: "THEN", - 0xa8: "NOT", - 0xa9: "STEP", - 0xaa: "OFF", - 0xab: "+", - 0xac: "-", - 0xad: "*", - 0xae: "/", - 0xaf: "^", - 0xb0: "AND", - 0xb1: "OR", - 0xb2: ">", - 0xb3: "=", - 0xb4: "<", - - # Function tokens - all proceeded by 0xff to differentiate from operators - - 0xff80: "SGN", - 0xff81: "INT", - 0xff82: "ABS", - 0xff83: "USR", - 0xff84: "RND", - 0xff85: "SIN", - 0xff86: "PEEK", - 0xff87: "LEN", - 0xff88: "STR$", - 0xff89: "VAL", - 0xff8a: "ASC", - 0xff8b: "CHR$", - 0xff8c: "EOF", - 0xff8d: "JOYSTK", - 0xff8e: "LEFT$", - 0xff8f: "RIGHT$", - 0xff90: "MID$", - 0xff91: "POINT", - 0xff92: "INKEY$", - 0xff93: "MEM", -} - -# Revesed word tokens from Extended Color BASIC 1.1: -COCO_EXTENDED_COLOR_BASIC_TOKENS = { - 0xb5: "DEL", - 0xb6: "EDIT", - 0xb7: "TRON", - 0xb8: "TROFF", - 0xb9: "DEF", - 0xba: "LET", - 0xbb: "LINE", - 0xbc: "PCLS", - 0xbd: "PSET", - 0xbe: "PRESET", - 0xbf: "SCREEN", - 0xc0: "PCLEAR", - 0xc1: "COLOR", - 0xc2: "CIRCLE", - 0xc3: "PAINT", - 0xc4: "GET", - 0xc5: "PUT", - 0xc6: "DRAW", - 0xc7: "PCOPY", - 0xc8: "PMODE", - 0xc9: "PLAY", - 0xca: "DLOAD", - 0xcb: "RENUM", - 0xcc: "FN", - 0xcd: "USING", - - # Function tokens - all proceeded by 0xff to differentiate from operators - - 0xff94: "ATN", - 0xff95: "COS", - 0xff96: "TAN", - 0xff97: "EXP", - 0xff98: "FIX", - 0xff99: "LOG", - 0xff9a: "POS", - 0xff9b: "SQR", - 0xff9c: "HEX$", - 0xff9d: "VARPTR", - 0xff9e: "INSTR", - 0xff9f: "TIMER", - 0xffa0: "PPOINT", - 0xffa1: "STRING$", -} - -# Merged tokens: -COCO_BASIC_TOKENS = COCO_COLOR_BASIC_TOKENS.copy() -COCO_BASIC_TOKENS.update(COCO_EXTENDED_COLOR_BASIC_TOKENS) - - -if __name__ == '__main__': - from dragonlib.dragon32.basic_tokens import DRAGON32_BASIC_TOKENS - - values = list(range(0x80, 0x100)) + list(range(0x8000, 0x10000)) - - # Generate Wiki Table for: - # http://archive.worldofdragon.org/index.php?title=Tokens - - print(""" -* "CoCo A": - Tokens from Color BASIC 1.3 -* "CoCo B": - Additional tokens from Extended Color BASIC 1.1 only -{| class="wikitable" style="font-family: monospace; background-color:#ffffcc;" cellpadding="10" -|- -! value -! Dragon -token -! CoCo A -token -! CoCo B -token -""") - for value in values: - coco_basic_statement = COCO_COLOR_BASIC_TOKENS.get(value, "") - coco_extended_basic_statement = COCO_EXTENDED_COLOR_BASIC_TOKENS.get(value, "") - dragon_statement = DRAGON32_BASIC_TOKENS.get(value, "") - - if coco_basic_statement == "" and coco_extended_basic_statement=="" and dragon_statement == "": - continue - - if value > 0xff: - value = "$%04x" % value - else: - value = "$%02x" % value - - print("|-") - print("| %s" % value) - print("| %s" % dragon_statement) - print("| %s" % coco_basic_statement) - print("| %s" % coco_extended_basic_statement) - - print("|-") - print("|}") diff --git a/dragonlib/__init__.py b/dragonlib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/api.py b/dragonlib/api.py deleted file mode 100644 index 509faf93..00000000 --- a/dragonlib/api.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python -# encoding:utf8 - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -from dragonlib.CoCo.basic_tokens import COCO_BASIC_TOKENS -from dragonlib.core.basic import BasicListing, RenumTool, BasicTokenUtil,\ - BasicLine -from dragonlib.core.basic_parser import BASICParser -from dragonlib.dragon32.basic_tokens import DRAGON32_BASIC_TOKENS -import logging - -log=logging.getLogger(__name__) - - -DRAGON32 = "Dragon32" -COCO2B = "CoCo" - - -class BaseAPI(object): - RENUM_REGEX = r""" - (?P GOTO|GOSUB|THEN|ELSE ) (?P\s*) (?P[\d*,\s*]+) - """ - - def __init__(self): - self.listing = BasicListing(self.BASIC_TOKENS) - self.renum_tool = RenumTool(self.RENUM_REGEX) - self.token_util = BasicTokenUtil(self.BASIC_TOKENS) - - def program_dump2ascii_lines(self, dump, program_start=None): - """ - convert a memory dump of a tokensized BASIC listing into - ASCII listing list. - """ - if program_start is None: - program_start = self.DEFAULT_PROGRAM_START - return self.listing.program_dump2ascii_lines(dump, program_start) - - def parse_ascii_listing(self, basic_program_ascii): - parser = BASICParser() - parsed_lines = parser.parse(basic_program_ascii) - if not parsed_lines: - log.critical("No parsed lines %s from %s ?!?" % ( - repr(parsed_lines), repr(basic_program_ascii) - )) - log.info("Parsed BASIC: %s", repr(parsed_lines)) - return parsed_lines - - def ascii_listing2basic_lines(self, basic_program_ascii, program_start): - parsed_lines = self.parse_ascii_listing(basic_program_ascii) - - basic_lines = [] - for line_no, code_objects in sorted(parsed_lines.items()): - basic_line = BasicLine(self.token_util) - basic_line.code_objects_load(line_no,code_objects) - basic_lines.append(basic_line) - - return basic_lines - - def ascii_listing2program_dump(self, basic_program_ascii, program_start=None): - """ - convert a ASCII BASIC program listing into tokens. - This tokens list can be used to insert it into the - Emulator RAM. - """ - if program_start is None: - program_start = self.DEFAULT_PROGRAM_START - - basic_lines = self.ascii_listing2basic_lines(basic_program_ascii, program_start) - - return self.listing.basic_lines2program_dump(basic_lines, program_start) - - def pformat_tokens(self, tokens): - """ - format a tokenized BASIC program line. Useful for debugging. - returns a list of formated string lines. - """ - return self.listing.token_util.pformat_tokens(tokens) - - def pformat_program_dump(self, program_dump, program_start=None): - """ - format a BASIC program dump. Useful for debugging. - returns a list of formated string lines. - """ - if program_start is None: - program_start = self.DEFAULT_PROGRAM_START - return self.listing.pformat_program_dump(program_dump, program_start) - - def renum_ascii_listing(self, content): - return self.renum_tool.renum(content) - - def reformat_ascii_listing(self, basic_program_ascii): - - parsed_lines = self.parse_ascii_listing(basic_program_ascii) - - ascii_lines = [] - for line_no, code_objects in sorted(parsed_lines.items()): - print() - print(line_no, code_objects) - basic_line = BasicLine(self.token_util) - basic_line.code_objects_load(line_no,code_objects) - - print(basic_line) - basic_line.reformat() - new_line = basic_line.get_content() - print(new_line) - ascii_lines.append(new_line) - - return "\n".join(ascii_lines) - - -class Dragon32API(BaseAPI): - CONFIG_NAME = DRAGON32 - MACHINE_NAME = "Dragon 32" - BASIC_TOKENS = DRAGON32_BASIC_TOKENS - - PROGRAM_START_ADDR = 0x0019 - VARIABLES_START_ADDR = 0x001B - ARRAY_START_ADDR = 0x001D - FREE_SPACE_START_ADDR = 0x001F - - # Default memory location of BASIC listing start - DEFAULT_PROGRAM_START = 0x1E01 - - -class CoCoAPI(Dragon32API): - """ - http://sourceforge.net/p/toolshed/code/ci/default/tree/cocoroms/dragon_equivs.asm - """ - CONFIG_NAME = COCO2B - MACHINE_NAME = "CoCo" - BASIC_TOKENS = COCO_BASIC_TOKENS - -if __name__ == '__main__': - import os - from dragonlib.utils.logging_utils import setup_logging - - setup_logging( -# level=1 # hardcore debug ;) -# level=10 # DEBUG -# level=20 # INFO -# level=30 # WARNING -# level=40 # ERROR -# level=50 # CRITICAL/FATAL - level=99 - ) - - api = Dragon32API() - - filepath = os.path.join(os.path.abspath(os.path.dirname(__file__)), - # "..", "BASIC examples", "hex_view01.bas" - "..", "BASIC games", "INVADER.bas" - ) - - with open(filepath, "r") as f: - listing_ascii = f.read() - - print( - api.reformat_ascii_listing(listing_ascii) - ) \ No newline at end of file diff --git a/dragonlib/core/__init__.py b/dragonlib/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/core/basic.py b/dragonlib/core/basic.py deleted file mode 100644 index a22ccddc..00000000 --- a/dragonlib/core/basic.py +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/env python -# encoding:utf8 - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - -import logging -import re - -from dragonlib.core import basic_parser -from dragonlib.utils import six -from dragonlib.utils.iter_utils import list_replace -from dragonlib.utils.logging_utils import pformat_byte_hex_list, \ - log_program_dump -from dragonpy.utils.byte_word_values import word2bytes - -log = logging.getLogger(__name__) - - -class BasicTokenUtil(object): - def __init__(self, basic_token_dict): - self.basic_token_dict = basic_token_dict - self.ascii2token_dict = dict([ - (code, token) - for token, code in list(basic_token_dict.items()) - ]) - - regex = r"(%s)" % "|".join([ - re.escape(statement) - for statement in sorted(list(self.basic_token_dict.values()), key=len, reverse=True) - ]) - self.regex = re.compile(regex) - - def token2ascii(self, value): - try: - result = self.basic_token_dict[value] - except KeyError: - if value > 0xff: - log.critical("ERROR: Token $%04x is not in BASIC_TOKENS!", value) - return "" - result = chr(value) - if six.PY2: - # Only for unittest, to avoid token representation as u"..." - # There is only ASCII characters possible - return str(result) - else: - return result - - def tokens2ascii(self, values): - line="" - old_value = None - for value in values: - if value == 0xff: - old_value = value - continue - if old_value is not None: - value = (old_value << 8) + value - old_value = None - code = self.token2ascii(value) - line += code - return line - - def chars2tokens(self, chars): - return [ord(char) for char in chars] - - def ascii2token(self, ascii_code, debug=False): - """ - TODO: replace no tokens in comments and strings - """ - log.critical(repr(ascii_code)) - parts = self.regex.split(ascii_code) - log.critical(repr(parts)) - tokens = [] - for part in parts: - if not part: - continue - - if part in self.ascii2token_dict: - new_token = self.ascii2token_dict[part] - log.critical("\t%r -> %x", part, new_token) - if new_token > 0xff: - tokens.append(new_token >> 8) - tokens.append(new_token & 0xff) - else: - tokens.append(new_token) - else: - tokens += self.chars2tokens(part) - return tokens - - def code_objects2token(self, code_objects): - tokens = [] - for code_object in code_objects: - if code_object.PART_TYPE == basic_parser.CODE_TYPE_CODE: - # Code part - content = code_object.content - """ - NOTE: The BASIC interpreter changed REM shortcut and ELSE - internaly: - "'" <-> ":'" - "ELSE" <-> ":ELSE" - - See also: - http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4310&p=11632#p11630 - """ - log.info("replace ' and ELSE with :' and :ELSE") - content = content.replace("'", ":'") - content = content.replace("ELSE", ":ELSE") - tokens += self.ascii2token(content) - else: - # Strings, Comments or DATA - tokens += self.chars2tokens(code_object.content) - return tokens - - def iter_token_values(self, tokens): - token_value = None - for token in tokens: - if token == 0xff: - token_value = token - continue - - if token_value is not None: - yield (token_value << 8) + token - token_value = None - else: - yield token - - def pformat_tokens(self, tokens): - """ - format a tokenized BASIC program line. Useful for debugging. - returns a list of formated string lines. - """ - result = [] - for token_value in self.iter_token_values(tokens): - char = self.token2ascii(token_value) - if token_value > 0xff: - result.append("\t$%04x -> %s" % (token_value, repr(char))) - else: - result.append("\t $%02x -> %s" % (token_value, repr(char))) - - return result - - -class BasicLine(object): - def __init__(self, token_util): - self.token_util = token_util - self.line_number = None - self.line_code = None - - try: - colon_token = self.token_util.ascii2token_dict[":"] - except KeyError: # XXX: Always not defined as token? - colon_token = ord(":") - rem_token = self.token_util.ascii2token_dict["'"] - else_token = self.token_util.ascii2token_dict["ELSE"] - self.tokens_replace_rules = ( - ((colon_token, rem_token), rem_token), - ((colon_token, else_token), else_token), - ) - - def token_load(self, line_number, tokens): - self.line_number = line_number - assert tokens[-1] == 0x00, "line code %s doesn't ends with \\x00: %s" % ( - repr(tokens), repr(tokens[-1]) - ) - - """ - NOTE: The BASIC interpreter changed REM shortcut and ELSE - internaly: - "'" <-> ":'" - "ELSE" <-> ":ELSE" - - See also: - http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4310&p=11632#p11630 - """ - for src, dst in self.tokens_replace_rules: - log.info("Relace tokens %s with $%02x", - pformat_byte_hex_list(src), dst - ) - log.debug("Before..: %s", pformat_byte_hex_list(tokens)) - tokens = list_replace(tokens, src, dst) - log.debug("After...: %s", pformat_byte_hex_list(tokens)) - - self.line_code = tokens[:-1] # rstrip \x00 - - def ascii_load(self, line_ascii): - try: - line_number, ascii_code = line_ascii.split(" ", 1) - except ValueError as err: - msg = "Error split line number and code in line: %r (Origin error: %s)" % ( - line_ascii, err - ) - raise ValueError(msg) - self.line_number = int(line_number) - self.line_code = self.token_util.ascii2token(ascii_code) - - def code_objects_load(self, line_number, code_objects): - self.line_number = line_number - self.line_code = self.token_util.code_objects2token(code_objects) - - def get_tokens(self): - """ - return two bytes line number + the code - """ - return list(word2bytes(self.line_number)) + self.line_code - - def reformat(self): - # TODO: Use BASICParser to exclude string/comments etc. - space = self.token_util.ascii2token(" ")[0] - - to_split=self.token_util.basic_token_dict.copy() - dont_split_tokens=self.token_util.ascii2token(":()+-*/^<=>") - - for token_value in dont_split_tokens: - try: - del(to_split[token_value]) - except KeyError: # e.g.: () are not tokens - pass - - tokens=tuple(self.token_util.iter_token_values(self.line_code)) - - temp = [] - was_token=False - for no, token in enumerate(tokens): - try: - next_token=tokens[no+1] - except IndexError: - next_token=None - - if token in to_split: - print("X%sX" % to_split[token]) - - try: - if temp[-1]!=space: - temp.append(space) - except IndexError: - pass - temp.append(token) - - if not (next_token and next_token in dont_split_tokens): - temp.append(space) - was_token=True - else: - if was_token and token==space: - was_token=False - continue - print("Y%rY" % self.token_util.tokens2ascii([token])) - temp.append(token) - - temp = list_replace(temp, self.token_util.ascii2token("GO TO"), self.token_util.ascii2token("GOTO")) - temp = list_replace(temp, self.token_util.ascii2token("GO SUB"), self.token_util.ascii2token("GOSUB")) - temp = list_replace(temp, self.token_util.ascii2token(": "), self.token_util.ascii2token(":")) - temp = list_replace(temp, self.token_util.ascii2token("( "), self.token_util.ascii2token("(")) - temp = list_replace(temp, self.token_util.ascii2token(", "), self.token_util.ascii2token(",")) - - self.line_code = temp - - - def get_content(self, code=None): - if code is None: # start - code = self.line_code - - line = "%i " % self.line_number - line += self.token_util.tokens2ascii(code) - - return line - - def __repr__(self): - return "%r: %s" % (self.get_content(), " ".join(["$%02x" % t for t in self.line_code])) - - def log_line(self): - log.critical("%r:\n\t%s", - self.get_content(), - "\n\t".join(self.token_util.pformat_tokens(self.line_code)) - ) - - -class BasicListing(object): - def __init__(self, basic_token_dict): - self.token_util = BasicTokenUtil(basic_token_dict) - - def dump2basic_lines(self, dump, program_start, basic_lines=None): - if basic_lines is None: - basic_lines = [] - - log.critical("progam start $%04x", program_start) - try: - next_address = (dump[0] << 8) + dump[1] - except IndexError as err: - log.critical("Can't get address: %s", err) - return basic_lines - - log.critical("next_address: $%04x", next_address) - if next_address == 0x0000: - # program end - log.critical("return: %s", repr(basic_lines)) - return basic_lines - - assert next_address > program_start, "Next address $%04x not bigger than program start $%04x ?!?" % ( - next_address, program_start - ) - - line_number = (dump[2] << 8) + dump[3] - log.critical("line_number: %i", line_number) - length = next_address - program_start - log.critical("length: %i", length) - tokens = dump[4:length] - log.critical("tokens:\n\t%s", "\n\t".join(self.token_util.pformat_tokens(tokens))) - - basic_line = BasicLine(self.token_util) - basic_line.token_load(line_number, tokens) - basic_lines.append(basic_line) - - return self.dump2basic_lines(dump[length:], next_address, basic_lines) - - def basic_lines2program_dump(self, basic_lines, program_start): - program_dump = [] - current_address = program_start - count = len(basic_lines) - for no, line in enumerate(basic_lines, 1): - line.log_line() - line_tokens = line.get_tokens() + [0x00] - - current_address += len(line_tokens) + 2 - program_dump += word2bytes(current_address) - if no == count: # It's the last line - line_tokens += [0x00, 0x00] - program_dump += line_tokens - - return program_dump - - def ascii_listing2basic_lines(self, txt): - basic_lines = [] - for line in txt.splitlines(): - line = line.strip() - if line: - basic_line = BasicLine(self.token_util) - basic_line.ascii_load(line) - basic_lines.append(basic_line) - return basic_lines - - def pformat_program_dump(self, program_dump, program_start, formated_dump=None): - """ - format a BASIC program dump. Useful for debugging. - returns a list of formated string lines. - """ - if formated_dump is None: - formated_dump = [] - formated_dump.append( - "program start address: $%04x" % program_start - ) - - try: - next_address = (program_dump[0] << 8) + program_dump[1] - except IndexError as err: - raise IndexError( - "Can't get next address from: %s program start: $%04x (Origin error: %s)" % ( - repr(program_dump), program_start, err - )) - - if next_address == 0x0000: - formated_dump.append("$%04x -> end address" % next_address) - return formated_dump - - assert next_address > program_start, "Next address $%04x not bigger than program start $%04x ?!?" % ( - next_address, program_start - ) - - length = next_address - program_start - formated_dump.append( - "$%04x -> next address (length: %i)" % (next_address, length) - ) - line_number = (program_dump[2] << 8) + program_dump[3] - formated_dump.append("$%04x -> %i (line number)" % (line_number, line_number)) - - tokens = program_dump[4:length] - formated_dump.append("tokens:") - formated_dump += self.token_util.pformat_tokens(tokens) - - return self.pformat_program_dump(program_dump[length:], next_address, formated_dump) - - def debug_listing(self, basic_lines): - for line in basic_lines: - line.log_line() - - def log_ram_content(self, program_start, level=99): - ram_content = self.basic_lines2program_dump(program_start) - log_program_dump(ram_content, level) - - def ascii_listing2program_dump(self, basic_program_ascii, program_start): - basic_lines = self.ascii_listing2basic_lines(basic_program_ascii) - self.debug_listing(basic_lines) - return self.basic_lines2program_dump(basic_lines, program_start) - - -# def parsed_lines2program_dump(self, parsed_lines, program_start): -# for line_no, code_objects in sorted(parsed_lines.items()): -# for code_object in code_objects: - - - def program_dump2ascii_lines(self, dump, program_start): - basic_lines = self.dump2basic_lines(dump, program_start) - log.critical("basic_lines: %s", repr(basic_lines)) - ascii_lines = [] - for line in basic_lines: - ascii_lines.append(line.get_content()) - return ascii_lines - - -class RenumTool(object): - """ - Renumber a BASIC program - """ - def __init__(self, renum_regex): - self.line_no_regex = re.compile("(?P\d+)(?P.+)") - self.renum_regex = re.compile(renum_regex, re.VERBOSE) - - def renum(self, ascii_listing): - self.renum_dict = self.create_renum_dict(ascii_listing) - log.info("renum: %s", - ", ".join([ - "%s->%s" % (o, n) - for o, n in sorted(self.renum_dict.items()) - ]) - ) - new_listing = [] - for new_number, line in enumerate(self._iter_lines(ascii_listing), 1): - new_number *= 10 - line = self.line_no_regex.sub("%s\g" % new_number, line) - new_line = self.renum_regex.sub(self.renum_inline, line) - log.debug("%r -> %r", line, new_line) - new_listing.append(new_line) - return "\n".join(new_listing) - - def get_destinations(self, ascii_listing): - """ - returns all line numbers that are used in a jump. - """ - self.destinations = set() - def collect_destinations(matchobj): - numbers = matchobj.group("no") - if numbers: - self.destinations.update(set( - [n.strip() for n in numbers.split(",")] - )) - - for line in self._iter_lines(ascii_listing): - self.renum_regex.sub(collect_destinations, line) - - return sorted([int(no) for no in self.destinations if no]) - - def _iter_lines(self, ascii_listing): - lines = ascii_listing.splitlines() - lines = [line.strip() for line in lines if line.strip()] - for line in lines: - yield line - - def _get_new_line_number(self, line, old_number): - try: - new_number = "%s" % self.renum_dict[old_number] - except KeyError: - log.error( - "Error in line '%s': line no. '%s' doesn't exist.", - line, old_number - ) - new_number = old_number - return new_number - - def renum_inline(self, matchobj): -# log.critical(matchobj.groups()) - old_numbers = matchobj.group("no") - if old_numbers[-1] == " ": - # e.g.: space before comment: ON X GOTO 1,2 ' Comment - space_after = " " - else: - space_after = "" - old_numbers = [n.strip() for n in old_numbers.split(",")] - new_numbers = [ - self._get_new_line_number(matchobj.group(0), old_number) - for old_number in old_numbers - ] - return "".join([ - matchobj.group("statement"), - matchobj.group("space"), - ",".join(new_numbers), space_after - ]) - - def create_renum_dict(self, ascii_listing): - old_numbers = [match[0] for match in self.line_no_regex.findall(ascii_listing)] - renum_dict = {} - for new_number, old_number in enumerate(old_numbers, 1): - new_number *= 10 - renum_dict[old_number] = new_number - return renum_dict - - -def _test_renum(): - from dragonlib.api import Dragon32API - - api = Dragon32API() - listing = """\ -1 PRINT "ONE" -2 ON X GOSUB 1,12 , 14 , 15,455 ' foo -11 GOTO 12 -12 PRINT "FOO":GOSUB 15 -14 IF A=1 THEN 20 ELSE 1 -15 PRINT "BAR" -16 RESUME -20 PRINT "END?" -30 GOTO 123 ' didn't exist -""" - print(listing) - print("-" * 79) - print(api.renum_ascii_listing(listing)) - print("-" * 79) - print(api.renum_tool.get_destinations(listing)) - print("-" * 79) - - -def _test_reformat(): - import os - from dragonlib.utils.logging_utils import setup_logging - - setup_logging( -# level=1 # hardcore debug ;) -# level=10 # DEBUG -# level=20 # INFO -# level=30 # WARNING -# level=40 # ERROR -# level=50 # CRITICAL/FATAL - level=99 - ) - - from dragonlib.api import Dragon32API - api = Dragon32API() - - # filepath = os.path.join(os.path.abspath(os.path.dirname(__file__)), - # # "..", "BASIC examples", "hex_view01.bas" - # "..", "..", "BASIC games", "INVADER.bas" - # ) - # - # with open(filepath, "r") as f: - # listing_ascii = f.read() - - listing_ascii="""\ -10 ONPOINT(Y,K)GOTO250,250'ONPOINT(Y,K)GOTO250,250 -20 FORT=479TO 542:T(T)=0:Y(T)=28:NEXT -30 I=I+1:PRINT"FORX=1TO 2:Y(Y)=0:NEXT" -730 CLS:PRINT"FIXME: PLEASE WAIT [ ]"; -""" - - print( - api.reformat_ascii_listing(listing_ascii) - ) - -if __name__ == "__main__": - # _test_renum() - _test_reformat() diff --git a/dragonlib/core/basic_parser.py b/dragonlib/core/basic_parser.py deleted file mode 100644 index 0c9d3b8d..00000000 --- a/dragonlib/core/basic_parser.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python -# encoding:utf8 - -""" - BASIC parser - ============ - - Note: - The parser does only split into: - * line number - * Code parts - * DATA - * Strings - * Comments - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import re - -import logging - -log = logging.getLogger(__name__) - - -CODE_TYPE_CODE = "CODE" -CODE_TYPE_DATA = "DATA" -CODE_TYPE_STRING = "STRING" -CODE_TYPE_COMMENT = "COMMENT" - - -class BaseCode(object): - def __init__(self, content): - self.content = content - - def __repr__(self): - return "<%s:%s>" % (self.PART_TYPE, self.content) - - -class BASIC_Code(BaseCode): - PART_TYPE = CODE_TYPE_CODE - - -class BASIC_Data(BaseCode): - PART_TYPE = CODE_TYPE_DATA - - -class BASIC_String(BaseCode): - PART_TYPE = CODE_TYPE_STRING - - -class BASIC_Comment(BaseCode): - PART_TYPE = CODE_TYPE_COMMENT - - -class ParsedBASIC(dict): - """ - Normal dict with special __repr__ - """ - def pformat(self): - ''' - Manually pformat to force using """...""" and supress escaping apostrophe - ''' - result = "{\n" - indent1 = " " * 4 - indent2 = " " * 8 - for line_no, code_objects in sorted(self.items()): - result += '%s%i: [\n' % (indent1, line_no) - for code_object in code_objects: - result += '%s"""<%s:%s>""",\n' % ( - indent2, code_object.PART_TYPE, code_object.content - ) - result += '%s],\n' % indent1 - result += "}" - - return result - - def __repr__(self): - return self.pformat() - - -class BASICParser(object): - """ - Split BASIC sourcecode into: - * line number - * Code parts - * DATA - * Strings - * Comments - """ - def __init__(self): - self.regex_line_no = re.compile( - # Split the line number from the code - "^\s*(?P\d+)\s?(?P.+)\s*$", - re.MULTILINE - ) - self.regex_split_all = re.compile( - # To split a code line for parse CODE, DATA, STRING or COMMENT - r""" ( " | DATA | REM | ') """, - re.VERBOSE | re.MULTILINE - ) - self.regex_split_data = re.compile( - # To consume the complete DATA until " or : - r""" ( " | : ) """, - re.VERBOSE | re.MULTILINE - ) - self.regex_split_string = re.compile( - # To consume a string - r""" ( " ) """, - re.VERBOSE | re.MULTILINE - ) - - def parse(self, ascii_listing): - """ - parse the given ASCII BASIC listing. - Return a ParsedBASIC() instance. - """ - self.parsed_lines = ParsedBASIC() - for match in self.regex_line_no.finditer(ascii_listing): - log.info("_" * 79) - log.info("parse line >>>%r<<<", match.group()) - line_no = int(match.group("no")) - line_content = match.group("content") - - self.line_data = [] - self._parse_code(line_content) - log.info("*** line %s result: %r", line_no, self.line_data) - - self.parsed_lines[line_no] = self.line_data - - return self.parsed_lines - - def _parse_data(self, line, old_data=""): - """ - Parse a DATA section until : or \n but exclude : in a string part. - e.g.: - 10 DATA 1,"FOO:BAR",2:PRINT "NO DATA" - """ - log.debug("*** parse DATA: >>>%r<<< old data: >>>%r<<<", line, old_data) - parts = self.regex_split_data.split(line, maxsplit=1) - if len(parts) == 1: # end - return old_data + parts[0], None - - pre, match, post = parts - log.debug("\tpre: >>>%r<<<", pre) - pre = old_data + pre - log.debug("\tmatch: >>>%r<<<", match) - log.debug("\tpost: >>>%r<<<", post) - if match == ":": - return old_data, match + post - elif match == '"': - string_part, rest = self._parse_string(post) - return self._parse_data(rest, old_data=pre + match + string_part) - - raise RuntimeError("Wrong Reg.Exp.? match is: %r" % match) - - def _parse_string(self, line): - """ - Consume the complete string until next " or \n - """ - log.debug("*** parse STRING: >>>%r<<<", line) - parts = self.regex_split_string.split(line, maxsplit=1) - if len(parts) == 1: # end - return parts[0], None - - pre, match, post = parts - log.debug("\tpre: >>>%r<<<", pre) - log.debug("\tmatch: >>>%r<<<", match) - log.debug("\tpost: >>>%r<<<", post) - pre = pre + match - log.debug("Parse string result: %r,%r", pre, post) - return pre, post - - def _parse_code(self, line): - """ - parse the given BASIC line and branch into DATA, String and - consume a complete Comment - """ - log.debug("*** parse CODE: >>>%r<<<", line) - parts = self.regex_split_all.split(line, maxsplit=1) - if len(parts) == 1: # end - self.line_data.append(BASIC_Code(parts[0])) - return - pre, match, post = parts - log.debug("\tpre: >>>%r<<<", pre) - log.debug("\tmatch: >>>%r<<<", match) - log.debug("\tpost: >>>%r<<<", post) - - if match == '"': - log.debug("%r --> parse STRING", match) - self.line_data.append(BASIC_Code(pre)) - string_part, rest = self._parse_string(post) - self.line_data.append(BASIC_String(match + string_part)) - if rest: - self._parse_code(rest) - return - - self.line_data.append(BASIC_Code(pre + match)) - - if match == "DATA": - log.debug("%r --> parse DATA", match) - data_part, rest = self._parse_data(post) - self.line_data.append(BASIC_Data(data_part)) - if rest: - self._parse_code(rest) - return - elif match in ("'", "REM"): - log.debug("%r --> consume rest of the line as COMMENT", match) - if post: - self.line_data.append(BASIC_Comment(post)) - return - - raise RuntimeError("Wrong Reg.Exp.? match is: %r" % match) - - -if __name__ == "__main__": - import unittest - from dragonlib.utils.logging_utils import setup_logging - - setup_logging(log, -# level=1 # hardcore debug ;) -# level=10 # DEBUG -# level=20 # INFO - level=30 # WARNING -# level=40 # ERROR -# level=50 # CRITICAL/FATAL - ) - - unittest.main( - module="dragonlib.tests.test_basic_parser", - verbosity=2, - # failfast=True, - ) - print(" --- END --- ") diff --git a/dragonlib/dragon32/__init__.py b/dragonlib/dragon32/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/dragon32/basic_tokens.py b/dragonlib/dragon32/basic_tokens.py deleted file mode 100644 index 06f48d82..00000000 --- a/dragonlib/dragon32/basic_tokens.py +++ /dev/null @@ -1,131 +0,0 @@ -# encoding:utf8 - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -DRAGON32_BASIC_TOKENS = { - 0x80:"FOR", - 0x81:"GO", - 0x82:"REM", - 0x83:"'", - 0x84:"ELSE", - 0x85:"IF", - 0x86:"DATA", - 0x87:"PRINT", - 0x88:"ON", - 0x89:"INPUT", - 0x8a:"END", - 0x8b:"NEXT", - 0x8c:"DIM", - 0x8d:"READ", - 0x8e:"LET", - 0x8f:"RUN", - 0x90:"RESTORE", - 0x91:"RETURN", - 0x92:"STOP", - 0x93:"POKE", - 0x94:"CONT", - 0x95:"LIST", - 0x96:"CLEAR", - 0x97:"NEW", - 0x98:"DEF", - 0x99:"CLOAD", - 0x9a:"CSAVE", - 0x9b:"OPEN", - 0x9c:"CLOSE", - 0x9d:"LLIST", - 0x9e:"SET", - 0x9f:"RESET", - 0xa0:"CLS", - 0xa1:"MOTOR", - 0xa2:"SOUND", - 0xa3:"AUDIO", - 0xa4:"EXEC", - 0xa5:"SKIPF", - 0xa6:"DEL", - 0xa7:"EDIT", - 0xa8:"TRON", - 0xa9:"TROFF", - 0xaa:"LINE", - 0xab:"PCLS", - 0xac:"PSET", - 0xad:"PRESET", - 0xae:"SCREEN", - 0xaf:"PCLEAR", - 0xb0:"COLOR", - 0xb1:"CIRCLE", - 0xb2:"PAINT", - 0xb3:"GET", - 0xb4:"PUT", - 0xb5:"DRAW", - 0xb6:"PCOPY", - 0xb7:"PMODE", - 0xb8:"PLAY", - 0xb9:"DLOAD", - 0xba:"RENUM", - 0xbb:"TAB(", - 0xbc:"TO", - 0xbd:"SUB", - 0xbe:"FN", - 0xbf:"THEN", - 0xc0:"NOT", - 0xc1:"STEP", - 0xc2:"OFF", - 0xc3:"+", - 0xc4:"-", - 0xc5:"*", - 0xc6:"/", - 0xc7:"^", - 0xc8:"AND", - 0xc9:"OR", - 0xca:">", - 0xcb:"=", - 0xcc:"<", - 0xcd:"USING", - -#Function tokens - all proceeded by 0xff to differentiate from operators -#Token Function", - 0xff80:"SGN", - 0xff81:"INT", - 0xff82:"ABS", - 0xff83:"POS", - 0xff84:"RND", - 0xff85:"SQR", - 0xff86:"LOG", - 0xff87:"EXP", - 0xff88:"SIN", - 0xff89:"COS", - 0xff8a:"TAN", - 0xff8b:"ATN", - 0xff8c:"PEEK", - 0xff8d:"LEN", - 0xff8e:"STR$", - 0xff8f:"VAL", - 0xff90:"ASC", - 0xff91:"CHR$", - 0xff92:"EOF", - 0xff93:"JOYSTK", - 0xff94:"FIX", - 0xff95:"HEX$", - 0xff96:"LEFT$", - 0xff97:"RIGHT$", - 0xff98:"MID$", - 0xff99:"POINT", - 0xff9a:"INKEY$", - 0xff9b:"MEM", - 0xff9c:"VARPTR", - 0xff9d:"INSTR", - 0xff9e:"TIMER", - 0xff9f:"PPOINT", - 0xffa0:"STRING$", - 0xffa1:"USR", -} diff --git a/dragonlib/tests/__init__.py b/dragonlib/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/tests/run_all_dragonlib_tests.py b/dragonlib/tests/run_all_dragonlib_tests.py deleted file mode 100644 index a98af22c..00000000 --- a/dragonlib/tests/run_all_dragonlib_tests.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import unittest - -from dragonpy.tests.test_base import TextTestRunner2 - - -if __name__ == "__main__": - loader = unittest.TestLoader() - tests = loader.discover('dragonlib') - - test_runner = TextTestRunner2(verbosity=2, -# failfast=True, - ) - - test_runner.run(tests) - print(" --- END --- ") \ No newline at end of file diff --git a/dragonlib/tests/test_api.py b/dragonlib/tests/test_api.py deleted file mode 100644 index 485c26e2..00000000 --- a/dragonlib/tests/test_api.py +++ /dev/null @@ -1,572 +0,0 @@ -#!/usr/bin/env python -# encoding:utf-8 - -""" - Dragon Lib unittests - ~~~~~~~~~~~~~~~~~~~~ - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import pprint -import sys -import unittest -import logging - -from dragonlib.api import Dragon32API -from dragonlib.core.basic import BasicLine -from dragonlib.tests.test_base import BaseTestCase -from dragonlib.utils.logging_utils import pformat_program_dump -from dragonpy.tests.test_base import TextTestRunner2 - - -log = logging.getLogger(__name__) - - -class BaseDragon32ApiTestCase(BaseTestCase): - def setUp(self): - self.dragon32api = Dragon32API() - - def assertEqualProgramDump(self, first, second, msg=None): - first = self.dragon32api.pformat_program_dump(first) - second = self.dragon32api.pformat_program_dump(second) - self.assertEqual(first, second, msg) - - def assertListing2Dump(self, ascii_listing,program_dump,debug=False): - if debug: - print("\n"+"_"*79) - print(" *** Debug Listing:\n%s" % ascii_listing) - print(" -"*39) - print(" *** Debug Dump:\n%s\n" % ( - pformat_program_dump(program_dump) - )) - print(" -"*39) - - created_program_dump = self.dragon32api.ascii_listing2program_dump( - ascii_listing - ) - if debug: - print(" *** Created dump from listing:\n%s\n" % ( - pformat_program_dump(created_program_dump) - )) - print(" -"*39) - - if not created_program_dump: - log.critical("Created dump empty? repr: %s", repr(created_program_dump)) - - if debug: - print(" *** Full Dump:\n%s" % "\n".join( - self.dragon32api.pformat_program_dump(created_program_dump) - )) - self.assertEqualProgramDump(created_program_dump, program_dump) - - def assertDump2Listing(self, ascii_listing,program_dump): -# log_program_dump(created_program_dump) -# print "\n".join( -# self.dragon32api.pformat_program_dump(created_program_dump) -# ) - created_listing = self.dragon32api.program_dump2ascii_lines(program_dump) - ascii_listing=ascii_listing.splitlines() - self.assertEqual(created_listing, ascii_listing) - - def _prepare_text(self, txt): - """ - prepare the multiline, indentation text. - from python-creole - """ - # txt = unicode(txt) - txt = txt.splitlines() - assert txt[0] == "", "First assertion line must be empty! Is: %s" % repr(txt[0]) - txt = txt[1:] # Skip the first line - - # get the indentation level from the first line - count = False - for count, char in enumerate(txt[0]): - if char != " ": - break - - assert count != False, "second line is empty!" - - # remove indentation from all lines - txt = [i[count:].rstrip(" ") for i in txt] - - # ~ txt = re.sub("\n {2,}", "\n", txt) - txt = "\n".join(txt) - - # strip *one* newline at the begining... - if txt.startswith("\n"): - txt = txt[1:] - # and strip *one* newline at the end of the text - if txt.endswith("\n"): - txt = txt[:-1] - # ~ print(repr(txt)) - # ~ print("-"*79) - - return str(txt) # turn to unicode, for better assertEqual error messages - - -class Dragon32BASIC_LowLevel_ApiTest(BaseDragon32ApiTestCase): - def setUp(self): - super(Dragon32BASIC_LowLevel_ApiTest, self).setUp() - self.token_util = self.dragon32api.listing.token_util - self.basic_line = BasicLine(self.token_util) - - def test_load_from_dump(self): - dump = ( - 0x1e, 0x07, # next_address - 0x00, 0x0a, # 10 - 0xa0, # CLS - 0x00, # end of line - 0x00, 0x00 # program end - ) - basic_lines = self.dragon32api.listing.dump2basic_lines(dump, program_start=0x1e01) - ascii_listing = basic_lines[0].get_content() - self.assertEqual(ascii_listing, "10 CLS") - self.assertEqual(len(basic_lines), 1) - - def test_tokens2ascii(self): - self.basic_line.token_load( - line_number=50, - tokens=(0x49, 0x24, 0x20, 0xcb, 0x20, 0xff, 0x9a, 0x3a, 0x85, 0x20, 0x49, 0x24, 0xcb, 0x22, 0x22, 0x20, 0xbf, 0x20, 0x35, 0x30, 0x00) - ) - code = self.basic_line.get_content() - self.assertEqual(code, - '50 I$ = INKEY$:IF I$="" THEN 50' - ) - - def test_ascii2tokens01(self): - basic_lines = self.dragon32api.listing.ascii_listing2basic_lines( - '10 CLS' - ) - tokens = basic_lines[0].get_tokens() - self.assertHexList(tokens, [ - 0x00, 0x0a, # 10 - 0xa0, # CLS - ]) - self.assertEqual(len(basic_lines), 1) - - def test_ascii2tokens02(self): - basic_lines = self.dragon32api.listing.ascii_listing2basic_lines( - '50 I$ = INKEY$:IF I$="" THEN 50' - ) - tokens = basic_lines[0].get_tokens() - self.assertHexList(tokens, [ - 0x00, 0x32, # 50 - # I$ = INKEY$:IF I$="" THEN 50 - 0x49, 0x24, 0x20, 0xcb, 0x20, 0xff, 0x9a, 0x3a, 0x85, 0x20, 0x49, 0x24, 0xcb, 0x22, 0x22, 0x20, 0xbf, 0x20, 0x35, 0x30, - ]) - self.assertEqual(len(basic_lines), 1) - - def test_format_tokens(self): - tokens = (0x49, 0x24, 0x20, 0xcb, 0x20, 0xff, 0x9a) # I$ = INKEY$ - formated_tokens = self.token_util.pformat_tokens(tokens) - self.assertEqual(formated_tokens, [ - "\t $49 -> 'I'", - "\t $24 -> '$'", - "\t $20 -> ' '", - "\t $cb -> '='", - "\t $20 -> ' '", - "\t$ff9a -> 'INKEY$'", - ]) - - -class Dragon32BASIC_HighLevel_ApiTest(BaseDragon32ApiTestCase): - DUMP = (0x1e, 0x07, 0x00, 0x0a, 0xa0, 0x00, 0x1e, 0x1a, 0x00, 0x14, 0x80, 0x20, 0x49, 0x20, 0xcb, 0x20, 0x30, 0x20, 0xbc, 0x20, 0x32, 0x35, 0x35, 0x3a, 0x00, 0x1e, 0x2d, 0x00, 0x1e, 0x93, 0x20, 0x31, 0x30, 0x32, 0x34, 0xc3, 0x28, 0x49, 0xc5, 0x32, 0x29, 0x2c, 0x49, 0x00, 0x1e, 0x35, 0x00, 0x28, 0x8b, 0x20, 0x49, 0x00, 0x1e, 0x4e, 0x00, 0x32, 0x49, 0x24, 0x20, 0xcb, 0x20, 0xff, 0x9a, 0x3a, 0x85, 0x20, 0x49, 0x24, 0xcb, 0x22, 0x22, 0x20, 0xbf, 0x20, 0x35, 0x30, 0x00, 0x00, 0x00) - LISTING = [ - '10 CLS', - '20 FOR I = 0 TO 255:', - '30 POKE 1024+(I*2),I', - '40 NEXT I', - '50 I$ = INKEY$:IF I$="" THEN 50' - ] - - def test_program_dump2ascii(self): - listing = self.dragon32api.program_dump2ascii_lines(self.DUMP) - self.assertEqual(listing, self.LISTING) - - def test_ascii_listing2tokens(self): - basic_program_ascii = "\n".join(self.LISTING) - program_dump = self.dragon32api.ascii_listing2program_dump(basic_program_ascii) -# print "\n".join(self.dragon32api.pformat_program_dump(program_dump)) - self.assertEqualProgramDump(program_dump, self.DUMP) - - def test_ascii2RAM01(self): - tokens = self.dragon32api.ascii_listing2program_dump("10 CLS") -# log_hexlist(ram_content) -# log_hexlist(dump) - self.assertEqualProgramDump(tokens, ( - 0x1e, 0x07, # next_address - 0x00, 0x0a, # 10 - 0xa0, # CLS - 0x00, # end of line - 0x00, 0x00 # program end - )) - - def test_ascii2RAM02(self): - tokens = self.dragon32api.ascii_listing2program_dump( - "10 A=1\n" - "20 B=2\n" - ) -# log_hexlist(ram_content) -# log_hexlist(dump) - self.assertEqualProgramDump(tokens, ( - 0x1e, 0x09, # next_address - 0x00, 0x0a, # 10 - 0x41, 0xcb, 0x31, # A=1 - 0x00, # end of line - 0x1e, 0x11, # next_address - 0x00, 0x14, # 20 - 0x42, 0xcb, 0x32, # B=2 - 0x00, # end of line - 0x00, 0x00 # program end - )) - - def test_listing2program_strings_dont_in_comment(self): - """ - Don't replace tokens in comments - """ - ascii_listing = self._prepare_text(""" - 10 'IF THEN ELSE" - """) - program_dump= ( - 0x1e, 0x15, # next address - 0x00, 0x0a, # 10 - 0x3a, # : - 0x83, # ' - 0x49, 0x46, # I, F - 0x20, # " " - 0x54, 0x48, 0x45, 0x4e, # T, H, E, N - 0x20, # " " - 0x45, 0x4c, 0x53, 0x45, # E, L, S, E - 0x22, # " - 0x00, # end of line - 0x00, 0x00, # program end - ) - self.assertListing2Dump(ascii_listing,program_dump, -# debug=True - ) - self.assertDump2Listing(ascii_listing,program_dump) - - def test_listing2program_strings_dont_in_strings(self): - """ - Don't replace tokens in strings - """ - ascii_listing = self._prepare_text(""" - 10 PRINT"FOR NEXT - """) - program_dump= ( - 0x1e, 0x10, # next address - 0x00, 0x0a, # 10 - 0x87, # PRINT - 0x22, # " - 0x46, 0x4f, 0x52, # F, O, R - 0x20, # " " - 0x4e, 0x45, 0x58, 0x54, # N, E, X, T - 0x00, # end of line - 0x00, 0x00, # program end - ) - self.assertListing2Dump(ascii_listing,program_dump, -# debug=True - ) - self.assertDump2Listing(ascii_listing,program_dump) - - - def test_ascii_listing2program_dump_with_bigger_line_number(self): - """ - Don't replace tokens in strings - """ - ascii_listing = self._prepare_text(""" - 65000 CLS - """) - program_dump = ( - 0x1e, 0x07, # start address - 0xfd, 0xe8, # 65000 - 0xa0, # CLS - 0x00, # end of line - 0x00, 0x00, # program end - ) - self.assertListing2Dump(ascii_listing,program_dump) - self.assertDump2Listing(ascii_listing,program_dump) - - def test_auto_add_colon_before_comment(self): - """ - NOTE: The REM shortcut >'< would be replace by >:'< internally from - the BASIC Interpreter. - - See also: - http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4310&p=11632#p11630 - """ - ascii_listing = self._prepare_text(""" - 100 'FOO - """) - program_dump = ( - 0x1e, 0x0b, # next address (length: 10) - 0x00, 0x64, # 100 (line number) - 0x3a, # : ===> Insert/remove it automaticly - 0x83, # ' - 0x46, # F - 0x4f, # O - 0x4f, # O - 0x00, # EOL - 0x00, 0x00, # end address - ) - self.assertListing2Dump(ascii_listing,program_dump, - debug=True - ) - self.assertDump2Listing(ascii_listing,program_dump) - - def test_auto_add_colon_before_else(self): - """ - NOTE: The REM shortcut >'< would be replace by >:'< internally from - the BASIC Interpreter. - - See also: - http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4310&p=11632#p11630 - """ - ascii_listing = self._prepare_text(""" - 100 IF A=1 THEN 10 ELSE 20 - """) - program_dump = ( - 0x1e, 0x16, # -> next address (length: 21) - 0x00, 0x64, # -> 100 (line number) - 0x85, # -> 'IF' - 0x20, # -> ' ' - 0x41, # -> 'A' - 0xcb, # -> '=' - 0x31, # -> '1' - 0x20, # -> ' ' - 0xbf, # -> 'THEN' - 0x20, # -> ' ' - 0x31, # -> '1' - 0x30, # -> '0' - 0x20, # -> ' ' - 0x3a, # : ===> Insert/remove it automaticly - 0x84, # -> 'ELSE' - 0x20, # -> ' ' - 0x32, # -> '2' - 0x30, # -> '0' - 0x00, # -> EOL - 0x00, 0x00, # -> end address - ) - self.assertListing2Dump(ascii_listing,program_dump, - debug=True - ) - self.assertDump2Listing(ascii_listing,program_dump) - - def test_two_byte_line_numbers(self): - """ - Every line number is saved as one word! - """ - ascii_listing = self._prepare_text(""" - 254 PRINT "A" - 255 PRINT "B" - 256 PRINT "C" - 257 PRINT "D" - """) - program_dump = ( - # program start address: $1e01 - 0x1e, 0x0b, # -> next address (length: 10) - 0x00, 0xfe, # -> 254 (line number) - 0x87, # -> 'PRINT' - 0x20, # -> ' ' - 0x22, # -> '"' - 0x41, # -> 'A' - 0x22, # -> '"' - 0x00, # -> '\x00' - 0x1e, 0x15, # -> next address (length: 10) - 0x00, 0xff, # -> 255 (line number) - 0x87, # -> 'PRINT' - 0x20, # -> ' ' - 0x22, # -> '"' - 0x42, # -> 'B' - 0x22, # -> '"' - 0x00, # -> '\x00' - 0x1e, 0x1f, # -> next address (length: 10) - 0x01, 0x00, # -> 256 (line number) - 0x87, # -> 'PRINT' - 0x20, # -> ' ' - 0x22, # -> '"' - 0x43, # -> 'C' - 0x22, # -> '"' - 0x00, # -> '\x00' - 0x1e, 0x29, # -> next address (length: 10) - 0x01, 0x01, # -> 257 (line number) - 0x87, # -> 'PRINT' - 0x20, # -> ' ' - 0x22, # -> '"' - 0x44, # -> 'D' - 0x22, # -> '"' - 0x00, # -> '\x00' - 0x00, 0x00, # -> end address - ) - self.assertListing2Dump(ascii_listing,program_dump, - # debug=True - ) - self.assertDump2Listing(ascii_listing,program_dump) - - -class RenumTests(BaseDragon32ApiTestCase): - def test_renum01(self): - old_listing = self._prepare_text(""" - 1 PRINT "ONE" - 11 GOTO 12 - 12 PRINT "FOO":GOSUB 15 - 14 IF A=1 THEN 20 ELSE 1 - 15 PRINT "BAR" - 16 RESUME - 20 PRINT "END?" - """) -# print old_listing -# print "-"*79 - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 PRINT "ONE" - 20 GOTO 30 - 30 PRINT "FOO":GOSUB 50 - 40 IF A=1 THEN 70 ELSE 10 - 50 PRINT "BAR" - 60 RESUME - 70 PRINT "END?" - """)) - - def test_missing_number01(self): - old_listing = self._prepare_text(""" - 1 GOTO 2 - 2 GOTO 123 ' 123 didn't exists - 3 IF A=1 THEN 456 ELSE 2 ' 456 didn't exists - """) - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 GOTO 20 - 20 GOTO 123 ' 123 didn't exists - 30 IF A=1 THEN 456 ELSE 20 ' 456 didn't exists - """)) - - def test_on_goto(self): - old_listing = self._prepare_text(""" - 1 ON X GOTO 2,3 - 2 ?"A" - 3 ?"B" - """) - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 ON X GOTO 20,30 - 20 ?"A" - 30 ?"B" - """)) - - def test_on_goto_spaces(self): - old_listing = self._prepare_text(""" - 1 ON X GOTO 2,30 , 4, 555 - 2 ?"A" - 30 ?"B" - 4 ?"C" - 555 ?"D" - """) - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 ON X GOTO 20,30,40,50 - 20 ?"A" - 30 ?"B" - 40 ?"C" - 50 ?"D" - """)) - - def test_on_goto_space_after(self): - old_listing = self._prepare_text(""" - 1 ON X GOTO 1,2 ' space before comment? - 2 ?"A" - """) -# print old_listing -# print "-"*79 - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 ON X GOTO 10,20 ' space before comment? - 20 ?"A" - """)) - - def test_on_gosub_dont_exists(self): - old_listing = self._prepare_text(""" - 1 ON X GOSUB 1,2,3 - 2 ?"A" - """) -# print old_listing -# print "-"*79 - new_listing = self.dragon32api.renum_ascii_listing(old_listing) -# print new_listing - self.assertEqual(new_listing, self._prepare_text(""" - 10 ON X GOSUB 10,20,3 - 20 ?"A" - """)) - - def test_get_destinations_1(self): - listing = self._prepare_text(""" - 10 PRINT "ONE" - 20 GOTO 30 - 30 PRINT "FOO":GOSUB 50 - 40 IF A=1 THEN 20 ELSE 10 - 50 PRINT "BAR" - 60 RESUME - 70 PRINT "END?" - 80 ON X GOTO 10, 20, 30 ,40 ,50 - 90 ON X GOSUB 10, 70, 999 - """) - destinations = self.dragon32api.renum_tool.get_destinations(listing) - self.assertEqual(destinations, - [10, 20, 30, 40, 50, 70, 999] - ) - - def test_on_gosub_and_goto(self): - old_listing = self._prepare_text(""" - 2 PRINT "2" - 13 ON X GOSUB 18 :ONY GOSUB 2,2:NEXT:GOTO99 - 18 PRINT "18" - 99 PRINT "99" - """) - # print(old_listing) - # print("-"*79) - new_listing = self.dragon32api.renum_ascii_listing(old_listing) - # print(new_listing) - self.assertEqual(new_listing, self._prepare_text(""" - 10 PRINT "2" - 20 ON X GOSUB 30 :ONY GOSUB 10,10:NEXT:GOTO40 - 30 PRINT "18" - 40 PRINT "99" - """)) - - - -if __name__ == '__main__': - from dragonlib.utils.logging_utils import setup_logging - - setup_logging( - level=1 # hardcore debug ;) - # level=10 # DEBUG - # level=20 # INFO - # level=30 # WARNING - # level=40 # ERROR - # level=50 # CRITICAL/FATAL - ) - - unittest.main( - testRunner= TextTestRunner2, - argv=( - sys.argv[0], -# "Dragon32BASIC_HighLevel_ApiTest.test_listing2program_strings_dont_in_comment", -# "Dragon32BASIC_HighLevel_ApiTest.test_two_byte_line_numbers", -# "RenumTests.test_on_gosub_and_goto" - ), - # verbosity=1, - verbosity=2, - failfast=True, - ) diff --git a/dragonlib/tests/test_base.py b/dragonlib/tests/test_base.py deleted file mode 100644 index 2c036d0d..00000000 --- a/dragonlib/tests/test_base.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# encoding:utf-8 - -""" - Dragon Lib unittests - ~~~~~~~~~~~~~~~~~~~~ - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import unittest - -class BaseTestCase(unittest.TestCase): - """ - Only some special assertments. - """ - maxDiff=3000 - - def assertHexList(self, first, second, msg=None): - first = ["$%x" % value for value in first] - second = ["$%x" % value for value in second] - self.assertEqual(first, second, msg) - - def assertEqualHex(self, hex1, hex2, msg=None): - first = "$%x" % hex1 - second = "$%x" % hex2 - if msg is None: - msg = "%s != %s" % (first, second) - self.assertEqual(first, second, msg) - - def assertIsByteRange(self, value): - self.assertTrue(0x0 <= value, "Value (dez: %i - hex: %x) is negative!" % (value, value)) - self.assertTrue(0xff >= value, "Value (dez: %i - hex: %x) is greater than 0xff!" % (value, value)) - - def assertIsWordRange(self, value): - self.assertTrue(0x0 <= value, "Value (dez: %i - hex: %x) is negative!" % (value, value)) - self.assertTrue(0xffff >= value, "Value (dez: %i - hex: %x) is greater than 0xffff!" % (value, value)) - - def assertEqualHexByte(self, hex1, hex2, msg=None): - self.assertIsByteRange(hex1) - self.assertIsByteRange(hex2) - first = "$%02x" % hex1 - second = "$%02x" % hex2 - if msg is None: - msg = "%s != %s" % (first, second) - self.assertEqual(first, second, msg) - - def assertEqualHexWord(self, hex1, hex2, msg=None): - self.assertIsWordRange(hex1) - self.assertIsWordRange(hex2) - first = "$%04x" % hex1 - second = "$%04x" % hex2 - if msg is None: - msg = "%s != %s" % (first, second) - self.assertEqual(first, second, msg) - diff --git a/dragonlib/tests/test_basic_parser.py b/dragonlib/tests/test_basic_parser.py deleted file mode 100644 index b21cd9f0..00000000 --- a/dragonlib/tests/test_basic_parser.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/env python -# encoding:utf8 - -""" - unittests for BASIC parser - ========================== - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import logging -import sys -import unittest - -from dragonlib.core.basic_parser import BASICParser - - -log = logging.getLogger(__name__) - - -class TestBASICParser(unittest.TestCase): - def setUp(self): - self.parser = BASICParser() - - def assertParser(self, ascii_listing, reference, print_parsed_lines=False): - ''' - parse the given ASCII Listing and compare it with the reference. - - Used a speacial representation of the parser result for a human - readable compare. Force using of """...""" to supress escaping apostrophe - ''' - parsed_lines = self.parser.parse(ascii_listing) - - string_dict = {} - for line_no, code_objects in list(parsed_lines.items()): - string_dict[line_no] = [repr(code_object) for code_object in code_objects] - - if print_parsed_lines: - print("-" * 79) - print("parsed lines:", parsed_lines) - print("-" * 79) - print("reference:", reference) - print("-" * 79) - - self.assertEqual(string_dict, reference) - - def test_only_code(self): - ascii_listing = """ - 10 CLS - 20 PRINT - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - ], - 20: [ - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_string(self): - ascii_listing = '10 A$="A STRING"' - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_strings(self): - ascii_listing = """ - 10 A$="1":B=2:C$="4":CLS:PRINT "ONLY CODE" - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - """""", - """""", - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_string_and_comment(self): - ascii_listing = """ - 10 A$="NO :'REM" ' BUT HERE! - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_string_not_terminated(self): - ascii_listing = """ - 10 PRINT "NOT TERMINATED STRING - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_data(self): - ascii_listing = """ - 10 DATA 1,2,A,FOO - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_data_with_string1(self): - ascii_listing = """ - 10 DATA 1,2,"A","FOO BAR",4,5 - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_data_string_colon(self): - ascii_listing = """ - 10 DATA "FOO : BAR" - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_code_after_data(self): - ascii_listing = """ - 10 DATA "FOO : BAR":PRINT 123 - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_comment(self): - ascii_listing = """ - 10 REM A COMMENT - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_nothing_after_comment1(self): - ascii_listing = """ - 10 REM - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_nothing_after_comment2(self): - ascii_listing = """ - 10 ' - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_no_code_after_comment(self): - ascii_listing = """ - 10 REM FOR "FOO : BAR":PRINT 123 - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_comment2(self): - ascii_listing = """ - 10 A=2 ' FOR "FOO : BAR":PRINT 123 - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_no_comment(self): - ascii_listing = """ - 10 B$="'" - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - """""", - ], - }, - # print_parsed_lines=True - ) - - def test_spaces_after_line_no(self): - ascii_listing = """ - 10 FOR I=1 TO 3: - 20 PRINT I - 30 NEXT - """ - self.assertParser(ascii_listing, - { - 10: [ - """""", - ], - 20: [ - """""", - ], - 30: [ - """""", - ], - }, -# print_parsed_lines=True - ) - - -if __name__ == "__main__": - from dragonlib.utils.logging_utils import setup_logging - - setup_logging( -# level=1 # hardcore debug ;) -# level=10 # DEBUG -# level=20 # INFO -# level=30 # WARNING -# level=40 # ERROR - level=50 # CRITICAL/FATAL - ) - - unittest.main( - argv=( - sys.argv[0], -# "TestBASICParser.test_spaces_after_line_no", - ), - # verbosity=1, - verbosity=2, - # failfast=True, - ) - print(" --- END --- ") diff --git a/dragonlib/utils/__init__.py b/dragonlib/utils/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dragonlib/utils/auto_shift.py b/dragonlib/utils/auto_shift.py deleted file mode 100644 index 9ef2e7db..00000000 --- a/dragonlib/utils/auto_shift.py +++ /dev/null @@ -1,43 +0,0 @@ -# encoding:utf8 - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -import string - -def invert_shift(chars): - """ - >>> invert_shift("a") - 'A' - >>> invert_shift("A") - 'a' - - >>> invert_shift("123 foo 456 BAR #!") - '123 FOO 456 bar #!' - """ - result = "" - for char in chars: - if char in string.ascii_lowercase: -# log.critical("auto shift lowercase char %s to UPPERCASE", repr(char)) - char = char.upper() - elif char in string.ascii_uppercase: -# log.critical("auto shift UPPERCASE char %s to lowercase", repr(char)) - char = char.lower() - result += char - return result - - -if __name__ == '__main__': - import doctest - print(doctest.testmod( - # verbose=1 - )) diff --git a/dragonlib/utils/get_six.sh b/dragonlib/utils/get_six.sh deleted file mode 100755 index 58152640..00000000 --- a/dragonlib/utils/get_six.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -( - set -x - wget --timestamp https://bitbucket.org/gutworth/six/raw/tip/six.py -) -echo -read -n1 -p "Start bash? [y,n]" doit -echo -case $doit in - y|Y) - bash -i - exit 0 - ;; - n|N) - echo "bye bye" - ;; - *) - echo "input, don't know, bye." - ;; -esac \ No newline at end of file diff --git a/dragonlib/utils/iter_utils.py b/dragonlib/utils/iter_utils.py deleted file mode 100644 index 45088468..00000000 --- a/dragonlib/utils/iter_utils.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# encoding:utf-8 - -""" - iter utilities - ~~~~~~~~~~~~~~ - - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -def list_replace(iterable, src, dst): - """ - Thanks to "EyDu": - http://www.python-forum.de/viewtopic.php?f=1&t=34539 (de) - - >>> list_replace([1,2,3], (1,2), "X") - ['X', 3] - - >>> list_replace([1,2,3,4], (2,3), 9) - [1, 9, 4] - - >>> list_replace([1,2,3], (2,), [9,8]) - [1, 9, 8, 3] - - >>> list_replace([1,2,3,4,5], (2,3,4), "X") - [1, 'X', 5] - - >>> list_replace([1,2,3,4,5], (4,5), "X") - [1, 2, 3, 'X'] - - >>> list_replace([1,2,3,4,5], (1,2), "X") - ['X', 3, 4, 5] - - >>> list_replace([1,2,3,3,3,4,5], (3,3), "X") - [1, 2, 'X', 3, 4, 5] - - >>> list_replace([1,2,3,3,3,4,5], (3,3), ("A","B","C")) - [1, 2, 'A', 'B', 'C', 3, 4, 5] - - >>> list_replace((58, 131, 73, 70), (58, 131), 131) - [131, 73, 70] - """ - result=[] - iterable=list(iterable) - - try: - dst=list(dst) - except TypeError: # e.g.: int - dst=[dst] - - src=list(src) - src_len=len(src) - index = 0 - while index < len(iterable): - element = iterable[index:index+src_len] -# print element, src - if element == src: - result += dst - index += src_len - else: - result.append(iterable[index]) - index += 1 - return result - - -if __name__ == "__main__": - import doctest - print(doctest.testmod()) \ No newline at end of file diff --git a/dragonlib/utils/logging_utils.py b/dragonlib/utils/logging_utils.py deleted file mode 100755 index 9c9103a4..00000000 --- a/dragonlib/utils/logging_utils.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python -# encoding:utf-8 - -""" - loggin utilities - ~~~~~~~~~~~~~~~~ - - :created: 2014 by Jens Diemer - www.jensdiemer.de - :copyleft: 2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function -from dragonlib.utils import six -xrange = six.moves.xrange - -import logging -import sys - -log = logging.getLogger(__name__) - - -# log.critical("Log handlers: %s", repr(log.handlers)) -# if len(log.handlers) > 1: # FIXME: tro avoid doublicated output -# log.handlers = (log.handlers[0],) -# log.critical("Fixed Log handlers: %s", repr(log.handlers)) - - -def get_log_levels(additional_levels=[100,99]): - levels = additional_levels[:] - try: - # Python 3 - levels += logging._nameToLevel.values() - except AttributeError: - # Python 2 - levels += [level for level in logging._levelNames if isinstance(level, int)] - - levels.sort() - return levels - -LOG_LEVELS = get_log_levels() - - - -def setup_logging(level, logger_name=None, handler=None, log_formatter=None): - """ - levels: - 1 - hardcode DEBUG ;) - 10 - DEBUG - 20 - INFO - 30 - WARNING - 40 - ERROR - 50 - CRITICAL/FATAL - 99 - nearly off - 100 - complete off - """ - root_logger = logging.getLogger() - - if logger_name is None: - logger = root_logger - root_logger.info("Set %i level to root logger", level) - else: - logger = logging.getLogger(logger_name) - root_logger.info("Set %i level to logger %r", level, logger_name) - - if level == 100: - logger.handlers = () - logger.disabled = True - return - - logger.setLevel(level=level) - - if log_formatter is None: - log_formatter = "%(relativeCreated)-5d %(levelname)8s %(module)13s %(lineno)d %(message)s" - formatter = logging.Formatter(log_formatter) - - if handler is None: - handler = logging.StreamHandler() - handler.setFormatter(formatter) - - if hasattr(handler, "baseFilename"): - root_logger.debug("Log to file: %s (%s)", handler.baseFilename, repr(handler)) - else: - root_logger.debug("Log to handler: %s", repr(handler)) - logger.handlers = (handler,) - - -def log_memory_dump(memory, start, end, mem_info, level=99): - log.log(level, "Memory dump from $%04x to $%04x:", start, end) - - for addr in xrange(start, end + 1): - value = memory[addr] - if isinstance(value, int): - msg = "$%04x: $%02x (dez: %i)" % (addr, value, value) - else: - msg = "$%04x: %s (is type: %s)" % (addr, repr(value), type(value)) - msg = "%-25s| %s" % ( - msg, mem_info.get_shortest(addr) - ) - log.log(level, "\t%s", msg) - - -def pformat_hex_list(hex_list): - return " ".join(["$%x" % v for v in hex_list]) - -def pformat_byte_hex_list(hex_list): - return " ".join(["$%02x" % v for v in hex_list]) - -def pformat_word_hex_list(hex_list): - return " ".join(["$%02x" % v for v in hex_list]) - -def log_hexlist(byte_list, group=8, start=0x0000, level=99): - def _log(level, addr, line): - msg = pformat_byte_hex_list(line) - msg = "%04x - %s" % (addr, msg) - log.log(level, msg) - - pos = 0 - addr = start - line = [] - for value in byte_list: - pos += 1 - line.append(value) - if pos >= group: - _log(level, addr, line) - addr += pos - pos = 0 - line = [] - _log(level, addr, line) - - -def pformat_program_dump(ram_content): - msg = pformat_byte_hex_list(ram_content) - msg = msg.replace("$00 ", "\n$00\n") - return msg - - -def log_program_dump(ram_content, level=99): - msg = "BASIC program dump:\n" - msg += pformat_program_dump(ram_content) - log.log(level, msg) - - - -#------------------------------------------------------------------------------ - - -def test_run(): - import os - import subprocess - cmd_args = [ - sys.executable, - os.path.join("..", "DragonPy_CLI.py"), -# "-h" -# "--log_list", - "--verbosity", "50", - "--log", "DragonPy.cpu6809,50;dragonpy.Dragon32.MC6821_PIA,40", - -# "--verbosity", " 1", # hardcode DEBUG ;) -# "--verbosity", "10", # DEBUG -# "--verbosity", "20", # INFO -# "--verbosity", "30", # WARNING -# "--verbosity", "40", # ERROR -# "--verbosity", "50", # CRITICAL/FATAL -# "--verbosity", "99", # nearly all off - "--machine", "Dragon32", "run", -# "--machine", "Vectrex", "run", -# "--max_ops", "1", -# "--trace", - ] - print("Startup CLI with: %s" % " ".join(cmd_args[1:])) - subprocess.Popen(cmd_args, cwd="..").wait() - -if __name__ == "__main__": - dump = (0x1e, 0x07, 0x00, 0x0a, 0xa0, 0x00, 0x1e, 0x1a, 0x00, 0x14, 0x80, 0x20, 0x49, 0x20, 0xcb, 0x20, 0x30, 0x20, 0xbc, 0x20, 0x32, 0x35, 0x35, 0x3a, 0x00, 0x1e, 0x2d, 0x00, 0x1e, 0x93, 0x20, 0x31, 0x30, 0x32, 0x34, 0xc3, 0x28, 0x49, 0xc5, 0x32, 0x29, 0x2c, 0x49, 0x00, 0x1e, 0x35, 0x00, 0x28, 0x8b, 0x20, 0x49, 0x00, 0x1e, 0x4e, 0x00, 0x32, 0x49, 0x24, 0x20, 0xcb, 0x20, 0xff, 0x9a, 0x3a, 0x85, 0x20, 0x49, 0x24, 0xcb, 0x22, 0x22, 0x20, 0xbf, 0x20, 0x35, 0x30, 0x00, 0x00, 0x00) - log_hexlist(dump) -# log_hexlist(dump, group=4) -# log_hexlist(dump, group=5) - - test_run() diff --git a/dragonlib/utils/six.py b/dragonlib/utils/six.py deleted file mode 100644 index 21b0e803..00000000 --- a/dragonlib/utils/six.py +++ /dev/null @@ -1,762 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2014 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import - -import functools -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.8.0" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - # This is a bit ugly, but it avoids running this again. - delattr(obj.__class__, self.name) - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("intern", "__builtin__", "sys"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), - MovedModule("winreg", "_winreg"), -] -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "urllib", "urllib.parse"), - MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), - MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), - MovedAttribute("uses_params", "urlparse", "urllib.parse"), - MovedAttribute("uses_query", "urlparse", "urllib.parse"), - MovedAttribute("uses_relative", "urlparse", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) -else: - def iterkeys(d, **kw): - return iter(d.iterkeys(**kw)) - - def itervalues(d, **kw): - return iter(d.itervalues(**kw)) - - def iteritems(d, **kw): - return iter(d.iteritems(**kw)) - - def iterlists(d, **kw): - return iter(d.iterlists(**kw)) - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - def u(s): - return s - unichr = chr - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO -else: - def b(s): - return s - # Workaround for standalone backslash - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - def byte2int(bs): - return ord(bs[0]) - def indexbytes(buf, i): - return ord(buf[i]) - def iterbytes(buf): - return (ord(byte) for byte in buf) - import StringIO - StringIO = BytesIO = StringIO.StringIO -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - - def reraise(tp, value, tb=None): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - def wrapper(f): - f = functools.wraps(wrapped)(f) - f.__wrapped__ = wrapped - return f - return wrapper -else: - wraps = functools.wraps - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(meta): - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -if globals().get("__spec__") is not None: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer) diff --git a/dragonpy/components/cpu6809.py b/dragonpy/components/cpu6809.py index 42b8a065..2fb0bed0 100755 --- a/dragonpy/components/cpu6809.py +++ b/dragonpy/components/cpu6809.py @@ -49,7 +49,7 @@ ) from dragonpy.components.cpu_utils.instruction_caller import OpCollection from dragonpy.utils.bits import is_bit_set, get_bit -from dragonpy.utils.byte_word_values import signed8, signed16, signed5 +from dragonlib.utils.byte_word_values import signed8, signed16, signed5 from dragonpy.components.MC6809data.MC6809_op_data import ( REG_A, REG_B, REG_CC, REG_D, REG_DP, REG_PC, REG_S, REG_U, REG_X, REG_Y diff --git a/dragonpy/tests/test_6809_StoreLoad.py b/dragonpy/tests/test_6809_StoreLoad.py index 592fbed1..32fc9e01 100644 --- a/dragonpy/tests/test_6809_StoreLoad.py +++ b/dragonpy/tests/test_6809_StoreLoad.py @@ -14,12 +14,12 @@ from __future__ import absolute_import, division, print_function - import logging import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseStackTestCase +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonpy.tests.test_base import BaseStackTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_6809_address_modes.py b/dragonpy/tests/test_6809_address_modes.py index 2b038ac4..ca1ad8c9 100644 --- a/dragonpy/tests/test_6809_address_modes.py +++ b/dragonpy/tests/test_6809_address_modes.py @@ -14,13 +14,12 @@ from __future__ import absolute_import, division, print_function - import logging import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase -from dragonlib.utils.logging_utils import setup_logging +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonpy.tests.test_base import BaseCPUTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_6809_arithmetic.py b/dragonpy/tests/test_6809_arithmetic.py index 647aa467..425ea668 100644 --- a/dragonpy/tests/test_6809_arithmetic.py +++ b/dragonpy/tests/test_6809_arithmetic.py @@ -8,6 +8,7 @@ """ from __future__ import absolute_import, division, print_function +from dragonlib.utils.unittest_utils import TextTestRunner2 from dragonlib.utils import six xrange = six.moves.xrange @@ -15,10 +16,7 @@ import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase -from dragonlib.utils.logging_utils import setup_logging -from dragonpy.tests.test_config import TestCfg -from dragonpy.components.cpu6809 import CPU +from dragonpy.tests.test_base import BaseCPUTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_6809_arithmetic_shift.py b/dragonpy/tests/test_6809_arithmetic_shift.py index cd7ae85d..045974c5 100644 --- a/dragonpy/tests/test_6809_arithmetic_shift.py +++ b/dragonpy/tests/test_6809_arithmetic_shift.py @@ -13,6 +13,7 @@ """ from __future__ import absolute_import, division, print_function +from dragonlib.utils.unittest_utils import TextTestRunner2 from dragonlib.utils import six xrange = six.moves.xrange @@ -20,8 +21,7 @@ import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase -from dragonlib.utils.logging_utils import setup_logging +from dragonpy.tests.test_base import BaseCPUTestCase from dragonpy.utils.bits import is_bit_set, get_bit diff --git a/dragonpy/tests/test_6809_branch_instructions.py b/dragonpy/tests/test_6809_branch_instructions.py index d0791bf8..7a659765 100644 --- a/dragonpy/tests/test_6809_branch_instructions.py +++ b/dragonpy/tests/test_6809_branch_instructions.py @@ -8,16 +8,14 @@ from __future__ import absolute_import, division, print_function - - import itertools import logging import operator import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase -from dragonlib.utils.logging_utils import setup_logging +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonpy.tests.test_base import BaseCPUTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_6809_program.py b/dragonpy/tests/test_6809_program.py index c066e30e..00a69d47 100644 --- a/dragonpy/tests/test_6809_program.py +++ b/dragonpy/tests/test_6809_program.py @@ -20,8 +20,10 @@ import sys import unittest +from dragonlib.utils.unittest_utils import TextTestRunner2 from dragonlib.utils import six -from dragonpy.tests.test_base import TextTestRunner2, BaseStackTestCase +from dragonpy.tests.test_base import BaseStackTestCase + log = logging.getLogger(__name__) diff --git a/dragonpy/tests/test_6809_register_changes.py b/dragonpy/tests/test_6809_register_changes.py index 4e389604..4a9b723e 100644 --- a/dragonpy/tests/test_6809_register_changes.py +++ b/dragonpy/tests/test_6809_register_changes.py @@ -14,13 +14,12 @@ from __future__ import absolute_import, division, print_function - import logging import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase -from dragonlib.utils.logging_utils import setup_logging +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonpy.tests.test_base import BaseCPUTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_BASIC_Dragon32.py b/dragonpy/tests/test_BASIC_Dragon32.py index bff6450f..993a390c 100644 --- a/dragonpy/tests/test_BASIC_Dragon32.py +++ b/dragonpy/tests/test_BASIC_Dragon32.py @@ -18,8 +18,10 @@ import unittest import logging -from dragonlib.utils.logging_utils import log, setup_logging -from dragonpy.tests.test_base import TextTestRunner2, Test6809_Dragon32_Base +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonlib.utils.logging_utils import setup_logging +from dragonpy.tests.test_base import Test6809_Dragon32_Base + log = logging.getLogger(__name__) diff --git a/dragonpy/tests/test_BASIC_simple09.py b/dragonpy/tests/test_BASIC_simple09.py index 9da5d98f..bf3b849c 100644 --- a/dragonpy/tests/test_BASIC_simple09.py +++ b/dragonpy/tests/test_BASIC_simple09.py @@ -18,7 +18,8 @@ import sys import unittest -from dragonpy.tests.test_base import TextTestRunner2, Test6809_BASIC_simple6809_Base +from dragonlib.utils.unittest_utils import TextTestRunner2 +from dragonpy.tests.test_base import Test6809_BASIC_simple6809_Base from dragonpy.utils.BASIC09_floating_point import BASIC09FloatingPoint diff --git a/dragonpy/tests/test_all.py b/dragonpy/tests/test_all.py index 041dc2dd..d9155bc2 100644 --- a/dragonpy/tests/test_all.py +++ b/dragonpy/tests/test_all.py @@ -15,9 +15,6 @@ import unittest -from dragonlib.utils.logging_utils import setup_logging -from dragonpy.tests.test_base import TextTestRunner2 - if __name__ == '__main__': from dragonlib.utils.logging_utils import setup_logging diff --git a/dragonpy/tests/test_base.py b/dragonpy/tests/test_base.py index 51f2a385..de4679c5 100644 --- a/dragonpy/tests/test_base.py +++ b/dragonpy/tests/test_base.py @@ -28,6 +28,7 @@ import Queue as queue # Python 2 from dragonlib.tests.test_base import BaseTestCase + from dragonpy.Dragon32.config import Dragon32Cfg from dragonpy.Dragon32.periphery_dragon import Dragon32PeripheryUnittest from dragonpy.Simple6809.config import Simple6809Cfg @@ -102,22 +103,6 @@ def setUp(self): self.cpu.user_stack_pointer.set(self.INITIAL_USER_STACK_ADDR) -class TextTestResult2(unittest.TextTestResult): - def startTest(self, test): - if not self.showAll: - super(TextTestResult2, self).startTest(test) - return - print() - print("_"*70) - self.showAll = False - print(self.getDescription(test), "...") - super(TextTestResult2, self).startTest(test) - self.showAll = True - -class TextTestRunner2(unittest.TextTestRunner): - resultclass = TextTestResult2 - - class TestCPU(object): def __init__(self): self.accu_a = ValueStorage8Bit("A", 0) # A - 8 bit accumulator diff --git a/dragonpy/tests/test_condition_code_register.py b/dragonpy/tests/test_condition_code_register.py index 4e635f15..d899e9b7 100644 --- a/dragonpy/tests/test_condition_code_register.py +++ b/dragonpy/tests/test_condition_code_register.py @@ -12,12 +12,10 @@ from dragonlib.utils import six xrange = six.moves.xrange -import logging -import sys import unittest -from dragonpy.tests.test_base import BaseCPUTestCase, TextTestRunner2 -from dragonpy.utils.byte_word_values import signed8 +from dragonpy.tests.test_base import BaseCPUTestCase +from dragonlib.utils.byte_word_values import signed8 class CCTestCase(BaseCPUTestCase): diff --git a/dragonpy/tests/test_cpu6809.py b/dragonpy/tests/test_cpu6809.py index 72309e72..de003340 100644 --- a/dragonpy/tests/test_cpu6809.py +++ b/dragonpy/tests/test_cpu6809.py @@ -8,6 +8,7 @@ """ from __future__ import absolute_import, division, print_function +from dragonlib.utils.unittest_utils import TextTestRunner2 from dragonlib.utils import six xrange = six.moves.xrange @@ -18,8 +19,7 @@ from dragonpy.components.cpu6809 import CPU from dragonpy.Dragon32.config import Dragon32Cfg from dragonpy.Dragon32.mem_info import DragonMemInfo -from dragonpy.tests.test_base import TextTestRunner2, BaseCPUTestCase, BaseStackTestCase -from dragonlib.utils.logging_utils import setup_logging +from dragonpy.tests.test_base import BaseCPUTestCase, BaseStackTestCase log = logging.getLogger("DragonPy") diff --git a/dragonpy/tests/test_sbc09.py b/dragonpy/tests/test_sbc09.py index ed8a11c8..270b9312 100644 --- a/dragonpy/tests/test_sbc09.py +++ b/dragonpy/tests/test_sbc09.py @@ -18,16 +18,15 @@ """ from __future__ import absolute_import, division, print_function +from dragonlib.utils.unittest_utils import TextTestRunner2 from dragonlib.utils import six xrange = six.moves.xrange import logging -import pprint import sys import unittest -from dragonlib.utils.logging_utils import setup_logging -from dragonpy.tests.test_base import TextTestRunner2, Test6809_sbc09_Base +from dragonpy.tests.test_base import Test6809_sbc09_Base from dragonpy.utils import srecord_utils diff --git a/dragonpy/utils/BASIC09_floating_point.py b/dragonpy/utils/BASIC09_floating_point.py index a397defc..cc5a3e8b 100644 --- a/dragonpy/utils/BASIC09_floating_point.py +++ b/dragonpy/utils/BASIC09_floating_point.py @@ -15,7 +15,7 @@ import math import decimal -from dragonpy.utils.byte_word_values import unsigned8, signed16 +from dragonlib.utils.byte_word_values import unsigned8, signed16 class BASIC09FloatingPoint(object): diff --git a/dragonpy/utils/byte_word_values.py b/dragonpy/utils/byte_word_values.py deleted file mode 100644 index 6db0b764..00000000 --- a/dragonpy/utils/byte_word_values.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -""" - DragonPy - Dragon 32 emulator in Python - ======================================= - - some code is borrowed from: - XRoar emulator by Ciaran Anscomb (GPL license) more info, see README - - :copyleft: 2013-2014 by the DragonPy team, see AUTHORS for more details. - :license: GNU GPL v3 or above, see LICENSE for more details. -""" - -from __future__ import absolute_import, division, print_function - - -def signed5(x): - """ convert to signed 5-bit """ - if x > 0xf: # 0xf == 2**4-1 == 15 - x = x - 0x20 # 0x20 == 2**5 == 32 - return x - -def signed8(x): - """ convert to signed 8-bit """ - if x > 0x7f: # 0x7f == 2**7-1 == 127 - x = x - 0x100 # 0x100 == 2**8 == 256 - return x - -def unsigned8(x): - """ convert a signed 8-Bit value into a unsigned value """ - if x < 0: - x = x + 0x0100 # 0x100 == 2**8 == 256 - return x - -def signed16(x): - """ convert to signed 16-bit """ - if x > 0x7fff: # 0x7fff == 2**15-1 == 32767 - x = x - 0x10000 # 0x100 == 2**16 == 65536 - return x - - -def word2bytes(value): - """ - >>> word2bytes(0xff09) - (255, 9) - - >>> [hex(i) for i in word2bytes(0xffab)] - ['0xff', '0xab'] - - >>> word2bytes(0xffff +1) - Traceback (most recent call last): - ... - AssertionError - """ - assert 0 <= value <= 0xffff - return (value >> 8, value & 0xff) - - -def bytes2word(byte_list): - """ - >>> bytes2word([0xff,0xab]) - 65451 - - >>> hex(bytes2word([0xff,0xab])) - '0xffab' - """ - assert len(byte_list) == 2 - return (byte_list[0] << 8) + byte_list[1] - - -if __name__ == "__main__": - import doctest - print(doctest.testmod(verbose=0)) diff --git a/setup.py b/setup.py index b8506d47..52bb3cf4 100755 --- a/setup.py +++ b/setup.py @@ -73,5 +73,5 @@ packages=find_packages(), include_package_data=True, zip_safe=False, - test_suite="dragonpy.tests", + test_suite="dragonpy.tests", # or: .../dragonpy $ python3 -m unittest discover ) From 18469a95f09e6309278551cff6b65041d55cc51b Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Thu, 13 Nov 2014 15:28:49 +0100 Subject: [PATCH 3/7] 'dragonlib' as dependency --- README.creole | 2 ++ setup.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.creole b/README.creole index 924cf881..a1e32f2d 100644 --- a/README.creole +++ b/README.creole @@ -89,6 +89,8 @@ There is a simple shell script to automatic download and extract the Dragon ROMs === Quick start: +**TODO:** External {{{dragonlib}}} dependency is needed: https://github.com/6809/dragonlib + {{{ # clone the repro: ~$ git clone https://github.com/jedie/DragonPy.git diff --git a/setup.py b/setup.py index 52bb3cf4..31326560 100755 --- a/setup.py +++ b/setup.py @@ -38,6 +38,9 @@ version=dragonpy.__version__, py_modules=["DragonPy"], provides=["DragonPy"], + install_requires=[ + "dragonlib", + ], author="Jens Diemer", author_email="DragonPy@jensdiemer.de", description="Emulator for 6809 CPU based system like Dragon 32 / CoCo written in Python...", From 3feb231028f2cef9461f2f851a3327ae4e512b8c Mon Sep 17 00:00:00 2001 From: Jens Diemer Date: Sat, 6 Dec 2014 17:00:56 +0100 Subject: [PATCH 4/7] Update README.creole --- BASIC tools/HexViewer/README.creole | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BASIC tools/HexViewer/README.creole b/BASIC tools/HexViewer/README.creole index b3ac29fc..5946e9f4 100644 --- a/BASIC tools/HexViewer/README.creole +++ b/BASIC tools/HexViewer/README.creole @@ -1,7 +1,7 @@ Simple memory HEX viewer written in BASIC -{{http://www.jensdiemer.de/media/jensdiemer.de/screenshots/hex_view_v01.png|hex_view_v01.png}} +{{http://www.jensdiemer.de/static/jensdiemer.de/screenshots/hex_view_v01.png|hex_view_v01.png}} copyleft: 2013 by Jens Diemer -license: GNU GPL v3 or above, see LICENSE for more details. \ No newline at end of file +license: GNU GPL v3 or above, see LICENSE for more details. From 039b2e80d8adf9364b1b6ebddc6257e14900163b Mon Sep 17 00:00:00 2001 From: Jens Diemer Date: Sat, 6 Dec 2014 17:20:19 +0100 Subject: [PATCH 5/7] Update .travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c78707f8..13684118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "3.4" - "pypy" install: true # There is no dependencies, yet. + - pip install dragonlib # - pip install coveralls script: # "python setup.py test" will not run the tests from dragonlib @@ -14,4 +15,4 @@ script: branches: only: - master - - stable \ No newline at end of file + - stable From a0fa4adcd0d895cd04814fb35b759f1faa2600e3 Mon Sep 17 00:00:00 2001 From: Jens Diemer Date: Sat, 6 Dec 2014 17:22:32 +0100 Subject: [PATCH 6/7] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 13684118..9a8087b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ python: - "2.7" - "3.4" - "pypy" -install: true # There is no dependencies, yet. +install: - pip install dragonlib # - pip install coveralls script: From ec10a0621a2cfda77860b8a976587d9bcd5ad9a6 Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Mon, 15 Dec 2014 17:22:59 +0100 Subject: [PATCH 7/7] use pygments syntax highlighter in BASIC editor --- README.creole | 1 + basic_editor/editor.py | 2 +- basic_editor/highlighting.py | 187 ++++++++++++++++++++--------------- dragonpy/__init__.py | 2 +- setup.py | 1 + 5 files changed, 110 insertions(+), 83 deletions(-) diff --git a/README.creole b/README.creole index a1e32f2d..fb142989 100644 --- a/README.creole +++ b/README.creole @@ -395,6 +395,7 @@ Six is a Python 2 and 3 compatibility library. == History +* 15.12.2014 - v0.3.2 - Use [[http://pygments.org/|Pygments]] syntax highlighter in BASIC editor * 08.10.2014 - Release as v0.3.1 * 30.09.2014 - Enhance the BASIC editor * 29.09.2014 - Merge [[https://github.com/jedie/PyDragon32|PyDragon32]] project diff --git a/basic_editor/editor.py b/basic_editor/editor.py index b49d5d73..839beedf 100644 --- a/basic_editor/editor.py +++ b/basic_editor/editor.py @@ -261,7 +261,7 @@ def set_content(self, listing_ascii): for line in listing_ascii: line = "%s\n" % line # use os.sep ?!? - log.critical("\t%s", repr(line)) + log.debug("\t%s", repr(line)) self.text.insert(tkinter.END, line) # self.text.config(state=Tkinter.DISABLED) self.text.mark_set(tkinter.INSERT, '1.0') # Set cursor at start diff --git a/basic_editor/highlighting.py b/basic_editor/highlighting.py index 76943fa3..504128b5 100644 --- a/basic_editor/highlighting.py +++ b/basic_editor/highlighting.py @@ -12,9 +12,13 @@ """ from __future__ import absolute_import, division, print_function + +import pygments +from pygments.styles import get_style_by_name + from basic_editor.tkinter_utils import TkTextTag -from dragonlib.utils import six -xrange = six.moves.xrange +from dragonlib.dragon32.pygments_lexer import BasicLexer + try: # python 3 @@ -30,6 +34,7 @@ from dragonlib.core import basic_parser + class TkTextHighlighting(BaseExtension): """ code based on idlelib.ColorDelegator.ColorDelegator @@ -40,101 +45,117 @@ class TkTextHighlighting(BaseExtension): def __init__(self, editor): super(TkTextHighlighting, self).__init__(editor) + self.lexer = BasicLexer() + self.machine_api = editor.machine_api - bold_font = font.Font(self.text, self.text.cget("font")) - bold_font.configure(weight="bold") - self.text.tag_configure("bold", font=bold_font) + self.tags = self.create_tags() + self.existing_tags = tuple(self.tags.values()) - self.tagdefs = { - self.TAG_LINE_NUMBER: {"foreground": "#333333", "background":"#f4f4f4"}, - self.TAG_JUMP_ADDESS: {"foreground":"#0000aa", "background":"#f4f4f4", "font":bold_font}, + # TODO: Add a bind callback list + # see: http://www.python-forum.de/viewtopic.php?f=18&t=35275 (de) + # self.editor.root.bind("", self.update) + # self.editor.root.bind("", self.force_update) - basic_parser.CODE_TYPE_CODE: {"foreground":"#222222", "font":bold_font}, - basic_parser.CODE_TYPE_DATA: {"foreground":"#ddaaff", "font":bold_font}, - basic_parser.CODE_TYPE_STRING: {"foreground":"#0000ff"},# , "font":bold_font}, - basic_parser.CODE_TYPE_COMMENT: {"foreground":"#00aa00"}, - } - for tag, args in list(self.tagdefs.items()): - self.text.tag_configure(tag, **args) + self.old_pos=None + self.__update_interval() -# self.notify_range("1.0", "end") + def __update_interval(self): + """ highlight the current line """ + self.update() + self.after_id = self.text.after(250, self.__update_interval) - self.old_pos = None - self.__update_interval() - def update(self, force=False): - pos = self.text.index(tkinter.INSERT) + def force_update(self, event): + print("force update") + self.update(event, force=True) - if not force: - if pos == self.old_pos: -# log.critical("No recolorize needed.") - return + def update(self, event=None, force=False): + pos = self.text.index(tkinter.INSERT) + # print("update %s" % pos) + if not force and pos == self.old_pos: + # print("Skip") + return self.recolorize() self.old_pos = pos - def __update_interval(self): - """ highlight the current line_no """ - self.update() - self.after_id = self.text.after(10, self.__update_interval) + # --------------------------------------------------------------------------------------- + + def create_tags(self): + tags={} + + bold_font = font.Font(self.text, self.text.cget("font")) + bold_font.configure(weight=font.BOLD) + + italic_font = font.Font(self.text, self.text.cget("font")) + italic_font.configure(slant=font.ITALIC) + + bold_italic_font = font.Font(self.text, self.text.cget("font")) + bold_italic_font.configure(weight=font.BOLD, slant=font.ITALIC) + + style = get_style_by_name("default") + for ttype, ndef in style: + # print(ttype, ndef) + tag_font = None + if ndef["bold"] and ndef["italic"]: + tag_font = bold_italic_font + elif ndef["bold"]: + tag_font = bold_font + elif ndef["italic"]: + tag_font = italic_font + + if ndef["color"]: + foreground = "#%s" % ndef["color"] + else: + foreground = None -# def notify_range(self, index1, index2=None): -# self.text.tag_add("TODO", index1, index2) + tags[ttype]=str(ttype) + self.text.tag_configure(tags[ttype], foreground=foreground, font=tag_font) + # self.text.tag_configure(str(ttype), foreground=foreground, font=tag_font) - def colorize(self, part_type, start, end): -# print "colorize", part_type, start, end - self.text.tag_add(part_type, start, end) + return tags def recolorize(self): - self.removecolors() + # print("recolorize") + listing = self.text.get("1.0", "end-1c") - listing = self.editor.get_content() destinations = self.machine_api.renum_tool.get_destinations(listing) - line_max = self.text.index(tkinter.END).split('.')[0] - line_max = int(line_max) - for line_no in xrange(line_max): - line_content = self.text.get("%s.0" % line_no, "%s.0+1lines" % line_no) -# print "line:", repr(line_content) - if not line_content.strip(): - continue - - parsed_lines = self.machine_api.parse_ascii_listing(line_content) - try: - code_line_no, code_objects = list(parsed_lines.items())[0] - except IndexError: - continue -# print "parsed line:", code_line_no, code_objects - - index = len(str(code_line_no) + " ") - - if code_line_no in destinations: - # The current line number is used as a jump address - part_type = self.TAG_JUMP_ADDESS + tokensource = self.lexer.get_tokens(listing) + + start_line=1 + start_index = 0 + end_line=1 + end_index = 0 + for ttype, value in tokensource: + if "\n" in value: + end_line += value.count("\n") + end_index = len(value.rsplit("\n",1)[1]) else: - part_type = self.TAG_LINE_NUMBER - self.colorize(part_type, - start="%s.0" % line_no, - end="%s.%s" % (line_no, index) - ) + end_index += len(value) + + if value not in (" ", "\n"): + index1 = "%s.%s" % (start_line, start_index) + index2 = "%s.%s" % (end_line, end_index) + + for tagname in self.text.tag_names(index1): # FIXME + # print("remove %s" % tagname) + if tagname not in self.existing_tags: # Don"t remove e.g.: "current line"-tag + # print("Skip...") + continue + self.text.tag_remove(tagname, index1, index2) - for code_object in code_objects: - end = index + len(code_object.content) - self.colorize(code_object.PART_TYPE, - start="%s.%s" % (line_no, index), - end="%s.%s" % (line_no, end), - ) - index = end + # Mark used line numbers extra: + if start_index==0 and ttype==pygments.token.Name.Label: + if int(value) in destinations: + ttype = pygments.token.Name.Tag -# print + self.text.tag_add(self.tags[ttype], index1, index2) -# line, column = self.text.index(Tkinter.INSERT).split('.') -# print "recolorize lines %s" % line + start_line = end_line + start_index = end_index - def removecolors(self): - for tag in self.tagdefs: - self.text.tag_remove(tag, "1.0", "end") @@ -147,23 +168,25 @@ def __init__(self, editor): self.tag_current_line = TkTextTag(self.text, background="#e8f2fe" - # relief='raised', borderwidth=1, + # relief="raised", borderwidth=1, ) self.current_line = None self.__update_interval() - def update(self, force=False): + # self.editor.root.bind("", self.update) + + def update(self, event=None, force=False): """ highlight the current line """ - line_no = self.text.index(tkinter.INSERT).split('.')[0] + line_no = self.text.index(tkinter.INSERT).split(".")[0] - if not force: - if line_no == self.current_line: + # if not force: + # if line_no == self.current_line: # log.critical("no highlight line needed.") - return +# return # log.critical("highlight line: %s" % line_no) - self.current_line = line_no +# self.current_line = line_no self.text.tag_remove(self.tag_current_line.id, "1.0", "end") self.text.tag_add(self.tag_current_line.id, "%s.0" % line_no, "%s.0+1lines" % line_no) @@ -171,4 +194,6 @@ def update(self, force=False): def __update_interval(self): """ highlight the current line """ self.update() - self.after_id = self.text.after(10, self.__update_interval) \ No newline at end of file + self.after_id = self.text.after(250, self.__update_interval) + + diff --git a/dragonpy/__init__.py b/dragonpy/__init__.py index 260c070a..f9aa3e11 100644 --- a/dragonpy/__init__.py +++ b/dragonpy/__init__.py @@ -1 +1 @@ -__version__ = "0.3.1" +__version__ = "0.3.2" diff --git a/setup.py b/setup.py index 31326560..de0fea51 100755 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ provides=["DragonPy"], install_requires=[ "dragonlib", + "pygments", ], author="Jens Diemer", author_email="DragonPy@jensdiemer.de",