From 16d0f4182b7779ae045d36e0bda877695010d7bb Mon Sep 17 00:00:00 2001 From: Jean Henry Date: Mon, 20 Apr 2026 12:51:45 +0200 Subject: [PATCH 1/7] chore: update .pre-commit-config.yaml with respect to the last template. --- .pre-commit-config.yaml | 65 +++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9178565..7b491fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,33 +1,38 @@ +ci: + autofix_commit_msg: 'chore: auto fixes from pre-commit hooks' + autoupdate_commit_msg: 'chore: pre-commit automatic update' + autoupdate_schedule: monthly + repos: - repo: https://github.com/ansys/pre-commit-hooks rev: v0.5.1 hooks: - - id: add-license-headers - args: - - --start_year=2023 + - id: add-license-headers + args: + - --start_year=2023 -- repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.9.2 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.4 hooks: - - id: ruff - args: [--fix] - - id: ruff-format + - id: ruff-check + args: [--fix] + - id: ruff-format - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - id: codespell additional_dependencies: - - tomli + - tomli exclude: > - (?x)^( - .*\.etp| - .*\.vsw| - .*\.scade| - .*\.xscade| - .*\.sct - )$ + (?x)^( + .*\.etp| + .*\.vsw| + .*\.scade| + .*\.xscade| + .*\.sct + )$ - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 @@ -37,3 +42,31 @@ repos: - id: check-yaml - id: trailing-whitespace exclude: (?x)^(?:.*\.tot|.*\.swan.?)$ + +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.33.2 + hooks: + - id: check-github-workflows + +- repo: https://github.com/numpy/numpydoc + rev: v1.9.0 + hooks: + - id: numpydoc-validation + exclude: | + (?x)( + tests/ + ) + +- repo: https://github.com/pre-commit-ci/pre-commit-ci-config + rev: v1.6.1 + hooks: + - id: check-pre-commit-ci-config + +# NOTE: Ruff does not check for python code in some parts of the documentation, +# e.g. python code block, ..., see https://github.com/astral-sh/ruff/issues/8237 +- repo: https://github.com/adamchainz/blacken-docs + rev: 1.19.1 + hooks: + - id: blacken-docs + additional_dependencies: [black==25.1.0] + args: [--line-length=120] From f0f1313076c5a7c544f993c06b59b8537fc5e881 Mon Sep 17 00:00:00 2001 From: Jean Henry Date: Mon, 20 Apr 2026 12:51:46 +0200 Subject: [PATCH 2/7] chore: update pyproject.toml with respect to the last template. --- pyproject.toml | 96 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index dfec3bd..9729fcc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,8 @@ [build-system] -requires = ["flit_core >=3.2,<4"] +requires = [ + "flit_core >=3.9,<3.12; python_version < '3.8'", + "flit_core >=3.12,<4; python_version >= '3.8'", +] build-backend = "flit_core.buildapi" [project] @@ -61,9 +64,6 @@ doc = [ ] -[tool.flit.module] -name = "ansys.scade.python_wrapper" - [project.urls] Source = "https://github.com/ansys/scade-python-wrapper" Issues = "https://github.com/ansys/scade-python-wrapper/issues" @@ -77,26 +77,20 @@ srg = "ansys.scade.python_wrapper:srg" register = "ansys.scade.python_wrapper.register:register" unregister = "ansys.scade.python_wrapper.unregister:unregister" + [project.scripts] ansys_scade_python_wrapper_swanpython = "ansys.scade.python_wrapper.swanpython:main" # backward compatibility register_ansys_scade_python_wrapper = "ansys.scade.python_wrapper.register:main" unregister_ansys_scade_python_wrapper = "ansys.scade.python_wrapper.unregister:main" + +[tool.flit.module] +name = "ansys.scade.python_wrapper" + + [tool.ruff] -line-length = 99 -lint.select = [ - "E", # pycodestyle, see https://beta.ruff.rs/docs/rules/#pycodestyle-e-w - "D", # pydocstyle, see https://beta.ruff.rs/docs/rules/#pydocstyle-d - "F", # pyflakes, see https://beta.ruff.rs/docs/rules/#pyflakes-f - "I", # isort, see https://beta.ruff.rs/docs/rules/#isort-i - "N", # pep8-naming, see https://beta.ruff.rs/docs/rules/#pep8-naming-n -] -lint.ignore = [ - "D203", # One blank line required before class docstring. - "D204", # One blank line required after class docstring. - "D206", # To ignore: conflict with the formatter -] +line-length = 100 exclude = [ # generated file "pydata.py", @@ -104,8 +98,23 @@ exclude = [ # TODO: "preserve" leads to an error, although it is documented # and used in other repositories +fix = true + [tool.ruff.format] quote-style = "single" +indent-style = "space" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle, see https://docs.astral.sh/ruff/rules/#pycodestyle-e-w + "D", # pydocstyle, see https://docs.astral.sh/ruff/rules/#pydocstyle-d + "F", # pyflakes, see https://docs.astral.sh/ruff/rules/#pyflakes-f + "I", # isort, see https://docs.astral.sh/ruff/rules/#isort-i + "N", # pep8-naming, see https://docs.astral.sh/ruff/rules/#pep8-naming-n + "PTH", # flake8-use-pathlib, https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth + "TD", # flake8-todos, https://docs.astral.sh/ruff/rules/#flake8-todos-td +] +ignore = [] [tool.ruff.lint.isort] combine-as-imports = true @@ -117,22 +126,25 @@ convention = "numpy" [tool.ruff.lint.per-file-ignores] "tests/*.py" = ["D",] -# generated file -"src/ansys/scade/python-wrapper/pydata.py" = ["D101", "D102", "D103"] -# naming rules not applicable -"tools/BuildData/*.py" = ["N",] + [tool.coverage.run] source = ["ansys.scade.python_wrapper"] +patch = ["subprocess"] [tool.coverage.report] show_missing = true +exclude_also = [ + "@(abc\\.)?abstractmethod", +] + [tool.pytest.ini_options] testpaths = "tests" addopts = "-ra --cov=ansys.scade.python_wrapper --cov-report html:.cov/html --cov-branch --cov-report xml:.cov/xml --cov-report term -vv" + [tool.towncrier] package = "ansys.scade.python_wrapper" directory = "doc/changelog.d" @@ -158,17 +170,18 @@ name = "Fixed" showcontent = true [[tool.towncrier.type]] -directory = "dependencies" -name = "Dependencies" +directory = "documentation" +name = "Documentation" showcontent = true [[tool.towncrier.type]] -directory = "miscellaneous" -name = "Miscellaneous" +directory = "test" +name = "Test" showcontent = true + [[tool.towncrier.type]] -directory = "documentation" -name = "Documentation" +directory = "dependencies" +name = "Dependencies" showcontent = true [[tool.towncrier.type]] @@ -177,6 +190,31 @@ name = "Maintenance" showcontent = true [[tool.towncrier.type]] -directory = "test" -name = "Test" +directory = "miscellaneous" +name = "Miscellaneous" showcontent = true + +[tool.codespell] +ignore-words-list = ["synopsys"] + +[tool.numpydoc_validation] +checks = [ + 'GL06', # Found unknown section + 'GL07', # Sections are in the wrong order. + 'GL08', # The object does not have a docstring + 'GL09', # Deprecation warning should precede extended summary + 'GL10', # reST directives {directives} must be followed by two colons + 'SS01', # No summary found + 'SS02', # Summary does not start with a capital letter + 'SS03', # Summary does not end with a period + 'SS04', # Summary contains heading whitespaces + # "SS05", # Summary must start with infinitive verb, not third person + 'RT02', # The first line of the Returns section should contain only the + # type, unless multiple values are being returned" +] +exclude = [ + '\._', # ignore private definitions + 'conftest.', + 'test.', +] + From f3c2f6a41bc72bf1c86680ea8dd0912977ba9d47 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Mon, 20 Apr 2026 10:57:31 +0000 Subject: [PATCH 3/7] chore: adding changelog file 62.maintenance.md [dependabot-skip] --- doc/changelog.d/62.maintenance.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/62.maintenance.md diff --git a/doc/changelog.d/62.maintenance.md b/doc/changelog.d/62.maintenance.md new file mode 100644 index 0000000..88b6f36 --- /dev/null +++ b/doc/changelog.d/62.maintenance.md @@ -0,0 +1 @@ +Update repository configuration files From b0ac9f103724548aba092b3ba2784ae8d68ef779 Mon Sep 17 00:00:00 2001 From: Jean Henry Date: Mon, 20 Apr 2026 14:35:18 +0200 Subject: [PATCH 4/7] chore: fix code-style findings --- doc/source/conf.py | 28 ------------------- doc/source/usage/proxy.rst | 5 ++-- pyproject.toml | 6 ++++ .../scade/python_wrapper/kcg_data_parser.py | 8 ++---- src/ansys/scade/python_wrapper/kcgpython.py | 2 +- src/ansys/scade/python_wrapper/rd/c_gen.py | 4 +-- src/ansys/scade/python_wrapper/rd/def_gen.py | 1 + .../scade/python_wrapper/rd/python_gen.py | 13 ++++----- tests/Debug/debug.py | 4 +-- 9 files changed, 22 insertions(+), 49 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index af182e4..85b28cc 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -61,30 +61,6 @@ # "grpc": ("https://grpc.github.io/grpc/python/", None), } -# numpydoc configuration -numpydoc_show_class_members = False -numpydoc_xref_param_type = True - -# Consider enabling numpydoc validation. See: -# https://numpydoc.readthedocs.io/en/latest/validation.html# -numpydoc_validate = True -numpydoc_validation_checks = { - 'GL06', # Found unknown section - 'GL07', # Sections are in the wrong order. - # Disabled the docstring validation as most of the methods doesn't have the docstring - # TODO: Add docstring and enable GL08 validation - # "GL08", # The object does not have a docstring - 'GL09', # Deprecation warning should precede extended summary - 'GL10', # reST directives {directives} must be followed by two colons - 'SS01', # No summary found - 'SS02', # Summary does not start with a capital letter - 'SS03', # Summary does not end with a period - 'SS04', # Summary contains heading whitespaces - # "SS05", # Summary must start with infinitive verb, not third person - 'RT02', # The first line of the Returns section should contain only the - # type, unless multiple values are being returned" -} - # Favicon html_favicon = ansys_favicon @@ -101,11 +77,7 @@ master_doc = 'index' -# TODO: remove ignore links after public release linkcheck_ignore = [ - 'https://github.com/ansys/scade-python-wrapper', - 'https://github.com/ansys/scade-python-wrapper/actions/workflows/ci_cd.yml', - 'https://pypi.org/project/ansys-scade-python-wrapper', # The link below takes a long time to check 'https://www.ansys.com/products/embedded-software/ansys-scade-suite', 'https://www.ansys.com/*', diff --git a/doc/source/usage/proxy.rst b/doc/source/usage/proxy.rst index 6e51546..c0663d8 100644 --- a/doc/source/usage/proxy.rst +++ b/doc/source/usage/proxy.rst @@ -102,5 +102,6 @@ Access to values Limitations ----------- -The wrapper does not support for now the ``input_threshold`` and -``global_context`` KCG options. +* The wrapper does not support for now the ``input_threshold`` and + ``global_context`` KCG options. +* Imported types are not supported. diff --git a/pyproject.toml b/pyproject.toml index 9729fcc..d150d47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,6 +126,10 @@ convention = "numpy" [tool.ruff.lint.per-file-ignores] "tests/*.py" = ["D",] +# generated file +"src/ansys/scade/python-wrapper/pydata.py" = ["D101", "D102", "D103"] # sync: skip +# naming rules not applicable +"tools/BuildData/*.py" = ["N",] # sync: skip [tool.coverage.run] @@ -216,5 +220,7 @@ exclude = [ '\._', # ignore private definitions 'conftest.', 'test.', + # generated file + 'pydata\.', ] diff --git a/src/ansys/scade/python_wrapper/kcg_data_parser.py b/src/ansys/scade/python_wrapper/kcg_data_parser.py index 74f9dcc..1ba79d8 100644 --- a/src/ansys/scade/python_wrapper/kcg_data_parser.py +++ b/src/ansys/scade/python_wrapper/kcg_data_parser.py @@ -87,9 +87,7 @@ def _build_type(model: data.Model, c_type: c.Type) -> Tuple[List[int], data.Type ) if c_type.is_context(): # consider only the interface, if any - c_fields = [ - _ for _ in c_type.get_fields() if isinstance(_.get_model(), m.Variable) - ] + c_fields = [_ for _ in c_type.get_fields() if isinstance(_.get_model(), m.Variable)] else: c_fields = [_ for _ in c_type.get_fields()] for c_field in c_fields: @@ -136,7 +134,7 @@ def _build_operator(model: data.Model, m_op: m.Operator): if c_op.get_reset(): op.set_reset(data.Function(c_name=c_op.get_reset().get_name())) - # TODO? + # is that needed? # _add_c_type(model, c_op.get_state_vector()) _, type_ = _build_type(model, c_op.get_input_struct()) if type_: @@ -148,7 +146,7 @@ def _build_operator(model: data.Model, m_op: m.Operator): op.in_context.link_type(type_) op.in_context.c_type = c_op.get_input_struct().get_name() op.in_context.pointer = True - # TODO? + # is that needed? # _add_c_type(model, c_op.get_output_struct()) _, type_ = _build_type(model, c_op.get_context()) if type_: diff --git a/src/ansys/scade/python_wrapper/kcgpython.py b/src/ansys/scade/python_wrapper/kcgpython.py index fafcf37..3e7c159 100644 --- a/src/ansys/scade/python_wrapper/kcgpython.py +++ b/src/ansys/scade/python_wrapper/kcgpython.py @@ -375,7 +375,7 @@ def _generate_display( ['%sLayer' % layer.name for spec in specifications for layer in spec.layers] ) - with open(str(pathname), 'w') as f: + with pathname.open('w') as f: f.write('import os.path\n') f.write('import ctypes\n') f.write('from sdyproxy import SdyProxy, SdyLayer\n') diff --git a/src/ansys/scade/python_wrapper/rd/c_gen.py b/src/ansys/scade/python_wrapper/rd/c_gen.py index f74014d..992a5c8 100644 --- a/src/ansys/scade/python_wrapper/rd/c_gen.py +++ b/src/ansys/scade/python_wrapper/rd/c_gen.py @@ -63,9 +63,7 @@ def generate_c(model: data.Model, c_pathname: Path, banner: str = '') -> None: f.write(' return 0;\n') else: # regular context to allocate - f.write( - ' {0} *ctx = ({0}*)malloc(sizeof({0}));\n'.format(op.context.c_type) - ) + f.write(' {0} *ctx = ({0}*)malloc(sizeof({0}));\n'.format(op.context.c_type)) if op.init is not None: f.write(' %s(ctx);\n' % op.init.c_name) f.write(' return (void*)ctx;\n') diff --git a/src/ansys/scade/python_wrapper/rd/def_gen.py b/src/ansys/scade/python_wrapper/rd/def_gen.py index 66f5b6a..24c42eb 100644 --- a/src/ansys/scade/python_wrapper/rd/def_gen.py +++ b/src/ansys/scade/python_wrapper/rd/def_gen.py @@ -32,6 +32,7 @@ def generate_def(model: data.Model, def_pathname: Path, cosim: bool, banner: str """Generate the C definition file for the DLL.""" def add_export(function: Optional[data.Function]): + """Add an export declaration for a declaration.""" nonlocal f, i if function: f.write('\t%s @ %d;\n' % (function.c_name, i)) diff --git a/src/ansys/scade/python_wrapper/rd/python_gen.py b/src/ansys/scade/python_wrapper/rd/python_gen.py index 19785dd..38fd2d0 100644 --- a/src/ansys/scade/python_wrapper/rd/python_gen.py +++ b/src/ansys/scade/python_wrapper/rd/python_gen.py @@ -28,7 +28,7 @@ # * add type: ignore comments # * use setattr/getattr functions -# TODO: +# room for improvements: # * error (or warning multiple instances not supported) with global context # * rename when name of io is either a Python keyword or conflicts with one of: # * call_reset @@ -38,7 +38,7 @@ # * in_c # * declare a structure of classes corresponding to the package hierarchy # * refactor the design: -# * rely more on c_op.get_cycle().get_parameters() to simply the algorithms +# * rely more on c_op.get_cycle().get_parameters() to simplify the algorithms from collections import namedtuple from keyword import iskeyword @@ -113,7 +113,7 @@ def _get_python_type_name(type_: data.Type, native: bool, sizes=None) -> str: # make anonymous structures, that must be contexts, private if type_.scalar: # must be a predefined type - # TODO: what about imported scalar types? + # (imported scalar types are nbot supported) pi = _get_predef_info(type_.m_name, native) assert pi is not None # nosec B101 # addresses linter name = pi.type_name @@ -208,6 +208,7 @@ def generate_python( global _pep8 def write_accessors(typed: data.Feature): + """Generate accessors to the feature.""" # typed is either a sensor or an i/o type_ = typed.type assert type_ is not None # nosec B101 # addresses linter @@ -217,12 +218,12 @@ def write_accessors(typed: data.Feature): else: assert isinstance(typed, data.IO) # nosec B101 # addresses linter setter = typed.input - # TODO: no name for not scalar types if typed.scalar(): type_name = _get_python_type_name(type_, True) arg_type = ': %s' % type_name return_type = ' -> %s' % type_name else: + # no name for not scalar types arg_type = '' return_type = '' f.write(' @property\n') @@ -480,7 +481,6 @@ def write_accessors(typed: data.Feature): if op.context: f.write('\n') f.write(' def __del__(self):\n') - # TODO: separate_io f.write(' free_fct = _lib.py_free_%s\n' % op.c_name) f.write(' free_fct.argtypes = [ctypes.c_void_p]\n') f.write(' free_fct.restype = None\n') @@ -488,7 +488,6 @@ def write_accessors(typed: data.Feature): f.write('\n') f.write(' def call_reset(self) -> None:\n') if op.reset: - # TODO: reuse function.parameters instead of hard-coding op.context arg = ('ctypes.byref(%s)' % op.context.py_member) if op.reset.parameters else '' f.write(' self.reset_fct(%s)\n' % arg) else: @@ -540,7 +539,7 @@ def write_accessors(typed: data.Feature): f.write('\n') for c_type in sorted(c_interface_types): - # TODO: share code with _get_cvt_name + # code could be shared with _get_cvt_name f.write( '_%s_cvt = _cvt(_lib.%s_to_string)\n' % ((utils.lower_name(c_type) if _pep8 else c_type), c_type) diff --git a/tests/Debug/debug.py b/tests/Debug/debug.py index 29877f6..41ef3f8 100644 --- a/tests/Debug/debug.py +++ b/tests/Debug/debug.py @@ -37,9 +37,7 @@ from scade.code.suite.sctoc import raw_tcl, sc_to_c_core parser = argparse.ArgumentParser(description='Python way for scade -code') -parser.add_argument( - '-p', '--project', metavar='', help='SCADE Suite', required=True -) +parser.add_argument('-p', '--project', metavar='', help='SCADE Suite', required=True) parser.add_argument( '-c', '--configuration', metavar='', help='configuration', required=True ) From 71c4a18274101b62b13f7b343e1e6b57f1deff5d Mon Sep 17 00:00:00 2001 From: Jean Henry Date: Mon, 20 Apr 2026 15:05:07 +0200 Subject: [PATCH 5/7] chore: fix changelog link --- doc/source/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index d28a8b5..c386d5f 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -150,7 +150,7 @@ Fixed - fix: documentation link `#23 `_ -`2.0.dev0 `_ - 2025-01-22 +`2.2.0 `_ - 2025-01-22 =============================================================================================== Fixed From b7f01dae3086ce93818bb9f7e1b0ab2f44f32004 Mon Sep 17 00:00:00 2001 From: Jean Henry Date: Wed, 29 Apr 2026 14:44:17 +0200 Subject: [PATCH 6/7] doc: ignore linkcheck on repository links --- doc/source/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 85b28cc..67a2630 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -76,9 +76,11 @@ # The master toctree document. master_doc = 'index' - +linkcheck_exclude_documents = ['changelog'] linkcheck_ignore = [ # The link below takes a long time to check + 'https://github.com/ansys/pre-commit-hooks/.*', + 'https://ansyshelp.ansys.com/*', 'https://www.ansys.com/products/embedded-software/ansys-scade-suite', 'https://www.ansys.com/*', ] From e9f0f3a7fab82514b7f648d9fa70fdb2105538a0 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Wed, 29 Apr 2026 12:46:35 +0000 Subject: [PATCH 7/7] chore: adding changelog file 62.maintenance.md [dependabot-skip] --- pyproject.toml | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d150d47..029c368 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,6 @@ doc = [ "sphinxnotes-strike==1.2.1; python_version <= '3.10'", ] - [project.urls] Source = "https://github.com/ansys/scade-python-wrapper" Issues = "https://github.com/ansys/scade-python-wrapper/issues" @@ -77,18 +76,15 @@ srg = "ansys.scade.python_wrapper:srg" register = "ansys.scade.python_wrapper.register:register" unregister = "ansys.scade.python_wrapper.unregister:unregister" - [project.scripts] ansys_scade_python_wrapper_swanpython = "ansys.scade.python_wrapper.swanpython:main" # backward compatibility register_ansys_scade_python_wrapper = "ansys.scade.python_wrapper.register:main" unregister_ansys_scade_python_wrapper = "ansys.scade.python_wrapper.unregister:main" - [tool.flit.module] name = "ansys.scade.python_wrapper" - [tool.ruff] line-length = 100 exclude = [ @@ -131,7 +127,6 @@ convention = "numpy" # naming rules not applicable "tools/BuildData/*.py" = ["N",] # sync: skip - [tool.coverage.run] source = ["ansys.scade.python_wrapper"] patch = ["subprocess"] @@ -142,13 +137,10 @@ exclude_also = [ "@(abc\\.)?abstractmethod", ] - [tool.pytest.ini_options] testpaths = "tests" addopts = "-ra --cov=ansys.scade.python_wrapper --cov-report html:.cov/html --cov-branch --cov-report xml:.cov/xml --cov-report term -vv" - - [tool.towncrier] package = "ansys.scade.python_wrapper" directory = "doc/changelog.d" @@ -159,13 +151,13 @@ title_format = "`{version}