Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@master
Expand All @@ -26,6 +26,8 @@ jobs:
run: |
python3 -m pip install --upgrade pip
pip3 install --upgrade coveralls
# Python >=3.12 does not ship setuptools with pip anymore.
pip3 install setuptools
pip3 install -e .[dev]

- name: Run checks
Expand Down
54 changes: 53 additions & 1 deletion icontract/_recompute.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def _translate_all_expression_to_a_module(
) # type: Union[ast.FunctionDef, ast.AsyncFunctionDef]

module_node = ast.Module(body=[func_def_node])
else:
elif sys.version_info < (3, 12):
func_def_node = ast.FunctionDef(
name=generated_function_name,
args=ast.arguments(
Expand All @@ -248,6 +248,24 @@ def _translate_all_expression_to_a_module(
body=block,
)

module_node = ast.Module(body=[func_def_node], type_ignores=[])
else:
func_def_node = ast.FunctionDef(
name=generated_function_name,
args=ast.arguments(
args=args,
posonlyargs=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[],
vararg=None,
kwarg=None,
),
body=block,
decorator_list=[],
type_params=[],
)

module_node = ast.Module(body=[func_def_node], type_ignores=[])
else:
if sys.version_info < (3, 8):
Expand All @@ -266,6 +284,23 @@ def _translate_all_expression_to_a_module(
)

module_node = ast.Module(body=[async_func_def_node])
elif sys.version_info < (3, 12):
async_func_def_node = ast.AsyncFunctionDef(
name=generated_function_name,
args=ast.arguments(
args=args,
posonlyargs=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[],
vararg=None,
kwarg=None,
),
decorator_list=[],
body=block,
)

module_node = ast.Module(body=[async_func_def_node], type_ignores=[])
else:
async_func_def_node = ast.AsyncFunctionDef(
name=generated_function_name,
Expand All @@ -280,6 +315,7 @@ def _translate_all_expression_to_a_module(
),
decorator_list=[],
body=block,
type_params=[],
)

module_node = ast.Module(body=[async_func_def_node], type_ignores=[])
Expand Down Expand Up @@ -925,6 +961,21 @@ def _execute_comprehension(
)

module_node = ast.Module(body=[func_def_node])
elif sys.version_info < (3, 12):
func_def_node = ast.FunctionDef(
name="generator_expr",
args=ast.arguments(
args=args,
posonlyargs=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[],
),
decorator_list=[],
body=[ast.Return(node)],
)

module_node = ast.Module(body=[func_def_node], type_ignores=[])
else:
func_def_node = ast.FunctionDef(
name="generator_expr",
Expand All @@ -937,6 +988,7 @@ def _execute_comprehension(
),
decorator_list=[],
body=[ast.Return(node)],
type_params=[],
)

module_node = ast.Module(body=[func_def_node], type_ignores=[])
Expand Down
12 changes: 11 additions & 1 deletion precommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,18 @@ def main() -> int:
pylint_targets.append("tests_3_8")
pylint_targets.append("tests_with_others")

import pylint
import packaging.version

if packaging.version.parse(pylint.__version__) < packaging.version.parse(
"3.3.7"
):
rcfile = "pylint.lt_3.3.7.rc"
else:
rcfile = "pylint.ge_3.3.7.rc"

subprocess.check_call(
["pylint", "--rcfile=pylint.rc"] + pylint_targets, cwd=str(repo_root)
["pylint", f"--rcfile={rcfile}"] + pylint_targets, cwd=str(repo_root)
)

print("Pydocstyle'ing...")
Expand Down
9 changes: 9 additions & 0 deletions pylint.ge_3.3.7.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[TYPECHECK]
ignored-modules = numpy
ignored-classes = numpy,PurePath

[FORMAT]
max-line-length=120

[MESSAGES CONTROL]
disable=too-few-public-methods,len-as-condition,duplicate-code,no-else-raise,too-many-locals,too-many-branches,too-many-lines,too-many-arguments,too-many-statements,too-many-nested-blocks,too-many-function-args,too-many-instance-attributes,too-many-public-methods,protected-access,consider-using-in,no-member,consider-using-f-string,use-dict-literal,redundant-keyword-arg,no-else-return,too-many-positional-arguments
2 changes: 0 additions & 2 deletions pylint.rc → pylint.lt_3.3.7.rc
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
[TYPECHECK]
ignored-modules = numpy
ignored-classes = numpy,PurePath
generated-members=bottle\.request\.forms\.decode,bottle\.request\.query\.decode

[FORMAT]
max-line-length=120

[MESSAGES CONTROL]
disable=too-few-public-methods,len-as-condition,duplicate-code,no-else-raise,too-many-locals,too-many-branches,too-many-lines,too-many-arguments,too-many-statements,too-many-nested-blocks,too-many-function-args,too-many-instance-attributes,too-many-public-methods,protected-access,consider-using-in,no-member,consider-using-f-string,use-dict-literal,redundant-keyword-arg,no-else-return

10 changes: 6 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@
# fmt: off
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.6',
'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',
# fmt: on
],
license="License :: OSI Approved :: MIT License",
Expand All @@ -55,7 +55,8 @@
],
extras_require={
"dev": [
'pylint==3.2.7;python_version>="3.8"',
'pylint==2.17.5;python_version>="3.7" and python_version<"3.12"',
'pylint==4.0.2;python_version>="3.12"',
"tox>=3.0.0",
"pydocstyle>=6.3.0,<7",
"coverage>=6.5.0,<7",
Expand All @@ -67,8 +68,9 @@
"typeguard>=2,<5",
"astor==0.8.1",
"numpy>=1,<2",
'mypy==1.14.1;python_version>="3.8"',
'black==24.8.0;python_version>="3.8"',
'mypy==1.5.1;python_version>="3.8" and python_version<"3.12"',
'mypy==1.18.2;python_version>="3.12"',
'black==23.9.1;python_version>="3.8"',
'deal>=4,<5;python_version>="3.8"',
'asyncstdlib==3.9.1;python_version>="3.8"',
]
Expand Down
7 changes: 6 additions & 1 deletion tests/test_inheritance_postcondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,11 +535,16 @@ class B(A):
"Can't instantiate abstract class B with abstract methods func",
str(type_err),
)
else:
elif sys.version_info < (3, 12):
self.assertEqual(
"Can't instantiate abstract class B with abstract method func",
str(type_err),
)
else:
self.assertEqual(
"Can't instantiate abstract class B without an implementation for abstract method 'func'",
str(type_err),
)


if __name__ == "__main__":
Expand Down
7 changes: 6 additions & 1 deletion tests/test_inheritance_precondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,16 @@ class B(A):
"Can't instantiate abstract class B with abstract methods func",
str(type_err),
)
else:
elif sys.version_info < (3, 12):
self.assertEqual(
"Can't instantiate abstract class B with abstract method func",
str(type_err),
)
else:
self.assertEqual(
"Can't instantiate abstract class B without an implementation for abstract method 'func'",
str(type_err),
)

def test_cant_weaken_base_function_without_preconditions(self) -> None:
class A(icontract.DBC):
Expand Down
7 changes: 5 additions & 2 deletions tests_with_others/test_deal.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# pylint: disable=missing-docstring
# pylint: disable=broad-except
# pylint: disable=invalid-name

import unittest
from typing import Optional

Expand All @@ -10,7 +9,11 @@

class TestDeal(unittest.TestCase):
def test_recursion_handled_in_preconditions(self) -> None:
@deal.pre(lambda _: another_func()) # type: ignore
# NOTE (mristin):
# Mypy 1.5.1 throws here a misc error -- that the untyped decorator forces the function to be untyped as well.
# On the other hand, mypy 1.18.2 can figure this situation, and throws unused-ignore. We ignore both cases
# to be able to support both versions of mypy.
@deal.pre(lambda _: another_func()) # type: ignore[unused-ignore,misc]
@deal.pre(lambda _: yet_another_func())
def some_func() -> bool:
return True
Expand Down