Skip to content
Open
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
87 changes: 27 additions & 60 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: CI

on:
on:
push:
pull_request:
workflow_dispatch:
Expand All @@ -12,84 +12,51 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest', 'windows-latest']
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
python-version: [ '3.10', '3.11', '3.12', '3.13' ]

runs-on: ${{ matrix.os }}
name: OS ${{ matrix.os }}, Python ${{ matrix.python-version }}

steps:
# Checks out a copy of your repository on the machine
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

# Setup python
- name: Setup python
uses: actions/setup-python@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}
architecture: x64

# Setup node.js (for pyright)
- name: Setup node.js (for pyright)
uses: actions/setup-node@v3
with:
node-version: 16

# Install pyright
- name: Install pyright
run: |
npm install -g pyright
pyright --version

# Install this package
- name: Install this package
run: |
python -m pip install .
- name: Install dependencies
run: uv sync

# Install dependencies
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
- name: Run type checks
run: uv run poe typecheck

# Run pytests
- name: Run pytests
run: |
pytest tests/ --showlocals --verbose

# Run mypy
- name: Run mypy
run: |
mypy tests construct_typed

# Run pyright
- name: Run pyright
run: |
pyright
run: pytest tests/ --showlocals --verbose

create_wheel_and_sdist:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.13'
architecture: x64
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: '3.13'
architecture: x64

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install wheel build
- name: Install dependencies
run: uv sync

- name: Build wheel and sdist
run: |
python -m build
- name: Build wheel and sdist
run: uv build

- name: Upload wheel and sdist as artifact
uses: actions/upload-artifact@v4
with:
name: Package-Distributions-construct-typing
path: dist/
- name: Upload wheel and sdist as artifact
uses: actions/upload-artifact@v4
with:
name: Package-Distributions-construct-typing
path: dist/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ dmypy.json
example_737
example_888
example_ksy.ksy

# Intellij, pyCharm, etc.
.idea/
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## [0.8.0] - 2026-06-12
- bumped minimum required Python version to 3.10 (previousl: 3.9 which has reached end-of-life)
- removed `version.py`, use `importlib.metadata` instead to get the version number
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This project is an extension of the python package [*construct*](https://pypi.or
- **construct_typed**: Adding additional classes that help with autocompletion and additional type hints.

## Installation
This package comply to [PEP 561](https://www.python.org/dev/peps/pep-0561/). So most of the static code analysers will recognise the stubs automatically. The installation only requires:
This package complies to [PEP 561](https://www.python.org/dev/peps/pep-0561/). So most of the static code analysers will recognise the stubs automatically. The installation only requires:
```
pip install construct-typing
```
Expand All @@ -21,9 +21,18 @@ The stubs are tested against the pytests of the *construct* package in a slightl
The new typed constructs have new written pytests, which also passes all pytests and the static type checkers.

The following static type checkers are fully supported:
- mypy
- ruff
- ty
- pyright

## Running Type Checks Locally

Type checks are run via [poethepoet](https://github.com/nat-n/poethepoet) and include [ruff](https://docs.astral.sh/ruff/), [ty](https://github.com/astral-sh/ty), and [pyright](https://github.com/microsoft/pyright):

```bash
uv run poe typecheck
```

## Explanation
### Stubs
The **construct-stubs** package is used for creating type hints for the orignial *construct* package. In particular the `build` and `parse` methods get type hints. So the core of the stubs are the `TypeVar`'s `ParsedType` and `BuildTypes`:
Expand Down Expand Up @@ -108,5 +117,3 @@ Image:
12
13
```


1 change: 0 additions & 1 deletion construct_typed/dataclass_struct.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# pyright: strict
import dataclasses
import textwrap
import typing as t
Expand Down
2 changes: 0 additions & 2 deletions construct_typed/version.py

This file was deleted.

124 changes: 106 additions & 18 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@

[build-system]
requires = ["setuptools >= 75.8.0"]
requires = ["setuptools>=82.0.1", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name="construct-typing"
dynamic = ["version"]
license = { file = "LICENSE" }
name = "construct-typing"
version = "0.8.0"
license = "MIT"
description="Extension for the python package 'construct' that adds typing features"
readme = "README.md"
authors=[{ name = "Tim Riddermann" }]
requires-python = ">=3.9"
dependencies = [
"construct==2.10.70",
"typing_extensions>=4.6.0"
]
authors = [{ name = "Tim Riddermann" }]
requires-python = ">=3.10"
keywords = [
"construct",
"kaitai",
Expand Down Expand Up @@ -42,20 +37,39 @@ keywords = [
]
classifiers = [
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: MIT License",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Code Generators",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Typing :: Typed",
]
dependencies = [
"arrow>=1.0.0",
"construct==2.10.70",
"typing_extensions>=4.6.0"
]

[dependency-groups]
dev = [
"poethepoet>=0.47.0",
"pyright>=1.1.411",
"pytest>=9.1.1",
"pytest-cov>=7.1.0",
"ruff>=0.15.20",
"ty>=0.0.55",
"setuptools>=82.0.1",
"cloudpickle", # optional "extra" from construct that the user may or may not have installed
"cryptography", # optional "extra" from construct that the user may or may not have installed
"lz4", # optional "extra" from construct that the user may or may not have installed
"numpy", # optional "extra" from construct that the user may or may not have installed
"ruamel.yaml", # optional "extra" from construct that the user may or may not have installed
]

[project.urls]
"Homepage" = "https://github.com/timrid/construct-typing"
Expand All @@ -68,9 +82,83 @@ packages=[
"construct_typed"
]

[tool.setuptools.dynamic]
version = {attr = "construct_typed.version.version_string"}
[tool.pyright]
typeCheckingMode = "strict"
exclude = [
"**/node_modules",
"**/__pycache__",
"**/.*",
".history",
".venv",
".venv*",
"build",
"dist",
"libs",
]

[tool.mypy]
strict = true
warn_unused_ignores = false
# These warnings should be activated as "error" in the future, but for now we don't want to refactor the entire codebase right now.
# Valid values: "error", "warning", "information", "none"
reportInvalidTypeForm = "none"
reportMissingParameterType = "none"
reportUnknownArgumentType = "none"
reportUnknownMemberType = "none"
reportUnknownParameterType = "none"
reportUnknownVariableType = "none"
# These "unnecessary isinstance" checks often enhance readability or increase the future-proofness of the code,
# since you can then explicitly "raise" for other types. So we don't want to complain about them.
reportUnnecessaryIsInstance = "none"

[tool.ty.src]
exclude = [
"**/node_modules",
"**/__pycache__",
"**/.*",
".history",
".venv",
".venv*",
"build",
"dist",
"libs",
]

# These warnings should be activated as "error" in the future, but for now we don't want to refactor the entire codebase right now.
# Valid values: "error", "warn", "ignore"
[tool.ty.rules]
invalid-argument-type = "ignore"
invalid-assignment = "ignore"
invalid-generic-class = "ignore"
invalid-legacy-type-variable = "ignore"
invalid-type-arguments = "ignore"
unused-type-ignore-comment = "ignore"

[tool.ty.terminal]
error-on-warning = true
output-format = "concise" # "full" | "concise" | "github" | "gitlab" | "junit"

[tool.ruff]
line-length = 140
indent-width = 4
output-format = "concise" # "full" | "concise" | "grouped" | "json" | "junit" | "github" | "gitlab" | "pylint" | "azure"

[tool.ruff.lint]
allowed-confusables = ["×", "–", "‘", "’"]

# select = [] Use Default ruleset, cp. https://docs.astral.sh/ruff/rules/

# These warnings should be activated as "error" in the future, but for now we don't want to refactor the entire codebase right now.
ignore = [
"E711", # Comparison to `None` should be `cond is None`
"E712", # Avoid equality comparisons to `True`
"E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks
"E741", # Ambiguous variable name: `...`
"F403", # `from ... import *` used; unable to detect undefined names
"F405", # `...` may be undefined, or defined from star imports
]

[tool.poe.tasks.typecheck]
sequence = [
{ cmd = "ruff check --fix --show-fixes" },
{ cmd = "ty check" },
{ cmd = "pyright" },
]
executor = {type = "uv", isolated = true}
14 changes: 0 additions & 14 deletions requirements.txt

This file was deleted.

3 changes: 2 additions & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,8 @@ def test_numpy() -> None:

@pytest.mark.xfail(reason="docs stated that it throws StreamError, not true at all")
def test_numpy_error() -> None:
import numpy, io
import numpy
import io
numpy.load(io.BytesIO(b"")) # type: ignore

def test_namedtuple() -> None:
Expand Down
1 change: 0 additions & 1 deletion tests/test_typed.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# pyright: strict
import dataclasses
import enum
import textwrap
Expand Down
Loading