1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00

Removed support for Python 3.7 (which is End Of Life since 2023-06-27) (#430)

* Removed support for Python 3.7 (which is End Of Life since 2023-06-27)
Removed stray ast.Str and the like , which throw deprecation warnings in Python 3.12

* corrected import pathj for raises_kind

* corrected `ord` value assignemnt in _toVerilog.py
removed forgotten ast.dump call from _analyze.py
This commit is contained in:
Josy Boelen 2024-06-03 11:57:39 +02:00 committed by GitHub
parent e95762e4ef
commit e356d8a589
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 122 additions and 284 deletions

View File

@ -34,7 +34,7 @@ jobs:
strategy:
fail-fast: false # So that one fail doesn't stop remaining tests
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.9", "3.11"]
python-version: ["3.8", "3.9", "pypy-3.9", "3.10", "pypy-3.10","3.11", "3.12"]
target: [core, iverilog, ghdl]
runs-on: ubuntu-latest
needs: [run_lint, build_ghdl_linux, build_iverilog_linux]
@ -85,7 +85,7 @@ jobs:
strategy:
fail-fast: false # So that one fail doesn't stop remaining tests
matrix:
python-version: ["3.11"]
python-version: ["3.12"]
#target: [core, iverilog, ghdl]
target: [core, ghdl]
runs-on: windows-latest

View File

@ -49,7 +49,7 @@ traceSignals -- function that enables signal tracing in a VCD file
toVerilog -- function that converts a design to Verilog
"""
__version__ = "0.11.45"
__version__ = "0.11.46"
class StopSimulation(Exception):

View File

@ -30,7 +30,6 @@ import ast
import builtins
from itertools import chain
import myhdl
import myhdl
from myhdl import *
from myhdl import ConversionError
@ -268,12 +267,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Call(self, node):
# ast.Call signature changed in python 3.5
# http://greentreesnakes.readthedocs.org/en/latest/nodes.html#Call
if sys.version_info >= (3, 5):
starargs = any(isinstance(arg, ast.Starred) for arg in node.args)
kwargs = any(kw.arg is None for kw in node.keywords)
else:
starargs = node.starargs is not None
kwargs = node.kwargs is not None
starargs = any(isinstance(arg, ast.Starred) for arg in node.args)
kwargs = any(kw.arg is None for kw in node.keywords)
if starargs:
self.raiseError(node, _error.NotSupported, "extra positional arguments")
@ -297,8 +292,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
# put official docstrings aside for separate processing
node.doc = None
if node.body and isinstance(node.body[0], ast.Expr) and \
isinstance(node.body[0].value, ast.Str):
node.doc = node.body[0].value.s
isinstance(node.body[0].value, ast.Constant) and isinstance(node.body[0].value.value, str):
node.doc = node.body[0].value.value
node.body = node.body[1:]
self.visitList(node.body)
@ -594,7 +589,11 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
# # node.obj = _EdgeDetector()
elif f is ord:
node.obj = int(-1)
if not (isinstance(node.args[0], ast.Str) and (len(node.args[0].s) == 1)):
if isinstance(node.args[0], ast.Constant) and \
isinstance(node.args[0].value, str) and \
(len(node.args[0].value) == 1):
pass
else:
self.raiseError(node, _error.NotSupported,
"ord: expect string argument with length 1")
elif f is delay:
@ -682,41 +681,20 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
elif v == 1:
node.edge = sig.posedge
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node):
node.obj = None # safeguarding?
# ToDo check for tuples?
if isinstance(node.value, int):
# Num
if node.value in (0, 1):
node.obj = bool(node.value)
else:
node.obj = node.value
elif node.value in (True, False, None):
# NameConstant
node.obj = node.value
elif isinstance(node.value, str):
# Str
node.obj = node.value
else:
def visit_Num(self, node):
n = node.n
# assign to value attribute for backwards compatibility
node.value = n
if n in (0, 1):
node.obj = bool(n)
elif isinstance(n, int):
node.obj = n
def visit_Constant(self, node):
node.obj = None # safeguarding?
# ToDo check for tuples?
if isinstance(node.value, int):
# Num
if node.value in (0, 1):
node.obj = bool(node.value)
else:
node.obj = None
def visit_Str(self, node):
node.obj = node.s
def visit_NameConstant(self, node):
node.obj = node.value
elif node.value in (True, False, None):
# NameConstant
node.obj = node.value
elif isinstance(node.value, str):
# Str
node.obj = node.value
def visit_Continue(self, node):
@ -918,12 +896,12 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
for n in node.args:
if isinstance(n, ast.BinOp) and isinstance(n.op, ast.Mod) and \
isinstance(n.left, ast.Str):
isinstance(n.left, ast.Constant) and isinstance(n.left.value, str):
if isinstance(n.right, ast.Tuple):
a.extend(n.right.elts)
else:
a.append(n.right)
s = n.left.s
s = n.left.value
while s:
if not s:
break
@ -950,8 +928,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
s = s[m.end():]
continue
self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
elif isinstance(n, ast.Str):
f.append(n.s)
elif isinstance(n, ast.Constant) and isinstance(n.value, str):
f.append(n.value)
else:
f.append(defaultConvSpec)
a.append(n)

View File

@ -937,64 +937,35 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# in python3 a negative Num is represented as an USub of a positive Num
# Fix: restore python2 behavior by a shortcut: invert value of Constant, inherit
# vhdl type from UnaryOp node, and visit the modified operand
if sys.version_info >= (3, 8, 0):
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Constant):
node.operand.n = -node.operand.n
node.operand.vhd = node.vhd
self.visit(node.operand)
return
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Constant) and isinstance(node.operand.value, int):
# assume number
node.operand.value = -node.operand.value
node.operand.vhd = node.vhd
self.visit(node.operand)
return
pre, suf = self.inferCast(node.vhd, node.vhdOri)
if isinstance(node.op, ast.UAdd):
op = ""
else:
op = opmap[type(node.op)]
if isinstance(node.operand, ast.Constant):
self.write("(")
self.write(op)
self.write("(")
self.write(pre)
self.visit(node.operand)
self.write(suf)
self.write(")")
self.write(")")
else:
self.write(pre)
self.write("(")
self.write(op)
self.visit(node.operand)
self.write(")")
self.write(suf)
pre, suf = self.inferCast(node.vhd, node.vhdOri)
if isinstance(node.op, ast.UAdd):
op = ""
else:
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num):
node.operand.n = -node.operand.n
node.operand.vhd = node.vhd
self.visit(node.operand)
return
op = opmap[type(node.op)]
pre, suf = self.inferCast(node.vhd, node.vhdOri)
if isinstance(node.op, ast.UAdd):
op = ""
else:
op = opmap[type(node.op)]
if isinstance(node.operand, ast.Num):
self.write("(")
self.write(op)
self.write("(")
self.write(pre)
self.visit(node.operand)
self.write(suf)
self.write(")")
self.write(")")
else:
self.write(pre)
self.write("(")
self.write(op)
self.visit(node.operand)
self.write(")")
self.write(suf)
if isinstance(node.operand, ast.Constant):
self.write("(")
self.write(op)
self.write("(")
self.write(pre)
self.visit(node.operand)
self.write(suf)
self.write(")")
self.write(")")
else:
self.write(pre)
self.write("(")
self.write(op)
self.visit(node.operand)
self.write(")")
self.write(suf)
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
@ -1185,20 +1156,16 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return
elif f is ord:
opening, closing = '', ''
v = ord(node.args[0].s)
node.args[0].s = v
v = ord(node.args[0].value)
node.args[0].value = v
self.write(v)
return
elif f is int:
opening, closing = '', ''
pre, suf = self.inferCast(node.vhd, node.vhdOri)
# convert number argument to integer
if sys.version_info >= (3, 8, 0):
if isinstance(node.args[0], ast.Constant):
node.args[0].n = int(node.args[0].n)
else:
if isinstance(node.args[0], ast.Num):
node.args[0].n = int(node.args[0].n)
if isinstance(node.args[0], ast.Constant):
node.args[0].n = int(node.args[0].value)
elif inspect.isclass(f) and issubclass(f, intbv):
pre, post = "", ""
arg = node.args[0]
@ -1277,53 +1244,18 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(right)
self.write(suf)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node):
if node.value is None:
# NameConstant
node.id = str(node.value)
self.getName(node)
elif isinstance(node.value, bool):
# NameConstant
node.id = str(node.value)
self.getName(node)
elif isinstance(node.value, int):
# Num
n = node.value
if isinstance(node.vhd, vhd_std_logic):
self.write("'%s'" % n)
elif isinstance(node.vhd, vhd_boolean):
self.write("%s" % bool(n))
# elif isinstance(node.vhd, (vhd_unsigned, vhd_signed)):
# self.write('"%s"' % tobin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_unsigned):
if abs(n) < 2 ** 31:
self.write("to_unsigned(%s, %s)" % (n, node.vhd.size))
else:
self.write('unsigned\'("%s")' % tobin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_signed):
if abs(n) < 2 ** 31:
self.write("to_signed(%s, %s)" % (n, node.vhd.size))
else:
self.write('signed\'("%s")' % tobin(n, node.vhd.size))
else:
if n < 0:
self.write("(")
self.write(n)
if n < 0:
self.write(")")
elif isinstance(node.value, str):
# Str
typemark = 'string'
if isinstance(node.vhd, vhd_unsigned):
typemark = 'unsigned'
self.write("%s'(\"%s\")" % (typemark, node.value))
else:
def visit_Num(self, node):
n = node.n
def visit_Constant(self, node):
if node.value is None:
# NameConstant
node.id = str(node.value)
self.getName(node)
elif isinstance(node.value, bool):
# NameConstant
node.id = str(node.value)
self.getName(node)
elif isinstance(node.value, int):
# Num
n = node.value
if isinstance(node.vhd, vhd_std_logic):
self.write("'%s'" % n)
elif isinstance(node.vhd, vhd_boolean):
@ -1346,16 +1278,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(n)
if n < 0:
self.write(")")
def visit_Str(self, node):
elif isinstance(node.value, str):
# Str
typemark = 'string'
if isinstance(node.vhd, vhd_unsigned):
typemark = 'unsigned'
self.write("%s'(\"%s\")" % (typemark, node.s))
def visit_NameConstant(self, node):
node.id = str(node.value)
self.getName(node)
self.write("%s'(\"%s\")" % (typemark, node.value))
def visit_Continue(self, node, *args):
self.write("next;")
@ -1363,17 +1291,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Expr(self, node):
expr = node.value
# docstrings on unofficial places
if isinstance(expr, ast.Str):
doc = _makeDoc(expr.s, self.ind)
if isinstance(expr, ast.Constant) and isinstance(expr.value, str):
doc = _makeDoc(expr.value, self.ind)
self.write(doc)
return
# skip extra semicolons
if sys.version_info >= (3, 8, 0):
if isinstance(expr, ast.Constant):
return
else:
if isinstance(expr, ast.Num):
return
if isinstance(expr, ast.Constant):
return
self.visit(expr)
# ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
@ -2419,7 +2343,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
if f is concat:
s = 0
for a in node.args:
if isinstance(a, ast.Str):
if isinstance(a, ast.Constant) and isinstance(a.value, str):
a.vhd = vhd_unsigned(a.vhd.size)
elif isinstance(a.vhd, vhd_signed):
a.vhd = vhd_unsigned(a.vhd.size)
@ -2458,42 +2382,23 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
right.vhd = vhd_signed(right.vhd.size + 1)
node.vhdOri = copy(node.vhd)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node):
if node.value is None:
# NameConstant
node.vhd = inferVhdlObj(node.value)
elif isinstance(node.value, bool):
# NameConstant
node.vhd = inferVhdlObj(node.value)
elif isinstance(node.value, int):
# Num
if node.value < 0:
node.vhd = vhd_int()
else:
node.vhd = vhd_nat()
elif isinstance(node.value, str):
# Str
node.vhd = vhd_string()
node.vhdOri = copy(node.vhd)
else:
def visit_Str(self, node):
node.vhd = vhd_string()
node.vhdOri = copy(node.vhd)
def visit_Num(self, node):
if node.n < 0:
def visit_Constant(self, node):
if node.value is None:
# NameConstant
node.vhd = inferVhdlObj(node.value)
elif isinstance(node.value, bool):
# NameConstant
node.vhd = inferVhdlObj(node.value)
elif isinstance(node.value, int):
# Num
if node.value < 0:
node.vhd = vhd_int()
else:
node.vhd = vhd_nat()
node.vhdOri = copy(node.vhd)
def visit_NameConstant(self, node):
node.vhd = inferVhdlObj(node.value)
node.vhdOri = copy(node.vhd)
elif isinstance(node.value, str):
# Str
node.vhd = vhd_string()
node.vhdOri = copy(node.vhd)
def visit_For(self, node):
var = node.target.id
@ -2513,7 +2418,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.inferShiftType(node)
elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)):
self.inferBitOpType(node)
elif isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Str): # format string
elif isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Constant) and isinstance(node.left.value, str): # format string
pass
else:
self.inferBinOpType(node)

View File

@ -858,16 +858,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return
elif f is ord:
opening, closing = '', ''
node.args[0].s = str(ord(node.args[0].s))
node.args[0].value = str(ord(node.args[0].value))
elif f is int:
opening, closing = '', ''
# convert number argument to integer
if sys.version_info >= (3, 8, 0):
if isinstance(node.args[0], ast.Constant):
node.args[0].n = int(node.args[0].n)
else:
if isinstance(node.args[0], ast.Num):
node.args[0].n = int(node.args[0].n)
if isinstance(node.args[0], ast.Constant):
node.args[0].value = int(node.args[0].value)
elif f in (intbv, modbv):
self.visit(node.args[0])
return
@ -919,40 +915,21 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")")
self.context = None
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node):
if node.value is None:
# NameConstant
self.write(nameconstant_map[node.obj])
elif isinstance(node.value, bool):
self.write(nameconstant_map[node.obj])
elif isinstance(node.value, int):
# Num
if self.context == _context.PRINT:
self.write('"%s"' % node.value)
else:
self.write(self.IntRepr(node.value))
elif isinstance(node.value, str):
# Str
s = node.value
if self.context == _context.PRINT:
self.write('"%s"' % s)
elif len(s) == s.count('0') + s.count('1'):
self.write("%s'b%s" % (len(s), s))
else:
self.write(s)
else:
def visit_Num(self, node):
def visit_Constant(self, node):
if node.value is None:
# NameConstant
self.write(nameconstant_map[node.obj])
elif isinstance(node.value, bool):
self.write(nameconstant_map[node.obj])
elif isinstance(node.value, int):
# Num
if self.context == _context.PRINT:
self.write('"%s"' % node.n)
self.write('"%s"' % node.value)
else:
self.write(self.IntRepr(node.n))
def visit_Str(self, node):
s = node.s
self.write(self.IntRepr(node.value))
elif isinstance(node.value, str):
# Str
s = node.value
if self.context == _context.PRINT:
self.write('"%s"' % s)
elif len(s) == s.count('0') + s.count('1'):
@ -960,26 +937,19 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else:
self.write(s)
def visit_NameConstant(self, node):
self.write(nameconstant_map[node.obj])
def visit_Continue(self, node):
self.write("disable %s;" % self.labelStack[-1])
def visit_Expr(self, node):
expr = node.value
# docstrings on unofficial places
if isinstance(expr, ast.Str):
doc = _makeDoc(expr.s, self.ind)
if isinstance(expr, ast.Constant) and isinstance(expr.value, str):
doc = _makeDoc(expr.value, self.ind)
self.write(doc)
return
# skip extra semicolons
if sys.version_info >= (3, 8, 0):
if isinstance(expr, ast.Constant):
return
else:
if isinstance(expr, ast.Num):
return
if isinstance(expr, ast.Constant):
return
self.visit(expr)
# ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
@ -1708,12 +1678,8 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.signed = node.operand.signed
if isinstance(node.op, ast.USub):
node.obj = int(-1)
if sys.version_info >= (3, 8, 0):
if isinstance(node.operand, ast.Constant):
node.signed = True
else:
if isinstance(node.operand, ast.Num):
node.signed = True
if isinstance(node.operand, ast.Constant):
node.signed = True
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
@ -1753,21 +1719,8 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
return
self.generic_visit(node)
if sys.version_info >= (3, 9, 0):
def visit_Constant(self, node):
node.signed = False
else:
def visit_Num(self, node):
node.signed = False
def visit_Str(self, node):
node.signed = False
def visit_NameConstant(self, node):
node.signed = False
def visit_Constant(self, node):
node.signed = False
def visit_Name(self, node):
if isinstance(node.ctx, ast.Store):

View File

@ -13,6 +13,7 @@ def bench_SliceSignal():
@instance
def check():
''' Running bench_SliceSignal '''
for i in range(N):
s.next = i
yield delay(10)

View File

@ -51,7 +51,7 @@ setup(
license="LGPL",
platforms='any',
keywords="HDL ASIC FPGA hardware design",
python_requires='>=3.7',
python_requires='>=3.8',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
@ -60,10 +60,11 @@ setup(
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3 :: Only',
]
)