Skip to content

Commit

Permalink
Merge pull request #17 from eriknw/py311
Browse files Browse the repository at this point in the history
Add support for Python 3.11
  • Loading branch information
eriknw committed Jun 12, 2023
2 parents d291d7f + 42af6e7 commit 85a7f3b
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 37 deletions.
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
26 changes: 18 additions & 8 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
jobs:
build_and_deploy:
runs-on: ubuntu-latest
if: github.repository == 'eriknw/innerscope'
defaults:
run:
shell: bash -l {0}
Expand All @@ -16,17 +17,26 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Create env
uses: conda-incubator/setup-miniconda@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
auto-update-conda: true
python-version: 3.9
- name: Build wheel
if: contains(github.ref, 'refs/tags/')
run: python setup.py sdist bdist_wheel
python-version: "3.8"
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build setuptools twine
- name: Build wheel and sdist
run: python -m build --sdist --wheel
- uses: actions/upload-artifact@v3
with:
name: releases
path: dist
if-no-files-found: error
- name: Check with twine
run: python -m twine check --strict dist/*
- name: Publish to PyPI
if: contains(github.ref, 'refs/tags/')
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@v1.8.6
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: [3.7, 3.8, 3.9, "3.10", "pypy-3.7", "pypy-3.8"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.7", "pypy-3.8", "pypy-3.9"]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Innerscope

[![Python Version](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%20PyPy-blue)](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%20PyPy-blue)
[![Python Version](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%20PyPy-blue)](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%20PyPy-blue)
[![Version](https://img.shields.io/pypi/v/innerscope.svg)](https://pypi.org/project/innerscope/)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://github.com/eriknw/innerscope/blob/master/LICENSE)
[![Build Status](https://github.com/eriknw/innerscope/workflows/Test/badge.svg)](https://github.com/eriknw/innerscope/actions)
[![Coverage Status](https://coveralls.io/repos/eriknw/innerscope/badge.svg?branch=master)](https://coveralls.io/r/eriknw/innerscope)
[![Code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

`innerscope` exposes the inner scope of functions and offers primitives suitable for creating pipelines. It explores a design space around functions, dictionaries, and classes.

Expand Down
106 changes: 87 additions & 19 deletions innerscope/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,67 @@ def code_replace(code, *, co_code, co_names, co_stacksize):
)


if sys.version_info.minor < 11:
NEW_CODE = (
bytes([dis.opmap["LOAD_GLOBAL"]])
+ b"%b"
+ bytes([dis.opmap["CALL_FUNCTION"], 0, dis.opmap["LOAD_GLOBAL"]])
+ b"%b"
+ bytes([dis.opmap["BUILD_TUPLE"], 3, dis.opmap["RETURN_VALUE"], 0])
)
else:
NEW_CODE = (
bytes([dis.opmap["LOAD_GLOBAL"]])
+ b"%b"
+ bytes(
[
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["PRECALL"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CALL"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["LOAD_GLOBAL"],
]
)
+ b"%b"
+ bytes(
[
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["CACHE"],
0,
dis.opmap["BUILD_TUPLE"],
3,
dis.opmap["RETURN_VALUE"],
0,
]
)
)
BUILTINS = set(dir(builtins))


Expand All @@ -77,7 +138,12 @@ def _get_globals_recursive(func, *, seen=None, isclass=False):
for inst in dis.get_instructions(func):
if inst.opname == "LOAD_CONST" and type(inst.argval) is CodeType:
if num_classes > 0:
code_inst = next(dis.get_instructions(inst.argval))
it = dis.get_instructions(inst.argval)
code_inst = next(it)
if code_inst.opname == "COPY_FREE_VARS":
code_inst = next(it)
if code_inst.opname == "RESUME":
code_inst = next(it)
isclass = code_inst.opname == "LOAD_NAME" and code_inst.argval == "__name__"
num_classes -= isclass
if inst.argval in seen: # pragma: no cover
Expand Down Expand Up @@ -474,20 +540,14 @@ def _create_code(self):

# Modify to end with `return (rv, locals(), secret)`
co_names = code.co_names + ("_innerscope_locals_", "_innerscope_secret_")
co_code = co_code + bytes(
[
dis.opmap["LOAD_GLOBAL"],
len(code.co_names),
dis.opmap["CALL_FUNCTION"],
0,
dis.opmap["LOAD_GLOBAL"],
len(code.co_names) + 1,
dis.opmap["BUILD_TUPLE"],
3,
dis.opmap["RETURN_VALUE"],
0,
]
)
if sys.version_info.minor < 11:
new_code = NEW_CODE % (bytes([len(code.co_names)]), bytes([len(code.co_names) + 1]))
else:
new_code = NEW_CODE % (
bytes([2 * len(code.co_names) + 1]),
bytes([2 * len(code.co_names) + 2]),
)
co_code = co_code + new_code

# stacksize must be at least 3, because we make a length three tuple
self._code = code_replace(
Expand Down Expand Up @@ -552,12 +612,20 @@ def trace_returns(frame, event, arg):
return_value = yield from return_value
except UnboundLocalError as exc:
message = exc.args and exc.args[0] or ""
if (
isinstance(message, str)
and message.startswith("local variable ")
if isinstance(message, str) and (
message.startswith("local variable ")
and message.endswith(" referenced before assignment")
or message.startswith("cannot access local variable")
and message.endswith("where it is not associated with a value")
):
name = message[len("local variable ") : -len(" referenced before assignment")]
if message.startswith("local variable "):
name = message[len("local variable ") : -len(" referenced before assignment")]
else:
name = message[
len("cannot access local variable ") : -len(
"where it is not associated with a value"
)
]
raise UnboundLocalError(
f"{message}.\n\n"
"This probably means you assigned to a local variable with the same name as a "
Expand Down
4 changes: 3 additions & 1 deletion innerscope/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,9 @@ def f2():
x = x + 1 # pragma: no cover

with raises(
UnboundLocalError, match="local variable 'x' referenced before assignment.\n\nThis probably"
UnboundLocalError,
match="local variable 'x' referenced before assignment.\n\nThis probably"
"|cannot access local variable 'x' where it is not associated with a value.\n\nThis probably",
):
f2()

Expand Down
6 changes: 2 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ exclude =
versioneer.py,
innerscope/tests/,
build/
ignore =
E203, # whitespace before ':'
E231, # Multiple spaces around ","
W503, # line break before binary operator
extend-ignore =
E203,

[isort]
sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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 :: Only",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
Expand Down

0 comments on commit 85a7f3b

Please sign in to comment.