diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6057d1a..0873dd35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,9 +13,9 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: '3.10' + python-version: '3.12' - run: | - python -m pip install pylint + python -m pip install setuptools pylint python -m pip install -e . - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 with: @@ -28,7 +28,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: '3.10' + python-version: '3.12' - name: Build sdist run: | python -m pip install --user build @@ -44,7 +44,7 @@ jobs: runs-on: ${{ matrix.platform.os }} strategy: matrix: - py: [cp310, cp311, cp312, cp313, cp314] + py: [cp312, cp313, cp314] platform: - { arch: x86_64, os: windows-latest, wheel_tag: win_amd64 } - { arch: x86_64, os: macos-15-intel, wheel_tag: macosx_x86_64 } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d78e4303..496a7cc6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,7 +61,7 @@ repos: rev: v3.21.2 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py312-plus] # Last modifier: Coding Standard - repo: https://github.com/psf/black-pre-commit-mirror diff --git a/.readthedocs.yml b/.readthedocs.yml index 00c0eb4f..11398bbf 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,7 +5,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.10" + python: "3.12" python: install: diff --git a/pypcode/__init__.py b/pypcode/__init__.py index 4927ce15..45f0e1d6 100644 --- a/pypcode/__init__.py +++ b/pypcode/__init__.py @@ -6,7 +6,8 @@ import os.path import xml.etree.ElementTree as ET from enum import IntEnum -from typing import cast, Generator, Sequence, Mapping +from typing import cast +from collections.abc import Generator, Sequence, Mapping from .__version__ import __version__ diff --git a/pypcode/processors/RISCV/scripts/binutil.py b/pypcode/processors/RISCV/scripts/binutil.py index d54e0965..8c1ec235 100644 --- a/pypcode/processors/RISCV/scripts/binutil.py +++ b/pypcode/processors/RISCV/scripts/binutil.py @@ -22,8 +22,6 @@ Data was copied from various files in binutils, a lot of it unused. """ -import sys -import re MATCH_SLLI_RV32=0x1013 MASK_SLLI_RV32=0xfe00707f @@ -2779,7 +2777,7 @@ def find_gaps(op): pattern = 0x0 for x in op.bitpattern: x = x.split('=')[0] - if not x in gap.keys(): + if x not in gap.keys(): print("GAP: %r" % x) exit(1) x = gap[x] diff --git a/pyproject.toml b/pyproject.toml index c525b405..937f6b54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,12 +8,11 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] -requires-python = ">=3.10" +requires-python = ">=3.12" dynamic = [ "version" ] [project.urls] @@ -48,7 +47,7 @@ ext-modules = [ [tool.black] line-length = 120 -target-version = ['py38'] +target-version = ['py312'] [tool.ruff] line-length = 120 diff --git a/scripts/benchmark.py b/scripts/benchmark.py index 92c16f46..72898c0b 100755 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -17,7 +17,8 @@ import time from dataclasses import dataclass -from typing import cast, Any, Callable, Dict, Iterable, List, Tuple +from typing import cast, Any +from collections.abc import Callable, Iterable logging.basicConfig(level=logging.INFO) log = logging.getLogger(__name__) @@ -85,9 +86,9 @@ def get_file_hash(binary_path: str) -> str: return d -def get_blocks(binary_path: str) -> List[Block]: +def get_blocks(binary_path: str) -> list[Block]: blocks_file_path = f"blocks_{get_file_hash(binary_path)[0:8]}.cache" - blocks: List[Block] = [] + blocks: list[Block] = [] if not os.path.exists(blocks_file_path): log.info("Recovering blocks from CFG...") @@ -121,7 +122,7 @@ def get_blocks(binary_path: str) -> List[Block]: return blocks -def benchmark_pypcode(blocks: List[Block], iter_ops: bool = False, iter_varnodes: bool = False) -> BenchmarkResult: +def benchmark_pypcode(blocks: list[Block], iter_ops: bool = False, iter_varnodes: bool = False) -> BenchmarkResult: assert pypcode is not None start_time = time.time() @@ -144,7 +145,7 @@ def benchmark_pypcode(blocks: List[Block], iter_ops: bool = False, iter_varnodes return BenchmarkResult(startup_duration, translation_duration) -def benchmark_pypcode_disassembly(blocks: List[Block]) -> BenchmarkResult: +def benchmark_pypcode_disassembly(blocks: list[Block]) -> BenchmarkResult: assert pypcode is not None start_time = time.time() @@ -161,7 +162,7 @@ def benchmark_pypcode_disassembly(blocks: List[Block]) -> BenchmarkResult: return BenchmarkResult(startup_duration, translation_duration) -def benchmark_pyvex(blocks: List[Block], **vex_args) -> BenchmarkResult: +def benchmark_pyvex(blocks: list[Block], **vex_args) -> BenchmarkResult: assert pyvex is not None start_time = time.time() @@ -176,7 +177,7 @@ def benchmark_pyvex(blocks: List[Block], **vex_args) -> BenchmarkResult: return BenchmarkResult(startup_duration, translation_duration) -def benchmark_capstone(blocks: List[Block], lite: bool = False) -> BenchmarkResult: +def benchmark_capstone(blocks: list[Block], lite: bool = False) -> BenchmarkResult: assert capstone is not None start_time = time.time() @@ -199,9 +200,9 @@ def benchmark_capstone(blocks: List[Block], lite: bool = False) -> BenchmarkResu def gen_benchmarks_from_configurations( - name: str, benchmark_func: Callable, configurations: List[Dict[str, Any]] -) -> List[Tuple[str, Callable]]: - benchmarks: List[Tuple[str, Callable]] = [] + name: str, benchmark_func: Callable, configurations: list[dict[str, Any]] +) -> list[tuple[str, Callable]]: + benchmarks: list[tuple[str, Callable]] = [] for config in configurations: name_append = "" if config: @@ -239,7 +240,7 @@ def main() -> None: for name, version, import_duration in imports: log.info("%s v%s took %.2f ms to import", name, version, import_duration * 1000) - benchmarks: List[Tuple[str, Callable]] = [] + benchmarks: list[tuple[str, Callable]] = [] if HAVE_CAPSTONE and "capstone" not in args.skip: benchmarks.extend( gen_benchmarks_from_configurations( @@ -300,7 +301,7 @@ def main() -> None: log.info("Benchmark includes %d blocks totaling %.1f KiB", num_blocks, blocks_total_size / 1024) gc.collect() - results: List[Tuple[str, BenchmarkResult]] = [] + results: list[tuple[str, BenchmarkResult]] = [] gc.disable() for name, benchmark in benchmarks: log.info("Benchmarking %s performance...", name) diff --git a/tests/test_pypcode.py b/tests/test_pypcode.py index 105743d2..4f258a87 100755 --- a/tests/test_pypcode.py +++ b/tests/test_pypcode.py @@ -5,7 +5,7 @@ import logging from unittest import main, TestCase from unittest.mock import create_autospec -from typing import cast, List +from typing import cast from pypcode import ( AddrSpace, @@ -27,7 +27,7 @@ log = logging.getLogger(__name__) -def get_imarks(translation: Translation) -> List[PcodeOp]: +def get_imarks(translation: Translation) -> list[PcodeOp]: return [op for op in translation.ops if op.opcode == OpCode.IMARK]