Compare commits

...

6 Commits

Author SHA1 Message Date
patricksurry fd342c1b6b
Merge f3d2eb2f22 into 74e2576894 2024-04-12 17:22:40 -07:00
Mike Naberezny 74e2576894 Back to .dev0 until next release 2024-04-12 14:03:26 -07:00
Mike Naberezny 9455a5c70e Prepare 1.2.0 release 2024-04-12 13:00:50 -07:00
Mike Naberezny 1870d65982 Fix interactive assembly on Python 3
Closes #81
Closes #78
Closes #65
Closes #64
Closes #63
2024-04-12 12:25:12 -07:00
Mike Naberezny 8dce37f6b8 Fix regular expression warnings on Python 3.12 2024-04-12 12:21:46 -07:00
Patrick Surry f3d2eb2f22 fixes https://github.com/mnaberez/py65/issues/45 2023-07-26 10:12:58 -04:00
10 changed files with 152 additions and 22 deletions

View File

@ -21,11 +21,14 @@ jobs:
run: python -V
- name: Install dependencies
run: $PIP install setuptools
run: $PIP install setuptools pexpect
- name: Run the tests
run: python setup.py test -q
- name: Run the end-to-end tests
run: END_TO_END=1 python setup.py test -q
build_py34:
runs-on: ubuntu-20.04
container: python:3.4
@ -44,11 +47,14 @@ jobs:
run: python -V
- name: Install dependencies
run: $PIP install setuptools
run: $PIP install setuptools pexpect
- name: Run the tests
run: python setup.py test -q
- name: Run the end-to-end tests
run: END_TO_END=1 python setup.py test -q
build_py35:
runs-on: ubuntu-20.04
container: python:3.5
@ -62,11 +68,14 @@ jobs:
run: python -V
- name: Install dependencies
run: $PIP install setuptools
run: $PIP install setuptools pexpect
- name: Run the tests
run: python setup.py test -q
- name: Run the end-to-end tests
run: END_TO_END=1 python setup.py test -q
build_py3x:
strategy:
fail-fast: false
@ -88,7 +97,10 @@ jobs:
run: python -V
- name: Install dependencies
run: $PIP install setuptools
run: $PIP install setuptools pexpect
- name: Run the tests
run: python setup.py test -q
- name: Run the end-to-end tests
run: END_TO_END=1 python setup.py test -q

View File

@ -1,10 +1,17 @@
1.2.0.dev0 (Next Release)
1.3.0.dev0 (Next Release)
-------------------------
1.2.0 (2024-04-12)
------------------
- Fixed a bug with character input that would cause characters to be
dropped when pasting in larger amounts of text. This makes it possible
to paste programs into EhBASIC and Taliforth. Patch by SamCoVT.
- Fixed interactive assembly on Python 3.
- Fixed regular expression warnings on Python 3.12.
- The ``fill`` command in the monitor now shows an error message if an
address or value is out of range.

View File

@ -49,7 +49,7 @@ copyright = u'2008-%d, Mike Naberezny and contributors' % year
# built documents.
#
# The short X.Y version.
version = '1.1.0.dev0'
version = '1.3.0.dev0'
# The full version, including alpha/beta/rc tags.
release = version

View File

@ -92,7 +92,7 @@ class Assembler:
and parsing the address part using AddressParser. The result of
the normalization is a tuple of two strings (opcode, operand).
"""
statement = ' '.join(str.split(statement))
statement = ' '.join(statement.split())
# normalize target in operand
match = self.Statement.match(statement)

21
py65/compat.py Normal file
View File

@ -0,0 +1,21 @@
import sys
PY2 = sys.version_info[0] == 2
if PY2:
unicode = unicode
def as_string(s, encoding='utf-8'):
if isinstance(s, unicode):
return s
else:
return s.decode(encoding)
else:
unicode = str
def as_string(s, encoding='utf-8'):
if isinstance(s, str):
return s
else:
return s.decode(encoding)

View File

@ -156,7 +156,8 @@ class Monitor(cmd.Cmd):
self._output(usage)
def onecmd(self, line):
line = self._preprocess_line(line)
if line:
line = self._preprocess_line(line)
result = None
try:
@ -167,7 +168,7 @@ class Monitor(cmd.Cmd):
error = ''.join(traceback.format_exception(*sys.exc_info()))
self._output(error)
if not line.startswith("quit"):
if line and not line.startswith("quit"):
self._output_mpu_status()
# Switch back to the previous input mode.
@ -239,7 +240,7 @@ class Monitor(cmd.Cmd):
line = command
break
pattern = '^%s\s+' % re.escape(shortcut)
pattern = r'^%s\s+' % re.escape(shortcut)
matches = re.match(pattern, line)
if matches:
start, end = matches.span()
@ -580,7 +581,7 @@ class Monitor(cmd.Cmd):
if args == '':
return
pairs = re.findall('([^=,\s]*)=([^=,\s]*)', args)
pairs = re.findall(r'([^=,\s]*)=([^=,\s]*)', args)
if pairs == []:
return self._output("Syntax error: %s" % args)

88
py65/tests/end_to_end.py Normal file
View File

@ -0,0 +1,88 @@
import os
import signal
import sys
import tempfile
import unittest
from py65.compat import unicode
# end-to-test tests are slow so only run them when asked
if 'END_TO_END' in os.environ:
if sys.platform == "win32":
raise NotImplementedError()
else:
import pexpect
BaseTestCase = unittest.TestCase
else:
BaseTestCase = object
class EndToEndTests(BaseTestCase):
def _spawn(self):
mon = pexpect.spawn(
sys.executable,
['-u', '-m', 'py65.monitor'],
encoding='utf-8'
)
mon.expect_exact(unicode("Py65 Monitor"))
self.addCleanup(mon.kill, signal.SIGINT)
return mon
def test_putc(self):
mon = self._spawn()
mon.sendline(unicode("add_label f001 putc"))
mon.sendline(unicode("a c000 lda #'H"))
mon.sendline(unicode("a c002 sta putc"))
mon.sendline(unicode("a c005 lda #'I"))
mon.sendline(unicode("a c007 sta putc"))
mon.sendline(unicode("a c00a brk"))
mon.sendline(unicode("g c000"))
mon.expect_exact(unicode("HI"))
mon.sendline(unicode("q"))
def test_getc(self):
mon = self._spawn()
mon.sendline(unicode("add_label f004 getc"))
mon.sendline(unicode("a c000 ldx #0"))
mon.sendline(unicode("a c002 lda getc"))
mon.sendline(unicode("a c005 beq c002"))
mon.sendline(unicode("a c007 cmp #'!"))
mon.sendline(unicode("a c009 bne c00c"))
mon.sendline(unicode("a c00b brk"))
mon.sendline(unicode("a c00c sta 1000,x"))
mon.sendline(unicode("a c00f inx"))
mon.sendline(unicode("a c010 jmp c002"))
mon.sendline(unicode("g c000"))
mon.send(unicode("HELLO!"))
mon.expect_exact(unicode("6502:"))
mon.sendline(unicode("m 1000:1004"))
mon.expect_exact(unicode("48 45 4c 4c 4f"))
def test_assemble_interactive(self):
mon = self._spawn()
mon.sendline(unicode("assemble 0"))
mon.expect_exact(unicode("$0000"))
mon.sendline(unicode("lda $1234"))
mon.expect_exact(unicode("ad 34 12"))
mon.expect_exact(unicode("$0003"))
mon.sendline(unicode("sta $4567"))
mon.expect_exact(unicode("8d 67 45"))
mon.sendline(unicode("invalid"))
mon.expect_exact(unicode("?Syntax"))
mon.sendline()
mon.sendline(unicode("quit"))
if __name__ == '__main__':
unittest.main()

View File

@ -61,7 +61,7 @@ class AddressParser(object):
return self.labels[num]
else:
matches = re.match('^([^\s+-]+)\s*([+\-])\s*([$+%]?\d+)$', num)
matches = re.match(r'^([^\s+-]+)\s*([+\-])\s*([$+%]?\d+)$', num)
if matches:
label, sign, offset = matches.groups()
@ -88,7 +88,7 @@ class AddressParser(object):
"""Parse a string containing an address or a range of addresses
into a tuple of (start address, end address)
"""
matches = re.match('^([^:,]+)\s*[:,]+\s*([^:,]+)$', addresses)
matches = re.match(r'^([^:,]+)\s*[:,]+\s*([^:,]+)$', addresses)
if matches:
start, end = map(self.number, matches.groups(0))
else:

View File

@ -1,5 +1,7 @@
import sys
from py65.compat import as_string
if sys.platform[:3] == "win":
import msvcrt
@ -24,10 +26,7 @@ if sys.platform[:3] == "win":
is available. Does not echo the character. The stdin argument is
for function signature compatibility and is ignored.
"""
c = msvcrt.getch()
if isinstance(c, bytes): # Python 3
c = c.decode('latin-1')
return c
return as_string(msvcrt.getch())
def getch_noblock(stdin):
""" Read one character from the Windows console without blocking.
@ -36,8 +35,8 @@ if sys.platform[:3] == "win":
available, an empty string is returned.
"""
if msvcrt.kbhit():
return getch(stdin)
return ''
return as_string(getch(stdin))
return u''
else:
import termios
@ -157,7 +156,7 @@ else:
# use select to make sure there is at least one char to read.
rd,wr,er = select([stdin], [], [], 0.01)
if rd != []:
char = stdin.read(1)
char = as_string(stdin.read(1))
except KeyboardInterrupt:
# Pass along a CTRL-C interrupt.
raise
@ -180,7 +179,7 @@ else:
# use select to make sure there is at least one char to read.
rd,wr,er = select([stdin], [], [], 0.01)
if rd != []:
char = stdin.read(1)
char = as_string(stdin.read(1))
except KeyboardInterrupt:
# Pass along a CTRL-C interrupt.
raise
@ -200,6 +199,7 @@ def line_input(prompt='', stdin=sys.stdin, stdout=sys.stdout):
is useful in modes like the interactive assembler.
"""
stdout.write(prompt)
stdout.flush()
line = ''
while True:
char = getch(stdin)
@ -211,6 +211,7 @@ def line_input(prompt='', stdin=sys.stdin, stdout=sys.stdout):
line = line[:-1]
stdout.write("\r%s\r%s%s" %
(' ' * (len(prompt + line) + 5), prompt, line))
stdout.flush()
elif code == 0x1b: # escape
pass
else:

View File

@ -1,4 +1,4 @@
__version__ = '2.0.0.dev0'
__version__ = '1.3.0.dev0'
import sys