Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Python 3.12 #713

Merged
merged 9 commits into from
Dec 19, 2023
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
12 changes: 2 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,22 @@ jobs:
container: python:${{ matrix.python }}
strategy:
matrix:
python: ["3.10", "3.11"]
python: ["3.10", "3.11", "3.12"]
steps:
- run: python3 --version
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install Python dependencies, Build, and Test
run: make setup-build-test

run-integration-tests:
runs-on: ubuntu-20.04
strategy:
matrix:
python: ["3.10", "3.11"]
python: ["3.10", "3.11", "3.12"]
steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: "${{ matrix.python }}"
Expand All @@ -53,8 +49,6 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: "${{ matrix.python }}"
Expand All @@ -77,8 +71,6 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install dependencies
run: make setup-wheel
- name: Build package
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ jobs:
container: python:${{ matrix.python }}
strategy:
matrix:
python: ["3.10", "3.11"]
python: ["3.10", "3.11", "3.12"]
steps:
- run: python3 --version
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check for code changes
id: check
run: make check-code-changes
Expand All @@ -32,12 +30,10 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python: ["3.10", "3.11"]
python: ["3.10", "3.11", "3.12"]
steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check for code changes
id: check
run: make check-code-changes
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Added

* Support for Python 3.12. ([#713](https://github.com/algorand/pyteal/pull/713))

## Fixed

## Changed
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sphinx==5.1.1
sphinx-rtd-theme==1.0.0
# dependencies from setup.py
docstring-parser==0.14.1
executing==1.2.0
executing==2.0.1
py-algorand-sdk>=2.0.0,<3.0.0
semantic-version>=2.9.0,<3.0.0
tabulate>=0.9.0,<0.10.0
4 changes: 3 additions & 1 deletion examples/application/sourcemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from feature_gates import FeatureGates

FeatureGates.set_sourcemap_enabled(True)
FeatureGates.set("sourcemap_enabled", True)

# INTENTIONALLY importing pyteal and objects _AFTER_ enabling the sourcemap feature
import pyteal as pt # noqa: E402
Expand Down Expand Up @@ -56,6 +56,8 @@ def is_even(i):
f.write(results.teal)

with open(annotated, "w") as f:
assert isinstance(results.sourcemap, pt.PyTealSourceMap)
assert isinstance(results.sourcemap.annotated_teal, str)
f.write(results.sourcemap.annotated_teal)

print(f"SUCCESS!!! Please check out {teal} and {annotated}")
4 changes: 3 additions & 1 deletion examples/signature/dutch_auction.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from feature_gates import FeatureGates

FeatureGates.set_sourcemap_enabled(True)
FeatureGates.set("sourcemap_enabled", True)


from pyteal import * # noqa: E402
Expand Down Expand Up @@ -157,4 +157,6 @@ def dutch_auction(
f.write(results.teal)

with open(EXAMPLES / "dutch_auction_annotated.teal", "w") as f:
assert isinstance(results.sourcemap, PyTealSourceMap)
assert isinstance(results.sourcemap.annotated_teal, str)
f.write(results.sourcemap.annotated_teal)
8 changes: 4 additions & 4 deletions pyteal/ast/abi/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ def test_type_spec_is_assignable_safe_bidirectional_full_coverage(ts: type):
def exists_in_safe_bidirectional(_ts: type):
for safe_bidirectional in SAFE_BIDIRECTIONAL_TEST_CASES:
for t in safe_bidirectional.xs:
if type(t) == _ts:
if type(t) is _ts:
return True
return False

Expand Down Expand Up @@ -943,10 +943,10 @@ def test_type_spec_is_assignable_safe_assignment(tc: SafeAssignment):
def test_type_spec_is_assignable_safe_assignment_full_coverage(ts: type):
def exists_in_safe_assignment(_ts: type):
for safe_assignment in SAFE_ASSIGNMENT_TEST_CASES:
if type(safe_assignment.a) == _ts:
if type(safe_assignment.a) is _ts:
return True
for t in safe_assignment.bs:
if type(t) == _ts:
if type(t) is _ts:
return True
return False

Expand Down Expand Up @@ -1049,7 +1049,7 @@ def test_type_spec_is_assignable_unsafe_bidirectional_full_coverage(ts: type):
def exists_in_unsafe_bidirectional(_ts: type):
for unsafe_bidirectional in UNSAFE_BIDIRECTIONAL_TEST_CASES:
for t in unsafe_bidirectional.xs:
if type(t) == _ts:
if type(t) is _ts:
return True
return False

Expand Down
4 changes: 2 additions & 2 deletions pyteal/ast/opup.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def ensure_budget(
should be sufficient for most use cases. If lack of budget is an issue then
consider moving the call to ensure_budget() earlier in the pyteal program."""
require_type(required_budget, TealType.uint64)
if not type(fee_source) == OpUpFeeSource:
if type(fee_source) is not OpUpFeeSource:
raise TealTypeError(type(fee_source), OpUpFeeSource)

# A budget buffer is necessary to deal with an edge case of ensure_budget():
Expand Down Expand Up @@ -179,7 +179,7 @@ def maximize_budget(
sufficient for most use cases. If lack of budget is an issue then consider
moving the call to maximize_budget() earlier in the pyteal program."""
require_type(fee, TealType.uint64)
if not type(fee_source) == OpUpFeeSource:
if type(fee_source) is not OpUpFeeSource:
raise TealTypeError(type(fee_source), OpUpFeeSource)

i = ScratchVar(TealType.uint64)
Expand Down
4 changes: 2 additions & 2 deletions pyteal/compiler/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def extractAddrValue(op: TealOp) -> Union[str, bytes]:
If the op is loading a template variable, returns the name of the variable as a string.
Otherwise, returns the bytes of the public key of the address that the op is loading.
"""
if len(op.args) != 1 or type(op.args[0]) != str:
if len(op.args) != 1 or type(op.args[0]) is not str:
raise TealInternalError("Unexpected args in addr opcode: {}".format(op.args))

value = cast(str, op.args[0])
Expand All @@ -96,7 +96,7 @@ def extractMethodSigValue(op: TealOp) -> bytes:
Returns:
The bytes of method selector computed from the method signature that the op is loading.
"""
if len(op.args) != 1 or type(op.args[0]) != str:
if len(op.args) != 1 or type(op.args[0]) is not str:
raise TealInternalError("Unexpected args in method opcode: {}".format(op.args))

methodSignature = cast(str, op.args[0])
Expand Down
8 changes: 4 additions & 4 deletions pyteal/compiler/optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def use_frame_pointers(self, version: int) -> bool:

def _remove_extraneous_slot_access(start: TealBlock, remove: Set[ScratchSlot]):
def keep_op(op: TealOp) -> bool:
if type(op) != TealOp or (op.op != Op.store and op.op != Op.load):
if type(op) is not TealOp or (op.op != Op.store and op.op != Op.load):
return True

return not set(op.getSlots()).issubset(remove)
Expand All @@ -84,7 +84,7 @@ def _has_load_dependencies(
if block == cur_block and i == pos:
continue

if type(op) == TealOp and op.op == Op.load and slot in set(op.getSlots()):
if type(op) is TealOp and op.op == Op.load and slot in set(op.getSlots()):
return True

return False
Expand All @@ -96,14 +96,14 @@ def _apply_slot_to_stack(
slots_to_remove = set()
# surprisingly, this slicing is totally safe - even if the list is empty.
for i, op in enumerate(cur_block.ops[:-1]):
if type(op) != TealOp or op.op != Op.store:
if type(op) is not TealOp or op.op != Op.store:
continue

if set(op.getSlots()).issubset(skip_slots):
continue

next_op = cur_block.ops[i + 1]
if type(next_op) != TealOp or next_op.op != Op.load:
if type(next_op) is not TealOp or next_op.op != Op.load:
continue

cur_slots, next_slots = op.getSlots(), next_op.getSlots()
Expand Down
6 changes: 3 additions & 3 deletions pyteal/compiler/sourcemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def __post_init__(self):

if entry >= entries[i + 1]:
raise TypeError(
f"Invalid source map as entries aren't properly ordered: entries[{i}] = {entry} >= entries[{i+1}] = {entries[i + 1]}"
f"Invalid source map as entries aren't properly ordered: entries[{i}] = {entry} >= entries[{i + 1}] = {entries[i + 1]}"
)

def __repr__(self) -> str:
Expand Down Expand Up @@ -1329,12 +1329,12 @@ def _validate_annotated(
):
if not annotated_line.startswith(teal_line):
raise cls._unexpected_error(
f"annotated teal ought to begin exactly with the teal line but line {i+1} [{annotated_line}] doesn't start with [{teal_line}]",
f"annotated teal ought to begin exactly with the teal line but line {i + 1} [{annotated_line}] doesn't start with [{teal_line}]",
)
pattern = r"^\s*($|//.*)"
if not re.match(pattern, annotated_line[len(teal_line) :]):
raise cls._unexpected_error(
f"annotated teal ought to begin exactly with the teal line followed by annotation in comments but line {i+1} [{annotated_line}] has non-commented out annotations"
f"annotated teal ought to begin exactly with the teal line followed by annotation in comments but line {i + 1} [{annotated_line}] has non-commented out annotations"
)

@classmethod
Expand Down
4 changes: 3 additions & 1 deletion pyteal/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ def __str__(self):


class SourceMapDisabledError(RuntimeError):
msg = value = """
msg = (
value
) = """
Cannot calculate Teal to PyTeal source map because stack frame discovery is turned off.

To enable source maps: import `from feature_gates import FeatureGates` and call `FeatureGates.set_sourcemap_enabled(True)`.
Expand Down
4 changes: 2 additions & 2 deletions pyteal/pragma/pragma.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
import pkg_resources
from importlib import metadata
from typing import Any
from semantic_version import Version, NpmSpec

Expand Down Expand Up @@ -116,7 +116,7 @@ def pragma(
# version constraint
pragma(compiler_version="^0.14.0")
"""
pkg_version = pkg_resources.require("pyteal")[0].version
pkg_version = metadata.version("pyteal")
pyteal_version = Version(__convert_pep440_compiler_version(pkg_version))
if pyteal_version not in NpmSpec(
__convert_pep440_compiler_version(compiler_version)
Expand Down
6 changes: 3 additions & 3 deletions pyteal/pragma/pragma_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
import pkg_resources
from importlib import metadata
from tests.mock_version import ( # noqa: F401
mock_version,
)
Expand Down Expand Up @@ -54,8 +54,8 @@ def test_convert_pep440_compiler_version(compiler_version, expected):
False,
), # Ignores local version (consistent with PEP 440)
(
pkg_resources.require("pyteal")[0].version,
pkg_resources.require("pyteal")[0].version,
metadata.version("pyteal"),
metadata.version("pyteal"),
False,
),
# invalid
Expand Down
2 changes: 1 addition & 1 deletion pyteal/stack_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import os
import re

from executing import Source # type: ignore
from executing import Source


class SourceMapStackFramesError(RuntimeError):
Expand Down
13 changes: 7 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
black==23.1.0
flake8==5.0.4
flake8-tidy-imports==4.6.0
black==23.12.0
flake8==6.1.0
flake8-tidy-imports==4.10.0
graviton@git+https://github.com/algorand/[email protected]
mypy==1.1.1
pytest==7.2.0
mypy==1.7.1
pytest==7.4.3
pytest-cov==3.0.0
pytest-custom-exit-code==0.3.0
pytest-timeout==2.1.0
pytest-xdist==3.0.2
types-setuptools==57.4.18
setuptools==69.0.2
types-setuptools==69.0.0.0
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
install_requires=[
# when changing this list, also update docs/requirements.txt
"docstring-parser==0.14.1",
"executing==1.2.0",
"executing==2.0.1",
"py-algorand-sdk>=2.0.0,<3.0.0",
"semantic-version>=2.9.0,<3.0.0",
"tabulate>=0.9.0,<0.10.0",
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/graviton_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ def blackbox_test_runner(
assert mode_has_property(exec_mode, dr_prop)

invariant = Invariant(predicate, name=f"{case_name}[{i}]@{mode}-{dr_prop}")
print(f"{i+1}. Assertion for {case_name}-{mode}: {dr_prop} <<{predicate}>>")
print(f"{i + 1}. Assertion for {case_name}-{mode}: {dr_prop} <<{predicate}>>")
invariant.validates(dr_prop, inspectors)

return inspectors
Expand Down
8 changes: 5 additions & 3 deletions tests/integration/pure_logicsig_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def payment_amount(x, y):
)

print(
f"generating a report for (a,p,q) = {a,p,q} with {M, N} dry-run calls and spreadsheet rows"
f"generating a report for (a,p,q) = {a, p, q} with {M, N} dry-run calls and spreadsheet rows"
)
filebase = f"factorizer_game_{a}_{p}_{q}"

Expand All @@ -105,15 +105,17 @@ def payment_amount(x, y):
with open(csvpath, "w") as f:
f.write(Inspector.csv_report(inputs, inspectors, txns=txns))

print(f"validating passing_invariant for (a,p,q) = {a,p,q} over {N} dry-run calls")
print(
f"validating passing_invariant for (a,p,q) = {a, p, q} over {N} dry-run calls"
)
passing_invariant = Invariant(
lambda args: bool(payment_amount(*args)),
name=f"passing invariant for coeffs {a, p, q}",
)
passing_invariant.validates(DRProp.passed, inspectors)

print(
f"validate procedurally that payment amount as expected for (a,p,q) = {a,p,q} over {M, N} dry-rundry-run calls"
f"validate procedurally that payment amount as expected for (a,p,q) = {a, p, q} over {M, N} dry-rundry-run calls"
)

for args, inspector in zip(inputs, inspectors):
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/sourcemap_monkey_integ_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ def first_diff(expected, actual):
elines = expected.splitlines()
for i, e in enumerate(elines):
if i >= len(alines):
return f"""LINE[{i+1}] missing from actual:
return f"""LINE[{i + 1}] missing from actual:
{e}"""
if e != (a := alines[i]):
return f"""LINE[{i+1}]
return f"""LINE[{i + 1}]
{e}
VS.
{a}
Expand Down
Loading