typing-protocol-intersection 0.5.3__tar.gz → 0.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- typing_protocol_intersection-0.6.1/.github/workflows/ci.yml +29 -0
- typing_protocol_intersection-0.6.1/.gitignore +161 -0
- typing_protocol_intersection-0.6.1/CHANGELOG.md +114 -0
- typing_protocol_intersection-0.6.1/DEVELOPMENT.md +41 -0
- typing_protocol_intersection-0.6.1/Makefile +94 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/PKG-INFO +11 -10
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/README.md +2 -2
- typing_protocol_intersection-0.6.1/pyproject.toml +110 -0
- typing_protocol_intersection-0.6.1/tests/conftest.py +34 -0
- typing_protocol_intersection-0.6.1/tests/test-mypy.ini +20 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/tests/test_mypy_plugin.py +6 -12
- typing_protocol_intersection-0.6.1/tests/test_past_issues/test_4_mypy_cache/input.py +37 -0
- typing_protocol_intersection-0.6.1/tests/test_past_issues/test_4_mypy_cache/test_4_mypy_cache.py +18 -0
- typing_protocol_intersection-0.6.1/tests/test_past_issues/test_8_non_protocol_member/input.py +19 -0
- typing_protocol_intersection-0.6.1/tests/test_past_issues/test_8_non_protocol_member/test_8_non_protocol_member.py +18 -0
- typing_protocol_intersection-0.6.1/tests/testcases/fails_for_non_protocols.py +20 -0
- typing_protocol_intersection-0.6.1/tests/testcases/function_return_type_happy_path.py +33 -0
- typing_protocol_intersection-0.6.1/tests/testcases/function_return_type_unhappy_path.py +36 -0
- typing_protocol_intersection-0.6.1/tests/testcases/in_generic_param_happy_path.py +49 -0
- typing_protocol_intersection-0.6.1/tests/testcases/in_generic_param_happy_path_covariant.py +50 -0
- typing_protocol_intersection-0.6.1/tests/testcases/in_generic_param_unhappy_path.py +60 -0
- typing_protocol_intersection-0.6.1/tests/testcases/multiple_params_happy_path.py +53 -0
- typing_protocol_intersection-0.6.1/tests/testcases/multiple_params_unhappy_path.py +56 -0
- typing_protocol_intersection-0.6.1/tests/testcases/protocol_extending_another_builder_happy_path.py +53 -0
- typing_protocol_intersection-0.6.1/tests/testcases/protocol_extending_another_builder_unhappy_path.py +55 -0
- typing_protocol_intersection-0.6.1/tests/testcases/protocol_extending_another_method_happy_path.py +37 -0
- typing_protocol_intersection-0.6.1/tests/testcases/protocol_extending_another_property_happy_path.py +34 -0
- typing_protocol_intersection-0.6.1/tools/prepare-pr-after-mypy-bump.sh +128 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/typing_protocol_intersection/mypy_plugin.py +12 -21
- typing_protocol_intersection-0.6.1/typing_protocol_intersection/py.typed +0 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/typing_protocol_intersection/types.py +2 -2
- typing_protocol_intersection-0.6.1/uv.lock +960 -0
- typing_protocol_intersection-0.5.3/pyproject.toml +0 -94
- typing_protocol_intersection-0.5.3/setup.cfg +0 -36
- typing_protocol_intersection-0.5.3/typing_protocol_intersection.egg-info/PKG-INFO +0 -200
- typing_protocol_intersection-0.5.3/typing_protocol_intersection.egg-info/SOURCES.txt +0 -18
- typing_protocol_intersection-0.5.3/typing_protocol_intersection.egg-info/dependency_links.txt +0 -1
- typing_protocol_intersection-0.5.3/typing_protocol_intersection.egg-info/top_level.txt +0 -1
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/LICENSE +0 -0
- /typing_protocol_intersection-0.5.3/typing_protocol_intersection/py.typed → /typing_protocol_intersection-0.6.1/tests/test_past_issues/test_8_non_protocol_member/__init__.py +0 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/tests/test_python_module.py +0 -0
- {typing_protocol_intersection-0.5.3 → typing_protocol_intersection-0.6.1}/typing_protocol_intersection/__init__.py +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: tests & static analysis
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: ["master"]
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "0 7 * * *"
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
|
|
16
|
+
mypy-version: ["1.5.0", "latest"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v4
|
|
22
|
+
- name: Set Python version
|
|
23
|
+
run: uv python install ${{ matrix.python-version }}
|
|
24
|
+
- name: Run linting
|
|
25
|
+
run: make lint
|
|
26
|
+
# Run tests with the matrix combination of Python and mypy versions
|
|
27
|
+
# Conditionally adds MYPY parameter only when not using latest
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: make test-version PYTHON=${{ matrix.python-version }} ${{ matrix.mypy-version != 'latest' && format('MYPY={0}', matrix.mypy-version) || '' }}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
|
|
2
|
+
# Created by https://www.toptal.com/developers/gitignore/api/python
|
|
3
|
+
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
|
4
|
+
|
|
5
|
+
### Python ###
|
|
6
|
+
# Byte-compiled / optimized / DLL files
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*$py.class
|
|
10
|
+
|
|
11
|
+
# C extensions
|
|
12
|
+
*.so
|
|
13
|
+
|
|
14
|
+
# Distribution / packaging
|
|
15
|
+
.Python
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
downloads/
|
|
20
|
+
eggs/
|
|
21
|
+
.eggs/
|
|
22
|
+
lib/
|
|
23
|
+
lib64/
|
|
24
|
+
parts/
|
|
25
|
+
sdist/
|
|
26
|
+
var/
|
|
27
|
+
wheels/
|
|
28
|
+
share/python-wheels/
|
|
29
|
+
*.egg-info/
|
|
30
|
+
.installed.cfg
|
|
31
|
+
*.egg
|
|
32
|
+
MANIFEST
|
|
33
|
+
|
|
34
|
+
# PyInstaller
|
|
35
|
+
# Usually these files are written by a python script from a template
|
|
36
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
37
|
+
*.manifest
|
|
38
|
+
*.spec
|
|
39
|
+
|
|
40
|
+
# Installer logs
|
|
41
|
+
pip-log.txt
|
|
42
|
+
pip-delete-this-directory.txt
|
|
43
|
+
|
|
44
|
+
# Unit test / coverage reports
|
|
45
|
+
htmlcov/
|
|
46
|
+
.tox/
|
|
47
|
+
.nox/
|
|
48
|
+
.coverage
|
|
49
|
+
.coverage.*
|
|
50
|
+
.cache
|
|
51
|
+
nosetests.xml
|
|
52
|
+
coverage.xml
|
|
53
|
+
*.cover
|
|
54
|
+
*.py,cover
|
|
55
|
+
.hypothesis/
|
|
56
|
+
.pytest_cache/
|
|
57
|
+
cover/
|
|
58
|
+
|
|
59
|
+
# Translations
|
|
60
|
+
*.mo
|
|
61
|
+
*.pot
|
|
62
|
+
|
|
63
|
+
# Django stuff:
|
|
64
|
+
*.log
|
|
65
|
+
local_settings.py
|
|
66
|
+
db.sqlite3
|
|
67
|
+
db.sqlite3-journal
|
|
68
|
+
|
|
69
|
+
# Flask stuff:
|
|
70
|
+
instance/
|
|
71
|
+
.webassets-cache
|
|
72
|
+
|
|
73
|
+
# Scrapy stuff:
|
|
74
|
+
.scrapy
|
|
75
|
+
|
|
76
|
+
# Sphinx documentation
|
|
77
|
+
docs/_build/
|
|
78
|
+
|
|
79
|
+
# PyBuilder
|
|
80
|
+
.pybuilder/
|
|
81
|
+
target/
|
|
82
|
+
|
|
83
|
+
# Jupyter Notebook
|
|
84
|
+
.ipynb_checkpoints
|
|
85
|
+
|
|
86
|
+
# IPython
|
|
87
|
+
profile_default/
|
|
88
|
+
ipython_config.py
|
|
89
|
+
|
|
90
|
+
# pyenv
|
|
91
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
92
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
93
|
+
# .python-version
|
|
94
|
+
|
|
95
|
+
# pipenv
|
|
96
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
97
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
98
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
99
|
+
# install all needed dependencies.
|
|
100
|
+
#Pipfile.lock
|
|
101
|
+
|
|
102
|
+
# poetry
|
|
103
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
104
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
105
|
+
# commonly ignored for libraries.
|
|
106
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
107
|
+
#poetry.lock
|
|
108
|
+
|
|
109
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
110
|
+
__pypackages__/
|
|
111
|
+
|
|
112
|
+
# Celery stuff
|
|
113
|
+
celerybeat-schedule
|
|
114
|
+
celerybeat.pid
|
|
115
|
+
|
|
116
|
+
# SageMath parsed files
|
|
117
|
+
*.sage.py
|
|
118
|
+
|
|
119
|
+
# Environments
|
|
120
|
+
.env
|
|
121
|
+
.venv
|
|
122
|
+
env/
|
|
123
|
+
venv/
|
|
124
|
+
ENV/
|
|
125
|
+
env.bak/
|
|
126
|
+
venv.bak/
|
|
127
|
+
|
|
128
|
+
# Spyder project settings
|
|
129
|
+
.spyderproject
|
|
130
|
+
.spyproject
|
|
131
|
+
|
|
132
|
+
# Rope project settings
|
|
133
|
+
.ropeproject
|
|
134
|
+
|
|
135
|
+
# mkdocs documentation
|
|
136
|
+
/site
|
|
137
|
+
|
|
138
|
+
# mypy
|
|
139
|
+
.mypy_cache/
|
|
140
|
+
.dmypy.json
|
|
141
|
+
dmypy.json
|
|
142
|
+
|
|
143
|
+
# Pyre type checker
|
|
144
|
+
.pyre/
|
|
145
|
+
|
|
146
|
+
# pytype static type analyzer
|
|
147
|
+
.pytype/
|
|
148
|
+
|
|
149
|
+
# Cython debug symbols
|
|
150
|
+
cython_debug/
|
|
151
|
+
|
|
152
|
+
# PyCharm
|
|
153
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
154
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
155
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
156
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
157
|
+
#.idea/
|
|
158
|
+
|
|
159
|
+
# End of https://www.toptal.com/developers/gitignore/api/python
|
|
160
|
+
.idea
|
|
161
|
+
create-github-release.sh
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
Add support for mypy==1.19.x.
|
|
6
|
+
|
|
7
|
+
## 0.6.0
|
|
8
|
+
|
|
9
|
+
- Drop support for Python 3.9.
|
|
10
|
+
- Drop support for mypy<1.5.0.
|
|
11
|
+
- Add support for mypy==1.18.x.
|
|
12
|
+
- Add support for Python 3.14.
|
|
13
|
+
- Use uv and ruff for dev environment, CI and linting.
|
|
14
|
+
- Mark package with free-threaded-support.
|
|
15
|
+
|
|
16
|
+
## 0.5.3
|
|
17
|
+
|
|
18
|
+
Add support for mypy==1.15.x.
|
|
19
|
+
|
|
20
|
+
## 0.5.2
|
|
21
|
+
|
|
22
|
+
Add support for mypy==1.14.x.
|
|
23
|
+
|
|
24
|
+
## 0.5.1
|
|
25
|
+
|
|
26
|
+
Add support for mypy==1.13.x.
|
|
27
|
+
|
|
28
|
+
## 0.5.0
|
|
29
|
+
|
|
30
|
+
- Drop support for Python 3.8.
|
|
31
|
+
- Add Python 3.13 support.
|
|
32
|
+
- Add support for mypy==1.12.x.
|
|
33
|
+
|
|
34
|
+
## 0.4.2
|
|
35
|
+
|
|
36
|
+
Add support for mypy==1.11.x.
|
|
37
|
+
|
|
38
|
+
## 0.4.1
|
|
39
|
+
|
|
40
|
+
Add support for mypy==1.10.x.
|
|
41
|
+
|
|
42
|
+
## 0.4.0
|
|
43
|
+
|
|
44
|
+
- Drop support for Python 3.7.
|
|
45
|
+
- Add support for mypy==1.9.x.
|
|
46
|
+
|
|
47
|
+
## 0.3.10
|
|
48
|
+
|
|
49
|
+
Add support for mypy==1.8.x.
|
|
50
|
+
|
|
51
|
+
## 0.3.9
|
|
52
|
+
|
|
53
|
+
Add support for mypy==1.7.x.
|
|
54
|
+
|
|
55
|
+
## 0.3.8
|
|
56
|
+
|
|
57
|
+
- Add support for mypy==1.6.x.
|
|
58
|
+
- Add Python 3.12 support.
|
|
59
|
+
|
|
60
|
+
## 0.3.7
|
|
61
|
+
|
|
62
|
+
Fixed mypy crashing in incremental mode (#5). Contributed by @drvink.
|
|
63
|
+
|
|
64
|
+
## 0.3.6
|
|
65
|
+
|
|
66
|
+
Add support for mypy==1.5.x.
|
|
67
|
+
|
|
68
|
+
## 0.3.5
|
|
69
|
+
|
|
70
|
+
Add support for mypy==1.5.x.
|
|
71
|
+
|
|
72
|
+
## 0.3.4
|
|
73
|
+
|
|
74
|
+
Add support for mypy==1.4.x.
|
|
75
|
+
|
|
76
|
+
## 0.3.3
|
|
77
|
+
|
|
78
|
+
Add support for mypy==1.3.x.
|
|
79
|
+
|
|
80
|
+
## 0.3.2
|
|
81
|
+
|
|
82
|
+
Add support for mypy==1.2.x.
|
|
83
|
+
|
|
84
|
+
## 0.3.1
|
|
85
|
+
|
|
86
|
+
Add support for mypy==1.1.x.
|
|
87
|
+
|
|
88
|
+
## 0.3.0
|
|
89
|
+
|
|
90
|
+
Add support for mypy==1.0.0.
|
|
91
|
+
|
|
92
|
+
## 0.2.3
|
|
93
|
+
|
|
94
|
+
Explicitly specify supported mypy versions as 0.920 <= x <= 0.991 and fail loudly for others.
|
|
95
|
+
|
|
96
|
+
## 0.2.2
|
|
97
|
+
|
|
98
|
+
Add Python 3.11 support.
|
|
99
|
+
|
|
100
|
+
## 0.2.1
|
|
101
|
+
|
|
102
|
+
Fix support for protocols inheriting another protocols when used as type arguments.
|
|
103
|
+
|
|
104
|
+
## 0.2
|
|
105
|
+
|
|
106
|
+
Fix support for protocols inheriting another protocols.
|
|
107
|
+
|
|
108
|
+
## 0.1.1
|
|
109
|
+
|
|
110
|
+
Add `py.typed` to the build artifact.
|
|
111
|
+
|
|
112
|
+
## 0.1
|
|
113
|
+
|
|
114
|
+
Initial version. Consists of a mypy plugin and a `ProtocolIntersection` type.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Running tests
|
|
2
|
+
|
|
3
|
+
Install [uv](https://docs.astral.sh/uv/) and run tests using the Makefile:
|
|
4
|
+
```shell
|
|
5
|
+
make install # Install package and dependencies
|
|
6
|
+
make lint # Run all linters (mypy, ruff check, ruff format --check, pylint)
|
|
7
|
+
make test # Run tests with coverage
|
|
8
|
+
make format # Format code with ruff
|
|
9
|
+
make all # Run both lint and test
|
|
10
|
+
make test-all # Run tests across all Python versions with mypy 1.5.0 and latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
# Publishing a new release
|
|
14
|
+
|
|
15
|
+
1. Run tests as described above.
|
|
16
|
+
2. Update [`CHANGELOG.md`](./CHANGELOG.md).
|
|
17
|
+
3. Bump version in [`pyproject.toml`](./pyproject.toml).
|
|
18
|
+
4. Build and upload to pypi:
|
|
19
|
+
```shell
|
|
20
|
+
make build # Build the package
|
|
21
|
+
make check-build # Check for common issues
|
|
22
|
+
make upload # Upload to testpypi (default)
|
|
23
|
+
make upload REPO=pypi # Upload to production PyPI
|
|
24
|
+
```
|
|
25
|
+
5. Create a new release on [github](https://github.com/klausweiss/typing-protocol-intersection/releases).
|
|
26
|
+
|
|
27
|
+
# When a new mypy version is released
|
|
28
|
+
|
|
29
|
+
Mypy may introduce breaking changes in minor versions (see [this blogpost](https://mypy-lang.blogspot.com/2023/02/mypy-10-released.html)).
|
|
30
|
+
We don't want to risk false positives when stating the plugin works with mypy versions that haven't been tested and may have introduced breaking changes.
|
|
31
|
+
That's why for every minor mypy release, this plugin should be updated as well.
|
|
32
|
+
This can be a very repetitive process, so it has been automated.
|
|
33
|
+
|
|
34
|
+
When a new mypy version is released, run the following script:
|
|
35
|
+
```shell
|
|
36
|
+
./tools/prepare-pr-after-mypy-bump.sh NEW_MYPY_VERSIONS
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
It will make necessary changes to code and commit them.
|
|
40
|
+
Review the commit made by the plugin, run tests, and if it looks good, push.
|
|
41
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
.PHONY: help
|
|
2
|
+
help: ## Show this help message
|
|
3
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
4
|
+
|
|
5
|
+
.PHONY: install
|
|
6
|
+
install: ## Install package and dependencies
|
|
7
|
+
uv sync --all-extras --dev
|
|
8
|
+
|
|
9
|
+
.PHONY: build
|
|
10
|
+
build: ## Build the package (wheel and sdist)
|
|
11
|
+
uv build
|
|
12
|
+
|
|
13
|
+
.PHONY: upload
|
|
14
|
+
upload: ## Upload package to PyPI repository (REPO=testpypi or pypi, default: testpypi)
|
|
15
|
+
@if [ -z "$(REPO)" ]; then \
|
|
16
|
+
echo "Uploading to testpypi (default)..."; \
|
|
17
|
+
uv run twine upload dist/* -r testpypi; \
|
|
18
|
+
elif [ "$(REPO)" = "pypi" ]; then \
|
|
19
|
+
echo "Uploading to production PyPI..."; \
|
|
20
|
+
uv run twine upload dist/*; \
|
|
21
|
+
elif [ "$(REPO)" = "testpypi" ]; then \
|
|
22
|
+
echo "Uploading to testpypi..."; \
|
|
23
|
+
uv run twine upload dist/* -r testpypi; \
|
|
24
|
+
else \
|
|
25
|
+
echo "Error: Invalid REPO value. Use 'pypi' or 'testpypi'"; \
|
|
26
|
+
exit 1; \
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
.PHONY: check-build
|
|
30
|
+
check-build: ## Check the built package for common issues
|
|
31
|
+
uv run twine check dist/*
|
|
32
|
+
|
|
33
|
+
.PHONY: test
|
|
34
|
+
test: ## Run tests with coverage
|
|
35
|
+
uv run pytest -vv --cov=typing_protocol_intersection
|
|
36
|
+
|
|
37
|
+
.PHONY: test-version
|
|
38
|
+
test-version: ## Run tests with specific Python and mypy versions (PYTHON=3.10 [MYPY=1.5.0])
|
|
39
|
+
@if [ -z "$(PYTHON)" ]; then \
|
|
40
|
+
echo "Error: PYTHON version must be specified. Usage: make test-version PYTHON=3.10 [MYPY=1.5.0]"; \
|
|
41
|
+
exit 1; \
|
|
42
|
+
fi
|
|
43
|
+
@if [ -n "$(MYPY)" ]; then \
|
|
44
|
+
echo "Running tests on Python $(PYTHON) with mypy==$(MYPY)..."; \
|
|
45
|
+
uv run --python $(PYTHON) --with mypy==$(MYPY) pytest -vv --cov=typing_protocol_intersection; \
|
|
46
|
+
else \
|
|
47
|
+
echo "Running tests on Python $(PYTHON) with latest mypy..."; \
|
|
48
|
+
uv run --python $(PYTHON) pytest -vv --cov=typing_protocol_intersection; \
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
.PHONY: test-all
|
|
52
|
+
test-all: ## Run tests across all supported Python versions with mypy 1.5.0 and latest
|
|
53
|
+
@$(MAKE) test-version PYTHON=3.10 MYPY=1.5.0
|
|
54
|
+
@$(MAKE) test-version PYTHON=3.10
|
|
55
|
+
@$(MAKE) test-version PYTHON=3.11 MYPY=1.5.0
|
|
56
|
+
@$(MAKE) test-version PYTHON=3.11
|
|
57
|
+
@$(MAKE) test-version PYTHON=3.12 MYPY=1.5.0
|
|
58
|
+
@$(MAKE) test-version PYTHON=3.12
|
|
59
|
+
@$(MAKE) test-version PYTHON=3.13 MYPY=1.5.0
|
|
60
|
+
@$(MAKE) test-version PYTHON=3.13
|
|
61
|
+
@$(MAKE) test-version PYTHON=3.14 MYPY=1.5.0
|
|
62
|
+
@$(MAKE) test-version PYTHON=3.14
|
|
63
|
+
@$(MAKE) test-version PYTHON=3.14t MYPY=1.5.0
|
|
64
|
+
@$(MAKE) test-version PYTHON=3.14t
|
|
65
|
+
|
|
66
|
+
.PHONY: lint
|
|
67
|
+
lint: ## Run all linters (mypy, ruff check, ruff format --check, pylint)
|
|
68
|
+
uv run mypy typing_protocol_intersection
|
|
69
|
+
uv run ruff check .
|
|
70
|
+
uv run ruff format --check .
|
|
71
|
+
uv run pylint typing_protocol_intersection tests
|
|
72
|
+
|
|
73
|
+
.PHONY: format
|
|
74
|
+
format: ## Format code with ruff
|
|
75
|
+
uv run ruff format .
|
|
76
|
+
|
|
77
|
+
.PHONY: all
|
|
78
|
+
all: lint test ## Run lint and test
|
|
79
|
+
|
|
80
|
+
.PHONY: clean
|
|
81
|
+
clean: ## Remove build artifacts, cache files, and compiled Python files
|
|
82
|
+
rm -rf build dist *.egg-info
|
|
83
|
+
rm -rf .pytest_cache .mypy_cache .ruff_cache
|
|
84
|
+
find . -type d -name __pycache__ -exec rm -rf {} +
|
|
85
|
+
find . -type f -name '*.pyc' -delete
|
|
86
|
+
find . -type f -name '*.pyo' -delete
|
|
87
|
+
|
|
88
|
+
.PHONY: bump-mypy
|
|
89
|
+
bump-mypy: ## Prepare PR for new mypy version (fetches latest or use VERSION=x.y.z)
|
|
90
|
+
@if [ -n "$(VERSION)" ]; then \
|
|
91
|
+
./tools/prepare-pr-after-mypy-bump.sh $(VERSION); \
|
|
92
|
+
else \
|
|
93
|
+
./tools/prepare-pr-after-mypy-bump.sh; \
|
|
94
|
+
fi
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: typing-protocol-intersection
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Protocol intersection for mypy
|
|
5
|
-
|
|
5
|
+
Project-URL: Homepage, https://github.com/klausweiss/typing-protocol-intersection
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/klausweiss/typing-protocol-intersection/issues
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
7
11
|
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
9
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
17
|
Classifier: Typing :: Typed
|
|
14
|
-
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Requires-Python: >=3.9
|
|
18
|
+
Requires-Python: >=3.10
|
|
17
19
|
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
20
|
|
|
20
21
|
# typing-protocol-intersection
|
|
21
22
|
|
|
@@ -31,14 +32,14 @@ See the [examples](#examples) section below.
|
|
|
31
32
|
|
|
32
33
|
## Supported versions
|
|
33
34
|
|
|
34
|
-
The plugin supports python 3.
|
|
35
|
+
The plugin supports python 3.10 up to 3.14 and mypy >= 1.5.0 and <= 1.19.x.
|
|
35
36
|
|
|
36
37
|
## Installation
|
|
37
38
|
|
|
38
39
|
The `typing-protocol-intersection` package is pip-installable:
|
|
39
40
|
|
|
40
41
|
```shell
|
|
41
|
-
pip install typing-protocol-intersection
|
|
42
|
+
pip install typing-protocol-intersection
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
## Configuration
|
|
@@ -12,14 +12,14 @@ See the [examples](#examples) section below.
|
|
|
12
12
|
|
|
13
13
|
## Supported versions
|
|
14
14
|
|
|
15
|
-
The plugin supports python 3.
|
|
15
|
+
The plugin supports python 3.10 up to 3.14 and mypy >= 1.5.0 and <= 1.19.x.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
19
|
The `typing-protocol-intersection` package is pip-installable:
|
|
20
20
|
|
|
21
21
|
```shell
|
|
22
|
-
pip install typing-protocol-intersection
|
|
22
|
+
pip install typing-protocol-intersection
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Configuration
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "typing-protocol-intersection"
|
|
7
|
+
version = "0.6.1"
|
|
8
|
+
description = "Protocol intersection for mypy"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
]
|
|
25
|
+
free-threaded-support = true
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/klausweiss/typing-protocol-intersection"
|
|
29
|
+
"Bug Tracker" = "https://github.com/klausweiss/typing-protocol-intersection/issues"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"mypy",
|
|
34
|
+
"pylint",
|
|
35
|
+
"pytest",
|
|
36
|
+
"pytest-cov",
|
|
37
|
+
"ruff",
|
|
38
|
+
"twine",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["."]
|
|
43
|
+
include = ["**/*.py", "**/*.pyi", "**/py.typed"]
|
|
44
|
+
|
|
45
|
+
[tool.ruff]
|
|
46
|
+
line-length = 120
|
|
47
|
+
target-version = "py310"
|
|
48
|
+
|
|
49
|
+
[tool.ruff.lint]
|
|
50
|
+
select = [
|
|
51
|
+
"E", # pycodestyle errors
|
|
52
|
+
"W", # pycodestyle warnings
|
|
53
|
+
"F", # pyflakes
|
|
54
|
+
"I", # isort
|
|
55
|
+
"N", # pep8-naming
|
|
56
|
+
"UP", # pyupgrade
|
|
57
|
+
"B", # flake8-bugbear
|
|
58
|
+
"S", # flake8-bandit
|
|
59
|
+
"C4", # flake8-comprehensions
|
|
60
|
+
"DTZ", # flake8-datetimez
|
|
61
|
+
"PIE", # flake8-pie
|
|
62
|
+
"Q", # flake8-quotes
|
|
63
|
+
"RET", # flake8-return
|
|
64
|
+
"SIM", # flake8-simplify
|
|
65
|
+
]
|
|
66
|
+
ignore = [
|
|
67
|
+
"S101", # allow assert statements
|
|
68
|
+
"E501", # some tests have too-long lines
|
|
69
|
+
"D", # pydocstyle - no docstrings required
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.format]
|
|
73
|
+
quote-style = "double"
|
|
74
|
+
indent-style = "space"
|
|
75
|
+
|
|
76
|
+
[tool.mypy]
|
|
77
|
+
check_untyped_defs = true
|
|
78
|
+
disallow_any_generics = true
|
|
79
|
+
disallow_any_unimported = true
|
|
80
|
+
disallow_incomplete_defs = true
|
|
81
|
+
disallow_subclassing_any = true
|
|
82
|
+
disallow_untyped_calls = true
|
|
83
|
+
disallow_untyped_decorators = true
|
|
84
|
+
disallow_untyped_defs = true
|
|
85
|
+
implicit_reexport = false
|
|
86
|
+
no_implicit_optional = true
|
|
87
|
+
show_column_numbers = true
|
|
88
|
+
show_error_codes = true
|
|
89
|
+
strict_equality = true
|
|
90
|
+
strict_optional = true
|
|
91
|
+
warn_no_return = true
|
|
92
|
+
warn_redundant_casts = true
|
|
93
|
+
warn_return_any = true
|
|
94
|
+
warn_unused_configs = true
|
|
95
|
+
|
|
96
|
+
[tool.pylint.MASTER]
|
|
97
|
+
extension-pkg-allow-list = "mypy"
|
|
98
|
+
|
|
99
|
+
[tool.pylint."MESSAGES CONTROL"]
|
|
100
|
+
disable = """
|
|
101
|
+
duplicate-code,
|
|
102
|
+
line-too-long,
|
|
103
|
+
missing-class-docstring,
|
|
104
|
+
missing-function-docstring,
|
|
105
|
+
missing-module-docstring,
|
|
106
|
+
no-name-in-module,
|
|
107
|
+
redefined-outer-name,
|
|
108
|
+
too-few-public-methods,
|
|
109
|
+
typevar-name-incorrect-variance,
|
|
110
|
+
"""
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import mypy.api
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
HERE = Path(__file__).parent
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def run_mypy(strip_invisible: typing.Callable[[str], str]):
|
|
12
|
+
def _run_mypy(input_file: Path, no_incremental: bool = True) -> tuple[str, str]:
|
|
13
|
+
args = [str(input_file), "--config-file", str(HERE / "test-mypy.ini")]
|
|
14
|
+
if no_incremental:
|
|
15
|
+
args.append("--no-incremental")
|
|
16
|
+
stdout, stderr, _ = mypy.api.run(args)
|
|
17
|
+
return strip_invisible(stdout), strip_invisible(stderr)
|
|
18
|
+
|
|
19
|
+
return _run_mypy
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def strip_invisible() -> typing.Callable[[str], str]:
|
|
24
|
+
def _strip_invisible(string: str) -> str:
|
|
25
|
+
"""Removes all zero-width spaces from the input text and strips
|
|
26
|
+
whitespaces.
|
|
27
|
+
|
|
28
|
+
The need for the former was born with an ugly hack that we use
|
|
29
|
+
to trick mypyc.
|
|
30
|
+
"""
|
|
31
|
+
zero_width_space = "\u200b"
|
|
32
|
+
return string.strip().replace(zero_width_space, "")
|
|
33
|
+
|
|
34
|
+
return _strip_invisible
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[mypy]
|
|
2
|
+
plugins = ../typing_protocol_intersection/mypy_plugin.py
|
|
3
|
+
check_untyped_defs = True
|
|
4
|
+
disallow_any_generics = True
|
|
5
|
+
disallow_any_unimported = True
|
|
6
|
+
disallow_incomplete_defs = True
|
|
7
|
+
disallow_subclassing_any = True
|
|
8
|
+
disallow_untyped_calls = True
|
|
9
|
+
disallow_untyped_decorators = True
|
|
10
|
+
disallow_untyped_defs = True
|
|
11
|
+
implicit_reexport = False
|
|
12
|
+
no_implicit_optional = True
|
|
13
|
+
show_column_numbers = True
|
|
14
|
+
show_error_codes = True
|
|
15
|
+
strict_equality = True
|
|
16
|
+
strict_optional = True
|
|
17
|
+
warn_no_return = True
|
|
18
|
+
warn_redundant_casts = True
|
|
19
|
+
warn_return_any = True
|
|
20
|
+
warn_unused_configs = True
|