Skip to content

Commit

Permalink
Add Python 3.12 support via "trace" method
Browse files Browse the repository at this point in the history
  • Loading branch information
eriknw authored Feb 17, 2024
2 parents 71835ec + d9f6eda commit 85eb91d
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 55 deletions.
14 changes: 14 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
coverage:
status:
project:
default:
informational: true
patch:
default:
informational: true
changes: false
comment:
layout: "header, diff"
behavior: default
github_checks:
annotations: false
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
name: pre-commit-hooks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: pre-commit/[email protected].0
- uses: pre-commit/[email protected].1
8 changes: 4 additions & 4 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ jobs:
if: github.repository == 'eriknw/innerscope'
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.8"
- name: Install build dependencies
Expand All @@ -24,7 +24,7 @@ jobs:
python -m pip install build twine
- name: Build wheel and sdist
run: python -m build --sdist --wheel
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: releases
path: dist
Expand All @@ -33,7 +33,7 @@ jobs:
run: python -m twine check --strict dist/*
- name: Publish to PyPI
if: contains(github.ref, 'refs/tags/')
uses: pypa/[email protected].6
uses: pypa/[email protected].11
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
34 changes: 12 additions & 22 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ on:
jobs:
test:
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash -l {0}
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.8", "pypy-3.9"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.8", "pypy-3.9", "pypy-3.10"]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand All @@ -29,27 +32,14 @@ jobs:
pip install -e . --no-deps
- name: PyTest
run: |
coverage run --branch -m pytest --doctest-modules --method bytecode
if [[ ${{ matrix.python-version }} != '3.12' ]]; then
coverage run --branch -m pytest --doctest-modules --method bytecode
fi
coverage run -a --branch -m pytest --doctest-modules --method trace
pytest --doctest-modules --method trace
- name: Coverage
if: (! contains(matrix.python-version, 'pypy'))
env:
GITHUB_TOKEN: ${{ secrets.github_token }}
COVERALLS_FLAG_NAME: ${{ matrix.python-version}}
COVERALLS_PARALLEL: true
run: |
pip install coveralls
coverage xml
coverage report --show-missing
coveralls --service=github
finish:
needs: test
if: always()
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
- name: codecov
uses: codecov/codecov-action@v4
32 changes: 16 additions & 16 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
Expand All @@ -33,58 +33,58 @@ repos:
- id: name-tests-test
args: ["--pytest-test-first"]
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.13
rev: v0.16
hooks:
- id: validate-pyproject
name: Validate pyproject.toml
# I don't yet trust ruff to do what autoflake does
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
rev: v2.2.1
hooks:
- id: autoflake
args: [--in-place]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v3.6.0
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py38-plus]
- repo: https://github.com/psf/black
rev: 23.3.0
rev: 24.2.0
hooks:
- id: black
# - repo: https://github.com/charliermarsh/ruff-pre-commit
# rev: v0.0.272
# - repo: https://github.com/astral-sh/ruff-pre-commit
# rev: v0.1.14
# hooks:
# - id: ruff
# args: [--fix-only, --show-fixes]
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
rev: 7.0.0
hooks:
- id: flake8
additional_dependencies: &flake8_dependencies
# These versions need updated manually
- flake8==6.0.0
- flake8==7.0.0
- flake8-comprehensions==3.12.0
- flake8-bugbear==23.6.5
- flake8-simplify==0.20.0
- flake8-bugbear==24.2.6
- flake8-simplify==0.21.0
- repo: https://github.com/asottile/yesqa
rev: v1.5.0
hooks:
- id: yesqa
additional_dependencies: *flake8_dependencies
- repo: https://github.com/codespell-project/codespell
rev: v2.2.4
rev: v2.2.6
hooks:
- id: codespell
types_or: [python, rst, markdown]
additional_dependencies: [tomli]
files: ^(innerscope|docs)/
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.272
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.1
hooks:
- id: ruff
# `pyroma` may help keep our package standards up to date if best practices change.
Expand All @@ -95,6 +95,6 @@ repos:
- id: pyroma
args: [-n, "10", .]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: no-commit-to-branch # no commit directly to main
8 changes: 7 additions & 1 deletion innerscope/cfg.py
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
default_method = "bytecode"
import sys

if sys.version_info < (3, 12):
default_method = "bytecode"
else:
default_method = "trace"
del sys
21 changes: 16 additions & 5 deletions innerscope/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
+ b"%b"
+ bytes([dis.opmap["BUILD_TUPLE"], 3, dis.opmap["RETURN_VALUE"], 0])
)
else:
elif sys.version_info < (3, 12):
NEW_CODE = (
bytes([dis.opmap["LOAD_GLOBAL"]])
+ b"%b"
Expand Down Expand Up @@ -73,6 +73,8 @@
]
)
)
else:
NEW_CODE = b"" # NOT YET SUPPORTED
BUILTINS = set(dir(builtins))


Expand Down Expand Up @@ -460,7 +462,7 @@ def __init__(self, func, *mappings, use_closures=True, use_globals=True, method=
self.missing.update(name for name in code.co_freevars if name not in outer_scope)
self.builtin_names -= self.outer_scope.keys()

if self._code is None:
if self._code is None and method == "bytecode":
self._create_code()

def _create_code(self):
Expand Down Expand Up @@ -503,11 +505,15 @@ def _create_code(self):
co_names = (*code.co_names, "_innerscope_locals_", "_innerscope_secret_")
if sys.version_info < (3, 11):
new_code = NEW_CODE % (bytes([len(code.co_names)]), bytes([len(code.co_names) + 1]))
else:
elif sys.version_info < (3, 12):
new_code = NEW_CODE % (
bytes([2 * len(code.co_names) + 1]),
bytes([2 * len(code.co_names) + 2]),
)
else:
raise NotImplementedError(
'Unable to create bytecode for method="bytecode" in this Python version'
)
co_code = co_code + new_code

# stacksize must be at least 3, because we make a length three tuple
Expand Down Expand Up @@ -615,7 +621,11 @@ def trace_returns(frame, event, arg):
del outer_scope["_innerscope_locals_"]
del outer_scope["_innerscope_secret_"]
# closures show up in locals, but we want them only in outer_scope
for key in self._code.co_freevars:
if is_trace:
freevars = self.func.__code__.co_freevars
else:
freevars = self._code.co_freevars
for key in freevars:
del inner_scope[key]
rv = Scope(self, outer_scope, return_value, inner_scope)
if type(self) is ScopedGeneratorFunction:
Expand Down Expand Up @@ -734,7 +744,8 @@ def __getstate__(self):

def __setstate__(self, state):
self.__dict__.update(state)
self._create_code()
if self.method == "bytecode":
self._create_code()


class ScopedGeneratorFunction(ScopedFunction):
Expand Down
14 changes: 10 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ classifiers = [
"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",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
Expand Down Expand Up @@ -70,7 +71,7 @@ dirty_template = "{tag}+{ccount}.g{sha}.dirty"

[tool.black]
line-length = 100
target-version = ["py38", "py39", "py310", "py311"]
target-version = ["py38", "py39", "py310", "py311", "py312"]

[tool.isort]
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
Expand Down Expand Up @@ -112,9 +113,14 @@ exclude_lines = [
]

[tool.ruff]
# https://github.com/charliermarsh/ruff/
# https://github.com/astral-sh/ruff/
line-length = 100
target-version = "py38"
[tool.ruff.lint]
unfixable = [
"F841", # unused-variable (Note: can leave useless expression)
"B905", # zip-without-explicit-strict (Note: prefer `zip(x, y, strict=True)`)
]
select = [
"ALL",
]
Expand Down Expand Up @@ -171,14 +177,14 @@ ignore = [
"PD", # pandas-vet (Intended for scripts that use pandas, not libraries)
]

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"] # Allow unused imports (w/o defining `__all__`)
"innerscope/tests/*py" = [
"S101", "S301", "T201", "D103", "D100", # Allow assert, print, pickle, and no docstring
"A001", "A002", "B018", "C408", "C416", "E702", "E703", "F821", "F841", # Let us test messy code
]
"innerscope/tests/test_repr.py" = ["E501"]

[tool.ruff.flake8-pytest-style]
[tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = false
mark-parentheses = false
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Simple setuptools script; see pyproject.toml for package info."""

from setuptools import setup

setup()

0 comments on commit 85eb91d

Please sign in to comment.