diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000000000000000000000000000000000000..7f68be50271a1371c3c93037f16bf315abda72b5 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,36 @@ +name: Tests +on: [push, pull_request] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.7, 3.8, 3.9, 3.10-dev] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: run tests + env: + PURE_EVAL_SLOW_TESTS: 1 + run: | + pip install -U pip + pip install --upgrade coveralls setuptools setuptools_scm pep517 + pip install .[tests] + coverage run --source pure_eval -m pytest + coverage report -m + - name: Coveralls Python + uses: AndreMiras/coveralls-python-action@v20201129 + with: + parallel: true + flag-name: test-${{ matrix.python-version }} + coveralls_finish: + needs: build + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: AndreMiras/coveralls-python-action@v20201129 + with: + parallel-finished: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fb89d46ed89341affbbd025db41ee8a1e565d92c..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -dist: xenial -language: python -sudo: false - -python: - - 3.5 - - 3.6 - - 3.7 - - 3.8-dev - - 3.9-dev - -env: - global: - - PURE_EVAL_SLOW_TESTS=1 - - COVERALLS_PARALLEL=true - -before_install: - - pip install --upgrade coveralls setuptools>=44 setuptools_scm>=3.4.3 pep517 - -install: - - pip install ".[tests]" - -script: - - coverage run --branch --include='pure_eval/*' -m pytest --junitxml=./rspec.xml - - coverage report -m - -after_success: - - coveralls - -notifications: - webhooks: https://coveralls.io/webhook - email: false diff --git a/MANIFEST.in b/MANIFEST.in index 42eb4101e514e6e82ecd5111fe09e81a786de694..09204c851bf40eabadb855860cc3490d5161b901 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,3 @@ include LICENSE.txt +include pure_eval/py.typed +include README.md diff --git a/make_release.sh b/make_release.sh index 228f62810063bfd41c8d29867a2394c4a363b6ed..f0c1ac84a64f29c6b0af412ba2f0f4bc7d55a9e0 100755 --- a/make_release.sh +++ b/make_release.sh @@ -26,5 +26,5 @@ export TAG="v${1}" git tag "${TAG}" git push origin master "${TAG}" rm -rf ./build ./dist -python3 -m pep517.build -b . -twine upload ./dist/*.whl +python -m build --sdist --wheel . +twine upload ./dist/*.whl dist/*.tar.gz diff --git a/pure_eval/core.py b/pure_eval/core.py index 0a0381eedac208e17a213195b6e29931579d6744..748f0518d4f941c6edb1cd95bc4273ded8f14455 100644 --- a/pure_eval/core.py +++ b/pure_eval/core.py @@ -15,6 +15,7 @@ from pure_eval.utils import ( of_standard_types, is_any, of_type, + ensure_dict, ) @@ -39,9 +40,9 @@ class Evaluator: """ return cls(ChainMap( - frame.f_locals, - frame.f_globals, - frame.f_builtins, + ensure_dict(frame.f_locals), + ensure_dict(frame.f_globals), + ensure_dict(frame.f_builtins), )) def __getitem__(self, node: ast.expr) -> Any: diff --git a/pure_eval/py.typed b/pure_eval/py.typed new file mode 100644 index 0000000000000000000000000000000000000000..298c64a9041faa49413d4025444a28acc4a1f44c --- /dev/null +++ b/pure_eval/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. The pure_eval package uses inline types. diff --git a/pure_eval/utils.py b/pure_eval/utils.py index 139d6dd9fdd216a898943a4d86622267829dd325..a8a37302daa000d736ef9d935813892a725cbede 100644 --- a/pure_eval/utils.py +++ b/pure_eval/utils.py @@ -189,3 +189,13 @@ def copy_ast_without_context(x): return list(map(copy_ast_without_context, x)) else: return x + + +def ensure_dict(x): + """ + Handles invalid non-dict inputs + """ + try: + return dict(x) + except Exception: + return {} diff --git a/setup.cfg b/setup.cfg index 6a76979ebf517c257110f04087fc96b6b841fcf0..3d07ca911dc4a3ab22835ecf0ed70b410e697255 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,6 +14,7 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 License :: OSI Approved :: MIT License Operating System :: OS Independent @@ -22,7 +23,10 @@ packages = pure_eval install_requires = include_package_data = True tests_require = pytest -setup_requires = setuptools>=44; wheel; setuptools_scm[toml]>=3.4.3 +setup_requires = setuptools>=44; setuptools_scm[toml]>=3.4.3 [options.extras_require] tests = pytest + +[options.package_data] +pure_eval = py.typed diff --git a/tests/test_utils.py b/tests/test_utils.py index 315ecc5563bdf4b01379a6639a679fbbaec57494..172f50ec2c359b1ba7a7082c80e1d60c0e4ebfbe 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -17,6 +17,7 @@ from pure_eval.utils import ( safe_name, typing_annotation_samples, is_standard_types, + ensure_dict, ) @@ -126,3 +127,10 @@ def test_is_standard_types(): assert is_standard_types(lst, deep=False, check_dict_values=True) assert is_standard_types(lst[0], deep=True, check_dict_values=True) assert not is_standard_types(lst, deep=True, check_dict_values=True) + + +def test_ensure_dict(): + assert ensure_dict({}) == {} + assert ensure_dict([]) == {} + assert ensure_dict('foo') == {} + assert ensure_dict({'a': 1}) == {'a': 1} diff --git a/tox.ini b/tox.ini index 9f52c890325a8430ed59e2025e126a8967842288..3feff03f683bca56831bb5fedce10334559561f8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,8 @@ [tox] -envlist = py{35,36,37,38,39} +envlist = py{35,36,37,38,39,310} [testenv] commands = pytest -deps = - .[tests] +extras = tests passenv = PURE_EVAL_SLOW_TESTS