diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000000..13eb5742dbf0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# We vendor typeshed from https://github.com/python/typeshed +mypy/typeshed/ linguist-vendored diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index ee2777a75fe6..1b3a16eebd2c 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -7,6 +7,12 @@ labels: "bug" **Bug Report** diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml new file mode 100644 index 000000000000..1d56057854c3 --- /dev/null +++ b/.github/workflows/build_wheels.yml @@ -0,0 +1,20 @@ +name: Trigger wheel build + +on: + push: + branches: [master, 'release*'] + tags: ['*'] + +jobs: + build-wheels: + if: github.repository == 'python/mypy' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.7' + - name: Trigger script + env: + WHEELS_PUSH_TOKEN: ${{ secrets.WHEELS_PUSH_TOKEN }} + run: ./misc/trigger_wheel_build.sh diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000000..d44f9143bdc7 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,30 @@ +name: Check documentation build + +on: + push: + branches: [master, 'release*'] + tags: ['*'] + pull_request: + paths: + - 'docs/**' + - '**/*.rst' + - '**/*.md' + - CREDITS + - LICENSE + +jobs: + docs: + runs-on: ubuntu-latest + env: + TOXENV: docs + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.7' + - name: Install tox + run: pip install --upgrade 'setuptools!=50' 'virtualenv<16.7.11' tox==3.20.1 + - name: Setup tox environment + run: tox -e ${{ env.TOXENV }} --notest + - name: Test + run: tox -e ${{ env.TOXENV }} --skip-pkg-install diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index b2166e12330d..fcd8b938f295 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -11,7 +11,7 @@ on: jobs: mypy_primer: - name: Run + name: Run mypy_primer runs-on: ubuntu-latest permissions: contents: read @@ -37,16 +37,19 @@ jobs: cd mypy_to_test echo "new commit" git rev-list --format=%s --max-count=1 $GITHUB_SHA - git checkout -b upstream_master origin/master + + MERGE_BASE=$(git merge-base $GITHUB_SHA origin/master) + git checkout -b base_commit $MERGE_BASE echo "base commit" - git rev-list --format=%s --max-count=1 upstream_master + git rev-list --format=%s --max-count=1 base_commit + echo '' cd .. # fail action if exit code isn't zero or one ( mypy_primer \ --repo mypy_to_test \ - --new $GITHUB_SHA --old upstream_master \ + --new $GITHUB_SHA --old base_commit \ --num-shards 3 --shard-index ${{ matrix.shard-index }} \ --debug \ --output concise \ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e176182b14ab..3081c15594cb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,8 @@ -name: main +name: Tests on: push: - branches: [master] + branches: [master, 'release*'] tags: ['*'] pull_request: paths-ignore: @@ -10,38 +10,127 @@ on: - '**/*.rst' - '**/*.md' - .gitignore - - .travis.yml - CREDITS - LICENSE jobs: - build: + main: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - name: [windows-py37-32, windows-py37-64] include: - - name: windows-py37-32 + - name: Test suite with py37-windows-32 python: '3.7' arch: x86 os: windows-latest toxenv: py37 - - name: windows-py37-64 + - name: Test suite with py37-windows-64 python: '3.7' arch: x64 os: windows-latest toxenv: py37 + - name: Test suite with py37-ubuntu + python: '3.7' + arch: x64 + os: ubuntu-latest + toxenv: py + tox_extra_args: "-n 2" + - name: Test suite with py38-ubuntu + python: '3.8' + arch: x64 + os: ubuntu-latest + toxenv: py + tox_extra_args: "-n 2" + - name: Test suite with py36-ubuntu, mypyc-compiled + python: '3.6' + arch: x64 + os: ubuntu-latest + toxenv: py + tox_extra_args: "-n 2" + test_mypyc: true + - name: Test suite with py39-ubuntu, mypyc-compiled + python: '3.9' + arch: x64 + os: ubuntu-latest + toxenv: py + tox_extra_args: "-n 2" + test_mypyc: true + - name: Test suite with py310-ubuntu + python: '3.10' + arch: x64 + os: ubuntu-latest + toxenv: py + tox_extra_args: "-n 2" + - name: mypyc runtime tests with py36-macos + python: '3.6' + arch: x64 + os: macos-latest + toxenv: py + tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py" + - name: mypyc runtime tests with py36-debug-build-ubuntu + python: '3.6.8' + arch: x64 + os: ubuntu-latest + toxenv: py36 + tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py" + debug_build: true + - name: Type check our own code + python: '3.7' + arch: x64 + os: ubuntu-latest + toxenv: type + - name: Code style with flake8 + python: '3.7' + arch: x64 + os: ubuntu-latest + toxenv: lint + name: ${{ matrix.name }} steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: python-version: ${{ matrix.python }} architecture: ${{ matrix.arch }} - - name: install tox - run: pip install --upgrade 'setuptools!=50' 'virtualenv<20' tox==3.20.1 - - name: setup tox environment + - name: Debug build + if: ${{ matrix.debug_build }} + run: | + PYTHONVERSION=${{ matrix.python }} + PYTHONDIR=~/python-debug/python-$PYTHONVERSION + VENV=$PYTHONDIR/env + ./misc/build-debug-python.sh $PYTHONVERSION $PYTHONDIR $VENV + source $VENV/bin/activate + - name: Install tox + run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.20.1 + - name: Compiled with mypyc + if: ${{ matrix.test_mypyc }} + run: | + pip install -r test-requirements.txt + CC=clang MYPYC_OPT_LEVEL=0 python3 setup.py --use-mypyc build_ext --inplace + - name: Setup tox environment run: tox -e ${{ matrix.toxenv }} --notest - - name: test - run: tox -e ${{ matrix.toxenv }} --skip-pkg-install + - name: Test + run: tox -e ${{ matrix.toxenv }} --skip-pkg-install -- ${{ matrix.tox_extra_args }} + +# TODO: uncomment this when 3.11-dev is available +# python-nightly: +# runs-on: ubuntu-latest +# name: Test suite with Python nightly +# steps: +# - uses: actions/checkout@v2 +# - uses: actions/setup-python@v2 +# with: +# python-version: '3.11-dev' +# - name: Install tox +# run: | +# pip install -U pip==21.2.3 setuptools +# pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 +# - name: Setup tox environment +# run: tox -e py --notest +# - name: Test +# run: tox -e py --skip-pkg-install -- "-n 2" +# continue-on-error: true +# - name: Mark as a success +# run: exit 0 + diff --git a/.github/workflows/test_stubgenc.yml b/.github/workflows/test_stubgenc.yml index 5aa0c7cdf200..6408f21ccffe 100644 --- a/.github/workflows/test_stubgenc.yml +++ b/.github/workflows/test_stubgenc.yml @@ -2,7 +2,7 @@ name: Test stubgenc on pybind11-mypy-demo on: push: - branches: [master] + branches: [master, 'release*'] tags: ['*'] pull_request: paths: diff --git a/.gitignore b/.gitignore index c6238dc32beb..3c0f60cfae4f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ docs/source/_build mypyc/doc/_build *.iml /out/ -.venv*/ +.venv venv/ .mypy_cache/ .incremental_checker_cache.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index da5bc67cf6ba..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,121 +0,0 @@ -# in the python/mypy repo, we only CI the master, release branches, tags and PRs -if: tag IS present OR type = pull_request OR ((branch = master OR branch =~ release-*) AND type = push) OR repo != python/mypy - -language: python -# cache package wheels (1 cache per python version) -cache: pip -# also cache the directories where we set up our custom pythons in some builds -cache: - directories: - - $HOME/python-debug - # I ran into some issues with this but will investigate again later. - # - $HOME/.pyenv/versions - - $HOME/Library/Caches/pip - -# newer python versions are available only on xenial (while some older only on trusty) Ubuntu distribution -dist: xenial - -env: - TOXENV=py - EXTRA_ARGS="-n 2" - TEST_MYPYC=0 - PYTHON_DEBUG_BUILD=0 - -jobs: - fast_finish: true - include: - - name: "run test suite with python 3.6 (compiled with mypyc)" - python: 3.6 # 3.6.3 pip 9.0.1 - env: - - TOXENV=py - - EXTRA_ARGS="-n 2" - - TEST_MYPYC=1 - - name: "run test suite with python 3.7" - python: 3.7 - - name: "run test suite with python 3.8" - python: 3.8 - - name: "run test suite with python 3.9 (compiled with mypyc)" - python: 3.9 - env: - - TOXENV=py - - EXTRA_ARGS="-n 2" - - TEST_MYPYC=1 - - name: "run test suite with python nightly" - python: nightly - - name: "run mypyc runtime tests with python 3.6 debug build" - language: generic - env: - - TOXENV=py36 - - PYTHONVERSION=3.6.8 - - PYTHON_DEBUG_BUILD=1 - - EXTRA_ARGS="-n 2 mypyc/test/test_run.py mypyc/test/test_external.py" - - name: "run mypyc runtime tests with python 3.6 on OS X" - os: osx - osx_image: xcode8.3 - language: generic - env: - - PYTHONVERSION=3.6.3 - - EXTRA_ARGS="-n 2 mypyc/test/test_run.py mypyc/test/test_external.py" - - name: "type check our own code" - python: 3.7 - env: - - TOXENV=type - - EXTRA_ARGS= - - name: "check code style with flake8" - python: 3.7 - env: - - TOXENV=lint - - EXTRA_ARGS= - - name: "trigger a build of wheels" - python: 3.7 - script: if [[ ($TRAVIS_BRANCH = "master" || $TRAVIS_BRANCH =~ release-*) && $TRAVIS_PULL_REQUEST = "false" ]]; then ./misc/trigger_wheel_build.sh; fi - - name: "check documentation build" - python: 3.7 - env: - - TOXENV=docs - # Disabled because of some pip bug? See #6716 - # - name: "check dev environment builds" - # python: 3.7 - # env: - # - TOXENV=dev - # - EXTRA_ARGS= - allow_failures: - - python: nightly - -install: -# pip 21.0 no longer works on Python 3.5 -- pip install -U pip==20.3.4 setuptools -- pip install -U 'virtualenv<20' -- pip install -U tox==3.20.1 -- python2 -m pip install --user -U typing -- tox --notest - -# This is a big hack and only works because the layout of our directories -# means that tox picks up the mypy from the source directories instead of -# the version it installed into a venv. This is also *why* we need to do this, -# since if we arranged for tox to build with mypyc, pytest wouldn't use it. -- if [[ $TEST_MYPYC == 1 ]]; then pip install -r test-requirements.txt; CC=clang MYPYC_OPT_LEVEL=0 python3 setup.py --use-mypyc build_ext --inplace; fi - -script: -- tox --skip-pkg-install -- $EXTRA_ARGS - -# Getting our hands on a debug build or the right OS X build is -# annoying, unfortunately. -before_install: | - set -e - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - if [[ $PYTHON_DEBUG_BUILD == 1 ]]; then - PYTHONDIR=~/python-debug/python-$PYTHONVERSION - VENV=$PYTHONDIR/env - misc/build-debug-python.sh $PYTHONVERSION $PYTHONDIR $VENV - source $VENV/bin/activate - fi - elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - # Attempt to install, skipping if version already exists. - pyenv install $PYTHONVERSION -s - # Regenerate shims - pyenv rehash - # Manually set pyenv variables per https://pythonhosted.org/CodeChat/.travis.yml.html - export PYENV_VERSION=$PYTHONVERSION - export PATH="/Users/travis/.pyenv/shims:${PATH}" - fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13aeab4d01f5..9e5bdeb90a69 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,74 +1,89 @@ -Contributing to Mypy -==================== +# Contributing to Mypy Welcome! Mypy is a community project that aims to work for a wide -range of Python users and Python codebases. If you're trying Mypy on +range of Python users and Python codebases. If you're trying mypy on your Python code, your experience and what you can contribute are important to the project's success. +## Code of Conduct -Getting started, building, and testing --------------------------------------- +Everyone participating in the Mypy community, and in particular in our +issue tracker, pull requests, and chat, is expected to treat +other people with respect and more generally to follow the guidelines +articulated in the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/). -If you haven't already, take a look at the project's -[README.md file](README.md) -and the [Mypy documentation](https://mypy.readthedocs.io/en/latest/), -and try adding type annotations to your file and type-checking it with Mypy. +## Getting started with development -Discussion ----------- +### Setup -If you've run into behavior in Mypy you don't understand, or you're -having trouble working out a good way to apply it to your code, or -you've found a bug or would like a feature it doesn't have, we want to -hear from you! +Run the following: +``` +# Clone the mypy repository +git clone https://github.com/python/mypy.git -Our main forum for discussion is the project's [GitHub issue -tracker](https://github.com/python/mypy/issues). This is the right -place to start a discussion of any of the above or most any other -topic concerning the project. +# Enter the repository +cd mypy -For less formal discussion we have a chat room on -[gitter.im](https://gitter.im/python/typing). Some Mypy core developers -are almost always present; feel free to find us there and we're happy -to chat. Substantive technical discussion will be directed to the -issue tracker. +# Create then activate a virtual environment +python3 -m venv venv +source venv/bin/activate -(We also have an IRC channel, `#python-mypy` on irc.freenode.net. -This is lightly used, we have mostly switched to the gitter room -mentioned above.) +# Install the test requirements and the project +python3 -m pip install -r test-requirements.txt +python3 -m pip install -e . +hash -r +``` -#### Code of Conduct +### Running tests -Everyone participating in the Mypy community, and in particular in our -issue tracker, pull requests, and IRC channel, is expected to treat -other people with respect and more generally to follow the guidelines -articulated in the [Python Community Code of -Conduct](https://www.python.org/psf/codeofconduct/). +Once setup, you should be able to run tests: +``` +python3 runtests.py +``` + +To use mypy to check mypy's own code, run: +``` +python3 runtests.py self +# or equivalently: +python3 -m mypy --config-file mypy_self_check.ini -p mypy +``` + +You can also use `tox` to run tests, for instance: +``` +tox -e py +``` + +## First time contributors + +If you're looking for things to help with, browse our [issue tracker](https://github.com/python/mypy/issues)! -First Time Contributors ------------------------ +In particular, look for: +- [good first issues](https://github.com/python/mypy/labels/good-first-issue) +- [good second issues](https://github.com/python/mypy/labels/good-second-issue) +- [documentation issues](https://github.com/python/mypy/labels/documentation) -Mypy appreciates your contribution! If you are interested in helping improve -mypy, there are several ways to get started: +It's also extremely easy to get started contributing to our sister project +[typeshed](https://github.com/python/typeshed/issues) that provides type stubs +for libraries. This is a great way to become familiar with type syntax. -* Contributing to [typeshed](https://github.com/python/typeshed/issues) is a great way to -become familiar with Python's type syntax. -* Work on [documentation issues](https://github.com/python/mypy/labels/documentation). -* Ask on [the chat](https://gitter.im/python/typing) or on -[the issue tracker](https://github.com/python/mypy/issues) about good beginner issues. +If you need help getting started, don't hesitate to ask on +[gitter](https://gitter.im/python/typing). -Submitting Changes ------------------- +To get help fixing a specific issue, it's often best to comment on the issue +itself. The more details you provide about what you've tried and where you've +looked, the easier it will be for you to get help. + +Interactive debuggers like `pdb` and `ipdb` are really useful for getting +started with the mypy codebase. This is a +[useful tutorial](https://realpython.com/python-debugging-pdb/). + +## Submitting changes Even more excellent than a good bug report is a fix for a bug, or the -implementation of a much-needed new feature. (*) We'd love to have +implementation of a much-needed new feature. We'd love to have your contributions. -(*) If your new feature will be a lot of work, we recommend talking to - us early -- see below. - We use the usual GitHub pull-request flow, which may be familiar to you if you've contributed to other projects on GitHub. For the mechanics, see [our git and GitHub workflow help page](https://github.com/python/mypy/wiki/Using-Git-And-GitHub), @@ -76,17 +91,8 @@ or [GitHub's own documentation](https://help.github.com/articles/using-pull-requ Anyone interested in Mypy may review your code. One of the Mypy core developers will merge your pull request when they think it's ready. -For every pull request, we aim to promptly either merge it or say why -it's not yet ready; if you go a few days without a reply, please feel -free to ping the thread by adding a new comment. - -For a list of mypy core developers, see the file [CREDITS](CREDITS). - -Preparing Changes ------------------ - -Before you begin: if your change will be a significant amount of work +If your change will be a significant amount of work to write, we highly recommend starting by opening an issue laying out what you want to do. That lets a conversation happen early in case other contributors disagree with what you'd like to do or have ideas @@ -113,8 +119,7 @@ You may also find other pages in the helpful in developing your change. -Core developer guidelines -------------------------- +## Core developer guidelines Core developers should follow these rules when processing pull requests: @@ -138,52 +143,3 @@ Core developers should follow these rules when processing pull requests: * If the PR fixes an issue, make sure something like "Fixes #xxx." occurs in the body of the message (not in the subject). * Use Markdown for formatting. - - -Issue-tracker conventions -------------------------- - -We aim to reply to all new issues promptly. We'll assign a milestone -to help us track which issues we intend to get to when, and may apply -labels to carry some other information. Here's what our milestones -and labels mean. - -### Task priority and sizing - -We use GitHub "labels" ([see our -list](https://github.com/python/mypy/labels)) to roughly order what we -want to do soon and less soon. There's two dimensions taken into -account: **priority** (does it matter to our users) and **size** (how -long will it take to complete). - -Bugs that aren't a huge deal but do matter to users and don't seem -like a lot of work to fix generally will be dealt with sooner; things -that will take longer may go further out. - -We are trying to keep the backlog at a manageable size, an issue that is -unlikely to be acted upon in foreseeable future is going to be -respectfully closed. This doesn't mean the issue is not important, but -rather reflects the limits of the team. - -The **question** label is for issue threads where a user is asking a -question but it isn't yet clear that it represents something to actually -change. We use the issue tracker as the preferred venue for such -questions, even when they aren't literally issues, to keep down the -number of distinct discussion venues anyone needs to track. These might -evolve into a bug or feature request. - -Issues **without a priority or size** haven't been triaged. We aim to -triage all new issues promptly, but there are some issues from previous -years that we haven't yet re-reviewed since adopting these conventions. - -### Other labels - -* **needs discussion**: This issue needs agreement on some kind of - design before it makes sense to implement it, and it either doesn't - yet have a design or doesn't yet have agreement on one. -* **feature**, **bug**, **crash**, **refactoring**, **documentation**: - These classify the user-facing impact of the change. Specifically - "refactoring" means there should be no user-facing effect. -* **topic-** labels group issues touching a similar aspect of the - project, for example PEP 484 compatibility, a specific command-line - option or dependency. diff --git a/CREDITS b/CREDITS index 508616cf2516..d0e53de5ee01 100644 --- a/CREDITS +++ b/CREDITS @@ -10,14 +10,16 @@ the release blog posts at https://mypy-lang.blogspot.com/. Dropbox core team: Jukka Lehtosalo - Guido van Rossum Ivan Levkivskyi - Michael J. Sullivan Non-Dropbox core team members: Ethan Smith + Guido van Rossum Jelle Zijlstra + Michael J. Sullivan + Shantanu Jain + Xuanda Yang Past Dropbox core team members: diff --git a/MANIFEST.in b/MANIFEST.in index 7e6bd3404929..fc657091a3dc 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,6 +3,7 @@ # stubs prune mypy/typeshed +include mypy/typeshed/LICENSE include mypy/typeshed/stdlib/VERSIONS recursive-include mypy/typeshed *.pyi @@ -40,7 +41,7 @@ include runtests.py include pytest.ini include LICENSE mypyc/README.md -exclude .gitmodules CONTRIBUTING.md CREDITS ROADMAP.md tox.ini +exclude .gitmodules CONTRIBUTING.md CREDITS ROADMAP.md tox.ini action.yml global-exclude *.py[cod] global-exclude .DS_Store diff --git a/README.md b/README.md index 3c7a1e708642..16436e208cd3 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,76 @@ mypy logo -Mypy: Optional Static Typing for Python +Mypy: Static Typing for Python ======================================= [![Build Status](https://api.travis-ci.com/python/mypy.svg?branch=master)](https://travis-ci.com/python/mypy) +[![Documentation Status](https://readthedocs.org/projects/mypy/badge/?version=latest)](https://mypy.readthedocs.io/en/latest/?badge=latest) [![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/) -Got a question? Join us on Gitter! ----------------------------------- +Got a question? +--------------- -We don't have a mailing list; but we are always happy to answer -questions on [gitter chat](https://gitter.im/python/typing). If you are -sure you've found a bug please search our issue trackers for a -duplicate before filing a new issue: +We are always happy to answer questions! Here are some good places to ask them: -- [mypy tracker](https://github.com/python/mypy/issues) - for mypy issues -- [typeshed tracker](https://github.com/python/typeshed/issues) - for issues with specific modules -- [typing tracker](https://github.com/python/typing/issues) - for discussion of new type system features (PEP 484 changes) and - runtime bugs in the typing module +- for anything you're curious about, try [gitter chat](https://gitter.im/python/typing) +- for general questions about Python typing, try [typing discussions](https://github.com/python/typing/discussions) -What is mypy? -------------- +If you're just getting started, +[the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) +and [type hints cheat sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html) +can also help answer questions. -Mypy is an optional static type checker for Python. You can add type -hints ([PEP 484](https://www.python.org/dev/peps/pep-0484/)) to your -Python programs, and use mypy to type check them statically. -Find bugs in your programs without even running them! +If you think you've found a bug: -You can mix dynamic and static typing in your programs. You can always -fall back to dynamic typing when static typing is not convenient, such -as for legacy code. +- check our [common issues page](https://mypy.readthedocs.io/en/stable/common_issues.html) +- search our [issue tracker](https://github.com/python/mypy/issues) to see if + it's already been reported +- consider asking on [gitter chat](https://gitter.im/python/typing) -Here is a small example to whet your appetite (Python 3): +To report a bug or request an enhancement: -```python -from typing import Iterator +- report at [our issue tracker](https://github.com/python/mypy/issues) +- if the issue is with a specific library or function, consider reporting it at + [typeshed tracker](https://github.com/python/typeshed/issues) or the issue + tracker for that library -def fib(n: int) -> Iterator[int]: - a, b = 0, 1 - while a < n: - yield a - a, b = b, a + b -``` -See [the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) for more examples. +To discuss a new type system feature: +- discuss at [typing-sig mailing list](https://mail.python.org/archives/list/typing-sig@python.org/) +- there is also some historical discussion [here](https://github.com/python/typing/issues) -For Python 2.7, the standard annotations are written as comments: -```python -def is_palindrome(s): - # type: (str) -> bool - return s == s[::-1] -``` -See [the documentation for Python 2 support](https://mypy.readthedocs.io/en/latest/python2.html). +What is mypy? +------------- -Mypy is in development; some features are missing and there are bugs. -See 'Development status' below. +Mypy is a static type checker for Python. -Requirements ------------- +Type checkers help ensure that you're using variables and functions in your code +correctly. With mypy, add type hints ([PEP 484](https://www.python.org/dev/peps/pep-0484/)) +to your Python programs, and mypy will warn you when you use those types +incorrectly. -You need Python 3.5 or later to run mypy. You can have multiple Python -versions (2.x and 3.x) installed on the same system without problems. +Python is a dynamic language, so usually you'll only see errors in your code +when you attempt to run it. Mypy is a *static* checker, so it finds bugs +in your programs without even running them! -In Ubuntu, Mint and Debian you can install Python 3 like this: +Mypy is designed with gradual typing in mind. This means you can add type +hints to your code base slowly and that you can always fall back to dynamic +typing when static typing is not convenient. - $ sudo apt-get install python3 python3-pip +Here is a small example to whet your appetite: -For other Linux flavors, macOS and Windows, packages are available at +```python +number = input("What is your favourite number?") +print("Well, my favourite number is: ", number + 1) # error: Unsupported operand types for + ("str" and "int") +``` + +See [the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) for more examples. - https://www.python.org/getit/ +In particular, see: +- [type hints cheat sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html) +- [getting started](https://mypy.readthedocs.io/en/stable/getting_started.html) Quick start @@ -81,23 +78,21 @@ Quick start Mypy can be installed using pip: - $ python3 -m pip install -U mypy + python3 -m pip install -U mypy If you want to run the latest version of the code, you can install from git: - $ python3 -m pip install -U git+git://github.com/python/mypy.git + python3 -m pip install -U git+git://github.com/python/mypy.git -Now, if Python on your system is configured properly (else see -"Troubleshooting" below), you can type-check the [statically typed parts] of a -program like this: +Now you can type-check the [statically typed parts] of a program like this: - $ mypy PROGRAM + mypy PROGRAM -You can always use a Python interpreter to run your statically typed -programs, even if they have type errors: +You can always use the Python interpreter to run your statically typed +programs, even if mypy reports type errors: - $ python3 PROGRAM + python3 PROGRAM You can also try mypy in an [online playground](https://mypy-play.net/) (developed by Yusuke Miyazaki). @@ -105,8 +100,8 @@ Yusuke Miyazaki). [statically typed parts]: https://mypy.readthedocs.io/en/latest/getting_started.html#function-signatures-and-dynamic-vs-static-typing -IDE, Linter Integrations, and Pre-commit ----------------------------------------- +Integrations +------------ Mypy can be integrated into popular IDEs: @@ -121,99 +116,34 @@ Mypy can be integrated into popular IDEs: * PyCharm: [mypy plugin](https://github.com/dropbox/mypy-PyCharm-plugin) (PyCharm integrates [its own implementation of PEP 484](https://www.jetbrains.com/help/pycharm/type-hinting-in-product.html)) * VS Code: provides [basic integration](https://code.visualstudio.com/docs/python/linting#_mypy) with mypy. - -Mypy can also be set up as a pre-commit hook using [pre-commit mirrors-mypy]. - -[pre-commit mirrors-mypy]: https://github.com/pre-commit/mirrors-mypy +* pre-commit: use [pre-commit mirrors-mypy](https://github.com/pre-commit/mirrors-mypy). Web site and documentation -------------------------- -Documentation and additional information is available at the web site: +Additional information is available at the web site: http://www.mypy-lang.org/ -Or you can jump straight to the documentation: +Jump straight to the documentation: https://mypy.readthedocs.io/ +Follow along our changelog at: -Troubleshooting ---------------- - -Depending on your configuration, you may have to run `pip` like -this: - - $ python3 -m pip install -U mypy - -This should automatically install the appropriate version of -mypy's parser, typed-ast. If for some reason it does not, you -can install it manually: - - $ python3 -m pip install -U typed-ast - -If the `mypy` command isn't found after installation: After -`python3 -m pip install`, the `mypy` script and -dependencies, including the `typing` module, will be installed to -system-dependent locations. Sometimes the script directory will not -be in `PATH`, and you have to add the target directory to `PATH` -manually or create a symbolic link to the script. In particular, on -macOS, the script may be installed under `/Library/Frameworks`: - - /Library/Frameworks/Python.framework/Versions//bin - -In Windows, the script is generally installed in -`\PythonNN\Scripts`. So, type check a program like this (replace -`\Python34` with your Python installation path): - - C:\>\Python34\python \Python34\Scripts\mypy PROGRAM - -### Working with `virtualenv` - -If you are using [`virtualenv`](https://virtualenv.pypa.io/en/stable/), -make sure you are running a python3 environment. Installing via `pip3` -in a v2 environment will not configure the environment to run installed -modules from the command line. - - $ python3 -m pip install -U virtualenv - $ python3 -m virtualenv env + https://mypy-lang.blogspot.com/ -Quick start for contributing to mypy ------------------------------------- - -If you want to contribute, first clone the mypy git repository: - - $ git clone https://github.com/python/mypy.git - -From the mypy directory, use pip to install mypy: - - $ cd mypy - $ python3 -m pip install -U . - -Replace `python3` with your Python 3 interpreter. You may have to do -the above as root. For example, in Ubuntu: - - $ sudo python3 -m pip install -U . - -Now you can use the `mypy` program just as above. In case of trouble -see "Troubleshooting" above. - -> NOTE: Installing with sudo can be a security risk. Please try with the `--user` flag first. - $ python3 -m pip install --user -U . - - -Tests ------ +Contributing +------------ -The basic way to run tests: +Help in testing, development, documentation and other tasks is +highly appreciated and useful to the project. There are tasks for +contributors of all experience levels. - $ pip3 install -r test-requirements.txt - $ python2 -m pip install -U typing - $ ./runtests.py +To get started with developing mypy, see [CONTRIBUTING.md](CONTRIBUTING.md). -For more on the tests, such as how to write tests and how to control -which tests to run, see [Test README.md](test-data/unit/README.md). +If you need help getting started, don't hesitate to ask on [gitter](https://gitter.im/python/typing). Development status @@ -223,58 +153,19 @@ Mypy is beta software, but it has already been used in production for several years at Dropbox and in many other organizations, and it has an extensive test suite. -See [the roadmap](ROADMAP.md) if you are interested in plans for the -future. - - -Changelog ---------- - -Follow mypy's updates on the blog: https://mypy-lang.blogspot.com/ - - -Issue tracker -------------- - -Please report any bugs and enhancement ideas using the mypy issue -tracker: https://github.com/python/mypy/issues - -If you have any questions about using mypy or types, please ask -in the typing gitter instead: https://gitter.im/python/typing - - -Compiled version of mypy ------------------------- +mypyc and compiled version of mypy +---------------------------------- -We have built a compiled version of mypy using the [mypyc -compiler](https://github.com/python/mypy/tree/master/mypyc) for -mypy-annotated Python code. It is approximately 4 times faster than -interpreted mypy and is available (and the default) for 64-bit -Windows, macOS, and Linux. +[Mypyc](https://github.com/mypyc/mypyc) uses Python type hints to compile Python +modules to faster C extensions. Mypy is itself compiled using mypyc: this makes +mypy approximately 4 times faster than if interpreted! To install an interpreted mypy instead, use: - $ python3 -m pip install --no-binary mypy -U mypy + python3 -m pip install --no-binary mypy -U mypy -If you wish to test out the compiled version of a development -version of mypy, you can directly install a binary from +To use a compiled version of a development +version of mypy, directly install a binary from https://github.com/mypyc/mypy_mypyc-wheels/releases/latest. - -Help wanted ------------ - -Any help in testing, development, documentation and other tasks is -highly appreciated and useful to the project. There are tasks for -contributors of all experience levels. If you're just getting started, -ask on the [gitter chat](https://gitter.im/python/typing) for ideas of good -beginner issues. - -For more details, see the file [CONTRIBUTING.md](CONTRIBUTING.md). - - -License -------- - -Mypy is licensed under the terms of the MIT License (see the file -LICENSE). +To contribute to the mypyc project, check out https://github.com/mypyc/mypyc diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index b881799be8f1..000000000000 --- a/ROADMAP.md +++ /dev/null @@ -1,38 +0,0 @@ -# Mypy Roadmap - -The goal of the roadmap is to document areas the mypy core team is -planning to work on in the future or is currently working on. PRs -targeting these areas are very welcome, but please check first with a -core team member that nobody else is working on the same thing. - -**Note:** This doesn’t include everything that the core team will work -on, and everything is subject to change. - -- Continue making error messages more useful and informative. - ([issues](https://github.com/python/mypy/labels/topic-usability)) - -- Refactor and simplify specific tricky parts of mypy internals, such - as the [conditional type binder](https://github.com/python/mypy/issues/3457) - and the [semantic analyzer](https://github.com/python/mypy/issues/6204). - -- Use the redesigned semantic analyzer to support general recursive types - ([issue](https://github.com/python/mypy/issues/731)). - -- Infer signature of a single function using static analysis and integrate this - functionality in mypy daemon. - -- Support user defined variadic generics (focus on the use cases needed for precise - typing of decorators, see [issue](https://github.com/python/mypy/issues/3157)). - -- Dedicated support for NumPy and Python numeric stack (including - integer generics/shape types, and a NumPy plugin, see - [issue](https://github.com/python/mypy/issues/3540)). - -- Gradual improvements to [mypyc compiler](https://github.com/mypyc/mypyc). - -- Invest some effort into systematically filling in missing - stubs in typeshed, with focus on libraries heavily used at Dropbox. - Help with [typeshed transformation](https://github.com/python/typeshed/issues/2491) - if needed. - -- Support selected IDE features and deeper editor integrations. diff --git a/action.yml b/action.yml new file mode 100644 index 000000000000..df8715327830 --- /dev/null +++ b/action.yml @@ -0,0 +1,83 @@ +name: "Mypy" +description: "Optional Static Typing for Python." +author: "Jukka Lehtosalo and contributors" +inputs: + options: + description: > + Options passed to mypy. Use `mypy --help` to see available options. + required: false + paths: + description: > + Explicit paths to run mypy on. Defaults to the current directory. + required: false + default: "." + version: + description: > + Mypy version to use (PEP440) - e.g. "0.910" + required: false + default: "" + install_types: + description: > + Whether to automatically install missing library stub packages. + ('yes'|'no', default: 'yes') + default: "yes" + install_project_dependencies: + description: > + Whether to attempt to install project dependencies into mypy + environment. ('yes'|'no', default: 'yes') + default: "yes" +branding: + color: "blue" + icon: "check-circle" +runs: + using: composite + steps: + - name: mypy setup + shell: bash + run: | + echo ::group::Installing mypy... + export PIP_DISABLE_PIP_VERSION_CHECK=1 + + if [ "$RUNNER_OS" == "Windows" ]; then + HOST_PYTHON=python + else + HOST_PYTHON=python3 + fi + + venv_script="import os.path; import venv; import sys; + path = os.path.join(r'${{ github.action_path }}', '.mypy-venv'); + venv.main([path]); + bin_subdir = 'Scripts' if sys.platform == 'win32' else 'bin'; + print(os.path.join(path, bin_subdir, 'python')); + " + + VENV_PYTHON=$(echo $venv_script | "$HOST_PYTHON") + mypy_spec="mypy" + + if [ -n "${{ inputs.version }}" ]; then + mypy_spec+="==${{ inputs.version }}" + fi + + if ! "$VENV_PYTHON" -m pip install "$mypy_spec"; then + echo "::error::Could not install mypy." + exit 1 + fi + echo ::endgroup:: + + if [ "${{ inputs.install_project_dependencies }}" == "yes" ]; then + VENV=$("$VENV_PYTHON" -c 'import sys;print(sys.prefix)') + echo ::group::Installing project dependencies... + "$VENV_PYTHON" -m pip download --dest="$VENV"/deps . + "$VENV_PYTHON" -m pip install -U --find-links="$VENV"/deps "$VENV"/deps/* + echo ::endgroup:: + fi + + echo ::group::Running mypy... + mypy_opts="" + if [ "${{ inputs.install_types }}" == "yes" ]; then + mypy_opts+="--install-types --non-interactive" + fi + + echo "mypy $mypy_opts ${{ inputs.options }} ${{ inputs.paths }}" + "$VENV_PYTHON" -m mypy $mypy_opts ${{ inputs.options }} ${{ inputs.paths }} + echo ::endgroup:: diff --git a/build-requirements.txt b/build-requirements.txt index eee2f9da3fe3..b4d024ee7f38 100644 --- a/build-requirements.txt +++ b/build-requirements.txt @@ -1,4 +1,2 @@ -r mypy-requirements.txt types-typed-ast>=1.4.0,<1.5.0 -types-toml>=0.0 -types-enum34>=0.0; python_version == '3.5' diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index d20641e7edf5..7e3d31ebea98 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,2 +1,2 @@ -Sphinx >= 1.4.4 -sphinx-rtd-theme >= 0.1.9 +sphinx>=4.2.0,<5.0.0 +sphinx-rtd-theme>=1.0.0,<2.0.0 diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index fc151598cff0..19e0d4dcce01 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -21,10 +21,10 @@ They can be defined using the :py:func:`@dataclasses.dataclass @dataclass class Application: name: str - plugins: List[str] = field(default_factory=list) + plugins: list[str] = field(default_factory=list) test = Application("Testing...") # OK - bad = Application("Testing...", "with plugin") # Error: List[str] expected + bad = Application("Testing...", "with plugin") # Error: list[str] expected Mypy will detect special methods (such as :py:meth:`__lt__ `) depending on the flags used to define dataclasses. For example: diff --git a/docs/source/casts.rst b/docs/source/casts.rst deleted file mode 100644 index 61eeb3062625..000000000000 --- a/docs/source/casts.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _casts: - -Casts and type assertions -========================= - -Mypy supports type casts that are usually used to coerce a statically -typed value to a subtype. Unlike languages such as Java or C#, -however, mypy casts are only used as hints for the type checker, and they -don't perform a runtime type check. Use the function :py:func:`~typing.cast` to perform a -cast: - -.. code-block:: python - - from typing import cast, List - - o: object = [1] - x = cast(List[int], o) # OK - y = cast(List[str], o) # OK (cast performs no actual runtime check) - -To support runtime checking of casts such as the above, we'd have to check -the types of all list items, which would be very inefficient for large lists. -Casts are used to silence spurious -type checker warnings and give the type checker a little help when it can't -quite understand what is going on. - -.. note:: - - You can use an assertion if you want to perform an actual runtime check: - - .. code-block:: python - - def foo(o: object) -> None: - print(o + 5) # Error: can't add 'object' and 'int' - assert isinstance(o, int) - print(o + 5) # OK: type of 'o' is 'int' here - -You don't need a cast for expressions with type ``Any``, or when -assigning to a variable with type ``Any``, as was explained earlier. -You can also use ``Any`` as the cast target type -- this lets you perform -any operations on the result. For example: - -.. code-block:: python - - from typing import cast, Any - - x = 1 - x.whatever() # Type check error - y = cast(Any, x) - y.whatever() # Type check OK (runtime error) diff --git a/docs/source/cheat_sheet_py3.rst b/docs/source/cheat_sheet_py3.rst index 35c60f5a0610..734bc16ddea5 100644 --- a/docs/source/cheat_sheet_py3.rst +++ b/docs/source/cheat_sheet_py3.rst @@ -45,6 +45,7 @@ Built-in types .. code-block:: python + from typing import List, Set, Dict, Tuple, Optional # For simple built-in types, just use the name of the type @@ -60,7 +61,7 @@ Built-in types x: set[int] = {6, 7} # In Python 3.8 and earlier, the name of the collection type is - # capitalized, and the type is imported from 'typing' + # capitalized, and the type is imported from the 'typing' module x: List[int] = [1] x: Set[int] = {6, 7} @@ -68,8 +69,8 @@ Built-in types x = [1] # type: List[int] # For mappings, we need the types of both keys and values - x: dict[str, float] = {'field': 2.0} # Python 3.9+ - x: Dict[str, float] = {'field': 2.0} + x: dict[str, float] = {"field": 2.0} # Python 3.9+ + x: Dict[str, float] = {"field": 2.0} # For tuples of fixed size, we specify the types of all the elements x: tuple[int, str, float] = (3, "yes", 7.5) # Python 3.9+ @@ -95,7 +96,7 @@ Python 3 supports an annotation syntax for function declarations. .. code-block:: python - from typing import Callable, Iterator, Union, Optional, List + from typing import Callable, Iterator, Union, Optional # This is how you annotate a function definition def stringify(num: int) -> str: @@ -121,12 +122,12 @@ Python 3 supports an annotation syntax for function declarations. i += 1 # You can of course split a function annotation over multiple lines - def send_email(address: Union[str, List[str]], + def send_email(address: Union[str, list[str]], sender: str, - cc: Optional[List[str]], - bcc: Optional[List[str]], + cc: Optional[list[str]], + bcc: Optional[list[str]], subject='', - body: Optional[List[str]] = None + body: Optional[list[str]] = None ) -> bool: ... @@ -143,7 +144,7 @@ When you're puzzled or when things are complicated .. code-block:: python - from typing import Union, Any, List, Optional, cast + from typing import Union, Any, Optional, cast # To find out what type mypy infers for an expression anywhere in # your program, wrap it in reveal_type(). Mypy will print an error @@ -151,7 +152,7 @@ When you're puzzled or when things are complicated reveal_type(1) # -> Revealed type is "builtins.int" # Use Union when something could be one of a few types - x: List[Union[int, str]] = [3, 5, "test", "fun"] + x: list[Union[int, str]] = [3, 5, "test", "fun"] # Use Any if you don't know the type of something or it's too # dynamic to write a type for @@ -159,7 +160,7 @@ When you're puzzled or when things are complicated # If you initialize a variable with an empty container or "None" # you may have to help mypy a bit by providing a type annotation - x: List[str] = [] + x: list[str] = [] x: Optional[str] = None # This makes each positional arg and each keyword arg a "str" @@ -176,8 +177,8 @@ When you're puzzled or when things are complicated # "cast" is a helper function that lets you override the inferred # type of an expression. It's only for mypy -- there's no runtime check. a = [4] - b = cast(List[int], a) # Passes fine - c = cast(List[str], a) # Passes fine (no runtime check) + b = cast(list[int], a) # Passes fine + c = cast(list[str], a) # Passes fine (no runtime check) reveal_type(c) # -> Revealed type is "builtins.list[builtins.str]" print(c) # -> [4]; the object is not cast @@ -209,25 +210,25 @@ that are common in idiomatic Python are standardized. .. code-block:: python - from typing import Mapping, MutableMapping, Sequence, Iterable, List, Set + from typing import Mapping, MutableMapping, Sequence, Iterable # Use Iterable for generic iterables (anything usable in "for"), # and Sequence where a sequence (supporting "len" and "__getitem__") is # required - def f(ints: Iterable[int]) -> List[str]: + def f(ints: Iterable[int]) -> list[str]: return [str(x) for x in ints] f(range(1, 3)) # Mapping describes a dict-like object (with "__getitem__") that we won't # mutate, and MutableMapping one (with "__setitem__") that we might - def f(my_mapping: Mapping[int, str]) -> List[int]: + def f(my_mapping: Mapping[int, str]) -> list[int]: my_mapping[5] = 'maybe' # if we try this, mypy will throw an error... return list(my_mapping.keys()) f({3: 'yes', 4: 'no'}) - def f(my_mapping: MutableMapping[int, str]) -> Set[str]: + def f(my_mapping: MutableMapping[int, str]) -> set[str]: my_mapping[5] = 'maybe' # ...but mypy is OK with this. return set(my_mapping.values()) @@ -262,12 +263,12 @@ Classes # You can use the ClassVar annotation to declare a class variable class Car: seats: ClassVar[int] = 4 - passengers: ClassVar[List[str]] + passengers: ClassVar[list[str]] # You can also declare the type of an attribute in "__init__" class Box: def __init__(self) -> None: - self.items: List[str] = [] + self.items: list[str] = [] Coroutines and asyncio diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index 330d9805be14..3c12b4b06d9b 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -33,7 +33,7 @@ a type annotation: .. code-block:: python class A: - x: List[int] # Declare attribute 'x' of type List[int] + x: list[int] # Declare attribute 'x' of type list[int] a = A() a.x = [1] # OK @@ -48,7 +48,7 @@ than 3.6: .. code-block:: python class A: - x = None # type: List[int] # Declare attribute 'x' of type List[int] + x = None # type: list[int] # Declare attribute 'x' of type list[int] Note that attribute definitions in the class body that use a type comment are special: a ``None`` value is valid as the initializer, even though @@ -62,7 +62,7 @@ in a method: class A: def __init__(self) -> None: - self.x: List[int] = [] + self.x: list[int] = [] def f(self) -> None: self.y: Any = 0 @@ -127,12 +127,6 @@ particular attribute should not be set on instances: a.x = 1 # Error: Cannot assign to class variable "x" via instance print(a.x) # OK -- can be read through an instance -.. note:: - - If you need to support Python 3 versions 3.5.2 or earlier, you have - to import ``ClassVar`` from ``typing_extensions`` instead (available on - PyPI). If you use Python 2.7, you can import it from ``typing``. - It's not necessary to annotate all class variables using :py:data:`~typing.ClassVar`. An attribute without the :py:data:`~typing.ClassVar` annotation can still be used as a class variable. However, mypy won't prevent it from @@ -166,7 +160,7 @@ This behavior will change in the future, since it's surprising. .. note:: A :py:data:`~typing.ClassVar` type parameter cannot include type variables: - ``ClassVar[T]`` and ``ClassVar[List[T]]`` + ``ClassVar[T]`` and ``ClassVar[list[T]]`` are both invalid if ``T`` is a type variable (see :ref:`generic-classes` for more about type variables). @@ -206,7 +200,7 @@ override has a compatible signature: You can also vary return types **covariantly** in overriding. For example, you could override the return type ``Iterable[int]`` with a - subtype such as ``List[int]``. Similarly, you can vary argument types + subtype such as ``list[int]``. Similarly, you can vary argument types **contravariantly** -- subclasses can have more general argument types. You can also override a statically typed method with a dynamically @@ -321,3 +315,35 @@ class, including an abstract method defined in an abstract base class. You can implement an abstract property using either a normal property or an instance variable. + +Slots +***** + +When a class has explicitly defined +`__slots__ `_, +mypy will check that all attributes assigned to are members of ``__slots__``: + +.. code-block:: python + + class Album: + __slots__ = ('name', 'year') + + def __init__(self, name: str, year: int) -> None: + self.name = name + self.year = year + # Error: Trying to assign name "released" that is not in "__slots__" of type "Album" + self.released = True + + my_album = Album('Songs about Python', 2021) + +Mypy will only check attribute assignments against ``__slots__`` when +the following conditions hold: + +1. All base classes (except builtin ones) must have explicit + ``__slots__`` defined (this mirrors Python semantics). + +2. ``__slots__`` does not include ``__dict__``. If ``__slots__`` + includes ``__dict__``, arbitrary attributes can be set, similar to + when ``__slots__`` is not defined (this mirrors Python semantics). + +3. All values in ``__slots__`` must be string literals. diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index ea3c91396f31..a729ac2baca0 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -58,12 +58,20 @@ for full details, see :ref:`running-mypy`. For instance, to avoid discovering any files named `setup.py` you could pass ``--exclude '/setup\.py$'``. Similarly, you can ignore discovering directories with a given name by e.g. ``--exclude /build/`` or - those matching a subpath with ``--exclude /project/vendor/``. + those matching a subpath with ``--exclude /project/vendor/``. To ignore + multiple files / directories / paths, you can provide the --exclude + flag more than once, e.g ``--exclude '/setup\.py$' --exclude '/build/'``. - Note that this flag only affects recursive discovery, that is, when mypy is - discovering files within a directory tree or submodules of a package to - check. If you pass a file or module explicitly it will still be checked. For - instance, ``mypy --exclude '/setup.py$' but_still_check/setup.py``. + Note that this flag only affects recursive directory tree discovery, that + is, when mypy is discovering files within a directory tree or submodules of + a package to check. If you pass a file or module explicitly it will still be + checked. For instance, ``mypy --exclude '/setup.py$' + but_still_check/setup.py``. + + In particular, ``--exclude`` does not affect mypy's :ref:`import following + `. You can use a per-module :confval:`follow_imports` config + option to additionally avoid mypy from following imports and checking code + you do not wish to be checked. Note that mypy will never recursively discover files and directories named "site-packages", "node_modules" or "__pycache__", or those whose name starts @@ -304,9 +312,8 @@ The following options are available: .. option:: --disallow-any-generics This flag disallows usage of generic types that do not specify explicit - type parameters. Moreover, built-in collections (such as :py:class:`list` and - :py:class:`dict`) become disallowed as you should use their aliases from the :py:mod:`typing` - module (such as :py:class:`List[int] ` and :py:class:`Dict[str, str] `). + type parameters. For example, you can't use a bare ``x: list``. Instead, you + must always write something like ``x: list[int]``. .. option:: --disallow-subclassing-any @@ -411,7 +418,7 @@ For more details, see :ref:`no_strict_optional`. Configuring warnings ******************** -The follow flags enable warnings for code that is sound but is +The following flags enable warnings for code that is sound but is potentially problematic or redundant in some way. .. option:: --warn-redundant-casts @@ -513,10 +520,10 @@ of the above sections. .. code-block:: python - def process(items: List[str]) -> None: - # 'items' has type List[str] + def process(items: list[str]) -> None: + # 'items' has type list[str] items = [item.split() for item in items] - # 'items' now has type List[List[str]] + # 'items' now has type list[list[str]] ... .. option:: --local-partial-types @@ -557,8 +564,13 @@ of the above sections. # This won't re-export the value from foo import bar + + # Neither will this + from foo import bar as bang + # This will re-export it as bar and allow other modules to import it from foo import bar as bar + # This will also re-export bar from foo import bar __all__ = ['bar'] @@ -572,9 +584,9 @@ of the above sections. .. code-block:: python - from typing import List, Text + from typing import Text - items: List[int] + items: list[int] if 'some string' in items: # Error: non-overlapping container check! ... @@ -687,6 +699,14 @@ in error messages. Show absolute paths to files. +.. option:: --soft-error-limit N + + This flag will adjust the limit after which mypy will (sometimes) + disable reporting most additional errors. The limit only applies + if it seems likely that most of the remaining errors will not be + useful or they may be overly noisy. If ``N`` is negative, there is + no limit. The default limit is 200. + .. _incremental: @@ -895,6 +915,20 @@ Miscellaneous selection of third-party package stubs, instead of having them installed separately. +.. option:: --non-interactive + + When used together with :option:`--install-types `, this causes mypy to install all suggested stub + packages using pip without asking for confirmation, and then + continues to perform type checking using the installed stubs, if + some files or modules are provided to type check. + + This is implemented as up to two mypy runs internally. The first run + is used to find missing stub packages, and output is shown from + this run only if no missing stub packages were found. If missing + stub packages were found, they are installed and then another run + is performed. + .. option:: --junit-xml JUNIT_XML Causes mypy to generate a JUnit XML test result document with diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index 0a513efc2d4f..c4adc9b563bd 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -14,7 +14,7 @@ Can't install mypy using pip If installation fails, you've probably hit one of these issues: -* Mypy needs Python 3.5 or later to run. +* Mypy needs Python 3.6 or later to run. * You may have to run pip like this: ``python3 -m pip install mypy``. @@ -26,102 +26,102 @@ No errors reported for obviously wrong code There are several common reasons why obviously wrong code is not flagged as an error. -- **The function containing the error is not annotated.** Functions that - do not have any annotations (neither for any argument nor for the - return type) are not type-checked, and even the most blatant type - errors (e.g. ``2 + 'a'``) pass silently. The solution is to add - annotations. Where that isn't possible, functions without annotations - can be checked using :option:`--check-untyped-defs `. +**The function containing the error is not annotated.** Functions that +do not have any annotations (neither for any argument nor for the +return type) are not type-checked, and even the most blatant type +errors (e.g. ``2 + 'a'``) pass silently. The solution is to add +annotations. Where that isn't possible, functions without annotations +can be checked using :option:`--check-untyped-defs `. - Example: +Example: - .. code-block:: python +.. code-block:: python - def foo(a): - return '(' + a.split() + ')' # No error! + def foo(a): + return '(' + a.split() + ')' # No error! - This gives no error even though ``a.split()`` is "obviously" a list - (the author probably meant ``a.strip()``). The error is reported - once you add annotations: +This gives no error even though ``a.split()`` is "obviously" a list +(the author probably meant ``a.strip()``). The error is reported +once you add annotations: - .. code-block:: python +.. code-block:: python - def foo(a: str) -> str: - return '(' + a.split() + ')' - # error: Unsupported operand types for + ("str" and List[str]) + def foo(a: str) -> str: + return '(' + a.split() + ')' + # error: Unsupported operand types for + ("str" and List[str]) - If you don't know what types to add, you can use ``Any``, but beware: +If you don't know what types to add, you can use ``Any``, but beware: -- **One of the values involved has type 'Any'.** Extending the above - example, if we were to leave out the annotation for ``a``, we'd get - no error: +**One of the values involved has type 'Any'.** Extending the above +example, if we were to leave out the annotation for ``a``, we'd get +no error: - .. code-block:: python +.. code-block:: python - def foo(a) -> str: - return '(' + a.split() + ')' # No error! + def foo(a) -> str: + return '(' + a.split() + ')' # No error! - The reason is that if the type of ``a`` is unknown, the type of - ``a.split()`` is also unknown, so it is inferred as having type - ``Any``, and it is no error to add a string to an ``Any``. +The reason is that if the type of ``a`` is unknown, the type of +``a.split()`` is also unknown, so it is inferred as having type +``Any``, and it is no error to add a string to an ``Any``. - If you're having trouble debugging such situations, - :ref:`reveal_type() ` might come in handy. +If you're having trouble debugging such situations, +:ref:`reveal_type() ` might come in handy. - Note that sometimes library stubs have imprecise type information, - e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285 - `_ for the reason). +Note that sometimes library stubs have imprecise type information, +e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285 +`_ for the reason). -- :py:meth:`__init__ ` **method has no annotated - arguments or return type annotation.** :py:meth:`__init__ ` - is considered fully-annotated **if at least one argument is annotated**, - while mypy will infer the return type as ``None``. - The implication is that, for a :py:meth:`__init__ ` method - that has no argument, you'll have to explicitly annotate the return type - as ``None`` to type-check this :py:meth:`__init__ ` method: +:py:meth:`__init__ ` **method has no annotated +arguments or return type annotation.** :py:meth:`__init__ ` +is considered fully-annotated **if at least one argument is annotated**, +while mypy will infer the return type as ``None``. +The implication is that, for a :py:meth:`__init__ ` method +that has no argument, you'll have to explicitly annotate the return type +as ``None`` to type-check this :py:meth:`__init__ ` method: - .. code-block:: python +.. code-block:: python - def foo(s: str) -> str: - return s - - class A(): - def __init__(self, value: str): # Return type inferred as None, considered as typed method - self.value = value - foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" - - class B(): - def __init__(self): # No argument is annotated, considered as untyped method - foo(1) # No error! - - class C(): - def __init__(self) -> None: # Must specify return type to type-check - foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" - -- **Some imports may be silently ignored**. Another source of - unexpected ``Any`` values are the :option:`--ignore-missing-imports - ` and :option:`--follow-imports=skip - ` flags. When you use :option:`--ignore-missing-imports `, - any imported module that cannot be found is silently replaced with - ``Any``. When using :option:`--follow-imports=skip ` the same is true for - modules for which a ``.py`` file is found but that are not specified - on the command line. (If a ``.pyi`` stub is found it is always - processed normally, regardless of the value of - :option:`--follow-imports `.) To help debug the former situation (no - module found at all) leave out :option:`--ignore-missing-imports `; to get - clarity about the latter use :option:`--follow-imports=error `. You can - read up about these and other useful flags in :ref:`command-line`. - -- **A function annotated as returning a non-optional type returns 'None' - and mypy doesn't complain**. + def foo(s: str) -> str: + return s - .. code-block:: python + class A(): + def __init__(self, value: str): # Return type inferred as None, considered as typed method + self.value = value + foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" - def foo() -> str: - return None # No error! + class B(): + def __init__(self): # No argument is annotated, considered as untyped method + foo(1) # No error! - You may have disabled strict optional checking (see - :ref:`no_strict_optional` for more). + class C(): + def __init__(self) -> None: # Must specify return type to type-check + foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" + +**Some imports may be silently ignored**. Another source of +unexpected ``Any`` values are the :option:`--ignore-missing-imports +` and :option:`--follow-imports=skip +` flags. When you use :option:`--ignore-missing-imports `, +any imported module that cannot be found is silently replaced with +``Any``. When using :option:`--follow-imports=skip ` the same is true for +modules for which a ``.py`` file is found but that are not specified +on the command line. (If a ``.pyi`` stub is found it is always +processed normally, regardless of the value of +:option:`--follow-imports `.) To help debug the former situation (no +module found at all) leave out :option:`--ignore-missing-imports `; to get +clarity about the latter use :option:`--follow-imports=error `. You can +read up about these and other useful flags in :ref:`command-line`. + +**A function annotated as returning a non-optional type returns 'None' +and mypy doesn't complain**. + +.. code-block:: python + + def foo() -> str: + return None # No error! + +You may have disabled strict optional checking (see +:ref:`no_strict_optional` for more). .. _silencing_checker: @@ -367,19 +367,38 @@ above example: Complex type tests ------------------ -Mypy can usually infer the types correctly when using :py:func:`isinstance ` -type tests, but for other kinds of checks you may need to add an +Mypy can usually infer the types correctly when using :py:func:`isinstance `, +:py:func:`issubclass `, +or ``type(obj) is some_class`` type tests, +and even :ref:`user-defined type guards `, +but for other kinds of checks you may need to add an explicit type cast: .. code-block:: python - def f(o: object) -> None: - if type(o) is int: - o = cast(int, o) - g(o + 1) # This would be an error without the cast - ... - else: - ... + from typing import Sequence, cast + + def find_first_str(a: Sequence[object]) -> str: + index = next((i for i, s in enumerate(a) if isinstance(s, str)), -1) + if index < 0: + raise ValueError('No str found') + + found = a[index] # Has type "object", despite the fact that we know it is "str" + return cast(str, found) # We need an explicit cast to make mypy happy + +Alternatively, you can use an ``assert`` statement together with some +of the supported type inference techniques: + +.. code-block:: python + + def find_first_str(a: Sequence[object]) -> str: + index = next((i for i, s in enumerate(a) if isinstance(s, str)), -1) + if index < 0: + raise ValueError('No str found') + + found = a[index] # Has type "object", despite the fact that we know it is "str" + assert isinstance(found, str) # Now, "found" will be narrowed to "str" + return found # No need for the explicit "cast()" anymore .. note:: @@ -390,19 +409,11 @@ explicit type cast: runtime. The cast above would have been unnecessary if the type of ``o`` was ``Any``. -Mypy can't infer the type of ``o`` after the :py:class:`type() ` check -because it only knows about :py:func:`isinstance` (and the latter is better -style anyway). We can write the above code without a cast by using -:py:func:`isinstance`: +.. note:: -.. code-block:: python + You can read more about type narrowing techniques :ref:`here `. - def f(o: object) -> None: - if isinstance(o, int): # Mypy understands isinstance checks - g(o + 1) # Okay; type of o is inferred as int here - ... - -Type inference in mypy is designed to work well in common cases, to be +Type inference in Mypy is designed to work well in common cases, to be predictable and to let the type checker give useful error messages. More powerful type inference strategies often have complex and difficult-to-predict failure modes and could result in very @@ -428,8 +439,8 @@ More specifically, mypy will understand the use of :py:data:`sys.version_info` a import sys # Distinguishing between different versions of Python: - if sys.version_info >= (3, 5): - # Python 3.5+ specific definitions and imports + if sys.version_info >= (3, 8): + # Python 3.8+ specific definitions and imports elif sys.version_info[0] >= 3: # Python 3 specific definitions and imports else: @@ -621,48 +632,67 @@ You can install the latest development version of mypy from source. Clone the sudo python3 -m pip install --upgrade . Variables vs type aliases ------------------------------------ +------------------------- -Mypy has both type aliases and variables with types like ``Type[...]`` and it is important to know their difference. +Mypy has both *type aliases* and variables with types like ``Type[...]``. These are +subtly different, and it's important to understand how they differ to avoid pitfalls. -1. Variables with type ``Type[...]`` should be created by assignments with an explicit type annotations: +1. A variable with type ``Type[...]`` is defined using an assignment with an + explicit type annotation: -.. code-block:: python + .. code-block:: python - class A: ... - tp: Type[A] = A + class A: ... + tp: Type[A] = A -2. Aliases are created by assignments without an explicit type: +2. You can define a type alias using an assignment without an explicit type annotation + at the top level of a module: -.. code-block:: python + .. code-block:: python - class A: ... - Alias = A + class A: ... + Alias = A -3. The difference is that aliases are completely known statically and can be used in type context (annotations): + You can also use ``TypeAlias`` (:pep:`613`) to define an *explicit type alias*: -.. code-block:: python + .. code-block:: python + + from typing import TypeAlias # "from typing_extensions" in Python 3.9 and earlier + + class A: ... + Alias: TypeAlias = A + + You should always use ``TypeAlias`` to define a type alias in a class body or + inside a function. - class A: ... - class B: ... +The main difference is that the target of an alias is precisely known statically, and this +means that they can be used in type annotations and other *type contexts*. Type aliases +can't be defined conditionally (unless using +:ref:`supported Python version and platform checks `): - if random() > 0.5: - Alias = A - else: - Alias = B # error: Cannot assign multiple types to name "Alias" without an explicit "Type[...]" annotation \ - # error: Incompatible types in assignment (expression has type "Type[B]", variable has type "Type[A]") + .. code-block:: python - tp: Type[object] # tp is a type variable - if random() > 0.5: - tp = A - else: - tp = B # This is OK + class A: ... + class B: ... - def fun1(x: Alias) -> None: ... # This is OK - def fun2(x: tp) -> None: ... # error: Variable "__main__.tp" is not valid as a type + if random() > 0.5: + Alias = A + else: + # error: Cannot assign multiple types to name "Alias" without an + # explicit "Type[...]" annotation + Alias = B + + tp: Type[object] # "tp" is a variable with a type object value + if random() > 0.5: + tp = A + else: + tp = B # This is OK + + def fun1(x: Alias) -> None: ... # OK + def fun2(x: tp) -> None: ... # Error: "tp" is not valid as a type Incompatible overrides ------------------------------- +---------------------- It's unsafe to override a method with a more specific argument type, as it violates the `Liskov substitution principle @@ -718,6 +748,8 @@ not necessary: def test(self, t: List[int]) -> Sequence[str]: # type: ignore[override] ... +.. _unreachable: + Unreachable code ---------------- @@ -773,7 +805,6 @@ False: If you use the :option:`--warn-unreachable ` flag, mypy will generate an error about each unreachable code block. - Narrowing and inner functions ----------------------------- diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index a5235516739f..c34f23d9e169 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -13,9 +13,7 @@ to read a different file instead (see :ref:`config-file-flag`). It is important to understand that there is no merging of configuration files, as it would lead to ambiguity. The :option:`--config-file ` flag has the highest precedence and must be correct; otherwise mypy will report -an error and exit. Without command line option, mypy will look for defaults, -but will use only one of them. The first one to read is ``mypy.ini``, -then ``.mypy.ini``, and finally ``setup.cfg``. +an error and exit. Without command line option, mypy will look for configuration files in the above mentioned order. Most flags correspond closely to :ref:`command-line flags ` but there are some differences in flag names and some @@ -199,12 +197,19 @@ section of the command line docs. .. confval:: exclude - :type: regular expression + :type: newline separated list of regular expressions - A regular expression that matches file names, directory names and paths + A newline list of regular expression that matches file names, directory names and paths which mypy should ignore while recursively discovering files to check. Use forward slashes on all platforms. + .. code-block:: ini + + [mypy] + exclude = + ^file1\.py$ + ^file2\.py$ + For more details, see :option:`--exclude `. This option may only be set in the global section (``[mypy]``). @@ -256,6 +261,10 @@ section of the command line docs. ``error``. For explanations see the discussion for the :option:`--follow-imports ` command line flag. + Using this option in a per-module section (potentially with a wildcard, + as described at the top of this page) is a good way to prevent mypy from + checking portions of your code. + If this option is used in a per-module section, the module name should match the name of the *imported* module, not the module containing the import statement. @@ -321,7 +330,7 @@ Platform configuration :type: string Specifies the Python version used to parse and check the target - program. The string should be in the format ``DIGIT.DIGIT`` -- + program. The string should be in the format ``MAJOR.MINOR`` -- for example ``2.7``. The default is the version of the Python interpreter used to run mypy. @@ -608,6 +617,18 @@ section of the command line docs. Prohibit equality checks, identity checks, and container checks between non-overlapping types. +.. confval:: strict + + :type: boolean + :default: False + + Enable all optional error checking flags. You can see the list of + flags enabled by strict mode in the full :option:`mypy --help` + output. + + Note: the exact list of flags enabled by :confval:`strict` may + change over time. + Configuring error messages ************************** @@ -926,10 +947,10 @@ Instead of using a ``mypy.ini`` file, a ``pyproject.toml`` file (as specified by * Boolean values should be all lower case -Please see the `TOML Documentation`_ for more details and information on +Please see the `TOML Documentation`_ for more details and information on what is allowed in a ``toml`` file. See `PEP 518`_ for more information on the layout and structure of the ``pyproject.toml`` file. - + Example ``pyproject.toml`` ************************** diff --git a/docs/source/dynamic_typing.rst b/docs/source/dynamic_typing.rst index cea5248a3712..add445009666 100644 --- a/docs/source/dynamic_typing.rst +++ b/docs/source/dynamic_typing.rst @@ -80,7 +80,7 @@ operations: n = 1 # type: int n = o # Error! -You can use :py:func:`~typing.cast` (see chapter :ref:`casts`) or :py:func:`isinstance` to -go from a general type such as :py:class:`object` to a more specific -type (subtype) such as ``int``. :py:func:`~typing.cast` is not needed with +You can use different :ref:`type narrowing ` +techniques to narrow :py:class:`object` to a more specific +type (subtype) such as ``int``. Type narrowing is not needed with dynamically typed values (values with type ``Any``). diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 3afde02e3ee6..852913ce79bb 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -117,15 +117,15 @@ Example: .. code-block:: python - from typing import List, Optional + from typing import Optional - def first(x: List[int]) -> Optional[int]: + def first(x: list[int]) -> Optional[int]: return x[0] if x else 0 - t = (5, 4) - # Error: Argument 1 to "first" has incompatible type "Tuple[int, int]"; - # expected "List[int]" [arg-type] - print(first(t)) + t = (5, 4) + # Error: Argument 1 to "first" has incompatible type "tuple[int, int]"; + # expected "list[int]" [arg-type] + print(first(t)) Check calls to overloaded functions [call-overload] --------------------------------------------------- @@ -171,26 +171,24 @@ This example incorrectly uses the function ``log`` as a type: .. code-block:: python - from typing import List + def log(x: object) -> None: + print('log:', repr(x)) - def log(x: object) -> None: - print('log:', repr(x)) - - # Error: Function "t.log" is not valid as a type [valid-type] - def log_all(objs: List[object], f: log) -> None: - for x in objs: - f(x) + # Error: Function "t.log" is not valid as a type [valid-type] + def log_all(objs: list[object], f: log) -> None: + for x in objs: + f(x) You can use :py:data:`~typing.Callable` as the type for callable objects: .. code-block:: python - from typing import List, Callable + from typing import Callable - # OK - def log_all(objs: List[object], f: Callable[[object], None]) -> None: - for x in objs: - f(x) + # OK + def log_all(objs: list[object], f: Callable[[object], None]) -> None: + for x in objs: + f(x) Require annotation if variable type is unclear [var-annotated] -------------------------------------------------------------- @@ -206,23 +204,21 @@ Example with an error: .. code-block:: python - class Bundle: - def __init__(self) -> None: - # Error: Need type annotation for "items" - # (hint: "items: List[] = ...") [var-annotated] - self.items = [] + class Bundle: + def __init__(self) -> None: + # Error: Need type annotation for "items" + # (hint: "items: list[] = ...") [var-annotated] + self.items = [] - reveal_type(Bundle().items) # list[Any] + reveal_type(Bundle().items) # list[Any] To address this, we add an explicit annotation: .. code-block:: python - from typing import List - - class Bundle: - def __init__(self) -> None: - self.items: List[str] = [] # OK + class Bundle: + def __init__(self) -> None: + self.items: list[str] = [] # OK reveal_type(Bundle().items) # list[str] @@ -377,10 +373,10 @@ Example: a['x'] # OK - # Error: Invalid index type "int" for "Dict[str, int]"; expected type "str" [index] + # Error: Invalid index type "int" for "dict[str, int]"; expected type "str" [index] print(a[1]) - # Error: Invalid index type "bytes" for "Dict[str, int]"; expected type "str" [index] + # Error: Invalid index type "bytes" for "dict[str, int]"; expected type "str" [index] a[b'x'] = 4 Check list items [list-item] @@ -394,10 +390,8 @@ Example: .. code-block:: python - from typing import List - # Error: List item 0 has incompatible type "int"; expected "str" [list-item] - a: List[str] = [0] + a: list[str] = [0] Check dict items [dict-item] ---------------------------- @@ -410,10 +404,8 @@ Example: .. code-block:: python - from typing import Dict - # Error: Dict entry 0 has incompatible type "str": "str"; expected "str": "int" [dict-item] - d: Dict[str, int] = {'key': 'value'} + d: dict[str, int] = {'key': 'value'} Check TypedDict items [typeddict-item] -------------------------------------- @@ -545,7 +537,7 @@ Check instantiation of abstract classes [abstract] -------------------------------------------------- Mypy generates an error if you try to instantiate an abstract base -class (ABC). An abtract base class is a class with at least one +class (ABC). An abstract base class is a class with at least one abstract method or attribute. (See also :py:mod:`abc` module documentation) Sometimes a class is made accidentally abstract, often due to an diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index d88525f33bb2..1e035fcf7f69 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -19,10 +19,10 @@ Check that type arguments exist [type-arg] ------------------------------------------ If you use :option:`--disallow-any-generics `, mypy requires that each generic -type has values for each type argument. For example, the types ``List`` or -``dict`` would be rejected. You should instead use types like ``List[int]`` or -``Dict[str, int]``. Any omitted generic type arguments get implicit ``Any`` -values. The type ``List`` is equivalent to ``List[Any]``, and so on. +type has values for each type argument. For example, the types ``list`` or +``dict`` would be rejected. You should instead use types like ``list[int]`` or +``dict[str, int]``. Any omitted generic type arguments get implicit ``Any`` +values. The type ``list`` is equivalent to ``list[Any]``, and so on. Example: @@ -30,10 +30,8 @@ Example: # mypy: disallow-any-generics - from typing import List - - # Error: Missing type parameters for generic type "List" [type-arg] - def remove_dups(items: List) -> List: + # Error: Missing type parameters for generic type "list" [type-arg] + def remove_dups(items: list) -> list: ... Check that every function has an annotation [no-untyped-def] @@ -214,3 +212,46 @@ mypy generates an error if it thinks that an expression is redundant. # Error: If condition in comprehension is always true [redundant-expr] [i for i in range(x) if isinstance(i, int)] + + +Check that expression is not implicitly true in boolean context [truthy-bool] +----------------------------------------------------------------------------- + +Warn when an expression whose type does not implement ``__bool__`` or ``__len__`` is used in boolean context, +since unless implemented by a sub-type, the expression will always evaluate to true. + +.. code-block:: python + + # mypy: enable-error-code truthy-bool + + class Foo: + pass + foo = Foo() + # Error: "foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context + if foo: + ... + + +This check might falsely imply an error. For example, ``Iterable`` does not implement +``__len__`` and so this code will be flagged: + +.. code-block:: python + + # mypy: enable-error-code truthy-bool + from typing import Iterable + + def transform(items: Iterable[int]) -> Iterable[int]: + # Error: "items" has type "Iterable[int]" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] + if not items: + return [42] + return [x + 1 for x in items] + + + +If called as ``transform((int(s) for s in []))``, this function would not return ``[42]`` unlike what the author +might have intended. Of course it's possible that ``transform`` is only passed ``list`` objects, and so there is +no error in practice. In such case, it might be prudent to annotate ``items: Sequence[int]``. + +This is similar in concept to ensuring that an expression's type implements an expected interface (e.g. ``Sized``), +except that attempting to invoke an undefined method (e.g. ``__len__``) results in an error, +while attempting to evaluate an object in boolean context without a concrete implementation results in a truthy value. diff --git a/docs/source/error_codes.rst b/docs/source/error_codes.rst index 8a654571bc6b..5255a6984b7b 100644 --- a/docs/source/error_codes.rst +++ b/docs/source/error_codes.rst @@ -31,6 +31,8 @@ or config `show_error_codes = True` to display error codes. Error codes are show $ mypy --show-error-codes prog.py prog.py:1: error: "str" has no attribute "trim" [attr-defined] +.. _silence-error-codes: + Silencing errors based on error codes ------------------------------------- diff --git a/docs/source/extending_mypy.rst b/docs/source/extending_mypy.rst index 90e5f2f1fec1..5c59bef506cc 100644 --- a/docs/source/extending_mypy.rst +++ b/docs/source/extending_mypy.rst @@ -9,10 +9,10 @@ Integrating mypy into another Python application ************************************************ It is possible to integrate mypy into another Python 3 application by -importing ``mypy.api`` and calling the ``run`` function with a parameter of type ``List[str]``, containing +importing ``mypy.api`` and calling the ``run`` function with a parameter of type ``list[str]``, containing what normally would have been the command line arguments to mypy. -Function ``run`` returns a ``Tuple[str, str, int]``, namely +Function ``run`` returns a ``tuple[str, str, int]``, namely ``(, , )``, in which ```` is what mypy normally writes to :py:data:`sys.stdout`, ```` is what mypy normally writes to :py:data:`sys.stderr` and ``exit_status`` is the exit status mypy normally @@ -246,7 +246,7 @@ when the configuration for a module changes, we want to invalidate mypy's cache for that module so that it can be rechecked. This hook should be used to report to mypy any relevant configuration data, so that mypy knows to recheck the module if the configuration changes. -The hooks hould return data encodable as JSON. +The hooks should return data encodable as JSON. Notes about the semantic analyzer ********************************* diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 43ba3d0d066e..2a79498dd792 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -201,7 +201,8 @@ the following aspects, among others: Does it run on PyPy? ********************* -No. MyPy relies on `typed-ast +Somewhat. With PyPy 3.8, mypy is at least able to type check itself. +With older versions of PyPy, mypy relies on `typed-ast `_, which uses several APIs that PyPy does not support (including some internal CPython APIs). diff --git a/docs/source/final_attrs.rst b/docs/source/final_attrs.rst index 8c42ae9ec56b..e5d209644fce 100644 --- a/docs/source/final_attrs.rst +++ b/docs/source/final_attrs.rst @@ -119,9 +119,9 @@ annotations. Using it in any other position is an error. In particular, .. code-block:: python - x: List[Final[int]] = [] # Error! + x: list[Final[int]] = [] # Error! - def fun(x: Final[List[int]]) -> None: # Error! + def fun(x: Final[list[int]]) -> None: # Error! ... ``Final`` and :py:data:`~typing.ClassVar` should not be used together. Mypy will infer diff --git a/docs/source/generics.rst b/docs/source/generics.rst index 817466d2469a..7e64aa181403 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -2,7 +2,7 @@ Generics ======== This section explains how you can define your own generic classes that take -one or more type parameters, similar to built-in types such as ``List[X]``. +one or more type parameters, similar to built-in types such as ``list[X]``. User-defined generics are a moderately advanced feature and you can get far without ever using them -- feel free to skip this section and come back later. @@ -13,8 +13,8 @@ Defining generic classes The built-in collection classes are generic classes. Generic types have one or more type parameters, which can be arbitrary types. For -example, ``Dict[int, str]`` has the type parameters ``int`` and -``str``, and ``List[int]`` has a type parameter ``int``. +example, ``dict[int, str]`` has the type parameters ``int`` and +``str``, and ``list[int]`` has a type parameter ``int``. Programs can also define new generic classes. Here is a very simple generic class that represents a stack: @@ -28,7 +28,7 @@ generic class that represents a stack: class Stack(Generic[T]): def __init__(self) -> None: # Create an empty list with items of type T - self.items: List[T] = [] + self.items: list[T] = [] def push(self, item: T) -> None: self.items.append(item) @@ -40,7 +40,7 @@ generic class that represents a stack: return not self.items The ``Stack`` class can be used to represent a stack of any type: -``Stack[int]``, ``Stack[Tuple[int, str]]``, etc. +``Stack[int]``, ``Stack[tuple[int, str]]``, etc. Using ``Stack`` is similar to built-in container types: @@ -77,8 +77,8 @@ Generic class internals *********************** You may wonder what happens at runtime when you index -``Stack``. Actually, indexing ``Stack`` returns essentially a copy -of ``Stack`` that returns instances of the original class on +``Stack``. Indexing ``Stack`` returns a *generic alias* +to ``Stack`` that returns instances of the original class on instantiation: .. code-block:: python @@ -90,25 +90,46 @@ instantiation: >>> print(Stack[int]().__class__) __main__.Stack -Note that built-in types :py:class:`list`, :py:class:`dict` and so on do not support -indexing in Python. This is why we have the aliases :py:class:`~typing.List`, :py:class:`~typing.Dict` -and so on in the :py:mod:`typing` module. Indexing these aliases gives -you a class that directly inherits from the target class in Python: +Generic aliases can be instantiated or subclassed, similar to real +classes, but the above examples illustrate that type variables are +erased at runtime. Generic ``Stack`` instances are just ordinary +Python objects, and they have no extra runtime overhead or magic due +to being generic, other than a metaclass that overloads the indexing +operator. + +Note that in Python 3.8 and lower, the built-in types +:py:class:`list`, :py:class:`dict` and others do not support indexing. +This is why we have the aliases :py:class:`~typing.List`, +:py:class:`~typing.Dict` and so on in the :py:mod:`typing` +module. Indexing these aliases gives you a generic alias that +resembles generic aliases constructed by directly indexing the target +class in more recent versions of Python: .. code-block:: python + >>> # Only relevant for Python 3.8 and below + >>> # For Python 3.9 onwards, prefer `list[int]` syntax >>> from typing import List >>> List[int] typing.List[int] - >>> List[int].__bases__ - (, typing.MutableSequence) -Generic types could be instantiated or subclassed as usual classes, -but the above examples illustrate that type variables are erased at -runtime. Generic ``Stack`` instances are just ordinary -Python objects, and they have no extra runtime overhead or magic due -to being generic, other than a metaclass that overloads the indexing -operator. +Note that the generic aliases in ``typing`` don't support constructing +instances: + +.. code-block:: python + + >>> from typing import List + >>> List[int]() + Traceback (most recent call last): + ... + TypeError: Type List cannot be instantiated; use list() instead + +.. note:: + + In Python 3.6 indexing generic types or type aliases results in actual + type objects. This means that generic types in type annotations can + have a significant runtime cost. This was changed in Python 3.7, and + indexing generic types became a cheap operation. .. _generic-subclasses: @@ -121,7 +142,7 @@ non-generic. For example: .. code-block:: python - from typing import Generic, TypeVar, Mapping, Iterator, Dict + from typing import Generic, TypeVar, Mapping, Iterator KT = TypeVar('KT') VT = TypeVar('VT') @@ -136,7 +157,7 @@ non-generic. For example: items: MyMap[str, int] # Okay - class StrDict(Dict[str, str]): # This is a non-generic subclass of Dict + class StrDict(dict[str, str]): # This is a non-generic subclass of dict def __str__(self) -> str: return 'StrDict({})'.format(super().__str__()) @@ -284,7 +305,7 @@ For class methods, you can also define generic ``cls``, using :py:class:`Type[T] .. code-block:: python - from typing import TypeVar, Tuple, Type + from typing import TypeVar, Type T = TypeVar('T', bound='Friend') @@ -292,7 +313,7 @@ For class methods, you can also define generic ``cls``, using :py:class:`Type[T] other = None # type: Friend @classmethod - def make_pair(cls: Type[T]) -> Tuple[T, T]: + def make_pair(cls: Type[T]) -> tuple[T, T]: a, b = cls(), cls() a.other = b b.other = a @@ -345,8 +366,8 @@ Let us illustrate this by few simple examples: .. code-block:: python - def salaries(staff: List[Manager], - accountant: Callable[[Manager], int]) -> List[int]: ... + def salaries(staff: list[Manager], + accountant: Callable[[Manager], int]) -> list[int]: ... This function needs a callable that can calculate a salary for managers, and if we give it a callable that can calculate a salary for an arbitrary @@ -363,10 +384,10 @@ Let us illustrate this by few simple examples: def rotate(self): ... - def add_one(things: List[Shape]) -> None: + def add_one(things: list[Shape]) -> None: things.append(Shape()) - my_things: List[Circle] = [] + my_things: list[Circle] = [] add_one(my_things) # This may appear safe, but... my_things[0].rotate() # ...this will fail @@ -532,7 +553,7 @@ Here's a complete example of a function decorator: .. code-block:: python - from typing import Any, Callable, TypeVar, Tuple, cast + from typing import Any, Callable, TypeVar, cast F = TypeVar('F', bound=Callable[..., Any]) @@ -562,7 +583,7 @@ non-function (e.g. ``my_decorator(1)``) will be rejected. Also note that the ``wrapper()`` function is not type-checked. Wrapper functions are typically small enough that this is not a big problem. This is also the reason for the :py:func:`~typing.cast` call in the -``return`` statement in ``my_decorator()``. See :ref:`casts`. +``return`` statement in ``my_decorator()``. See :ref:`casts `. .. _decorator-factories: @@ -724,11 +745,11 @@ variables replaced with ``Any``. Examples (following :pep:`PEP 484: Type aliases .. code-block:: python - from typing import TypeVar, Iterable, Tuple, Union, Callable + from typing import TypeVar, Iterable, Union, Callable S = TypeVar('S') - TInt = Tuple[int, S] + TInt = tuple[int, S] UInt = Union[S, int] CBack = Callable[..., S] @@ -736,11 +757,11 @@ variables replaced with ``Any``. Examples (following :pep:`PEP 484: Type aliases ... def activate(cb: CBack[S]) -> S: # Same as Callable[..., S] ... - table_entry: TInt # Same as Tuple[int, Any] + table_entry: TInt # Same as tuple[int, Any] T = TypeVar('T', int, float, complex) - Vec = Iterable[Tuple[T, T]] + Vec = Iterable[tuple[T, T]] def inproduct(v: Vec[T]) -> T: return sum(x*y for x, y in v) @@ -748,8 +769,8 @@ variables replaced with ``Any``. Examples (following :pep:`PEP 484: Type aliases def dilate(v: Vec[T], scale: T) -> Vec[T]: return ((x * scale, y * scale) for x, y in v) - v1: Vec[int] = [] # Same as Iterable[Tuple[int, int]] - v2: Vec = [] # Same as Iterable[Tuple[Any, Any]] + v1: Vec[int] = [] # Same as Iterable[tuple[int, int]] + v2: Vec = [] # Same as Iterable[tuple[Any, Any]] v3: Vec[int, int] = [] # Error: Invalid alias, too many type arguments! Type aliases can be imported from modules just like other names. An diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 12c05c0d32e0..f9b21d8dbf60 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -12,7 +12,7 @@ may not make much sense otherwise. Installing and running mypy *************************** -Mypy requires Python 3.5 or later to run. Once you've +Mypy requires Python 3.6 or later to run. Once you've `installed Python 3 `_, install mypy using pip: @@ -153,8 +153,8 @@ Arguments with default values can be annotated like so: .. code-block:: python def stars(*args: int, **kwargs: float) -> None: - # 'args' has type 'Tuple[int, ...]' (a tuple of ints) - # 'kwargs' has type 'Dict[str, float]' (a dict of strs to floats) + # 'args' has type 'tuple[int, ...]' (a tuple of ints) + # 'kwargs' has type 'dict[str, float]' (a dict of strs to floats) for arg in args: print(arg) for key, value in kwargs: @@ -182,8 +182,8 @@ strings, use the ``list[str]`` type (Python 3.9 and later): greet_all(names) # Ok! greet_all(ages) # Error due to incompatible types -The ``list`` type is an example of something called a *generic type*: it can -accept one or more *type parameters*. In this case, we *parameterized* ``list`` +The :py:class:`list` type is an example of something called a *generic type*: it can +accept one or more *type parameters*. In this case, we *parameterized* :py:class:`list` by writing ``list[str]``. This lets mypy know that ``greet_all`` accepts specifically lists containing strings, and not lists containing ints or any other type. @@ -207,9 +207,8 @@ After all, there's no reason why this function must accept *specifically* a list it would run just fine if you were to pass in a tuple, a set, or any other custom iterable. You can express this idea using the -:py:class:`collections.abc.Iterable` type instead of -:py:class:`~typing.List` (or :py:class:`typing.Iterable` in Python -3.8 and earlier): +:py:class:`collections.abc.Iterable` (or :py:class:`typing.Iterable` in Python +3.8 and earlier) type instead of :py:class:`list` : .. code-block:: python @@ -268,7 +267,7 @@ generic types or your own type aliases) by looking through the In some examples we use capitalized variants of types, such as ``List``, and sometimes we use plain ``list``. They are equivalent, - but the prior variant is needed if you are not using a recent Python. + but the prior variant is needed if you are using Python 3.8 or earlier. Local type inference ******************** @@ -286,7 +285,7 @@ in that if statement. As another example, consider the following function. Mypy can type check this function without a problem: it will use the available context and deduce that ``output`` must be -of type ``List[float]`` and that ``num`` must be of type ``float``: +of type ``list[float]`` and that ``num`` must be of type ``float``: .. code-block:: python @@ -351,7 +350,7 @@ additional stubs using pip (see :ref:`fix-missing-imports` and :ref:`installed-packages` for the details). For example, you can install the stubs for the ``requests`` package like this: -.. code-block:: +.. code-block:: shell python3 -m pip install types-requests diff --git a/docs/source/index.rst b/docs/source/index.rst index c9ee1ce1f9ad..9cd9220c60b9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -39,7 +39,7 @@ Mypy is a static type checker for Python 3 and Python 2.7. protocols dynamic_typing python2 - casts + type_narrowing duck_type_compatibility stubs generics @@ -60,6 +60,7 @@ Mypy is a static type checker for Python 3 and Python 2.7. installed_packages extending_mypy stubgen + stubtest .. toctree:: :maxdepth: 2 diff --git a/docs/source/installed_packages.rst b/docs/source/installed_packages.rst index d640f5d13afb..8db113e4ba9e 100644 --- a/docs/source/installed_packages.rst +++ b/docs/source/installed_packages.rst @@ -177,3 +177,13 @@ If you have separate stubs for Python 2 and Python 3, you can place the Python 2 stubs in a directory with the suffix ``-python2-stubs``. We recommend that Python 2 and Python 3 stubs are bundled together for simplicity, instead of distributing them separately. + +The instructions above are enough to ensure that the built wheels +contain the appropriate files. However, to ensure inclusion inside the +``sdist`` (``.tar.gz`` archive), you may also need to modify the +inclusion rules in your ``MANIFEST.in``: + +.. code-block:: text + + global-include *.pyi + global-include *.typed diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 1efc2b30c328..866535949d74 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -108,23 +108,24 @@ The ``Any`` type is discussed in more detail in section :ref:`dynamic-typing`. Tuple types *********** -The type ``Tuple[T1, ..., Tn]`` represents a tuple with the item types ``T1``, ..., ``Tn``: +The type ``tuple[T1, ..., Tn]`` represents a tuple with the item types ``T1``, ..., ``Tn``: .. code-block:: python - def f(t: Tuple[int, str]) -> None: + # Use `typing.Tuple` in Python 3.8 and earlier + def f(t: tuple[int, str]) -> None: t = 1, 'foo' # OK t = 'foo', 1 # Type check error A tuple type of this kind has exactly a specific number of items (2 in the above example). Tuples can also be used as immutable, -varying-length sequences. You can use the type ``Tuple[T, ...]`` (with +varying-length sequences. You can use the type ``tuple[T, ...]`` (with a literal ``...`` -- it's part of the syntax) for this purpose. Example: .. code-block:: python - def print_squared(t: Tuple[int, ...]) -> None: + def print_squared(t: tuple[int, ...]) -> None: for n in t: print(n, n ** 2) @@ -134,12 +135,12 @@ purpose. Example: .. note:: - Usually it's a better idea to use ``Sequence[T]`` instead of ``Tuple[T, ...]``, as + Usually it's a better idea to use ``Sequence[T]`` instead of ``tuple[T, ...]``, as :py:class:`~typing.Sequence` is also compatible with lists and other non-tuple sequences. .. note:: - ``Tuple[...]`` is valid as a base class in Python 3.6 and later, and + ``tuple[...]`` is valid as a base class in Python 3.6 and later, and always in stub files. In earlier Python versions you can sometimes work around this limitation by using a named tuple as a base class (see section :ref:`named-tuples`). @@ -194,7 +195,7 @@ using bidirectional type inference: .. code-block:: python - l = map(lambda x: x + 1, [1, 2, 3]) # Infer x as int and l as List[int] + l = map(lambda x: x + 1, [1, 2, 3]) # Infer x as int and l as list[int] If you want to give the argument or return value types explicitly, use an ordinary, perhaps nested function definition. @@ -353,20 +354,16 @@ and ``None`` is used as a dummy, placeholder initializer: .. code-block:: python - from typing import List - class Container: - items = None # type: List[str] # OK (only with type comment) + items = None # type: list[str] # OK (only with type comment) This is not a problem when using variable annotations, since no initializer is needed: .. code-block:: python - from typing import List - class Container: - items: List[str] # No initializer + items: list[str] # No initializer Mypy generally uses the first assignment to a variable to infer the type of the variable. However, if you assign both a ``None`` @@ -419,8 +416,6 @@ the runtime with some limitations (see :ref:`runtime_troubles`). .. code-block:: python - from typing import List - t1: int | str # equivalent to Union[int, str] t2: int | None # equivalent to Optional[int] @@ -505,7 +500,7 @@ In certain situations, type names may end up being long and painful to type: .. code-block:: python - def f() -> Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]]: + def f() -> Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]]: ... When cases like this arise, you can define a type alias by simply @@ -513,7 +508,7 @@ assigning the type to a variable: .. code-block:: python - AliasType = Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]] + AliasType = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]] # Now we can use AliasType in place of the full name: @@ -526,6 +521,25 @@ assigning the type to a variable: another type -- it's equivalent to the target type except for :ref:`generic aliases `. +Since Mypy 0.930 you can also use *explicit type aliases*, which were +introduced in :pep:`613`. + +There can be confusion about exactly when an assignment defines an implicit type alias -- +for example, when the alias contains forward references, invalid types, or violates some other +restrictions on type alias declarations. Because the +distinction between an unannotated variable and a type alias is implicit, +ambiguous or incorrect type alias declarations default to defining +a normal variable instead of a type alias. + +Explicit type aliases are unambiguous and can also improve readability by +making the intent clear: + +.. code-block:: python + + from typing import TypeAlias # "from typing_extensions" in Python 3.9 and earlier + + AliasType: TypeAlias = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]] + .. _named-tuples: Named tuples @@ -566,6 +580,31 @@ Python 3.6 introduced an alternative, class-based syntax for named tuples with t p = Point(x=1, y='x') # Argument has incompatible type "str"; expected "int" +.. note:: + + You can use the raw ``NamedTuple`` "pseudo-class" in type annotations + if any ``NamedTuple`` object is valid. + + For example, it can be useful for deserialization: + + .. code-block:: python + + def deserialize_named_tuple(arg: NamedTuple) -> Dict[str, Any]: + return arg._asdict() + + Point = namedtuple('Point', ['x', 'y']) + Person = NamedTuple('Person', [('name', str), ('age', int)]) + + deserialize_named_tuple(Point(x=1, y=2)) # ok + deserialize_named_tuple(Person(name='Nikita', age=18)) # ok + + # Error: Argument 1 to "deserialize_named_tuple" has incompatible type + # "Tuple[int, int]"; expected "NamedTuple" + deserialize_named_tuple((1, 2)) + + Note that this behavior is highly experimental, non-standard, + and may not be supported by other type checkers and IDEs. + .. _type-of-class: The type of class objects @@ -702,7 +741,7 @@ For more details, see :ref:`type-variable-value-restriction`. Generators ********** -A basic generator that only yields values can be annotated as having a return +A basic generator that only yields values can be succinctly annotated as having a return type of either :py:class:`Iterator[YieldType] ` or :py:class:`Iterable[YieldType] `. For example: .. code-block:: python @@ -711,9 +750,20 @@ type of either :py:class:`Iterator[YieldType] ` or :py:class:`I for i in range(n): yield i * i +A good rule of thumb is to annotate functions with the most specific return +type possible. However, you should also take care to avoid leaking implementation +details into a function's public API. In keeping with these two principles, prefer +:py:class:`Iterator[YieldType] ` over +:py:class:`Iterable[YieldType] ` as the return-type annotation for a +generator function, as it lets mypy know that users are able to call :py:func:`next` on +the object returned by the function. Nonetheless, bear in mind that ``Iterable`` may +sometimes be the better option, if you consider it an implementation detail that +``next()`` can be called on the object returned by your function. + If you want your generator to accept values via the :py:meth:`~generator.send` method or return -a value, you should use the -:py:class:`Generator[YieldType, SendType, ReturnType] ` generic type instead. For example: +a value, on the other hand, you should use the +:py:class:`Generator[YieldType, SendType, ReturnType] ` generic type instead of +either ``Iterator`` or ``Iterable``. For example: .. code-block:: python @@ -736,7 +786,7 @@ annotated the first example as the following: for i in range(n): yield i * i -This is slightly different from using ``Iterable[int]`` or ``Iterator[int]``, +This is slightly different from using ``Iterator[int]`` or ``Iterable[int]``, since generators have :py:meth:`~generator.close`, :py:meth:`~generator.send`, and :py:meth:`~generator.throw` methods that -generic iterables don't. If you will call these methods on the returned -generator, use the :py:class:`~typing.Generator` type instead of :py:class:`~typing.Iterable` or :py:class:`~typing.Iterator`. +generic iterators and iterables don't. If you plan to call these methods on the returned +generator, use the :py:class:`~typing.Generator` type instead of :py:class:`~typing.Iterator` or :py:class:`~typing.Iterable`. diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index a223011effe9..b1669d01062a 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -142,7 +142,7 @@ as adding an explicit ``Literal[...]`` annotation, it often leads to the same ef in practice. The main cases where the behavior of context-sensitive vs true literal types differ are -when you try using those types in places that are not explicitly expecting a ``Literal[...]``. +when you try using those types in places that are not explicitly expecting a ``Literal[...]``. For example, compare and contrast what happens when you try appending these types to a list: .. code-block:: python @@ -152,16 +152,16 @@ For example, compare and contrast what happens when you try appending these type a: Final = 19 b: Literal[19] = 19 - # Mypy will chose to infer List[int] here. + # Mypy will choose to infer list[int] here. list_of_ints = [] list_of_ints.append(a) - reveal_type(list_of_ints) # Revealed type is "List[int]" + reveal_type(list_of_ints) # Revealed type is "list[int]" # But if the variable you're appending is an explicit Literal, mypy - # will infer List[Literal[19]]. + # will infer list[Literal[19]]. list_of_lits = [] list_of_lits.append(b) - reveal_type(list_of_lits) # Revealed type is "List[Literal[19]]" + reveal_type(list_of_lits) # Revealed type is "list[Literal[19]]" Intelligent indexing @@ -208,7 +208,7 @@ corresponding to some particular index, we can use Literal types like so: # You can also index using unions of literals id_key: Literal["main_id", "backup_id"] - reveal_type(d[id_key]) # Revealed type is "int" + reveal_type(d[id_key]) # Revealed type is "int" .. _tagged_unions: @@ -248,7 +248,7 @@ type. Then, you can discriminate between each kind of TypedDict by checking the # Literal["new-job", "cancel-job"], but the check below will narrow # the type to either Literal["new-job"] or Literal["cancel-job"]. # - # This in turns narrows the type of 'event' to either NewJobEvent + # This in turns narrows the type of 'event' to either NewJobEvent # or CancelJobEvent. if event["tag"] == "new-job": print(event["job_name"]) @@ -289,6 +289,73 @@ using ``isinstance()``: This feature is sometimes called "sum types" or "discriminated union types" in other programming languages. +Exhaustiveness checks +********************* + +You may want to check that some code covers all possible +``Literal`` or ``Enum`` cases. Example: + +.. code-block:: python + + from typing import Literal + + PossibleValues = Literal['one', 'two'] + + def validate(x: PossibleValues) -> bool: + if x == 'one': + return True + elif x == 'two': + return False + raise ValueError(f'Invalid value: {x}') + + assert validate('one') is True + assert validate('two') is False + +In the code above, it's easy to make a mistake. You can +add a new literal value to ``PossibleValues`` but forget +to handle it in the ``validate`` function: + +.. code-block:: python + + PossibleValues = Literal['one', 'two', 'three'] + +Mypy won't catch that ``'three'`` is not covered. If you want mypy to +perform an exhaustiveness check, you need to update your code to use an +``assert_never()`` check: + +.. code-block:: python + + from typing import Literal, NoReturn + + PossibleValues = Literal['one', 'two'] + + def assert_never(value: NoReturn) -> NoReturn: + # This also works at runtime as well + assert False, f'This code should never be reached, got: {value}' + + def validate(x: PossibleValues) -> bool: + if x == 'one': + return True + elif x == 'two': + return False + assert_never(x) + +Now if you add a new value to ``PossibleValues`` but don't update ``validate``, +mypy will spot the error: + +.. code-block:: python + + PossibleValues = Literal['one', 'two', 'three'] + + def validate(x: PossibleValues) -> bool: + if x == 'one': + return True + elif x == 'two': + return False + # Error: Argument 1 to "assert_never" has incompatible type "Literal['three']"; + # expected "NoReturn" + assert_never(x) + Limitations *********** diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index 16ec058f6d67..82a6568afcb2 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -84,7 +84,7 @@ certain values from base class instances. Example: ... However, this approach introduces some runtime overhead. To avoid this, the typing -module provides a helper function :py:func:`NewType ` that creates simple unique types with +module provides a helper object :py:func:`NewType ` that creates simple unique types with almost zero runtime overhead. Mypy will treat the statement ``Derived = NewType('Derived', Base)`` as being roughly equivalent to the following definition: @@ -95,7 +95,7 @@ definition: def __init__(self, _x: Base) -> None: ... -However, at runtime, ``NewType('Derived', Base)`` will return a dummy function that +However, at runtime, ``NewType('Derived', Base)`` will return a dummy callable that simply returns its argument: .. code-block:: python @@ -127,7 +127,7 @@ containing the name of the new type and must equal the name of the variable to w type is assigned. The second argument must be a properly subclassable class, i.e., not a type construct like :py:data:`~typing.Union`, etc. -The function returned by :py:func:`NewType ` accepts only one argument; this is equivalent to +The callable returned by :py:func:`NewType ` accepts only one argument; this is equivalent to supporting only one constructor accepting an instance of the base class (see above). Example: @@ -148,8 +148,7 @@ Example: tcp_packet = TcpPacketId(127, 0) # Fails in type checker and at runtime You cannot use :py:func:`isinstance` or :py:func:`issubclass` on the object returned by -:py:func:`~typing.NewType`, because function objects don't support these operations. You cannot -create subclasses of these objects either. +:py:func:`~typing.NewType`, nor can you subclass an object returned by :py:func:`~typing.NewType`. .. note:: @@ -295,6 +294,25 @@ return type by using overloads like so: subtypes, you can use a :ref:`value restriction `. +The default values of a function's arguments don't affect its signature -- only +the absence or presence of a default value does. So in order to reduce +redundancy, it's possible to replace default values in overload definitions with +``...`` as a placeholder: + +.. code-block:: python + + from typing import overload + + class M: ... + + @overload + def get_model(model_or_pk: M, flag: bool = ...) -> M: ... + @overload + def get_model(model_or_pk: int, flag: bool = ...) -> M | None: ... + + def get_model(model_or_pk: int | M, flag: bool = True) -> M | None: + ... + Runtime behavior ---------------- @@ -336,13 +354,15 @@ program: .. code-block:: python - from typing import List, overload + # For Python 3.8 and below you must use `typing.List` instead of `list`. e.g. + # from typing import List + from typing import overload @overload - def summarize(data: List[int]) -> float: ... + def summarize(data: list[int]) -> float: ... @overload - def summarize(data: List[str]) -> str: ... + def summarize(data: list[str]) -> str: ... def summarize(data): if not data: @@ -356,7 +376,7 @@ program: output = summarize([]) The ``summarize([])`` call matches both variants: an empty list could -be either a ``List[int]`` or a ``List[str]``. In this case, mypy +be either a ``list[int]`` or a ``list[str]``. In this case, mypy will break the tie by picking the first matching variant: ``output`` will have an inferred type of ``float``. The implementor is responsible for making sure ``summarize`` breaks ties in the same way at runtime. @@ -378,7 +398,7 @@ matching variant returns: .. code-block:: python - some_list: Union[List[int], List[str]] + some_list: Union[list[int], list[str]] # output3 is of type 'Union[float, str]' output3 = summarize(some_list) @@ -505,7 +525,7 @@ suppose we modify the above snippet so it calls ``summarize`` instead of .. code-block:: python - some_list: List[str] = [] + some_list: list[str] = [] summarize(some_list) + "danger danger" # Type safe, yet crashes at runtime! We run into a similar issue here. This program type checks if we look just at the @@ -552,7 +572,7 @@ with ``Union[int, slice]`` and ``Union[T, Sequence]``. Previously, mypy used to perform type erasure on all overload variants. For example, the ``summarize`` example from the previous section used to be - illegal because ``List[str]`` and ``List[int]`` both erased to just ``List[Any]``. + illegal because ``list[str]`` and ``list[int]`` both erased to just ``list[Any]``. This restriction was removed in mypy 0.620. Mypy also previously used to select the best matching variant using a different @@ -595,7 +615,7 @@ argument is itself generic: .. code-block:: python - T = TypeVar('T') + T = TypeVar('T', covariant=True) S = TypeVar('S') class Storage(Generic[T]): @@ -604,7 +624,7 @@ argument is itself generic: def first_chunk(self: Storage[Sequence[S]]) -> S: return self.content[0] - page: Storage[List[str]] + page: Storage[list[str]] page.first_chunk() # OK, type is "str" Storage(0).first_chunk() # Error: Invalid self argument "Storage[int]" to attribute function @@ -689,13 +709,13 @@ classes are generic, self-type allows giving them precise signatures: self.item = item @classmethod - def make_pair(cls: Type[Q], item: T) -> Tuple[Q, Q]: + def make_pair(cls: Type[Q], item: T) -> tuple[Q, Q]: return cls(item), cls(item) class Sub(Base[T]): ... - pair = Sub.make_pair('yes') # Type is "Tuple[Sub[str], Sub[str]]" + pair = Sub.make_pair('yes') # Type is "tuple[Sub[str], Sub[str]]" bad = Sub[int].make_pair('no') # Error: Argument 1 to "make_pair" of "Base" # has incompatible type "str"; expected "int" @@ -887,7 +907,7 @@ Here is a typical example: Only a fixed set of string keys is expected (``'name'`` and ``'year'`` above), and each key has an independent value type (``str`` for ``'name'`` and ``int`` for ``'year'`` above). We've previously -seen the ``Dict[K, V]`` type, which lets you declare uniform +seen the ``dict[K, V]`` type, which lets you declare uniform dictionary types, where every value has the same type, and arbitrary keys are supported. This is clearly not a good fit for ``movie`` above. Instead, you can use a ``TypedDict`` to give a precise @@ -906,7 +926,7 @@ dictionary value depends on the key: and ``'year'`` (with type ``int``). Note that we used an explicit type annotation for the ``movie`` variable. This type annotation is important -- without it, mypy will try to infer a regular, uniform -:py:class:`~typing.Dict` type for ``movie``, which is not what we want here. +:py:class:`dict` type for ``movie``, which is not what we want here. .. note:: @@ -915,7 +935,7 @@ important -- without it, mypy will try to infer a regular, uniform desired type based on the declared argument type. Also, if an assignment target has been previously defined, and it has a ``TypedDict`` type, mypy will treat the assigned value as a ``TypedDict``, - not :py:class:`~typing.Dict`. + not :py:class:`dict`. Now mypy will recognize these as valid: @@ -952,12 +972,12 @@ arbitrarily complex types. For example, you can define nested ``TypedDict``\s and containers with ``TypedDict`` items. Unlike most other types, mypy uses structural compatibility checking (or structural subtyping) with ``TypedDict``\s. A ``TypedDict`` object with -extra items is a compatible with (a subtype of) a narrower +extra items is compatible with (a subtype of) a narrower ``TypedDict``, assuming item types are compatible (*totality* also affects subtyping, as discussed below). -A ``TypedDict`` object is not a subtype of the regular ``Dict[...]`` -type (and vice versa), since :py:class:`~typing.Dict` allows arbitrary keys to be +A ``TypedDict`` object is not a subtype of the regular ``dict[...]`` +type (and vice versa), since :py:class:`dict` allows arbitrary keys to be added and removed, unlike ``TypedDict``. However, any ``TypedDict`` object is a subtype of (that is, compatible with) ``Mapping[str, object]``, since :py:class:`~typing.Mapping` only provides read-only access to the dictionary items: @@ -1130,5 +1150,5 @@ TypedDict in the same way you can with regular objects. Instead, you can use the :ref:`tagged union pattern `. The referenced section of the docs has a full description with an example, but in short, you will need to give each TypedDict the same key where each value has a unique -unique :ref:`Literal type `. Then, check that key to distinguish +:ref:`Literal type `. Then, check that key to distinguish between your TypedDicts. diff --git a/docs/source/protocols.rst b/docs/source/protocols.rst index 38d1ee9bf357..cd59f841d8a0 100644 --- a/docs/source/protocols.rst +++ b/docs/source/protocols.rst @@ -455,19 +455,19 @@ member: .. code-block:: python - from typing import Optional, Iterable, List + from typing import Optional, Iterable from typing_extensions import Protocol class Combiner(Protocol): - def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> List[bytes]: ... + def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ... def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes: for item in data: ... - def good_cb(*vals: bytes, maxlen: Optional[int] = None) -> List[bytes]: + def good_cb(*vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ... - def bad_cb(*vals: bytes, maxitems: Optional[int]) -> List[bytes]: + def bad_cb(*vals: bytes, maxitems: Optional[int]) -> list[bytes]: ... batch_proc([], good_cb) # OK diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index 8a2fbc2df599..d1c701e27e5a 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -81,7 +81,7 @@ Note that if you use namespace packages (in particular, packages without $ mypy -c 'x = [1, 2]; print(x())' ...will type check the above string as a mini-program (and in this case, - will report that ``List[int]`` is not callable). + will report that ``list[int]`` is not callable). Reading a list of files from a file @@ -133,14 +133,12 @@ Missing imports *************** When you import a module, mypy may report that it is unable to follow -the import. - -This can cause errors that look like the following: +the import. This can cause errors that look like the following: .. code-block:: text - main.py:1: error: Library stubs not installed for "requests" (or incompatible with Python 3.8) - main.py:2: error: Skipping analyzing 'django': found module but no type hints or library stubs + main.py:1: error: Skipping analyzing 'django': module is installed, but missing library stubs or py.typed marker + main.py:2: error: Library stubs not installed for "requests" (or incompatible with Python 3.8) main.py:3: error: Cannot find implementation or library stub for module named "this_module_does_not_exist" If you get any of these errors on an import, mypy will assume the type of that @@ -155,44 +153,14 @@ attribute of the module will automatically succeed: # But this type checks, and x will have type 'Any' x = does_not_exist.foobar() -The next sections describe what each error means and recommended next steps. - -Library stubs not installed ---------------------------- - -If mypy can't find stubs for a third-party library, and it knows that stubs exist for -the library, you will get a message like this: - -.. code-block:: text - - main.py:1: error: Library stubs not installed for "yaml" (or incompatible with Python 3.8) - main.py:1: note: Hint: "python3 -m pip install types-PyYAML" - main.py:1: note: (or run "mypy --install-types" to install all missing stub packages) - -You can resolve the issue by running the suggested pip command or -commands. Alternatively, you can use :option:`--install-types ` to install all known missing stubs: - -.. code-block:: text - - mypy --install-types - -This installs any stub packages that were suggested in the previous -mypy run. You can also use your normal mypy command line with the -extra :option:`--install-types ` option to -install missing stubs at the end of the run (if any were found). - -You can also get this message if the stubs only support Python 3 and -your target Python version is Python 2, or vice versa. In this case -follow instructions in -:ref:`missing-type-hints-for-third-party-library`. +The next sections describe what each of these errors means and recommended next steps; scroll to +the section that matches your error. -.. _missing-type-hints-for-third-party-library: -Missing type hints for third party library ------------------------------------------- +Missing library stubs or py.typed marker +---------------------------------------- -If you are getting a "Skipping analyzing X: found module but no type hints or library stubs", +If you are getting a ``Skipping analyzing X: module is installed, but missing library stubs or py.typed marker``, error, this means mypy was able to find the module you were importing, but no corresponding type hints. @@ -266,10 +234,54 @@ will continue to be of type ``Any``. We recommend using this approach only as a last resort: it's equivalent to adding a ``# type: ignore`` to all unresolved imports in your codebase. -Unable to find module ---------------------- -If you are getting a "Cannot find implementation or library stub for module" +Library stubs not installed +--------------------------- + +If mypy can't find stubs for a third-party library, and it knows that stubs exist for +the library, you will get a message like this: + +.. code-block:: text + + main.py:1: error: Library stubs not installed for "yaml" (or incompatible with Python 3.8) + main.py:1: note: Hint: "python3 -m pip install types-PyYAML" + main.py:1: note: (or run "mypy --install-types" to install all missing stub packages) + +You can resolve the issue by running the suggested pip command or +commands. Alternatively, you can use :option:`--install-types ` to install all known missing stubs: + +.. code-block:: text + + mypy --install-types + +This installs any stub packages that were suggested in the previous +mypy run. You can also use your normal mypy command line with the +extra :option:`--install-types ` option to +install missing stubs at the end of the run (if any were found). + +Use :option:`--install-types ` with +:option:`--non-interactive ` to install all suggested +stub packages without asking for confirmation, *and* type check your +code, in a single command: + +.. code-block:: text + + mypy --install-types --non-interactive src/ + +This can be useful in Continuous Integration jobs if you'd prefer not +to manage stub packages manually. This is somewhat slower than +explicitly installing stubs before running mypy, since it may type +check your code twice -- the first time to find the missing stubs, and +the second time to type check your code properly after mypy has +installed the stubs. + +.. _missing-type-hints-for-third-party-library: + +Cannot find implementation or library stub +------------------------------------------ + +If you are getting a ``Cannot find implementation or library stub for module`` error, this means mypy was not able to find the module you are trying to import, whether it comes bundled with type hints or not. If you are getting this error, try: @@ -296,7 +308,7 @@ this error, try: or by using the ``MYPYPATH`` environment variable. Note: if the module you are trying to import is actually a *submodule* of - some package, you should specific the directory containing the *entire* package. + some package, you should specify the directory containing the *entire* package. For example, suppose you are trying to add the module ``foo.bar.baz`` which is located at ``~/foo-project/src/foo/bar/baz.py``. In this case, you must run ``mypy ~/foo-project/src`` (or set the ``MYPYPATH`` to @@ -373,6 +385,10 @@ We do not recommend using ``skip`` unless you know what you are doing: while this option can be quite powerful, it can also cause many hard-to-debug errors. +Adjusting import following behaviour is often most useful when restricted to +specific modules. This can be accomplished by setting a per-module +:confval:`follow_imports` config option. + .. _mapping-paths-to-modules: @@ -437,7 +453,7 @@ How mypy determines fully qualified module names depends on if the options fully qualified module name. For example, say your directory tree consists solely of - ``src/namespace_pkg/mod.py``. If you run the command following command, mypy + ``src/namespace_pkg/mod.py``. If you run the following command, mypy will correctly associate ``mod.py`` with ``namespace_pkg.mod``:: $ MYPYPATH=src mypy --namespace-packages --explicit-package-bases . diff --git a/docs/source/runtime_troubles.rst b/docs/source/runtime_troubles.rst index 39558464cf55..e748fb000b71 100644 --- a/docs/source/runtime_troubles.rst +++ b/docs/source/runtime_troubles.rst @@ -9,7 +9,7 @@ and explains how to get your code running again. Generally speaking, we have three tools at our disposal: * For Python 3.7 through 3.9, use of ``from __future__ import annotations`` - (:pep:`563`), made the default in Python 3.10 and later + (:pep:`563`), made the default in Python 3.11 and later * Use of string literal types or type comments * Use of ``typing.TYPE_CHECKING`` @@ -30,7 +30,7 @@ string-literal types with non-string-literal types freely: .. code-block:: python - def f(a: List['A']) -> None: ... # OK + def f(a: list['A']) -> None: ... # OK def g(n: 'int') -> None: ... # OK, though not useful class A: pass @@ -47,7 +47,7 @@ Future annotations import (PEP 563) ----------------------------------- Many of the issues described here are caused by Python trying to evaluate -annotations. From Python 3.10 on, Python will no longer attempt to evaluate +annotations. From Python 3.11 on, Python will no longer attempt to evaluate function and variable annotations. This behaviour is made available in Python 3.7 and later through the use of ``from __future__ import annotations``. @@ -62,7 +62,7 @@ required to be valid Python syntax. For more details, see :pep:`563`. of forward references or generics in: * :ref:`type aliases `; - * :ref:`casts `; + * :ref:`type narrowing `; * type definitions (see :py:class:`~typing.TypeVar`, :py:func:`~typing.NewType`, :py:class:`~typing.NamedTuple`); * base classes. @@ -70,7 +70,7 @@ required to be valid Python syntax. For more details, see :pep:`563`. # base class example from __future__ import annotations - class A(Tuple['B', 'C']): ... # String literal types needed here + class A(tuple['B', 'C']): ... # String literal types needed here class B: ... class C: ... @@ -94,12 +94,6 @@ Since code inside ``if TYPE_CHECKING:`` is not executed at runtime, it provides a convenient way to tell mypy something without the code being evaluated at runtime. This is most useful for resolving :ref:`import cycles `. -.. note:: - - Python 3.5.1 and below don't have :py:data:`~typing.TYPE_CHECKING`. An - alternative is to define a constant named ``MYPY`` that has the value - ``False`` at runtime. Mypy considers it to be ``True`` when type checking. - Class name forward references ----------------------------- @@ -162,23 +156,22 @@ File ``foo.py``: .. code-block:: python - from typing import List, TYPE_CHECKING + from typing import TYPE_CHECKING if TYPE_CHECKING: import bar - def listify(arg: 'bar.BarClass') -> 'List[bar.BarClass]': + def listify(arg: 'bar.BarClass') -> 'list[bar.BarClass]': return [arg] File ``bar.py``: .. code-block:: python - from typing import List from foo import listify class BarClass: - def listifyme(self) -> 'List[BarClass]': + def listifyme(self) -> 'list[BarClass]': return listify(self) .. _not-generic-runtime: diff --git a/docs/source/stubgen.rst b/docs/source/stubgen.rst index a58a022e6c67..33fdac2089f7 100644 --- a/docs/source/stubgen.rst +++ b/docs/source/stubgen.rst @@ -1,4 +1,4 @@ -.. _stugen: +.. _stubgen: .. program:: stubgen diff --git a/docs/source/stubs.rst b/docs/source/stubs.rst index a15c16d85da3..38eded7ce57d 100644 --- a/docs/source/stubs.rst +++ b/docs/source/stubs.rst @@ -36,11 +36,16 @@ the source code. This can be useful, for example, if you use 3rd party open source libraries in your program (and there are no stubs in typeshed yet). -That's it! Now you can access the module in mypy programs and type check +That's it! + +Now you can access the module in mypy programs and type check code that uses the library. If you write a stub for a library module, consider making it available for other programmers that use mypy by contributing it back to the typeshed repo. +Mypy also ships with two tools for making it easier to create and maintain +stubs: :ref:`stubgen` and :ref:`stubtest`. + The following sections explain the kinds of type annotations you can use in your programs and stub files. @@ -112,22 +117,21 @@ For example: .. code-block:: python - from typing import List from typing_extensions import Protocol class Resource(Protocol): - def ok_1(self, foo: List[str] = ...) -> None: ... + def ok_1(self, foo: list[str] = ...) -> None: ... - def ok_2(self, foo: List[str] = ...) -> None: + def ok_2(self, foo: list[str] = ...) -> None: raise NotImplementedError() - def ok_3(self, foo: List[str] = ...) -> None: + def ok_3(self, foo: list[str] = ...) -> None: """Some docstring""" pass # Error: Incompatible default for argument "foo" (default has - # type "ellipsis", argument has type "List[str]") - def not_ok(self, foo: List[str] = ...) -> None: + # type "ellipsis", argument has type "list[str]") + def not_ok(self, foo: list[str] = ...) -> None: print(foo) .. note:: diff --git a/docs/source/stubtest.rst b/docs/source/stubtest.rst new file mode 100644 index 000000000000..828931fbdf2b --- /dev/null +++ b/docs/source/stubtest.rst @@ -0,0 +1,136 @@ +.. _stubtest: + +.. program:: stubtest + +Automatic stub testing (stubtest) +================================= + +Stub files are files containing type annotations. See +`PEP 484 `_ +for more motivation and details. + +A common problem with stub files is that they tend to diverge from the +actual implementation. Mypy includes the ``stubtest`` tool that can +automatically check for discrepancies between the stubs and the +implementation at runtime. + +What stubtest does and does not do +********************************** + +Stubtest will import your code and introspect your code objects at runtime, for +example, by using the capabilities of the :py:mod:`inspect` module. Stubtest +will then analyse the stub files, and compare the two, pointing out things that +differ between stubs and the implementation at runtime. + +It's important to be aware of the limitations of this comparison. Stubtest will +not make any attempt to statically analyse your actual code and relies only on +dynamic runtime introspection (in particular, this approach means stubtest works +well with extension modules). However, this means that stubtest has limited +visibility; for instance, it cannot tell if a return type of a function is +accurately typed in the stubs. + +For clarity, here are some additional things stubtest can't do: + +* Type check your code -- use ``mypy`` instead +* Generate stubs -- use ``stubgen`` or ``pyright --createstub`` instead +* Generate stubs based on running your application or test suite -- use ``monkeytype`` instead +* Apply stubs to code to produce inline types -- use ``retype`` or ``libcst`` instead + +In summary, stubtest works very well for ensuring basic consistency between +stubs and implementation or to check for stub completeness. It's used to +test Python's official collection of library stubs, +`typeshed `_. + +Example +******* + +Here's a quick example of what stubtest can do: + +.. code-block:: shell + + $ python3 -m pip install mypy + + $ cat library.py + x = "hello, stubtest" + + def foo(x=None): + print(x) + + $ cat library.pyi + x: int + + def foo(x: int) -> None: ... + + $ python3 -m mypy.stubtest library + error: library.foo is inconsistent, runtime argument "x" has a default value but stub argument does not + Stub: at line 3 + def (x: builtins.int) + Runtime: at line 3 in file ~/library.py + def (x=None) + + error: library.x variable differs from runtime type Literal['hello, stubtest'] + Stub: at line 1 + builtins.int + Runtime: + hello, stubtest + + +Usage +***** + +Running stubtest can be as simple as ``stubtest module_to_check``. +Run :option:`stubtest --help` for a quick summary of options. + +Subtest must be able to import the code to be checked, so make sure that mypy +is installed in the same environment as the library to be tested. In some +cases, setting ``PYTHONPATH`` can help stubtest find the code to import. + +Similarly, stubtest must be able to find the stubs to be checked. Stubtest +respects the ``MYPYPATH`` environment variable. + +If you wish to ignore some of stubtest's complaints, stubtest supports a +pretty handy allowlist system. + +The rest of this section documents the command line interface of stubtest. + +.. option:: --concise + + Makes stubtest's output more concise, one line per error + +.. option:: --ignore-missing-stub + + Ignore errors for stub missing things that are present at runtime + +.. option:: --ignore-positional-only + + Ignore errors for whether an argument should or shouldn't be positional-only + +.. option:: --allowlist FILE + + Use file as an allowlist. Can be passed multiple times to combine multiple + allowlists. Allowlists can be created with --generate-allowlist. Allowlists + support regular expressions. + +.. option:: --generate-allowlist + + Print an allowlist (to stdout) to be used with --allowlist + +.. option:: --ignore-unused-allowlist + + Ignore unused allowlist entries + +.. option:: --mypy-config-file FILE + + Use specified mypy config file to determine mypy plugins and mypy path + +.. option:: --custom-typeshed-dir DIR + + Use the custom typeshed in DIR + +.. option:: --check-typeshed + + Check all stdlib modules in typeshed + +.. option:: --help + + Show a help message :-) diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index 38518a8f2c3b..8150f88e579e 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -12,7 +12,7 @@ static type of the value expression: .. code-block:: python i = 1 # Infer type "int" for i - l = [1, 2] # Infer type "List[int]" for l + l = [1, 2] # Infer type "list[int]" for l Type inference is not used in dynamically typed functions (those without a function type annotation) — every local variable type defaults @@ -84,24 +84,33 @@ In these cases you can give the type explicitly using a type annotation: .. code-block:: python - l: List[int] = [] # Create empty list with type List[int] - d: Dict[str, int] = {} # Create empty dictionary (str -> int) + l: list[int] = [] # Create empty list with type list[int] + d: dict[str, int] = {} # Create empty dictionary (str -> int) Similarly, you can also give an explicit type when creating an empty set: .. code-block:: python - s: Set[int] = set() + s: set[int] = set() + +.. note:: + + Using type arguments (e.g. ``list[int]``) on builtin collections like + :py:class:`list`, :py:class:`dict`, :py:class:`tuple`, and :py:class:`set` + only works in Python 3.9 and later. For Python 3.8 and earlier, you must use + :py:class:`~typing.List` (e.g. ``List[int]``), :py:class:`~typing.Dict`, and + so on. + Compatibility of container types ******************************** -The following program generates a mypy error, since ``List[int]`` -is not compatible with ``List[object]``: +The following program generates a mypy error, since ``list[int]`` +is not compatible with ``list[object]``: .. code-block:: python - def f(l: List[object], k: List[int]) -> None: + def f(l: list[object], k: list[int]) -> None: l = k # Type check error: incompatible types in assignment The reason why the above assignment is disallowed is that allowing the @@ -109,12 +118,12 @@ assignment could result in non-int values stored in a list of ``int``: .. code-block:: python - def f(l: List[object], k: List[int]) -> None: + def f(l: list[object], k: list[int]) -> None: l = k l.append('x') - print(k[-1]) # Ouch; a string in List[int] + print(k[-1]) # Ouch; a string in list[int] -Other container types like :py:class:`~typing.Dict` and :py:class:`~typing.Set` behave similarly. We +Other container types like :py:class:`dict` and :py:class:`set` behave similarly. We will discuss how you can work around this in :ref:`variance`. You can still run the above program; it prints ``x``. This illustrates @@ -132,23 +141,23 @@ example, the following is valid: .. code-block:: python - def f(l: List[object]) -> None: - l = [1, 2] # Infer type List[object] for [1, 2], not List[int] + def f(l: list[object]) -> None: + l = [1, 2] # Infer type list[object] for [1, 2], not list[int] In an assignment, the type context is determined by the assignment target. In this case this is ``l``, which has the type -``List[object]``. The value expression ``[1, 2]`` is type checked in -this context and given the type ``List[object]``. In the previous +``list[object]``. The value expression ``[1, 2]`` is type checked in +this context and given the type ``list[object]``. In the previous example we introduced a new variable ``l``, and here the type context was empty. Declared argument types are also used for type context. In this program -mypy knows that the empty list ``[]`` should have type ``List[int]`` based +mypy knows that the empty list ``[]`` should have type ``list[int]`` based on the declared type of ``arg`` in ``foo``: .. code-block:: python - def foo(arg: List[int]) -> None: + def foo(arg: list[int]) -> None: print('Items:', ''.join(str(a) for a in arg)) foo([]) # OK @@ -159,7 +168,7 @@ in the following statement: .. code-block:: python - def foo(arg: List[int]) -> None: + def foo(arg: list[int]) -> None: print('Items:', ', '.join(arg)) a = [] # Error: Need type annotation for "a" @@ -170,7 +179,7 @@ Working around the issue is easy by adding a type annotation: .. code-block:: Python ... - a: List[int] = [] # OK + a: list[int] = [] # OK foo(a) Declaring multiple variable types at a time @@ -206,13 +215,77 @@ right-hand side of an assignment, but not always: p, q, *rs = 1, 2 # Error: Type of rs cannot be inferred On first line, the type of ``bs`` is inferred to be -``List[int]``. However, on the second line, mypy cannot infer the type +``list[int]``. However, on the second line, mypy cannot infer the type of ``rs``, because there is no right-hand side value for ``rs`` to infer the type from. In cases like these, the starred expression needs to be annotated with a starred type: .. code-block:: python - p, q, *rs = 1, 2 # type: int, int, List[int] + p, q, *rs = 1, 2 # type: int, int, list[int] + +Here, the type of ``rs`` is set to ``list[int]``. + +Silencing type errors +********************* + +You might want to disable type checking on specific lines, or within specific +files in your codebase. To do that, you can use a ``# type: ignore`` comment. + +For example, say that the web framework that you use now takes an integer +argument to ``run()``, which starts it on localhost on that port. Like so: + +.. code-block:: python + + # Starting app on http://localhost:8000 + app.run(8000) + +However, the type stubs that the package uses is not up-to-date, and it still +expects only ``str`` types for ``run()``. This would give you the following error: + +.. code-block:: text + + error: Argument 1 to "run" of "A" has incompatible type "int"; expected "str" + +If you cannot directly fix the type stubs yourself, you can temporarily +disable type checking on that line, by adding a ``# type: ignore``: + +.. code-block:: python -Here, the type of ``rs`` is set to ``List[int]``. + # Starting app on http://localhost:8000 + app.run(8000) # type: ignore + +This will suppress any mypy errors that would have raised on that specific line. + +You should probably add some more information on the ``# type: ignore`` comment, +to explain why the ignore was added in the first place. This could be a link to +an issue on the repository responsible for the type stubs, or it could be a +short explanation of the bug. To do that, use this format: + +.. code-block:: python + + # Starting app on http://localhost:8000 + app.run(8000) # type: ignore # `run()` now accepts an `int`, as a port + + +Mypy displays an error code for each error if you use +:option:`--show-error-codes `: + +.. code-block:: text + + error: "str" has no attribute "trim" [attr-defined] + + +It is possible to add a specific error-code in your ignore comment (e.g. +``# type: ignore[attr-defined]``) to clarify what's being silenced. You can +find more information about error codes :ref:`here `. + +Similarly, you can also ignore all mypy checks in a file, by adding a +``# type: ignore`` at the top of the file: + +.. code-block:: python + + # type: ignore + # This is a test file, skipping type checking in it. + import unittest + ... diff --git a/docs/source/type_narrowing.rst b/docs/source/type_narrowing.rst new file mode 100644 index 000000000000..b5f297d283c0 --- /dev/null +++ b/docs/source/type_narrowing.rst @@ -0,0 +1,361 @@ +.. _type-narrowing: + +Type narrowing +============== + +This section is dedicated to several type narrowing +techniques which are supported by mypy. + +Type narrowing is when you convince a type checker that a broader type is actually more specific, for instance, that an object of type ``Shape`` is actually of the narrower type ``Square``. + + +Type narrowing expressions +-------------------------- + +The simplest way to narrow a type is to use one of the supported expressions: + +- :py:func:`isinstance` like in ``isinstance(obj, float)`` will narrow ``obj`` to have ``float`` type +- :py:func:`issubclass` like in ``issubclass(cls, MyClass)`` will narrow ``cls`` to be ``Type[MyClass]`` +- :py:func:`type` like in ``type(obj) is int`` will narrow ``obj`` to have ``int`` type +- :py:func:`callable` like in ``callable(obj)`` will narrow object to callable type + +Type narrowing is contextual. For example, based on the condition, mypy will narrow an expression only within an ``if`` branch: + +.. code-block:: python + + def function(arg: object): + if isinstance(arg, int): + # Type is narrowed within the ``if`` branch only + reveal_type(arg) # Revealed type: "builtins.int" + elif isinstance(arg, str) or isinstance(arg, bool): + # Type is narrowed differently within this ``elif`` branch: + reveal_type(arg) # Revealed type: "builtins.str | builtins.bool" + + # Subsequent narrowing operations will narrow the type further + if isinstance(arg, bool): + reveal_type(arg) # Revealed type: "builtins.bool" + + # Back outside of the ``if`` statement, the type isn't narrowed: + reveal_type(arg) # Revealed type: "builtins.object" + +Mypy understands the implications ``return`` or exception raising can have +for what type an object could be: + +.. code-block:: python + + def function(arg: int | str): + if isinstance(arg, int): + return + + # `arg` can't be `int` at this point: + reveal_type(arg) # Revealed type: "builtins.str" + +We can also use ``assert`` to narrow types in the same context: + +.. code-block:: python + + def function(arg: Any): + assert isinstance(arg, int) + reveal_type(arg) # Revealed type: "builtins.int" + +.. note:: + + With :option:`--warn-unreachable ` + narrowing types to some impossible state will be treated as an error. + + .. code-block:: python + + def function(arg: int): + # error: Subclass of "int" and "str" cannot exist: + # would have incompatible method signatures + assert isinstance(arg, str) + + # error: Statement is unreachable + print("so mypy concludes the assert will always trigger") + + Without ``--warn-unreachable`` mypy will simply not check code it deems to be + unreachable. See :ref:`unreachable` for more information. + + .. code-block:: python + + x: int = 1 + assert isinstance(x, str) + reveal_type(x) # Revealed type is "builtins.int" + print(x + '!') # Typechecks with `mypy`, but fails in runtime. + +issubclass +~~~~~~~~~~ + +Mypy can also use :py:func:`issubclass` +for better type inference when working with types and metaclasses: + +.. code-block:: python + + class MyCalcMeta(type): + @classmethod + def calc(cls) -> int: + ... + + def f(o: object) -> None: + t = type(o) # We must use a variable here + reveal_type(t) # Revealed type is "builtins.type" + + if issubtype(t, MyCalcMeta): # `issubtype(type(o), MyCalcMeta)` won't work + reveal_type(t) # Revealed type is "Type[MyCalcMeta]" + t.calc() # Okay + +callable +~~~~~~~~ + +Mypy knows what types are callable and which ones are not during type checking. +So, we know what ``callable()`` will return. For example: + +.. code-block:: python + + from typing import Callable + + x: Callable[[], int] + + if callable(x): + reveal_type(x) # N: Revealed type is "def () -> builtins.int" + else: + ... # Will never be executed and will raise error with `--warn-unreachable` + +``callable`` function can even split ``Union`` type +for callable and non-callable parts: + +.. code-block:: python + + from typing import Callable, Union + + x: Union[int, Callable[[], int]] + + if callable(x): + reveal_type(x) # N: Revealed type is "def () -> builtins.int" + else: + reveal_type(x) # N: Revealed type is "builtins.int" + +.. _casts: + +Casts +----- + +Mypy supports type casts that are usually used to coerce a statically +typed value to a subtype. Unlike languages such as Java or C#, +however, mypy casts are only used as hints for the type checker, and they +don't perform a runtime type check. Use the function :py:func:`~typing.cast` +to perform a cast: + +.. code-block:: python + + from typing import cast + + o: object = [1] + x = cast(list[int], o) # OK + y = cast(list[str], o) # OK (cast performs no actual runtime check) + +To support runtime checking of casts such as the above, we'd have to check +the types of all list items, which would be very inefficient for large lists. +Casts are used to silence spurious +type checker warnings and give the type checker a little help when it can't +quite understand what is going on. + +.. note:: + + You can use an assertion if you want to perform an actual runtime check: + + .. code-block:: python + + def foo(o: object) -> None: + print(o + 5) # Error: can't add 'object' and 'int' + assert isinstance(o, int) + print(o + 5) # OK: type of 'o' is 'int' here + +You don't need a cast for expressions with type ``Any``, or when +assigning to a variable with type ``Any``, as was explained earlier. +You can also use ``Any`` as the cast target type -- this lets you perform +any operations on the result. For example: + +.. code-block:: python + + from typing import cast, Any + + x = 1 + x.whatever() # Type check error + y = cast(Any, x) + y.whatever() # Type check OK (runtime error) + + +.. _type-guards: + +User-Defined Type Guards +------------------------ + +Mypy supports User-Defined Type Guards (:pep:`647`). + +A type guard is a way for programs to influence conditional +type narrowing employed by a type checker based on runtime checks. + +Basically, a ``TypeGuard`` is a "smart" alias for a ``bool`` type. +Let's have a look at the regular ``bool`` example: + +.. code-block:: python + + def is_str_list(val: list[object]) -> bool: + """Determines whether all objects in the list are strings""" + return all(isinstance(x, str) for x in val) + + def func1(val: list[object]) -> None: + if is_str_list(val): + reveal_type(val) # Reveals list[object] + print(" ".join(val)) # Error: incompatible type + +The same example with ``TypeGuard``: + +.. code-block:: python + + from typing import TypeGuard # use `typing_extensions` for Python 3.9 and below + + def is_str_list(val: list[object]) -> TypeGuard[list[str]]: + """Determines whether all objects in the list are strings""" + return all(isinstance(x, str) for x in val) + + def func1(val: list[object]) -> None: + if is_str_list(val): + reveal_type(val) # list[str] + print(" ".join(val)) # ok + +How does it work? ``TypeGuard`` narrows the first function argument (``val``) +to the type specified as the first type parameter (``list[str]``). + +.. note:: + + Narrowing is + `not strict `_. + For example, you can narrow ``str`` to ``int``: + + .. code-block:: python + + def f(value: str) -> TypeGuard[int]: + return True + + Note: since strict narrowing is not enforced, it's easy + to break type safety. + + However, there are many ways a determined or uninformed developer can + subvert type safety -- most commonly by using cast or Any. + If a Python developer takes the time to learn about and implement + user-defined type guards within their code, + it is safe to assume that they are interested in type safety + and will not write their type guard functions in a way + that will undermine type safety or produce nonsensical results. + +Generic TypeGuards +~~~~~~~~~~~~~~~~~~ + +``TypeGuard`` can also work with generic types: + +.. code-block:: python + + from typing import TypeVar + from typing import TypeGuard # use `typing_extensions` for `python<3.10` + + _T = TypeVar("_T") + + def is_two_element_tuple(val: tuple[_T, ...]) -> TypeGuard[tuple[_T, _T]]: + return len(val) == 2 + + def func(names: tuple[str, ...]): + if is_two_element_tuple(names): + reveal_type(names) # tuple[str, str] + else: + reveal_type(names) # tuple[str, ...] + +Typeguards with parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Type guard functions can accept extra arguments: + +.. code-block:: python + + from typing import Type, TypeVar + from typing import TypeGuard # use `typing_extensions` for `python<3.10` + + _T = TypeVar("_T") + + def is_set_of(val: set[Any], type: Type[_T]) -> TypeGuard[set[_T]]: + return all(isinstance(x, type) for x in val) + + items: set[Any] + if is_set_of(items, str): + reveal_type(items) # set[str] + +TypeGuards as methods +~~~~~~~~~~~~~~~~~~~~~ + + A method can also serve as the ``TypeGuard``: + +.. code-block:: python + + class StrValidator: + def is_valid(self, instance: object) -> TypeGuard[str]: + return isinstance(instance, str) + + def func(to_validate: object) -> None: + if StrValidator().is_valid(to_validate): + reveal_type(to_validate) # Revealed type is "builtins.str" + +.. note:: + + Note, that ``TypeGuard`` + `does not narrow `_ + types of ``self`` or ``cls`` implicit arguments. + + If narrowing of ``self`` or ``cls`` is required, + the value can be passed as an explicit argument to a type guard function: + + .. code-block:: python + + class Parent: + def method(self) -> None: + reveal_type(self) # Revealed type is "Parent" + if is_child(self): + reveal_type(self) # Revealed type is "Child" + + class Child(Parent): + ... + + def is_child(instance: Parent) -> TypeGuard[Child]: + return isinstance(instance, Child) + +Assignment expressions as TypeGuards +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you might need to create a new variable and narrow it +to some specific type at the same time. +This can be achieved by using ``TypeGuard`` together +with `:= operator `_. + +.. code-block:: python + + from typing import TypeGuard # use `typing_extensions` for `python<3.10` + + def is_float(a: object) -> TypeGuard[float]: + return isinstance(a, float) + + def main(a: object) -> None: + if is_float(x := a): + reveal_type(x) # N: Revealed type is 'builtins.float' + reveal_type(a) # N: Revealed type is 'builtins.object' + reveal_type(x) # N: Revealed type is 'builtins.object' + reveal_type(a) # N: Revealed type is 'builtins.object' + +What happens here? + +1. We create a new variable ``x`` and assign a value of ``a`` to it +2. We run ``is_float()`` type guard on ``x`` +3. It narrows ``x`` to be ``float`` in the ``if`` context and does not touch ``a`` + +.. note:: + + The same will work with ``isinstance(x := a, float)`` as well. diff --git a/misc/build_wheel.py b/misc/build_wheel.py index bf27f11d2c25..44b40c2e8fed 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -3,13 +3,11 @@ The main GitHub workflow where this script is used: https://github.com/mypyc/mypy_mypyc-wheels/blob/master/.github/workflows/build.yml -This uses cibuildwheel (https://github.com/joerick/cibuildwheel) to -build the wheels. +This uses cibuildwheel (https://github.com/pypa/cibuildwheel) to build the wheels. Usage: - build_wheel_ci.py --python-version \ - --output-dir + build_wheel.py --python-version --output-dir Wheels for the given Python version will be created in the given directory. Python version is in form "39". @@ -18,15 +16,12 @@ You can test locally by using --extra-opts. macOS example: - mypy/misc/build_wheel_ci.py --python-version 39 --output-dir out --extra-opts="--platform macos" - -Other supported values for platform: linux, windows + mypy/misc/build_wheel.py --python-version 39 --output-dir out --extra-opts="--platform macos" """ import argparse import os import subprocess -import sys from typing import Dict # Clang package we use on Linux @@ -40,13 +35,13 @@ def create_environ(python_version: str) -> Dict[str, str]: """Set up environment variables for cibuildwheel.""" env = os.environ.copy() - env['CIBW_BUILD'] = "cp{}-*".format(python_version) + env['CIBW_BUILD'] = f"cp{python_version}-*" # Don't build 32-bit wheels env['CIBW_SKIP'] = "*-manylinux_i686 *-win32" # Apple Silicon support - # When cross-compiling on Intel, it is not possible to test arm64 and + # When cross-compiling on Intel, it is not possible to test arm64 and # the arm64 part of a universal2 wheel. Warnings will be silenced with # following CIBW_TEST_SKIP env['CIBW_ARCHS_MACOS'] = "x86_64 arm64" @@ -57,20 +52,15 @@ def create_environ(python_version: str) -> Dict[str, str]: # mypy's isolated builds don't specify the requirements mypyc needs, so install # requirements and don't use isolated builds. we need to use build-requirements.txt # with recent mypy commits to get stub packages needed for compilation. - # - # TODO: remove use of mypy-requirements.txt once we no longer need to support - # building pre modular typeshed releases env['CIBW_BEFORE_BUILD'] = """ - pip install -r {package}/mypy-requirements.txt && - (pip install -r {package}/build-requirements.txt || true) + pip install -r {package}/build-requirements.txt """.replace('\n', ' ') # download a copy of clang to use to compile on linux. this was probably built in 2018, # speeds up compilation 2x env['CIBW_BEFORE_BUILD_LINUX'] = """ (cd / && curl -L %s | tar xzf -) && - pip install -r {package}/mypy-requirements.txt && - (pip install -r {package}/build-requirements.txt || true) + pip install -r {package}/build-requirements.txt """.replace('\n', ' ') % LLVM_URL # the double negative is counterintuitive, https://github.com/pypa/pip/issues/5735 @@ -129,8 +119,7 @@ def main() -> None: output_dir = args.output_dir extra_opts = args.extra_opts environ = create_environ(python_version) - script = 'python -m cibuildwheel {} --output-dir {} {}'.format(extra_opts, output_dir, - ROOT_DIR) + script = f'python -m cibuildwheel {extra_opts} --output-dir {output_dir} {ROOT_DIR}' subprocess.check_call(script, shell=True, env=environ) diff --git a/misc/cherry-pick-typeshed.py b/misc/cherry-pick-typeshed.py new file mode 100644 index 000000000000..627c8990a155 --- /dev/null +++ b/misc/cherry-pick-typeshed.py @@ -0,0 +1,67 @@ +"""Cherry-pick a commit from typeshed. + +Usage: + + python3 misc/cherry-pick-typeshed.py --typeshed-dir dir hash +""" + +import argparse +import os.path +import re +import subprocess +import sys +import tempfile + + +def parse_commit_title(diff: str) -> str: + m = re.search("\n ([^ ].*)", diff) + assert m is not None, "Could not parse diff" + return m.group(1) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--typeshed-dir", help="location of typeshed", metavar="dir", required=True + ) + parser.add_argument( + "commit", help="typeshed commit hash to cherry-pick" + ) + args = parser.parse_args() + typeshed_dir = args.typeshed_dir + commit = args.commit + + if not os.path.isdir(typeshed_dir): + sys.exit(f"error: {typeshed_dir} does not exist") + if not re.match("[0-9a-fA-F]+$", commit): + sys.exit(f"error: Invalid commit {commit!r}") + + if not os.path.exists("mypy") or not os.path.exists("mypyc"): + sys.exit(f"error: This script must be run at the mypy repository root directory") + + with tempfile.TemporaryDirectory() as d: + diff_file = os.path.join(d, "diff") + out = subprocess.run(["git", "show", commit], + capture_output=True, + text=True, + check=True, + cwd=typeshed_dir) + with open(diff_file, "w") as f: + f.write(out.stdout) + subprocess.run(["git", + "apply", + "--index", + "--directory=mypy/typeshed", + "--exclude=**/tests/**", + diff_file], + check=True) + + title = parse_commit_title(out.stdout) + subprocess.run(["git", "commit", "-m", f"Typeshed cherry-pick: {title}"], check=True) + + print() + print(f"Cherry-picked commit {commit} from {typeshed_dir}") + + +if __name__ == '__main__': + main() diff --git a/misc/proper_plugin.py b/misc/proper_plugin.py index c30999448387..249ad983266b 100644 --- a/misc/proper_plugin.py +++ b/misc/proper_plugin.py @@ -34,6 +34,9 @@ def get_function_hook(self, fullname: str def isinstance_proper_hook(ctx: FunctionContext) -> Type: + if len(ctx.arg_types) != 2 or not ctx.arg_types[1]: + return ctx.default_return_type + right = get_proper_type(ctx.arg_types[1][0]) for arg in ctx.arg_types[0]: if (is_improper_type(arg) or @@ -63,6 +66,7 @@ def is_special_target(right: ProperType) -> bool: if right.type_object().fullname in ( 'mypy.types.UnboundType', 'mypy.types.TypeVarType', + 'mypy.types.ParamSpecType', 'mypy.types.RawExpressionType', 'mypy.types.EllipsisType', 'mypy.types.StarType', diff --git a/misc/sync-typeshed.py b/misc/sync-typeshed.py index 631cc7682514..93cbd951e0f6 100644 --- a/misc/sync-typeshed.py +++ b/misc/sync-typeshed.py @@ -1,4 +1,4 @@ -"""Sync stdlib stubs from typeshed. +"""Sync stdlib stubs (and a few other files) from typeshed. Usage: @@ -8,7 +8,6 @@ """ import argparse -import glob import os import shutil import subprocess @@ -49,6 +48,7 @@ def update_typeshed(typeshed_dir: str, commit: Optional[str]) -> str: os.makedirs(stubs_dir) shutil.copytree(os.path.join(typeshed_dir, 'stubs', 'mypy-extensions'), os.path.join(stubs_dir, 'mypy-extensions')) + shutil.copy(os.path.join(typeshed_dir, 'LICENSE'), os.path.join('mypy', 'typeshed')) return commit @@ -69,7 +69,7 @@ def main() -> None: ) args = parser.parse_args() check_state() - print('Update contents of mypy/typeshed/stdlib from typeshed? [yN] ', end='') + print('Update contents of mypy/typeshed from typeshed? [yN] ', end='') answer = input() if answer.lower() != 'y': sys.exit('Aborting') diff --git a/misc/trigger_wheel_build.sh b/misc/trigger_wheel_build.sh index 469064fe8133..b00b08a15c55 100755 --- a/misc/trigger_wheel_build.sh +++ b/misc/trigger_wheel_build.sh @@ -3,8 +3,8 @@ # Trigger a build of mypyc compiled mypy wheels by updating the mypy # submodule in the git repo that drives those builds. -# $WHEELS_PUSH_TOKEN is stored in travis and is an API token for the -# mypy-build-bot account. +# $WHEELS_PUSH_TOKEN is stored in Github Settings and is an API token +# for the mypy-build-bot account. git config --global user.email "nobody" git config --global user.name "mypy wheels autopush" diff --git a/mypy-requirements.txt b/mypy-requirements.txt index ba0b689e2f98..61e0a9f28e01 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -typing_extensions>=3.7.4 -mypy_extensions>=0.4.3,<0.5.0 -typed_ast>=1.4.0,<1.5.0 -toml +typing_extensions>=3.10 +mypy_extensions>=0.4.3 +typed_ast>=1.4.0,<2; python_version<'3.8' +tomli>=1.1.0 diff --git a/mypy/__main__.py b/mypy/__main__.py index 353e8e526758..aebeb4baedf8 100644 --- a/mypy/__main__.py +++ b/mypy/__main__.py @@ -1,9 +1,10 @@ """Mypy type checker command line tool.""" - -import sys import os +import sys +import traceback -from mypy.main import main +from mypy.main import main, process_options +from mypy.util import FancyFormatter def console_entry() -> None: @@ -17,6 +18,16 @@ def console_entry() -> None: devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) sys.exit(2) + except KeyboardInterrupt: + _, options = process_options(args=sys.argv[1:]) + if options.show_traceback: + sys.stdout.write(traceback.format_exc()) + formatter = FancyFormatter(sys.stdout, sys.stderr, False) + msg = "Interrupted\n" + sys.stdout.write(formatter.style(msg, color="red", bold=True)) + sys.stdout.flush() + sys.stderr.flush() + sys.exit(2) if __name__ == '__main__': diff --git a/mypy/api.py b/mypy/api.py index ef3016ac31da..f6e40b4fc3ec 100644 --- a/mypy/api.py +++ b/mypy/api.py @@ -67,7 +67,7 @@ def run(args: List[str]) -> Tuple[str, str, int]: # Lazy import to avoid needing to import all of mypy to call run_dmypy from mypy.main import main return _run(lambda stdout, stderr: main(None, args=args, - stdout=stdout, stderr=stderr)) + stdout=stdout, stderr=stderr, clean_exit=True)) def run_dmypy(args: List[str]) -> Tuple[str, str, int]: diff --git a/mypy/applytype.py b/mypy/applytype.py index 2bc2fa92f7dc..5b803a4aaa0b 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -5,21 +5,22 @@ from mypy.expandtype import expand_type from mypy.types import ( Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types, - TypeVarDef, TypeVarLikeDef, ProperType + TypeVarLikeType, ProperType, ParamSpecType, get_proper_type ) from mypy.nodes import Context def get_target_type( - tvar: TypeVarLikeDef, + tvar: TypeVarLikeType, type: ProperType, callable: CallableType, report_incompatible_typevar_value: Callable[[CallableType, Type, str, Context], None], context: Context, skip_unsatisfied: bool ) -> Optional[Type]: - # TODO(shantanu): fix for ParamSpecDef - assert isinstance(tvar, TypeVarDef) + if isinstance(tvar, ParamSpecType): + return type + assert isinstance(tvar, TypeVarType) values = get_proper_types(tvar.values) if values: if isinstance(type, AnyType): @@ -75,7 +76,7 @@ def apply_generic_arguments( types = get_proper_types(orig_types) # Create a map from type variable id to target type. - id_to_type = {} # type: Dict[TypeVarId, Type] + id_to_type: Dict[TypeVarId, Type] = {} for tvar, type in zip(tvars, types): assert not isinstance(type, PartialType), "Internal error: must never apply partial type" @@ -88,6 +89,14 @@ def apply_generic_arguments( if target_type is not None: id_to_type[tvar.id] = target_type + param_spec = callable.param_spec() + if param_spec is not None: + nt = id_to_type.get(param_spec.id) + if nt is not None: + nt = get_proper_type(nt) + if isinstance(nt, CallableType): + callable = callable.expand_param_spec(nt) + # Apply arguments to argument types. arg_types = [expand_type(at, id_to_type) for at in callable.arg_types] diff --git a/mypy/argmap.py b/mypy/argmap.py index ff7e94e93cbe..bcb864472038 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -1,16 +1,20 @@ """Utilities for mapping between actual and formal arguments (and their types).""" -from typing import List, Optional, Sequence, Callable, Set +from typing import TYPE_CHECKING, List, Optional, Sequence, Callable, Set +from mypy.maptype import map_instance_to_supertype from mypy.types import ( - Type, Instance, TupleType, AnyType, TypeOfAny, TypedDictType, get_proper_type + Type, Instance, TupleType, AnyType, TypeOfAny, TypedDictType, ParamSpecType, get_proper_type ) from mypy import nodes +if TYPE_CHECKING: + from mypy.infer import ArgumentInferContext -def map_actuals_to_formals(actual_kinds: List[int], + +def map_actuals_to_formals(actual_kinds: List[nodes.ArgKind], actual_names: Optional[Sequence[Optional[str]]], - formal_kinds: List[int], + formal_kinds: List[nodes.ArgKind], formal_names: Sequence[Optional[str]], actual_arg_type: Callable[[int], Type]) -> List[List[int]]: @@ -23,14 +27,13 @@ def map_actuals_to_formals(actual_kinds: List[int], argument type with the given index. """ nformals = len(formal_kinds) - formal_to_actual = [[] for i in range(nformals)] # type: List[List[int]] - ambiguous_actual_kwargs = [] # type: List[int] + formal_to_actual: List[List[int]] = [[] for i in range(nformals)] + ambiguous_actual_kwargs: List[int] = [] fi = 0 for ai, actual_kind in enumerate(actual_kinds): if actual_kind == nodes.ARG_POS: if fi < nformals: - if formal_kinds[fi] in [nodes.ARG_POS, nodes.ARG_OPT, - nodes.ARG_NAMED, nodes.ARG_NAMED_OPT]: + if not formal_kinds[fi].is_star(): formal_to_actual[fi].append(ai) fi += 1 elif formal_kinds[fi] == nodes.ARG_STAR: @@ -52,14 +55,14 @@ def map_actuals_to_formals(actual_kinds: List[int], # Assume that it is an iterable (if it isn't, there will be # an error later). while fi < nformals: - if formal_kinds[fi] in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT, nodes.ARG_STAR2): + if formal_kinds[fi].is_named(star=True): break else: formal_to_actual[fi].append(ai) if formal_kinds[fi] == nodes.ARG_STAR: break fi += 1 - elif actual_kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT): + elif actual_kind.is_named(): assert actual_names is not None, "Internal error: named kinds without names given" name = actual_names[ai] if name in formal_names: @@ -70,7 +73,7 @@ def map_actuals_to_formals(actual_kinds: List[int], assert actual_kind == nodes.ARG_STAR2 actualt = get_proper_type(actual_arg_type(ai)) if isinstance(actualt, TypedDictType): - for name, value in actualt.items.items(): + for name in actualt.items: if name in formal_names: formal_to_actual[formal_names.index(name)].append(ai) elif nodes.ARG_STAR2 in formal_kinds: @@ -99,9 +102,9 @@ def map_actuals_to_formals(actual_kinds: List[int], return formal_to_actual -def map_formals_to_actuals(actual_kinds: List[int], +def map_formals_to_actuals(actual_kinds: List[nodes.ArgKind], actual_names: Optional[Sequence[Optional[str]]], - formal_kinds: List[int], + formal_kinds: List[nodes.ArgKind], formal_names: List[Optional[str]], actual_arg_type: Callable[[int], Type]) -> List[List[int]]: @@ -112,7 +115,7 @@ def map_formals_to_actuals(actual_kinds: List[int], formal_names, actual_arg_type) # Now reverse the mapping. - actual_to_formal = [[] for _ in actual_kinds] # type: List[List[int]] + actual_to_formal: List[List[int]] = [[] for _ in actual_kinds] for formal, actuals in enumerate(formal_to_actual): for actual in actuals: actual_to_formal[actual].append(formal) @@ -141,17 +144,19 @@ def f(x: int, *args: str) -> None: ... needs a separate instance since instances have per-call state. """ - def __init__(self) -> None: + def __init__(self, context: 'ArgumentInferContext') -> None: # Next tuple *args index to use. self.tuple_index = 0 # Keyword arguments in TypedDict **kwargs used. - self.kwargs_used = set() # type: Set[str] + self.kwargs_used: Set[str] = set() + # Type context for `*` and `**` arg kinds. + self.context = context def expand_actual_type(self, actual_type: Type, - actual_kind: int, + actual_kind: nodes.ArgKind, formal_name: Optional[str], - formal_kind: int) -> Type: + formal_kind: nodes.ArgKind) -> Type: """Return the actual (caller) type(s) of a formal argument with the given kinds. If the actual argument is a tuple *args, return the next individual tuple item that @@ -165,14 +170,18 @@ def expand_actual_type(self, """ actual_type = get_proper_type(actual_type) if actual_kind == nodes.ARG_STAR: - if isinstance(actual_type, Instance): - if actual_type.type.fullname == 'builtins.list': - # List *arg. - return actual_type.args[0] - elif actual_type.args: - # TODO: Try to map type arguments to Iterable - return actual_type.args[0] + if isinstance(actual_type, Instance) and actual_type.args: + from mypy.subtypes import is_subtype + if is_subtype(actual_type, self.context.iterable_type): + return map_instance_to_supertype( + actual_type, + self.context.iterable_type.type, + ).args[0] else: + # We cannot properly unpack anything other + # than `Iterable` type with `*`. + # Just return `Any`, other parts of code would raise + # a different error for improper use. return AnyType(TypeOfAny.from_error) elif isinstance(actual_type, TupleType): # Get the next tuple item of a tuple *arg. @@ -182,9 +191,13 @@ def expand_actual_type(self, else: self.tuple_index += 1 return actual_type.items[self.tuple_index - 1] + elif isinstance(actual_type, ParamSpecType): + # ParamSpec is valid in *args but it can't be unpacked. + return actual_type else: return AnyType(TypeOfAny.from_error) elif actual_kind == nodes.ARG_STAR2: + from mypy.subtypes import is_subtype if isinstance(actual_type, TypedDictType): if formal_kind != nodes.ARG_STAR2 and formal_name in actual_type.items: # Lookup type based on keyword argument name. @@ -194,11 +207,20 @@ def expand_actual_type(self, formal_name = (set(actual_type.items.keys()) - self.kwargs_used).pop() self.kwargs_used.add(formal_name) return actual_type.items[formal_name] - elif (isinstance(actual_type, Instance) - and (actual_type.type.fullname == 'builtins.dict')): - # Dict **arg. - # TODO: Handle arbitrary Mapping - return actual_type.args[1] + elif ( + isinstance(actual_type, Instance) and + len(actual_type.args) > 1 and + is_subtype(actual_type, self.context.mapping_type) + ): + # Only `Mapping` type can be unpacked with `**`. + # Other types will produce an error somewhere else. + return map_instance_to_supertype( + actual_type, + self.context.mapping_type.type, + ).args[1] + elif isinstance(actual_type, ParamSpecType): + # ParamSpec is valid in **kwargs but it can't be unpacked. + return actual_type else: return AnyType(TypeOfAny.from_error) else: diff --git a/mypy/backports.py b/mypy/backports.py new file mode 100644 index 000000000000..df5afcb2416f --- /dev/null +++ b/mypy/backports.py @@ -0,0 +1,18 @@ +import sys +from contextlib import contextmanager +from typing import Iterator + +if sys.version_info < (3, 6): + from collections import OrderedDict as OrderedDict # noqa: F401 +else: + # OrderedDict is kind of slow, so for most of our uses in Python 3.6 + # and later we'd rather just use dict + OrderedDict = dict + + +if sys.version_info < (3, 7): + @contextmanager + def nullcontext() -> Iterator[None]: + yield +else: + from contextlib import nullcontext as nullcontext # noqa: F401 diff --git a/mypy/binder.py b/mypy/binder.py index c1b6862c9e6d..2f83ffb095fc 100644 --- a/mypy/binder.py +++ b/mypy/binder.py @@ -2,7 +2,7 @@ from collections import defaultdict from typing import Dict, List, Set, Iterator, Union, Optional, Tuple, cast -from typing_extensions import DefaultDict +from typing_extensions import DefaultDict, TypeAlias as _TypeAlias from mypy.types import ( Type, AnyType, PartialType, UnionType, TypeOfAny, NoneType, get_proper_type @@ -13,10 +13,10 @@ from mypy.erasetype import remove_instance_last_known_values from mypy.nodes import Expression, Var, RefExpr from mypy.literals import Key, literal, literal_hash, subkeys -from mypy.nodes import IndexExpr, MemberExpr, NameExpr +from mypy.nodes import IndexExpr, MemberExpr, AssignmentExpr, NameExpr -BindableExpression = Union[IndexExpr, MemberExpr, NameExpr] +BindableExpression: _TypeAlias = Union[IndexExpr, MemberExpr, AssignmentExpr, NameExpr] class Frame: @@ -31,9 +31,11 @@ class Frame: that were assigned in that frame. """ - def __init__(self) -> None: - self.types = {} # type: Dict[Key, Type] + def __init__(self, id: int, conditional_frame: bool = False) -> None: + self.id = id + self.types: Dict[Key, Type] = {} self.unreachable = False + self.conditional_frame = conditional_frame # Should be set only if we're entering a frame where it's not # possible to accurately determine whether or not contained @@ -69,37 +71,43 @@ class A: """ # Stored assignments for situations with tuple/list lvalue and rvalue of union type. # This maps an expression to a list of bound types for every item in the union type. - type_assignments = None # type: Optional[Assigns] + type_assignments: Optional[Assigns] = None def __init__(self) -> None: + self.next_id = 1 + # The stack of frames currently used. These map # literal_hash(expr) -- literals like 'foo.bar' -- # to types. The last element of this list is the # top-most, current frame. Each earlier element # records the state as of when that frame was last # on top of the stack. - self.frames = [Frame()] + self.frames = [Frame(self._get_id())] # For frames higher in the stack, we record the set of # Frames that can escape there, either by falling off # the end of the frame or by a loop control construct # or raised exception. The last element of self.frames # has no corresponding element in this list. - self.options_on_return = [] # type: List[List[Frame]] + self.options_on_return: List[List[Frame]] = [] # Maps literal_hash(expr) to get_declaration(expr) # for every expr stored in the binder - self.declarations = {} # type: Dict[Key, Optional[Type]] + self.declarations: Dict[Key, Optional[Type]] = {} # Set of other keys to invalidate if a key is changed, e.g. x -> {x.a, x[0]} # Whenever a new key (e.g. x.a.b) is added, we update this - self.dependencies = {} # type: Dict[Key, Set[Key]] + self.dependencies: Dict[Key, Set[Key]] = {} # Whether the last pop changed the newly top frame on exit self.last_pop_changed = False - self.try_frames = set() # type: Set[int] - self.break_frames = [] # type: List[int] - self.continue_frames = [] # type: List[int] + self.try_frames: Set[int] = set() + self.break_frames: List[int] = [] + self.continue_frames: List[int] = [] + + def _get_id(self) -> int: + self.next_id += 1 + return self.next_id def _add_dependencies(self, key: Key, value: Optional[Key] = None) -> None: if value is None: @@ -109,9 +117,9 @@ def _add_dependencies(self, key: Key, value: Optional[Key] = None) -> None: for elt in subkeys(key): self._add_dependencies(elt, value) - def push_frame(self) -> Frame: + def push_frame(self, conditional_frame: bool = False) -> Frame: """Push a new frame into the binder.""" - f = Frame() + f = Frame(self._get_id(), conditional_frame) self.frames.append(f) self.options_on_return.append([]) return f @@ -128,7 +136,7 @@ def _get(self, key: Key, index: int = -1) -> Optional[Type]: return None def put(self, expr: Expression, typ: Type) -> None: - if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)): + if not isinstance(expr, (IndexExpr, MemberExpr, AssignmentExpr, NameExpr)): return if not literal(expr): return @@ -347,7 +355,7 @@ def allow_jump(self, index: int) -> None: # so make sure the index is positive if index < 0: index += len(self.options_on_return) - frame = Frame() + frame = Frame(self._get_id()) for f in self.frames[index + 1:]: frame.types.update(f.types) if f.unreachable: @@ -365,6 +373,7 @@ def handle_continue(self) -> None: @contextmanager def frame_context(self, *, can_skip: bool, fall_through: int = 1, break_frame: int = 0, continue_frame: int = 0, + conditional_frame: bool = False, try_frame: bool = False) -> Iterator[Frame]: """Return a context manager that pushes/pops frames on enter/exit. @@ -399,7 +408,7 @@ def frame_context(self, *, can_skip: bool, fall_through: int = 1, if try_frame: self.try_frames.add(len(self.frames) - 1) - new_frame = self.push_frame() + new_frame = self.push_frame(conditional_frame) if try_frame: # An exception may occur immediately self.allow_jump(-1) diff --git a/mypy/build.py b/mypy/build.py index 6b5f83aa6e09..5eebc0a22a85 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -15,6 +15,7 @@ import gc import json import os +import platform import re import stat import sys @@ -22,8 +23,8 @@ import types from typing import (AbstractSet, Any, Dict, Iterable, Iterator, List, Sequence, - Mapping, NamedTuple, Optional, Set, Tuple, Union, Callable, TextIO) -from typing_extensions import ClassVar, Final, TYPE_CHECKING + Mapping, NamedTuple, Optional, Set, Tuple, TypeVar, Union, Callable, TextIO) +from typing_extensions import ClassVar, Final, TYPE_CHECKING, TypeAlias as _TypeAlias from mypy_extensions import TypedDict from mypy.nodes import MypyFile, ImportBase, Import, ImportFrom, ImportAll, SymbolTable @@ -35,7 +36,7 @@ from mypy.errors import Errors, CompileError, ErrorInfo, report_internal_error from mypy.util import ( DecodeError, decode_python_encoding, is_sub_path, get_mypy_comments, module_prefix, - read_py_file, hash_digest, is_typeshed_file, is_stub_package_file + read_py_file, hash_digest, is_typeshed_file, is_stub_package_file, get_top_two_prefixes ) if TYPE_CHECKING: from mypy.report import Reports # Avoid unconditional slow import @@ -58,7 +59,7 @@ from mypy.renaming import VariableRenameVisitor from mypy.config_parser import parse_mypy_comments from mypy.freetree import free_tree -from mypy.stubinfo import legacy_bundled_packages +from mypy.stubinfo import legacy_bundled_packages, is_legacy_bundled_package from mypy import errorcodes as codes @@ -66,10 +67,10 @@ # mode only that is useful during development. This produces only a subset of # output compared to --verbose output. We use a global flag to enable this so # that it's easy to enable this when running tests. -DEBUG_FINE_GRAINED = False # type: Final +DEBUG_FINE_GRAINED: Final = False # These modules are special and should always come from typeshed. -CORE_BUILTIN_MODULES = { +CORE_BUILTIN_MODULES: Final = { 'builtins', 'typing', 'types', @@ -81,7 +82,7 @@ } -Graph = Dict[str, 'State'] +Graph: _TypeAlias = Dict[str, 'State'] # TODO: Get rid of BuildResult. We might as well return a BuildManager. @@ -102,7 +103,7 @@ def __init__(self, manager: 'BuildManager', graph: Graph) -> None: self.files = manager.modules self.types = manager.all_types # Non-empty if export_types True in options self.used_cache = manager.cache_enabled - self.errors = [] # type: List[str] # Filled in by build if desired + self.errors: List[str] = [] # Filled in by build if desired class BuildSourceSet: @@ -110,8 +111,8 @@ class BuildSourceSet: def __init__(self, sources: List[BuildSource]) -> None: self.source_text_present = False - self.source_modules = set() # type: Set[str] - self.source_paths = set() # type: Set[str] + self.source_modules: Set[str] = set() + self.source_paths: Set[str] = set() for source in sources: if source.text is not None: @@ -201,8 +202,9 @@ def _build(sources: List[BuildSource], stderr: TextIO, extra_plugins: Sequence[Plugin], ) -> BuildResult: - # This seems the most reasonable place to tune garbage collection. - gc.set_threshold(150 * 1000) + if platform.python_implementation() == 'CPython': + # This seems the most reasonable place to tune garbage collection. + gc.set_threshold(150 * 1000) data_dir = default_data_dir() fscache = fscache or FileSystemCache() @@ -224,7 +226,8 @@ def _build(sources: List[BuildSource], lambda path: read_py_file(path, cached_read, options.python_version), options.show_absolute_path, options.enabled_error_codes, - options.disabled_error_codes) + options.disabled_error_codes, + options.many_errors_threshold) plugin, snapshot = load_plugins(options, errors, stdout, extra_plugins) # Add catch-all .gitignore to cache dir if we created it @@ -328,7 +331,7 @@ def cache_meta_from_dict(meta: Dict[str, Any], data_json: str) -> CacheMeta: meta: JSON metadata read from the metadata cache file data_json: Path to the .data.json file containing the AST trees """ - sentinel = None # type: Any # Values to be validated by the caller + sentinel: Any = None # Values to be validated by the caller return CacheMeta( meta.get('id', sentinel), meta.get('path', sentinel), @@ -352,12 +355,12 @@ def cache_meta_from_dict(meta: Dict[str, Any], data_json: str) -> CacheMeta: # Priorities used for imports. (Here, top-level includes inside a class.) # These are used to determine a more predictable order in which the # nodes in an import cycle are processed. -PRI_HIGH = 5 # type: Final # top-level "from X import blah" -PRI_MED = 10 # type: Final # top-level "import X" -PRI_LOW = 20 # type: Final # either form inside a function -PRI_MYPY = 25 # type: Final # inside "if MYPY" or "if TYPE_CHECKING" -PRI_INDIRECT = 30 # type: Final # an indirect dependency -PRI_ALL = 99 # type: Final # include all priorities +PRI_HIGH: Final = 5 # top-level "from X import blah" +PRI_MED: Final = 10 # top-level "import X" +PRI_LOW: Final = 20 # either form inside a function +PRI_MYPY: Final = 25 # inside "if MYPY" or "if TYPE_CHECKING" +PRI_INDIRECT: Final = 30 # an indirect dependency +PRI_ALL: Final = 99 # include all priorities def import_priority(imp: ImportBase, toplevel_priority: int) -> int: @@ -382,7 +385,8 @@ def load_plugins_from_config( plugins (for cache validation). """ import importlib - snapshot = {} # type: Dict[str, str] + + snapshot: Dict[str, str] = {} if not options.config_file: return [], snapshot @@ -395,11 +399,11 @@ def plugin_error(message: str) -> None: errors.report(line, 0, message) errors.raise_error(use_stdout=False) - custom_plugins = [] # type: List[Plugin] + custom_plugins: List[Plugin] = [] errors.set_file(options.config_file, None) for plugin_path in options.plugins: func_name = 'plugin' - plugin_dir = None # type: Optional[str] + plugin_dir: Optional[str] = None if ':' in os.path.basename(plugin_path): plugin_path, func_name = plugin_path.rsplit(':', 1) if plugin_path.endswith('.py'): @@ -475,7 +479,7 @@ def load_plugins(options: Options, custom_plugins += extra_plugins - default_plugin = DefaultPlugin(options) # type: Plugin + default_plugin: Plugin = DefaultPlugin(options) if not custom_plugins: return default_plugin, snapshot @@ -490,6 +494,7 @@ def take_module_snapshot(module: types.ModuleType) -> str: (e.g. if there is a change in modules imported by a plugin). """ if hasattr(module, '__file__'): + assert module.__file__ is not None with open(module.__file__, 'rb') as f: digest = hash_digest(f.read()) else: @@ -580,7 +585,7 @@ def __init__(self, data_dir: str, stdout: TextIO, stderr: TextIO, ) -> None: - self.stats = {} # type: Dict[str, Any] # Values are ints or floats + self.stats: Dict[str, Any] = {} # Values are ints or floats self.stdout = stdout self.stderr = stderr self.start_time = time.time() @@ -592,31 +597,31 @@ def __init__(self, data_dir: str, self.reports = reports self.options = options self.version_id = version_id - self.modules = {} # type: Dict[str, MypyFile] - self.missing_modules = set() # type: Set[str] - self.fg_deps_meta = {} # type: Dict[str, FgDepMeta] + self.modules: Dict[str, MypyFile] = {} + self.missing_modules: Set[str] = set() + self.fg_deps_meta: Dict[str, FgDepMeta] = {} # fg_deps holds the dependencies of every module that has been # processed. We store this in BuildManager so that we can compute # dependencies as we go, which allows us to free ASTs and type information, # saving a ton of memory on net. - self.fg_deps = {} # type: Dict[str, Set[str]] + self.fg_deps: Dict[str, Set[str]] = {} # Always convert the plugin to a ChainedPlugin so that it can be manipulated if needed if not isinstance(plugin, ChainedPlugin): plugin = ChainedPlugin(options, [plugin]) self.plugin = plugin # Set of namespaces (module or class) that are being populated during semantic # analysis and may have missing definitions. - self.incomplete_namespaces = set() # type: Set[str] + self.incomplete_namespaces: Set[str] = set() self.semantic_analyzer = SemanticAnalyzer( self.modules, self.missing_modules, self.incomplete_namespaces, self.errors, self.plugin) - self.all_types = {} # type: Dict[Expression, Type] # Enabled by export_types + self.all_types: Dict[Expression, Type] = {} # Enabled by export_types self.indirection_detector = TypeIndirectionVisitor() - self.stale_modules = set() # type: Set[str] - self.rechecked_modules = set() # type: Set[str] + self.stale_modules: Set[str] = set() + self.rechecked_modules: Set[str] = set() self.flush_errors = flush_errors has_reporters = reports is not None and reports.reporters self.cache_enabled = (options.incremental @@ -629,13 +634,13 @@ def __init__(self, data_dir: str, # a mapping from source files to their corresponding shadow files # for efficient lookup - self.shadow_map = {} # type: Dict[str, str] + self.shadow_map: Dict[str, str] = {} if self.options.shadow_file is not None: self.shadow_map = {source_file: shadow_file for (source_file, shadow_file) in self.options.shadow_file} # a mapping from each file being typechecked to its possible shadow file - self.shadow_equivalence_map = {} # type: Dict[str, Optional[str]] + self.shadow_equivalence_map: Dict[str, Optional[str]] = {} self.plugin = plugin self.plugins_snapshot = plugins_snapshot self.old_plugins_snapshot = read_plugins_snapshot(self) @@ -643,9 +648,9 @@ def __init__(self, data_dir: str, # Fine grained targets (module top levels and top level functions) processed by # the semantic analyzer, used only for testing. Currently used only by the new # semantic analyzer. - self.processed_targets = [] # type: List[str] + self.processed_targets: List[str] = [] # Missing stub packages encountered. - self.missing_stub_packages = set() # type: Set[str] + self.missing_stub_packages: Set[str] = set() # Cache for mypy ASTs that have completed semantic analysis # pass 1. When multiple files are added to the build in a # single daemon increment, only one of the files gets added @@ -653,7 +658,7 @@ def __init__(self, data_dir: str, # until all the files have been added. This means that a # new file can be processed O(n**2) times. This cache # avoids most of this redundant work. - self.ast_cache = {} # type: Dict[str, Tuple[MypyFile, List[ErrorInfo]]] + self.ast_cache: Dict[str, Tuple[MypyFile, List[ErrorInfo]]] = {} def dump_stats(self) -> None: if self.options.dump_build_stats: @@ -726,7 +731,7 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: return new_id - res = [] # type: List[Tuple[int, str, int]] + res: List[Tuple[int, str, int]] = [] for imp in file.imports: if not imp.is_unreachable: if isinstance(imp, Import): @@ -749,7 +754,6 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: res.append((ancestor_pri, ".".join(ancestors), imp.line)) elif isinstance(imp, ImportFrom): cur_id = correct_rel_imp(imp) - pos = len(res) all_are_submodules = True # Also add any imported names that are submodules. pri = import_priority(imp, PRI_MED) @@ -766,7 +770,10 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: # if all of the imports are submodules, do the import at a lower # priority. pri = import_priority(imp, PRI_HIGH if not all_are_submodules else PRI_LOW) - res.insert(pos, ((pri, cur_id, imp.line))) + # The imported module goes in after the + # submodules, for the same namespace related + # reasons discussed in the Import case. + res.append((pri, cur_id, imp.line)) elif isinstance(imp, ImportAll): pri = import_priority(imp, PRI_HIGH) res.append((pri, correct_rel_imp(imp), imp.line)) @@ -860,13 +867,13 @@ def deps_to_json(x: Dict[str, Set[str]]) -> str: # File for storing metadata about all the fine-grained dependency caches -DEPS_META_FILE = '@deps.meta.json' # type: Final +DEPS_META_FILE: Final = "@deps.meta.json" # File for storing fine-grained dependencies that didn't a parent in the build -DEPS_ROOT_FILE = '@root.deps.json' # type: Final +DEPS_ROOT_FILE: Final = "@root.deps.json" # The name of the fake module used to store fine-grained dependencies that # have no other place to go. -FAKE_ROOT_MODULE = '@root' # type: Final +FAKE_ROOT_MODULE: Final = "@root" def write_deps_cache(rdeps: Dict[str, Dict[str, Set[str]]], @@ -909,7 +916,7 @@ def write_deps_cache(rdeps: Dict[str, Dict[str, Set[str]]], else: fg_deps_meta[id] = {'path': deps_json, 'mtime': manager.getmtime(deps_json)} - meta_snapshot = {} # type: Dict[str, str] + meta_snapshot: Dict[str, str] = {} for id, st in graph.items(): # If we didn't parse a file (so it doesn't have a # source_hash), then it must be a module with a fresh cache, @@ -948,7 +955,7 @@ def invert_deps(deps: Dict[str, Set[str]], # Prepopulate the map for all the modules that have been processed, # so that we always generate files for processed modules (even if # there aren't any dependencies to them.) - rdeps = {id: {} for id, st in graph.items() if st.tree} # type: Dict[str, Dict[str, Set[str]]] + rdeps: Dict[str, Dict[str, Set[str]]] = {id: {} for id, st in graph.items() if st.tree} for trigger, targets in deps.items(): module = module_prefix(graph, trigger_to_target(trigger)) if not module or not graph[module].tree: @@ -989,7 +996,7 @@ def generate_deps_for_cache(manager: BuildManager, return rdeps -PLUGIN_SNAPSHOT_FILE = '@plugins_snapshot.json' # type: Final +PLUGIN_SNAPSHOT_FILE: Final = "@plugins_snapshot.json" def write_plugins_snapshot(manager: BuildManager) -> None: @@ -1017,11 +1024,11 @@ def read_plugins_snapshot(manager: BuildManager) -> Optional[Dict[str, str]]: def read_quickstart_file(options: Options, stdout: TextIO, ) -> Optional[Dict[str, Tuple[float, int, str]]]: - quickstart = None # type: Optional[Dict[str, Tuple[float, int, str]]] + quickstart: Optional[Dict[str, Tuple[float, int, str]]] = None if options.quickstart_file: # This is very "best effort". If the file is missing or malformed, # just ignore it. - raw_quickstart = {} # type: Dict[str, Any] + raw_quickstart: Dict[str, Any] = {} try: with open(options.quickstart_file, "r") as f: raw_quickstart = json.load(f) @@ -1089,8 +1096,10 @@ def _load_json_file(file: str, manager: BuildManager, if manager.verbosity() >= 2: manager.trace(log_success + data.rstrip()) try: + t1 = time.time() result = json.loads(data) - except ValueError: # TODO: JSONDecodeError in 3.5 + manager.add_stats(data_json_load_time=time.time() - t1) + except json.JSONDecodeError: manager.errors.set_file(file, None) manager.errors.report(-1, -1, "Error reading JSON file;" @@ -1149,7 +1158,7 @@ def exclude_from_backups(target_dir: str) -> None: def create_metastore(options: Options) -> MetadataStore: """Create the appropriate metadata store.""" if options.sqlite_cache: - mds = SqliteMetadataStore(_cache_dir_prefix(options)) # type: MetadataStore + mds: MetadataStore = SqliteMetadataStore(_cache_dir_prefix(options)) else: mds = FilesystemMetadataStore(_cache_dir_prefix(options)) return mds @@ -1302,8 +1311,11 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], assert path is not None, "Internal error: meta was provided without a path" if not manager.options.skip_cache_mtime_checks: # Check data_json; assume if its mtime matches it's good. - # TODO: stat() errors - data_mtime = manager.getmtime(meta.data_json) + try: + data_mtime = manager.getmtime(meta.data_json) + except OSError: + manager.log('Metadata abandoned for {}: failed to stat data_json'.format(id)) + return None if data_mtime != meta.data_mtime: manager.log('Metadata abandoned for {}: data cache is modified'.format(id)) return None @@ -1315,7 +1327,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], st = manager.get_stat(path) except OSError: return None - if not stat.S_ISREG(st.st_mode): + if not (stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode)): manager.log('Metadata abandoned for {}: file {} does not exist'.format(id, path)) return None @@ -1358,7 +1370,11 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], t0 = time.time() try: - source_hash = manager.fscache.hash_digest(path) + # dir means it is a namespace package + if stat.S_ISDIR(st.st_mode): + source_hash = '' + else: + source_hash = manager.fscache.hash_digest(path) except (OSError, UnicodeDecodeError, DecodeError): return None manager.add_stats(validate_hash_time=time.time() - t0) @@ -1495,9 +1511,6 @@ def write_cache(id: str, path: str, tree: MypyFile, # Write data cache file, if applicable # Note that for Bazel we don't record the data file's mtime. if old_interface_hash == interface_hash: - # If the interface is unchanged, the cached data is guaranteed - # to be equivalent, and we only need to update the metadata. - data_mtime = manager.getmtime(data_json) manager.trace("Interface for {} is unchanged".format(id)) else: manager.trace("Interface for {} has changed".format(id)) @@ -1514,7 +1527,12 @@ def write_cache(id: str, path: str, tree: MypyFile, # Both have the effect of slowing down the next run a # little bit due to an out-of-date cache file. return interface_hash, None + + try: data_mtime = manager.getmtime(data_json) + except OSError: + manager.log("Error in os.stat({!r}), skipping cache write".format(data_json)) + return interface_hash, None mtime = 0 if bazel else int(st.st_mtime) size = st.st_size @@ -1723,40 +1741,40 @@ class State: case path is None. Otherwise source is None and path isn't. """ - manager = None # type: BuildManager - order_counter = 0 # type: ClassVar[int] - order = None # type: int # Order in which modules were encountered - id = None # type: str # Fully qualified module name - path = None # type: Optional[str] # Path to module source - abspath = None # type: Optional[str] # Absolute path to module source - xpath = None # type: str # Path or '' - source = None # type: Optional[str] # Module source code - source_hash = None # type: Optional[str] # Hash calculated based on the source code - meta_source_hash = None # type: Optional[str] # Hash of the source given in the meta, if any - meta = None # type: Optional[CacheMeta] - data = None # type: Optional[str] - tree = None # type: Optional[MypyFile] + manager: BuildManager + order_counter: ClassVar[int] = 0 + order: int # Order in which modules were encountered + id: str # Fully qualified module name + path: Optional[str] = None # Path to module source + abspath: Optional[str] = None # Absolute path to module source + xpath: str # Path or '' + source: Optional[str] = None # Module source code + source_hash: Optional[str] = None # Hash calculated based on the source code + meta_source_hash: Optional[str] = None # Hash of the source given in the meta, if any + meta: Optional[CacheMeta] = None + data: Optional[str] = None + tree: Optional[MypyFile] = None # We keep both a list and set of dependencies. A set because it makes it efficient to # prevent duplicates and the list because I am afraid of changing the order of # iteration over dependencies. # They should be managed with add_dependency and suppress_dependency. - dependencies = None # type: List[str] # Modules directly imported by the module - dependencies_set = None # type: Set[str] # The same but as a set for deduplication purposes - suppressed = None # type: List[str] # Suppressed/missing dependencies - suppressed_set = None # type: Set[str] # Suppressed/missing dependencies - priorities = None # type: Dict[str, int] + dependencies: List[str] # Modules directly imported by the module + dependencies_set: Set[str] # The same but as a set for deduplication purposes + suppressed: List[str] # Suppressed/missing dependencies + suppressed_set: Set[str] # Suppressed/missing dependencies + priorities: Dict[str, int] # Map each dependency to the line number where it is first imported - dep_line_map = None # type: Dict[str, int] + dep_line_map: Dict[str, int] # Parent package, its parent, etc. - ancestors = None # type: Optional[List[str]] + ancestors: Optional[List[str]] = None # List of (path, line number) tuples giving context for import - import_context = None # type: List[Tuple[str, int]] + import_context: List[Tuple[str, int]] # The State from which this module was imported, if any - caller_state = None # type: Optional[State] + caller_state: Optional["State"] = None # If caller_state is set, the line number in the caller where the import occurred caller_line = 0 @@ -1765,10 +1783,10 @@ class State: externally_same = True # Contains a hash of the public interface in incremental mode - interface_hash = "" # type: str + interface_hash: str = "" # Options, specialized for this file - options = None # type: Options + options: Options # Whether to ignore all errors ignore_all = False @@ -1778,11 +1796,11 @@ class State: # Errors reported before semantic analysis, to allow fine-grained # mode to keep reporting them. - early_errors = None # type: List[ErrorInfo] + early_errors: List[ErrorInfo] # Type checker used for checking this file. Use type_checker() for # access and to construct this on demand. - _type_checker = None # type: Optional[TypeChecker] + _type_checker: Optional[TypeChecker] = None fine_grained_deps_loaded = False @@ -1833,15 +1851,15 @@ def __init__(self, if path: self.abspath = os.path.abspath(path) self.xpath = path or '' - if path and source is None and self.manager.fscache.isdir(path): - source = '' - self.source = source if path and source is None and self.manager.cache_enabled: self.meta = find_cache_meta(self.id, path, manager) # TODO: Get mtime if not cached. if self.meta is not None: self.interface_hash = self.meta.interface_hash self.meta_source_hash = self.meta.hash + if path and source is None and self.manager.fscache.isdir(path): + source = '' + self.source = source self.add_ancestors() t0 = time.time() self.meta = validate_meta(self.meta, self.id, self.path, self.ignore_all, manager) @@ -1968,17 +1986,17 @@ def load_fine_grained_deps(self) -> Dict[str, Set[str]]: def load_tree(self, temporary: bool = False) -> None: assert self.meta is not None, "Internal error: this method must be called only" \ " for cached modules" + + data = _load_json_file(self.meta.data_json, self.manager, "Load tree ", + "Could not load tree: ") + if data is None: + return None + t0 = time.time() - raw = self.manager.metastore.read(self.meta.data_json) - t1 = time.time() - data = json.loads(raw) - t2 = time.time() # TODO: Assert data file wasn't changed. self.tree = MypyFile.deserialize(data) - t3 = time.time() - self.manager.add_stats(data_read_time=t1 - t0, - data_json_load_time=t2 - t1, - deserialize_time=t3 - t2) + t1 = time.time() + self.manager.add_stats(deserialize_time=t1 - t0) if not temporary: self.manager.modules[self.id] = self.tree self.manager.add_stats(fresh_trees=1) @@ -2036,6 +2054,9 @@ def parse_file(self) -> None: else: err = "mypy: can't decode file '{}': {}".format(self.path, str(decodeerr)) raise CompileError([err], module_with_blocker=self.id) from decodeerr + elif self.path and self.manager.fscache.isdir(self.path): + source = '' + self.source_hash = '' else: assert source is not None self.source_hash = compute_hash(source) @@ -2442,13 +2463,18 @@ def find_module_and_diagnose(manager: BuildManager, # search path or the module has not been installed. ignore_missing_imports = options.ignore_missing_imports - top_level = file_id.partition('.')[0] + top_level, second_level = get_top_two_prefixes(file_id) # Don't honor a global (not per-module) ignore_missing_imports # setting for modules that used to have bundled stubs, as # otherwise updating mypy can silently result in new false - # negatives. + # negatives. (Unless there are stubs but they are incomplete.) global_ignore_missing_imports = manager.options.ignore_missing_imports - if top_level in legacy_bundled_packages and global_ignore_missing_imports: + py_ver = options.python_version[0] + if ((is_legacy_bundled_package(top_level, py_ver) + or is_legacy_bundled_package(second_level, py_ver)) + and global_ignore_missing_imports + and not options.ignore_missing_imports_per_module + and result is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED): ignore_missing_imports = False if skip_diagnose: @@ -2515,7 +2541,7 @@ def in_partial_package(id: str, manager: BuildManager) -> bool: while '.' in id: parent, _ = id.rsplit('.', 1) if parent in manager.modules: - parent_mod = manager.modules[parent] # type: Optional[MypyFile] + parent_mod: Optional[MypyFile] = manager.modules[parent] else: # Parent is not in build, try quickly if we can find it. try: @@ -2550,13 +2576,15 @@ def module_not_found(manager: BuildManager, line: int, caller_state: State, msg, notes = reason.error_message_templates(daemon) pyver = '%d.%d' % manager.options.python_version errors.report(line, 0, msg.format(module=target, pyver=pyver), code=codes.IMPORT) - top_level = target.partition('.')[0] + top_level, second_level = get_top_two_prefixes(target) + if second_level in legacy_bundled_packages: + top_level = second_level for note in notes: if '{stub_dist}' in note: - note = note.format(stub_dist=legacy_bundled_packages[top_level]) + note = note.format(stub_dist=legacy_bundled_packages[top_level].name) errors.report(line, 0, note, severity='note', only_once=True, code=codes.IMPORT) if reason is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED: - manager.missing_stub_packages.add(legacy_bundled_packages[top_level]) + manager.missing_stub_packages.add(legacy_bundled_packages[top_level].name) errors.set_import_context(save_import_context) @@ -2714,8 +2742,8 @@ class NodeInfo: def __init__(self, index: int, scc: List[str]) -> None: self.node_id = "n%d" % index self.scc = scc - self.sizes = {} # type: Dict[str, int] # mod -> size in bytes - self.deps = {} # type: Dict[str, int] # node_id -> pri + self.sizes: Dict[str, int] = {} # mod -> size in bytes + self.deps: Dict[str, int] = {} # node_id -> pri def dumps(self) -> str: """Convert to JSON string.""" @@ -2781,13 +2809,13 @@ def load_graph(sources: List[BuildSource], manager: BuildManager, there are syntax errors. """ - graph = old_graph if old_graph is not None else {} # type: Graph + graph: Graph = old_graph if old_graph is not None else {} # The deque is used to implement breadth-first traversal. # TODO: Consider whether to go depth-first instead. This may # affect the order in which we process files within import cycles. new = new_modules if new_modules is not None else [] - entry_points = set() # type: Set[str] + entry_points: Set[str] = set() # Seed the graph with the initial root sources. for bs in sources: try: @@ -2871,7 +2899,14 @@ def load_graph(sources: List[BuildSource], manager: BuildManager, -1, 0, 'Source file found twice under different module names: ' '"{}" and "{}"'.format(seen_files[newst_path].id, newst.id), - blocker=True) + blocker=True, + ) + manager.errors.report( + -1, 0, + "See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules " # noqa: E501 + "for more info", + severity='note', + ) manager.errors.raise_error() seen_files[newst_path] = newst @@ -2892,7 +2927,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: manager.log("Found %d SCCs; largest has %d nodes" % (len(sccs), max(len(scc) for scc in sccs))) - fresh_scc_queue = [] # type: List[List[str]] + fresh_scc_queue: List[List[str]] = [] # We're processing SCCs from leaves (those without further # dependencies) to roots (those from which everything else can be @@ -3149,9 +3184,9 @@ def sorted_components(graph: Graph, sccs = list(strongly_connected_components(vertices, edges)) # Topsort. sccsmap = {id: frozenset(scc) for scc in sccs for id in scc} - data = {} # type: Dict[AbstractSet[str], Set[AbstractSet[str]]] + data: Dict[AbstractSet[str], Set[AbstractSet[str]]] = {} for scc in sccs: - deps = set() # type: Set[AbstractSet[str]] + deps: Set[AbstractSet[str]] = set() for id in scc: deps.update(sccsmap[x] for x in deps_filtered(graph, vertices, id, pri_max)) data[frozenset(scc)] = deps @@ -3196,10 +3231,10 @@ def strongly_connected_components(vertices: AbstractSet[str], From http://code.activestate.com/recipes/578507/. """ - identified = set() # type: Set[str] - stack = [] # type: List[str] - index = {} # type: Dict[str, int] - boundaries = [] # type: List[int] + identified: Set[str] = set() + stack: List[str] = [] + index: Dict[str, int] = {} + boundaries: List[int] = [] def dfs(v: str) -> Iterator[Set[str]]: index[v] = len(stack) @@ -3225,21 +3260,22 @@ def dfs(v: str) -> Iterator[Set[str]]: yield from dfs(v) -def topsort(data: Dict[AbstractSet[str], - Set[AbstractSet[str]]]) -> Iterable[Set[AbstractSet[str]]]: +T = TypeVar("T") + + +def topsort(data: Dict[T, Set[T]]) -> Iterable[Set[T]]: """Topological sort. Args: - data: A map from SCCs (represented as frozen sets of strings) to - sets of SCCs, its dependencies. NOTE: This data structure + data: A map from vertices to all vertices that it has an edge + connecting it to. NOTE: This data structure is modified in place -- for normalization purposes, self-dependencies are removed and entries representing orphans are added. Returns: - An iterator yielding sets of SCCs that have an equivalent - ordering. NOTE: The algorithm doesn't care about the internal - structure of SCCs. + An iterator yielding sets of vertices that have an equivalent + ordering. Example: Suppose the input has the following structure: diff --git a/mypy/checker.py b/mypy/checker.py index dde8a3441c35..b90221a0a5a5 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -8,8 +8,9 @@ Any, Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator, Iterable, Sequence, Mapping, Generic, AbstractSet, Callable ) -from typing_extensions import Final +from typing_extensions import Final, TypeAlias as _TypeAlias +from mypy.backports import nullcontext from mypy.errors import Errors, report_internal_error from mypy.nodes import ( SymbolTable, Statement, MypyFile, Var, Expression, Lvalue, Node, @@ -22,20 +23,22 @@ Context, Decorator, PrintStmt, BreakStmt, PassStmt, ContinueStmt, ComparisonExpr, StarExpr, EllipsisExpr, RefExpr, PromoteExpr, Import, ImportFrom, ImportAll, ImportBase, TypeAlias, - ARG_POS, ARG_STAR, LITERAL_TYPE, MDEF, GDEF, + ARG_POS, ARG_STAR, LITERAL_TYPE, LDEF, MDEF, GDEF, CONTRAVARIANT, COVARIANT, INVARIANT, TypeVarExpr, AssignmentExpr, is_final_node, ARG_NAMED) from mypy import nodes +from mypy import operators from mypy.literals import literal, literal_hash, Key -from mypy.typeanal import has_any_from_unimported_type, check_for_explicit_any +from mypy.typeanal import has_any_from_unimported_type, check_for_explicit_any, make_optional_type from mypy.types import ( Type, AnyType, CallableType, FunctionLike, Overloaded, TupleType, TypedDictType, Instance, NoneType, strip_type, TypeType, TypeOfAny, - UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarDef, + UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType, is_named_instance, union_items, TypeQuery, LiteralType, is_optional, remove_optional, TypeTranslator, StarType, get_proper_type, ProperType, - get_proper_types, is_literal_type, TypeAliasType, TypeGuardType) + get_proper_types, is_literal_type, TypeAliasType, TypeGuardedType, ParamSpecType +) from mypy.sametypes import is_same_type from mypy.messages import ( MessageBuilder, make_inferred_type_note, append_invariance_notes, pretty_seq, @@ -43,17 +46,21 @@ ) import mypy.checkexpr from mypy.checkmember import ( - analyze_member_access, analyze_descriptor_access, type_object_type, + MemberContext, analyze_member_access, analyze_descriptor_access, + type_object_type, + analyze_decorator_or_funcbase_access, ) +from mypy.semanal_enum import ENUM_BASES, ENUM_SPECIAL_PROPS from mypy.typeops import ( map_type_from_supertype, bind_self, erase_to_bound, make_simplified_union, erase_def_to_union_or_bound, erase_to_union_or_bound, coerce_to_literal, try_getting_str_literals_from_type, try_getting_int_literals_from_type, - tuple_fallback, is_singleton_type, try_expanding_enum_to_union, + tuple_fallback, is_singleton_type, try_expanding_sum_type_to_union, true_only, false_only, function_type, get_type_vars, custom_special_method, is_literal_type_like, ) from mypy import message_registry +from mypy.message_registry import ErrorMessage from mypy.subtypes import ( is_subtype, is_equivalent, is_proper_subtype, is_more_precise, restrict_subtype_away, is_subtype_ignoring_tvars, is_callable_compatible, @@ -82,10 +89,10 @@ T = TypeVar('T') -DEFAULT_LAST_PASS = 1 # type: Final # Pass numbers start at 0 +DEFAULT_LAST_PASS: Final = 1 # Pass numbers start at 0 -DeferredNodeType = Union[FuncDef, LambdaExpr, OverloadedFuncDef, Decorator] -FineGrainedDeferredNodeType = Union[FuncDef, MypyFile, OverloadedFuncDef] +DeferredNodeType: _TypeAlias = Union[FuncDef, LambdaExpr, OverloadedFuncDef, Decorator] +FineGrainedDeferredNodeType: _TypeAlias = Union[FuncDef, MypyFile, OverloadedFuncDef] # A node which is postponed to be processed during the next pass. # In normal mode one can defer functions and methods (also decorated and/or overloaded) @@ -122,7 +129,7 @@ # probably be better to have the dict keyed by the nodes' literal_hash # field instead. -TypeMap = Optional[Dict[Expression, Type]] +TypeMap: _TypeAlias = Optional[Dict[Expression, Type]] # An object that represents either a precise type or a type with an upper bound; # it is important for correct type inference with isinstance. @@ -153,33 +160,33 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface): # Are we type checking a stub? is_stub = False # Error message reporter - errors = None # type: Errors + errors: Errors # Utility for generating messages - msg = None # type: MessageBuilder + msg: MessageBuilder # Types of type checked nodes - type_map = None # type: Dict[Expression, Type] + type_map: Dict[Expression, Type] # Helper for managing conditional types - binder = None # type: ConditionalTypeBinder + binder: ConditionalTypeBinder # Helper for type checking expressions - expr_checker = None # type: mypy.checkexpr.ExpressionChecker + expr_checker: mypy.checkexpr.ExpressionChecker - tscope = None # type: Scope - scope = None # type: CheckerScope + tscope: Scope + scope: "CheckerScope" # Stack of function return types - return_types = None # type: List[Type] + return_types: List[Type] # Flags; true for dynamically typed functions - dynamic_funcs = None # type: List[bool] + dynamic_funcs: List[bool] # Stack of collections of variables with partial types - partial_types = None # type: List[PartialTypeScope] + partial_types: List[PartialTypeScope] # Vars for which partial type errors are already reported # (to avoid logically duplicate errors with different error context). - partial_reported = None # type: Set[Var] - globals = None # type: SymbolTable - modules = None # type: Dict[str, MypyFile] + partial_reported: Set[Var] + globals: SymbolTable + modules: Dict[str, MypyFile] # Nodes that couldn't be checked because some types weren't available. We'll run # another pass and try these again. - deferred_nodes = None # type: List[DeferredNode] + deferred_nodes: List[DeferredNode] # Type checking pass number (0 = first pass) pass_num = 0 # Last pass number to take @@ -191,20 +198,28 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface): is_typeshed_stub = False # Should strict Optional-related errors be suppressed in this file? suppress_none_errors = False # TODO: Get it from options instead - options = None # type: Options + options: Options # Used for collecting inferred attribute types so that they can be checked # for consistency. - inferred_attribute_types = None # type: Optional[Dict[Var, Type]] + inferred_attribute_types: Optional[Dict[Var, Type]] = None # Don't infer partial None types if we are processing assignment from Union - no_partial_types = False # type: bool + no_partial_types: bool = False # The set of all dependencies (suppressed or not) that this module accesses, either # directly or indirectly. - module_refs = None # type: Set[str] + module_refs: Set[str] + + # A map from variable nodes to a snapshot of the frame ids of the + # frames that were active when the variable was declared. This can + # be used to determine nearest common ancestor frame of a variable's + # declaration and the current frame, which lets us determine if it + # was declared in a different branch of the same `if` statement + # (if that frame is a conditional_frame). + var_decl_frames: Dict[Var, Set[int]] # Plugin that provides special type checking rules for specific library # functions such as open(), etc. - plugin = None # type: Plugin + plugin: Plugin def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Options, tree: MypyFile, path: str, plugin: Plugin) -> None: @@ -228,6 +243,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option self.dynamic_funcs = [] self.partial_types = [] self.partial_reported = set() + self.var_decl_frames = {} self.deferred_nodes = [] self.type_map = {} self.module_refs = set() @@ -287,29 +303,31 @@ def check_first_pass(self) -> None: self.recurse_into_functions = True with state.strict_optional_set(self.options.strict_optional): self.errors.set_file(self.path, self.tree.fullname, scope=self.tscope) - self.tscope.enter_file(self.tree.fullname) - with self.enter_partial_types(): - with self.binder.top_frame_context(): + with self.tscope.module_scope(self.tree.fullname): + with self.enter_partial_types(), self.binder.top_frame_context(): for d in self.tree.defs: + if (self.binder.is_unreachable() + and self.should_report_unreachable_issues() + and not self.is_raising_or_empty(d)): + self.msg.unreachable_statement(d) + break self.accept(d) - assert not self.current_node_deferred + assert not self.current_node_deferred - all_ = self.globals.get('__all__') - if all_ is not None and all_.type is not None: - all_node = all_.node - assert all_node is not None - seq_str = self.named_generic_type('typing.Sequence', - [self.named_type('builtins.str')]) - if self.options.python_version[0] < 3: + all_ = self.globals.get('__all__') + if all_ is not None and all_.type is not None: + all_node = all_.node + assert all_node is not None seq_str = self.named_generic_type('typing.Sequence', - [self.named_type('builtins.unicode')]) - if not is_subtype(all_.type, seq_str): - str_seq_s, all_s = format_type_distinctly(seq_str, all_.type) - self.fail(message_registry.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s), - all_node) - - self.tscope.leave() + [self.named_type('builtins.str')]) + if self.options.python_version[0] < 3: + seq_str = self.named_generic_type('typing.Sequence', + [self.named_type('builtins.unicode')]) + if not is_subtype(all_.type, seq_str): + str_seq_s, all_s = format_type_distinctly(seq_str, all_.type) + self.fail(message_registry.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s), + all_node) def check_second_pass(self, todo: Optional[Sequence[Union[DeferredNode, @@ -324,25 +342,26 @@ def check_second_pass(self, if not todo and not self.deferred_nodes: return False self.errors.set_file(self.path, self.tree.fullname, scope=self.tscope) - self.tscope.enter_file(self.tree.fullname) - self.pass_num += 1 - if not todo: - todo = self.deferred_nodes - else: - assert not self.deferred_nodes - self.deferred_nodes = [] - done = set() # type: Set[Union[DeferredNodeType, FineGrainedDeferredNodeType]] - for node, active_typeinfo in todo: - if node in done: - continue - # This is useful for debugging: - # print("XXX in pass %d, class %s, function %s" % - # (self.pass_num, type_name, node.fullname or node.name)) - done.add(node) - with self.tscope.class_scope(active_typeinfo) if active_typeinfo else nothing(): - with self.scope.push_class(active_typeinfo) if active_typeinfo else nothing(): - self.check_partial(node) - self.tscope.leave() + with self.tscope.module_scope(self.tree.fullname): + self.pass_num += 1 + if not todo: + todo = self.deferred_nodes + else: + assert not self.deferred_nodes + self.deferred_nodes = [] + done: Set[Union[DeferredNodeType, FineGrainedDeferredNodeType]] = set() + for node, active_typeinfo in todo: + if node in done: + continue + # This is useful for debugging: + # print("XXX in pass %d, class %s, function %s" % + # (self.pass_num, type_name, node.fullname or node.name)) + done.add(node) + with self.tscope.class_scope(active_typeinfo) if active_typeinfo \ + else nullcontext(): + with self.scope.push_class(active_typeinfo) if active_typeinfo \ + else nullcontext(): + self.check_partial(node) return True def check_partial(self, node: Union[DeferredNodeType, FineGrainedDeferredNodeType]) -> None: @@ -410,7 +429,7 @@ def accept_loop(self, body: Statement, else_body: Optional[Statement] = None, *, Then check the else_body. """ # The outer frame accumulates the results of all iterations - with self.binder.frame_context(can_skip=False): + with self.binder.frame_context(can_skip=False, conditional_frame=True): while True: with self.binder.frame_context(can_skip=True, break_frame=2, continue_frame=1): @@ -465,11 +484,18 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None: # At this point we should have set the impl already, and all remaining # items are decorators + if self.msg.errors.file in self.msg.errors.ignored_files: + # This is a little hacky, however, the quadratic check here is really expensive, this + # method has no side effects, so we should skip it if we aren't going to report + # anything. In some other places we swallow errors in stubs, but this error is very + # useful for stubs! + return + # Compute some info about the implementation (if it exists) for use below - impl_type = None # type: Optional[CallableType] + impl_type: Optional[CallableType] = None if defn.impl: if isinstance(defn.impl, FuncDef): - inner_type = defn.impl.type # type: Optional[Type] + inner_type: Optional[Type] = defn.impl.type elif isinstance(defn.impl, Decorator): inner_type = defn.impl.var.type else: @@ -479,8 +505,26 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None: # decorator or if the implementation is untyped -- we gave up on the types. inner_type = get_proper_type(inner_type) if inner_type is not None and not isinstance(inner_type, AnyType): - assert isinstance(inner_type, CallableType) - impl_type = inner_type + if isinstance(inner_type, CallableType): + impl_type = inner_type + elif isinstance(inner_type, Instance): + inner_call = get_proper_type( + analyze_member_access( + name='__call__', + typ=inner_type, + context=defn.impl, + is_lvalue=False, + is_super=False, + is_operator=True, + msg=self.msg, + original_type=inner_type, + chk=self, + ), + ) + if isinstance(inner_call, CallableType): + impl_type = inner_call + if impl_type is None: + self.msg.not_callable(inner_type, defn.impl) is_descriptor_get = defn.info and defn.name == "__get__" for i, item in enumerate(defn.items): @@ -857,7 +901,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) if isinstance(typ.ret_type, TypeVarType): if typ.ret_type.variance == CONTRAVARIANT: self.fail(message_registry.RETURN_TYPE_CANNOT_BE_CONTRAVARIANT, - typ.ret_type) + typ.ret_type) # Check that Generator functions have the appropriate return type. if defn.is_generator: @@ -904,7 +948,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) with self.scope.push_function(defn): # We temporary push the definition to get the self type as # visible from *inside* of this function/method. - ref_type = self.scope.active_self_type() # type: Optional[Type] + ref_type: Optional[Type] = self.scope.active_self_type() if (isinstance(defn, FuncDef) and ref_type is not None and i == 0 and not defn.is_static and typ.arg_kinds[0] not in [nodes.ARG_STAR, nodes.ARG_STAR2]): @@ -943,18 +987,20 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) arg_type.variance == COVARIANT and defn.name not in ('__init__', '__new__') ): - ctx = arg_type # type: Context + ctx: Context = arg_type if ctx.line < 0: ctx = typ self.fail(message_registry.FUNCTION_PARAMETER_CANNOT_BE_COVARIANT, ctx) if typ.arg_kinds[i] == nodes.ARG_STAR: - # builtins.tuple[T] is typing.Tuple[T, ...] - arg_type = self.named_generic_type('builtins.tuple', - [arg_type]) + if not isinstance(arg_type, ParamSpecType): + # builtins.tuple[T] is typing.Tuple[T, ...] + arg_type = self.named_generic_type('builtins.tuple', + [arg_type]) elif typ.arg_kinds[i] == nodes.ARG_STAR2: - arg_type = self.named_generic_type('builtins.dict', - [self.str_type(), - arg_type]) + if not isinstance(arg_type, ParamSpecType): + arg_type = self.named_generic_type('builtins.dict', + [self.str_type(), + arg_type]) item.arguments[i].variable.type = arg_type # Type check initialization expressions. @@ -975,7 +1021,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) self.accept(item.body) unreachable = self.binder.is_unreachable() - if (self.options.warn_no_return and not unreachable): + if self.options.warn_no_return and not unreachable: if (defn.is_generator or is_named_instance(self.return_types[-1], 'typing.AwaitableGenerator')): return_type = self.get_generator_return_type(self.return_types[-1], @@ -992,10 +1038,9 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) # entirely pass/Ellipsis/raise NotImplementedError. if isinstance(return_type, UninhabitedType): # This is a NoReturn function - self.msg.fail(message_registry.INVALID_IMPLICIT_RETURN, defn) + self.fail(message_registry.INVALID_IMPLICIT_RETURN, defn) else: - self.msg.fail(message_registry.MISSING_RETURN_STATEMENT, defn, - code=codes.RETURN) + self.fail(message_registry.MISSING_RETURN_STATEMENT, defn) self.return_types.pop() @@ -1026,13 +1071,13 @@ def is_forward_op_method(self, method_name: str) -> bool: if self.options.python_version[0] == 2 and method_name == '__div__': return True else: - return method_name in nodes.reverse_op_methods + return method_name in operators.reverse_op_methods def is_reverse_op_method(self, method_name: str) -> bool: if self.options.python_version[0] == 2 and method_name == '__rdiv__': return True else: - return method_name in nodes.reverse_op_method_set + return method_name in operators.reverse_op_method_set def check_for_missing_annotations(self, fdef: FuncItem) -> None: # Check for functions with unspecified/not fully specified types. @@ -1051,38 +1096,42 @@ def is_unannotated_any(t: Type) -> bool: if fdef.type is None and self.options.disallow_untyped_defs: if (not fdef.arguments or (len(fdef.arguments) == 1 and (fdef.arg_names[0] == 'self' or fdef.arg_names[0] == 'cls'))): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) if not has_return_statement(fdef) and not fdef.is_generator: self.note('Use "-> None" if function does not return a value', fdef, code=codes.NO_UNTYPED_DEF) else: - self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) elif isinstance(fdef.type, CallableType): ret_type = get_proper_type(fdef.type.ret_type) if is_unannotated_any(ret_type): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) elif fdef.is_generator: if is_unannotated_any(self.get_generator_return_type(ret_type, - fdef.is_coroutine)): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + fdef.is_coroutine)): + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) elif fdef.is_coroutine and isinstance(ret_type, Instance): if is_unannotated_any(self.get_coroutine_return_type(ret_type)): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) if any(is_unannotated_any(t) for t in fdef.type.arg_types): - self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef, - code=codes.NO_UNTYPED_DEF) + self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef) def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None: self_type = fill_typevars_with_any(fdef.info) bound_type = bind_self(typ, self_type, is_classmethod=True) # Check that __new__ (after binding cls) returns an instance # type (or any). - if not isinstance(get_proper_type(bound_type.ret_type), + if isinstance(fdef.info, TypeInfo) and fdef.info.is_metaclass(): + # This is a metaclass, so it must return a new unrelated type. + self.check_subtype( + bound_type.ret_type, + self.type_type(), + fdef, + message_registry.INVALID_NEW_TYPE, + 'returns', + 'but must return a subtype of' + ) + elif not isinstance(get_proper_type(bound_type.ret_type), (AnyType, Instance, TupleType)): self.fail( message_registry.NON_INSTANCE_NEW_TYPE.format( @@ -1188,7 +1237,7 @@ def check_reverse_op_method(self, defn: FuncItem, if self.options.python_version[0] == 2 and reverse_name == '__rdiv__': forward_name = '__div__' else: - forward_name = nodes.normal_from_reverse_op[reverse_name] + forward_name = operators.normal_from_reverse_op[reverse_name] forward_inst = get_proper_type(reverse_type.arg_types[1]) if isinstance(forward_inst, TypeVarType): forward_inst = get_proper_type(forward_inst.upper_bound) @@ -1265,7 +1314,7 @@ def check_overlapping_op_methods(self, reverse_class, reverse_name, forward_base, forward_name, context) elif isinstance(forward_item, Overloaded): - for item in forward_item.items(): + for item in forward_item.items: if self.is_unsafe_overlapping_op(item, forward_base, reverse_type): self.msg.operator_method_signatures_overlap( reverse_class, reverse_name, @@ -1327,7 +1376,7 @@ def check_inplace_operator_method(self, defn: FuncBase) -> None: They cannot arbitrarily overlap with __add__. """ method = defn.name - if method not in nodes.inplace_operator_methods: + if method not in operators.inplace_operator_methods: return typ = bind_self(self.function_type(defn)) cls = defn.info @@ -1350,7 +1399,7 @@ def check_getattr_method(self, typ: Type, context: Context, name: str) -> None: if len(self.scope.stack) == 1: # module scope if name == '__getattribute__': - self.msg.fail(message_registry.MODULE_LEVEL_GETATTRIBUTE, context) + self.fail(message_registry.MODULE_LEVEL_GETATTRIBUTE, context) return # __getattr__ is fine at the module level as of Python 3.7 (PEP 562). We could # show an error for Python < 3.7, but that would be annoying in code that supports @@ -1388,20 +1437,20 @@ def check_setattr_method(self, typ: Type, context: Context) -> None: def expand_typevars(self, defn: FuncItem, typ: CallableType) -> List[Tuple[FuncItem, CallableType]]: # TODO use generator - subst = [] # type: List[List[Tuple[TypeVarId, Type]]] + subst: List[List[Tuple[TypeVarId, Type]]] = [] tvars = list(typ.variables) or [] if defn.info: # Class type variables tvars += defn.info.defn.type_vars or [] - # TODO(shantanu): audit for paramspec + # TODO(PEP612): audit for paramspec for tvar in tvars: - if isinstance(tvar, TypeVarDef) and tvar.values: + if isinstance(tvar, TypeVarType) and tvar.values: subst.append([(tvar.id, value) for value in tvar.values]) # Make a copy of the function to check for each combination of # value restricted type variables. (Except when running mypyc, # where we need one canonical version of the function.) if subst and not self.options.mypyc: - result = [] # type: List[Tuple[FuncItem, CallableType]] + result: List[Tuple[FuncItem, CallableType]] = [] for substitutions in itertools.product(*subst): mapping = dict(substitutions) expanded = cast(CallableType, expand_type(typ, mapping)) @@ -1447,7 +1496,7 @@ def check_method_or_accessor_override_for_base(self, defn: Union[FuncDef, # (__init__, __new__, __init_subclass__ are special). if self.check_method_override_for_base_with_name(defn, name, base): return True - if name in nodes.inplace_operator_methods: + if name in operators.inplace_operator_methods: # Figure out the name of the corresponding operator method. method = '__' + name[3:] # An inplace operator method such as __iadd__ might not be @@ -1478,7 +1527,7 @@ def check_method_override_for_base_with_name( # Construct the type of the overriding method. if isinstance(defn, (FuncDef, OverloadedFuncDef)): - typ = self.function_type(defn) # type: Type + typ: Type = self.function_type(defn) override_class_or_static = defn.is_class or defn.is_static override_class = defn.is_class else: @@ -1505,6 +1554,16 @@ def check_method_override_for_base_with_name( original_type = self.function_type(original_node) elif isinstance(original_node, Decorator): original_type = self.function_type(original_node.func) + elif isinstance(original_node, Var): + # Super type can define method as an attribute. + # See https://github.com/python/mypy/issues/10134 + + # We also check that sometimes `original_node.type` is None. + # This is the case when we use something like `__hash__ = None`. + if original_node.type is not None: + original_type = get_proper_type(original_node.type) + else: + original_type = NoneType() else: assert False, str(base_attr.node) if isinstance(original_node, (FuncDef, OverloadedFuncDef)): @@ -1571,7 +1630,7 @@ def get_op_other_domain(self, tp: FunctionLike) -> Optional[Type]: return tp.arg_types[0] return None elif isinstance(tp, Overloaded): - raw_items = [self.get_op_other_domain(it) for it in tp.items()] + raw_items = [self.get_op_other_domain(it) for it in tp.items] items = [it for it in raw_items if it] if items: return make_simplified_union(items) @@ -1670,13 +1729,13 @@ def erase_override(t: Type) -> Type: # (in that order), and if the child swaps the two and does f(str) -> str and # f(int) -> int order = [] - for child_variant in override.items(): - for i, parent_variant in enumerate(original.items()): + for child_variant in override.items: + for i, parent_variant in enumerate(original.items): if is_subtype(child_variant, parent_variant): order.append(i) break - if len(order) == len(original.items()) and order != sorted(order): + if len(order) == len(original.items) and order != sorted(order): self.msg.overload_signature_incompatible_with_supertype( name, name_in_super, supertype, override, node) emitted_msg = True @@ -1684,7 +1743,7 @@ def erase_override(t: Type) -> Type: if not emitted_msg: # Fall back to generic incompatibility message. self.msg.signature_incompatible_with_supertype( - name, name_in_super, supertype, node) + name, name_in_super, supertype, node, original=original, override=override) if op_method_wider_note: self.note("Overloaded operator methods can't have wider argument types" " in overrides", node, code=codes.OVERRIDE) @@ -1731,9 +1790,10 @@ def visit_class_def(self, defn: ClassDef) -> None: if not defn.has_incompatible_baseclass: # Otherwise we've already found errors; more errors are not useful self.check_multiple_inheritance(typ) + self.check_final_deletable(typ) if defn.decorators: - sig = type_object_type(defn.info, self.named_type) # type: Type + sig: Type = type_object_type(defn.info, self.named_type) # Decorators are applied in reverse order. for decorator in reversed(defn.decorators): if (isinstance(decorator, CallExpr) @@ -1757,6 +1817,14 @@ def visit_class_def(self, defn: ClassDef) -> None: if typ.is_protocol and typ.defn.type_vars: self.check_protocol_variance(defn) + def check_final_deletable(self, typ: TypeInfo) -> None: + # These checks are only for mypyc. Only perform some checks that are easier + # to implement here than in mypyc. + for attr in typ.deletable_attributes: + node = typ.names.get(attr) + if node and isinstance(node.node, Var) and node.node.is_final: + self.fail(message_registry.CANNOT_MAKE_DELETABLE_FINAL, node.node) + def check_init_subclass(self, defn: ClassDef) -> None: """Check that keywords in a class definition are valid arguments for __init_subclass__(). @@ -1786,7 +1854,7 @@ def check_init_subclass(self, defn: ClassDef) -> None: name_expr.node = base callee = MemberExpr(name_expr, '__init_subclass__') args = list(defn.keywords.values()) - arg_names = list(defn.keywords.keys()) # type: List[Optional[str]] + arg_names: List[Optional[str]] = list(defn.keywords.keys()) # 'metaclass' keyword is consumed by the rest of the type machinery, # and is never passed to __init_subclass__ implementations if 'metaclass' in arg_names: @@ -1817,10 +1885,14 @@ def check_protocol_variance(self, defn: ClassDef) -> None: object_type = Instance(info.mro[-1], []) tvars = info.defn.type_vars for i, tvar in enumerate(tvars): - up_args = [object_type if i == j else AnyType(TypeOfAny.special_form) - for j, _ in enumerate(tvars)] # type: List[Type] - down_args = [UninhabitedType() if i == j else AnyType(TypeOfAny.special_form) - for j, _ in enumerate(tvars)] # type: List[Type] + up_args: List[Type] = [ + object_type if i == j else AnyType(TypeOfAny.special_form) + for j, _ in enumerate(tvars) + ] + down_args: List[Type] = [ + UninhabitedType() if i == j else AnyType(TypeOfAny.special_form) + for j, _ in enumerate(tvars) + ] up, down = Instance(info, up_args), Instance(info, down_args) # TODO: add advanced variance checks for recursive protocols if is_subtype(down, up, ignore_declared_variance=True): @@ -1829,7 +1901,7 @@ def check_protocol_variance(self, defn: ClassDef) -> None: expected = CONTRAVARIANT else: expected = INVARIANT - if expected != tvar.variance: + if isinstance(tvar, TypeVarType) and expected != tvar.variance: self.msg.bad_proto_variance(tvar.variance, tvar.name, expected, defn) def check_multiple_inheritance(self, typ: TypeInfo) -> None: @@ -1927,8 +1999,8 @@ class C(B, A[int]): ... # this is unsafe because... self.msg.cant_override_final(name, base2.name, ctx) if is_final_node(first.node): self.check_if_final_var_override_writable(name, second.node, ctx) - # __slots__ is special and the type can vary across class hierarchy. - if name == '__slots__': + # __slots__ and __deletable__ are special and the type can vary across class hierarchy. + if name in ('__slots__', '__deletable__'): ok = True if not ok: self.msg.base_class_definitions_incompatible(name, base1, base2, @@ -1975,7 +2047,8 @@ def visit_block(self, b: Block) -> None: self.accept(s) def should_report_unreachable_issues(self) -> bool: - return (self.options.warn_unreachable + return (self.in_checked_function() + and self.options.warn_unreachable and not self.binder.is_unreachable_warning_suppressed()) def is_raising_or_empty(self, s: Statement) -> bool: @@ -1995,10 +2068,9 @@ def is_raising_or_empty(self, s: Statement) -> bool: if isinstance(s.expr, EllipsisExpr): return True elif isinstance(s.expr, CallExpr): - self.expr_checker.msg.disable_errors() - typ = get_proper_type(self.expr_checker.accept( - s.expr, allow_none_return=True, always_allow_any=True)) - self.expr_checker.msg.enable_errors() + with self.expr_checker.msg.disable_errors(): + typ = get_proper_type(self.expr_checker.accept( + s.expr, allow_none_return=True, always_allow_any=True)) if isinstance(typ, UninhabitedType): return True @@ -2009,13 +2081,15 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: Handle all kinds of assignment statements (simple, indexed, multiple). """ - with self.enter_final_context(s.is_final_def): - self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax) + # Avoid type checking type aliases in stubs to avoid false + # positives about modern type syntax available in stubs such + # as X | Y. + if not (s.is_alias_def and self.is_stub): + with self.enter_final_context(s.is_final_def): + self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax) if s.is_alias_def: - # We do this mostly for compatibility with old semantic analyzer. - # TODO: should we get rid of this? - self.store_type(s.lvalues[-1], self.expr_checker.accept(s.rvalue)) + self.check_type_alias_rvalue(s) if (s.type is not None and self.options.disallow_any_unimported and @@ -2044,6 +2118,29 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: and self.scope.active_class() is not None): self.fail(message_registry.DEPENDENT_FINAL_IN_CLASS_BODY, s) + def check_type_alias_rvalue(self, s: AssignmentStmt) -> None: + if not (self.is_stub and isinstance(s.rvalue, OpExpr) and s.rvalue.op == '|'): + # We do this mostly for compatibility with old semantic analyzer. + # TODO: should we get rid of this? + alias_type = self.expr_checker.accept(s.rvalue) + else: + # Avoid type checking 'X | Y' in stubs, since there can be errors + # on older Python targets. + alias_type = AnyType(TypeOfAny.special_form) + + def accept_items(e: Expression) -> None: + if isinstance(e, OpExpr) and e.op == '|': + accept_items(e.left) + accept_items(e.right) + else: + # Nested union types have been converted to type context + # in semantic analysis (such as in 'list[int | str]'), + # so we don't need to deal with them here. + self.expr_checker.accept(e) + + accept_items(s.rvalue) + self.store_type(s.lvalues[-1], alias_type) + def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type: bool = True, new_syntax: bool = False) -> None: """Type check a single assignment: lvalue = rvalue.""" @@ -2121,6 +2218,31 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type rvalue_type, lvalue_type, infer_lvalue_type = self.check_member_assignment( instance_type, lvalue_type, rvalue, context=rvalue) else: + # Hacky special case for assigning a literal None + # to a variable defined in a previous if + # branch. When we detect this, we'll go back and + # make the type optional. This is somewhat + # unpleasant, and a generalization of this would + # be an improvement! + if (is_literal_none(rvalue) and + isinstance(lvalue, NameExpr) and + lvalue.kind == LDEF and + isinstance(lvalue.node, Var) and + lvalue.node.type and + lvalue.node in self.var_decl_frames and + not isinstance(get_proper_type(lvalue_type), AnyType)): + decl_frame_map = self.var_decl_frames[lvalue.node] + # Check if the nearest common ancestor frame for the definition site + # and the current site is the enclosing frame of an if/elif/else block. + has_if_ancestor = False + for frame in reversed(self.binder.frames): + if frame.id in decl_frame_map: + has_if_ancestor = frame.conditional_frame + break + if has_if_ancestor: + lvalue_type = make_optional_type(lvalue_type) + self.set_inferred_type(lvalue.node, lvalue, lvalue_type) + rvalue_type = self.check_simple_assignment(lvalue_type, rvalue, context=rvalue, code=codes.ASSIGNMENT) @@ -2150,12 +2272,13 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type if not inferred.is_final: rvalue_type = remove_instance_last_known_values(rvalue_type) self.infer_variable_type(inferred, lvalue, rvalue_type, rvalue) + self.check_assignment_to_slots(lvalue) # (type, operator) tuples for augmented assignments supported with partial types - partial_type_augmented_ops = { + partial_type_augmented_ops: Final = { ('builtins.list', '+'), ('builtins.set', '|'), - } # type: Final + } def try_infer_partial_generic_type_from_assignment(self, lvalue: Lvalue, @@ -2237,6 +2360,9 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, lvalue_type: Optional[ # redefine it. if lvalue_node.name == "__slots__" and base.fullname != "builtins.object": continue + # We don't care about the type of "__deletable__". + if lvalue_node.name == "__deletable__": + continue if is_private(lvalue_node.name): continue @@ -2352,7 +2478,7 @@ def lvalue_type_from_base(self, expr_node: Var, OverloadedFuncDef): # Same for properties with setter if base_node.is_property: - base_type = base_type.items()[0].ret_type + base_type = base_type.items[0].ret_type return base_type, base_node @@ -2391,13 +2517,14 @@ def check_compatibility_final_super(self, node: Var, self.msg.cant_override_final(node.name, base.name, node) return False if node.is_final: + if base.fullname in ENUM_BASES and node.name in ENUM_SPECIAL_PROPS: + return True self.check_if_final_var_override_writable(node.name, base_node, node) return True def check_if_final_var_override_writable(self, name: str, - base_node: - Optional[Node], + base_node: Optional[Node], ctx: Context) -> None: """Check that a final variable doesn't override writeable attribute. @@ -2460,7 +2587,7 @@ def check_final(self, name = lv.node.name cls = self.scope.active_class() if cls is not None: - # Theses additional checks exist to give more error messages + # These additional checks exist to give more error messages # even if the final attribute was overridden with a new symbol # (which is itself an error)... for base in cls.mro[1:]: @@ -2476,6 +2603,59 @@ def check_final(self, if lv.node.is_final and not is_final_decl: self.msg.cant_assign_to_final(name, lv.node.info is None, s) + def check_assignment_to_slots(self, lvalue: Lvalue) -> None: + if not isinstance(lvalue, MemberExpr): + return + + inst = get_proper_type(self.expr_checker.accept(lvalue.expr)) + if not isinstance(inst, Instance): + return + if inst.type.slots is None: + return # Slots do not exist, we can allow any assignment + if lvalue.name in inst.type.slots: + return # We are assigning to an existing slot + for base_info in inst.type.mro[:-1]: + if base_info.names.get('__setattr__') is not None: + # When type has `__setattr__` defined, + # we can assign any dynamic value. + # We exclude object, because it always has `__setattr__`. + return + + definition = inst.type.get(lvalue.name) + if definition is None: + # We don't want to duplicate + # `"SomeType" has no attribute "some_attr"` + # error twice. + return + if self.is_assignable_slot(lvalue, definition.type): + return + + self.fail( + message_registry.NAME_NOT_IN_SLOTS.format( + lvalue.name, inst.type.fullname, + ), + lvalue, + ) + + def is_assignable_slot(self, lvalue: Lvalue, typ: Optional[Type]) -> bool: + if getattr(lvalue, 'node', None): + return False # This is a definition + + typ = get_proper_type(typ) + if typ is None or isinstance(typ, AnyType): + return True # Any can be literally anything, like `@propery` + if isinstance(typ, Instance): + # When working with instances, we need to know if they contain + # `__set__` special method. Like `@property` does. + # This makes assigning to properties possible, + # even without extra slot spec. + return typ.type.get('__set__') is not None + if isinstance(typ, FunctionLike): + return True # Can be a property, or some other magic + if isinstance(typ, UnionType): + return all(self.is_assignable_slot(lvalue, u) for u in typ.items) + return False + def check_assignment_to_multiple_lvalues(self, lvalues: List[Lvalue], rvalue: Expression, context: Context, infer_lvalue_type: bool = True) -> None: @@ -2484,9 +2664,9 @@ def check_assignment_to_multiple_lvalues(self, lvalues: List[Lvalue], rvalue: Ex # using the type of rhs, because this allowed more fine grained # control in cases like: a, b = [int, str] where rhs would get # type List[object] - rvalues = [] # type: List[Expression] - iterable_type = None # type: Optional[Type] - last_idx = None # type: Optional[int] + rvalues: List[Expression] = [] + iterable_type: Optional[Type] = None + last_idx: Optional[int] = None for idx_rval, rval in enumerate(rvalue.items): if isinstance(rval, StarExpr): typs = get_proper_type(self.expr_checker.visit_star_expr(rval).type) @@ -2495,21 +2675,21 @@ def check_assignment_to_multiple_lvalues(self, lvalues: List[Lvalue], rvalue: Ex elif self.type_is_iterable(typs) and isinstance(typs, Instance): if (iterable_type is not None and iterable_type != self.iterable_item_type(typs)): - self.fail("Contiguous iterable with same type expected", context) + self.fail(message_registry.CONTIGUOUS_ITERABLE_EXPECTED, context) else: if last_idx is None or last_idx + 1 == idx_rval: rvalues.append(rval) last_idx = idx_rval iterable_type = self.iterable_item_type(typs) else: - self.fail("Contiguous iterable with same type expected", context) + self.fail(message_registry.CONTIGUOUS_ITERABLE_EXPECTED, context) else: - self.fail("Invalid type '{}' for *expr (iterable expected)".format(typs), + self.fail(message_registry.ITERABLE_TYPE_EXPECTED.format(typs), context) else: rvalues.append(rval) - iterable_start = None # type: Optional[int] - iterable_end = None # type: Optional[int] + iterable_start: Optional[int] = None + iterable_end: Optional[int] = None for i, rval in enumerate(rvalues): if isinstance(rval, StarExpr): typs = get_proper_type(self.expr_checker.visit_star_expr(rval).type) @@ -2558,8 +2738,7 @@ def check_rvalue_count_in_assignment(self, lvalues: List[Lvalue], rvalue_count: len(lvalues) - 1, context) return False elif rvalue_count != len(lvalues): - self.msg.wrong_number_values_to_unpack(rvalue_count, - len(lvalues), context) + self.msg.wrong_number_values_to_unpack(rvalue_count, len(lvalues), context) return False return True @@ -2616,8 +2795,7 @@ def check_multi_assignment_from_union(self, lvalues: List[Expression], rvalue: E for binder. """ self.no_partial_types = True - transposed = tuple([] for _ in - self.flatten_lvalues(lvalues)) # type: Tuple[List[Type], ...] + transposed: Tuple[List[Type], ...] = tuple([] for _ in self.flatten_lvalues(lvalues)) # Notify binder that we want to defer bindings and instead collect types. with self.binder.accumulate_type_assignments() as assignments: for item in rvalue_type.items: @@ -2636,7 +2814,7 @@ def check_multi_assignment_from_union(self, lvalues: List[Expression], rvalue: E # TODO: See todo in binder.py, ConditionalTypeBinder.assign_type # It's unclear why the 'declared_type' param is sometimes 'None' - clean_items = [] # type: List[Tuple[Type, Type]] + clean_items: List[Tuple[Type, Type]] = [] for type, declared_type in items: assert declared_type is not None clean_items.append((type, declared_type)) @@ -2657,7 +2835,7 @@ def check_multi_assignment_from_union(self, lvalues: List[Expression], rvalue: E self.no_partial_types = False def flatten_lvalues(self, lvalues: List[Expression]) -> List[Expression]: - res = [] # type: List[Expression] + res: List[Expression] = [] for lv in lvalues: if isinstance(lv, (TupleExpr, ListExpr)): res.extend(self.flatten_lvalues(lv.items)) @@ -2695,8 +2873,13 @@ def check_multi_assignment_from_tuple(self, lvalues: List[Lvalue], rvalue: Expre reinferred_rvalue_type, context, infer_lvalue_type) return - if isinstance(reinferred_rvalue_type, AnyType) and self.current_node_deferred: - # Doing more inference in deferred nodes can be hard, so give up for now. + if isinstance(reinferred_rvalue_type, AnyType): + # We can get Any if the current node is + # deferred. Doing more inference in deferred nodes + # is hard, so give up for now. We can also get + # here if reinferring types above changes the + # inferred return type for an overloaded function + # to be ambiguous. return assert isinstance(reinferred_rvalue_type, TupleType) rvalue_type = reinferred_rvalue_type @@ -2723,7 +2906,7 @@ def lvalue_type_for_inference(self, lvalues: List[Lvalue], rvalue_type: TupleTyp left_rv_types, star_rv_types, right_rv_types = self.split_around_star( rvalue_type.items, star_index, len(lvalues)) - type_parameters = [] # type: List[Type] + type_parameters: List[Type] = [] def append_types_for_inference(lvs: List[Expression], rv_types: List[Type]) -> None: for lv, rv_type in zip(lvs, rv_types): @@ -2796,7 +2979,9 @@ def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type], index_lvalue = None inferred = None - if self.is_definition(lvalue): + if self.is_definition(lvalue) and ( + not isinstance(lvalue, NameExpr) or isinstance(lvalue.node, Var) + ): if isinstance(lvalue, NameExpr): inferred = cast(Var, lvalue.node) assert isinstance(inferred, Var) @@ -2807,8 +2992,7 @@ def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type], elif isinstance(lvalue, IndexExpr): index_lvalue = lvalue elif isinstance(lvalue, MemberExpr): - lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, - True) + lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, True) self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, NameExpr): lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True) @@ -2937,6 +3121,9 @@ def set_inferred_type(self, var: Var, lvalue: Lvalue, type: Type) -> None: if var and not self.current_node_deferred: var.type = type var.is_inferred = True + if var not in self.var_decl_frames: + # Used for the hack to improve optional type inference in conditionals + self.var_decl_frames[var] = {frame.id for frame in self.binder.frames} if isinstance(lvalue, MemberExpr) and self.inferred_attribute_types is not None: # Store inferred attribute type so that we can check consistency afterwards. if lvalue.def_var is not None: @@ -3016,9 +3203,12 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, code=codes.ASSIGNMENT) return rvalue_type, attribute_type, True - get_type = analyze_descriptor_access( - instance_type, attribute_type, self.named_type, - self.msg, context, chk=self) + mx = MemberContext( + is_lvalue=False, is_super=False, is_operator=False, + original_type=instance_type, context=context, self_type=None, + msg=self.msg, chk=self, + ) + get_type = analyze_descriptor_access(attribute_type, mx) if not attribute_type.type.has_readable_member('__set__'): # If there is no __set__, we type-check that the assigned value matches # the return type of __get__. This doesn't match the python semantics, @@ -3030,12 +3220,12 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, dunder_set = attribute_type.type.get_method('__set__') if dunder_set is None: - self.msg.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type), - context) + self.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type), context) return AnyType(TypeOfAny.from_error), get_type, False - function = function_type(dunder_set, self.named_type('builtins.function')) - bound_method = bind_self(function, attribute_type) + bound_method = analyze_decorator_or_funcbase_access( + defn=dunder_set, itype=attribute_type, info=attribute_type.type, + self_type=attribute_type, name='__set__', mx=mx) typ = map_instance_to_supertype(attribute_type, dunder_set.info) dunder_set_type = expand_type_by_instance(bound_method, typ) @@ -3050,14 +3240,13 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, # For non-overloaded setters, the result should be type-checked like a regular assignment. # Hence, we first only try to infer the type by using the rvalue as type context. type_context = rvalue - self.msg.disable_errors() - _, inferred_dunder_set_type = self.expr_checker.check_call( - dunder_set_type, - [TempNode(instance_type, context=context), type_context], - [nodes.ARG_POS, nodes.ARG_POS], - context, object_type=attribute_type, - callable_name=callable_name) - self.msg.enable_errors() + with self.msg.disable_errors(): + _, inferred_dunder_set_type = self.expr_checker.check_call( + dunder_set_type, + [TempNode(instance_type, context=context), type_context], + [nodes.ARG_POS, nodes.ARG_POS], + context, object_type=attribute_type, + callable_name=callable_name) # And now we in fact type check the call, to show errors related to wrong arguments # count, etc., replacing the type context for non-overloaded setters only. @@ -3094,25 +3283,9 @@ def check_indexed_assignment(self, lvalue: IndexExpr, """ self.try_infer_partial_type_from_indexed_assignment(lvalue, rvalue) basetype = get_proper_type(self.expr_checker.accept(lvalue.base)) - if (isinstance(basetype, TypedDictType) or (isinstance(basetype, TypeVarType) - and isinstance(get_proper_type(basetype.upper_bound), TypedDictType))): - if isinstance(basetype, TypedDictType): - typed_dict_type = basetype - else: - upper_bound_type = get_proper_type(basetype.upper_bound) - assert isinstance(upper_bound_type, TypedDictType) - typed_dict_type = upper_bound_type - item_type = self.expr_checker.visit_typeddict_index_expr(typed_dict_type, lvalue.index) - method_type = CallableType( - arg_types=[self.named_type('builtins.str'), item_type], - arg_kinds=[ARG_POS, ARG_POS], - arg_names=[None, None], - ret_type=NoneType(), - fallback=self.named_type('builtins.function') - ) # type: Type - else: - method_type = self.expr_checker.analyze_external_member_access( - '__setitem__', basetype, context) + method_type = self.expr_checker.analyze_external_member_access( + '__setitem__', basetype, lvalue) + lvalue.method_type = method_type self.expr_checker.check_method_call( '__setitem__', basetype, method_type, [lvalue.index, rvalue], @@ -3215,8 +3388,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None: # Functions returning a value of type None are allowed to have a None return. if is_lambda or isinstance(typ, NoneType): return - self.fail(message_registry.NO_RETURN_VALUE_EXPECTED, s, - code=codes.RETURN_VALUE) + self.fail(message_registry.NO_RETURN_VALUE_EXPECTED, s) else: self.check_subtype( subtype_label='got', @@ -3238,13 +3410,13 @@ def check_return_stmt(self, s: ReturnStmt) -> None: return if self.in_checked_function(): - self.fail(message_registry.RETURN_VALUE_EXPECTED, s, code=codes.RETURN_VALUE) + self.fail(message_registry.RETURN_VALUE_EXPECTED, s) def visit_if_stmt(self, s: IfStmt) -> None: """Type check an if statement.""" # This frame records the knowledge from previous if/elif clauses not being taken. # Fall-through to the original frame is handled explicitly in each block. - with self.binder.frame_context(can_skip=False, fall_through=0): + with self.binder.frame_context(can_skip=False, conditional_frame=True, fall_through=0): for e, b in zip(s.expr, s.body): t = get_proper_type(self.expr_checker.accept(e)) @@ -3337,6 +3509,10 @@ def type_check_raise(self, e: Expression, s: RaiseStmt, expected_type.items.append(TupleType([any_type, any_type, any_type], tuple_type)) self.check_subtype(typ, expected_type, s, message_registry.INVALID_EXCEPTION) + if isinstance(typ, FunctionLike): + # https://github.com/python/mypy/issues/11089 + self.expr_checker.check_call(typ, [], [], e) + def visit_try_stmt(self, s: TryStmt) -> None: """Type check a try statement.""" # Our enclosing frame will get the result if the try/except falls through. @@ -3383,7 +3559,7 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None: # was the top frame on entry. with self.binder.frame_context(can_skip=False, fall_through=2, try_frame=try_frame): # This frame receives exit via exception, and runs exception handlers - with self.binder.frame_context(can_skip=False, fall_through=2): + with self.binder.frame_context(can_skip=False, conditional_frame=True, fall_through=2): # Finally, the body of the try statement with self.binder.frame_context(can_skip=False, fall_through=2, try_frame=True): self.accept(s.body) @@ -3420,7 +3596,8 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None: source = ('(exception variable "{}", which we do not ' 'accept outside except: blocks even in ' 'python 2)'.format(var.name)) - cast(Var, var.node).type = DeletedType(source=source) + if isinstance(var.node, Var): + var.node.type = DeletedType(source=source) self.binder.cleanse(var) if s.else_body: self.accept(s.else_body) @@ -3429,7 +3606,7 @@ def check_except_handler_test(self, n: Expression) -> Type: """Type check an exception handler test clause.""" typ = self.expr_checker.accept(n) - all_types = [] # type: List[Type] + all_types: List[Type] = [] test_types = self.get_types_from_except_handler(typ, n) for ttype in get_proper_types(test_types): @@ -3438,7 +3615,7 @@ def check_except_handler_test(self, n: Expression) -> Type: continue if isinstance(ttype, FunctionLike): - item = ttype.items()[0] + item = ttype.items[0] if not item.is_type_obj(): self.fail(message_registry.INVALID_EXCEPTION_TYPE, n) return AnyType(TypeOfAny.from_error) @@ -3502,7 +3679,7 @@ def analyze_iterable_item_type(self, expr: Expression) -> Tuple[Type, Type]: iterator = echk.check_method_call_by_name('__iter__', iterable, [], [], expr)[0] if isinstance(iterable, TupleType): - joined = UninhabitedType() # type: Type + joined: Type = UninhabitedType() for item in iterable.items: joined = join_types(joined, item) return iterator, joined @@ -3521,7 +3698,7 @@ def analyze_container_item_type(self, typ: Type) -> Optional[Type]: """ typ = get_proper_type(typ) if isinstance(typ, UnionType): - types = [] # type: List[Type] + types: List[Type] = [] for item in typ.items: c_type = self.analyze_container_item_type(item) if c_type: @@ -3572,7 +3749,7 @@ def visit_decorator(self, e: Decorator) -> None: # Process decorators from the inside out to determine decorated signature, which # may be different from the declared signature. - sig = self.function_type(e.func) # type: Type + sig: Type = self.function_type(e.func) for d in reversed(e.decorators): if refers_to_fullname(d, 'typing.overload'): self.fail(message_registry.MULTIPLE_OVERLOADS_REQUIRED, e) @@ -3582,10 +3759,17 @@ def visit_decorator(self, e: Decorator) -> None: fullname = None if isinstance(d, RefExpr): fullname = d.fullname + # if this is a expression like @b.a where b is an object, get the type of b + # so we can pass it the method hook in the plugins + object_type: Optional[Type] = None + if fullname is None and isinstance(d, MemberExpr) and d.expr in self.type_map: + object_type = self.type_map[d.expr] + fullname = self.expr_checker.method_fullname(object_type, d.name) self.check_for_untyped_decorator(e.func, dec, d) sig, t2 = self.expr_checker.check_call(dec, [temp], [nodes.ARG_POS], e, - callable_name=fullname) + callable_name=fullname, + object_type=object_type) self.check_untyped_after_decorator(sig, e.func) sig = set_callable_name(sig, e.func) e.var.type = sig @@ -3697,8 +3881,21 @@ def visit_print_stmt(self, s: PrintStmt) -> None: if s.target: target_type = get_proper_type(self.expr_checker.accept(s.target)) if not isinstance(target_type, NoneType): - # TODO: Also verify the type of 'write'. - self.expr_checker.analyze_external_member_access('write', target_type, s.target) + write_type = self.expr_checker.analyze_external_member_access( + 'write', target_type, s.target) + required_type = CallableType( + arg_types=[self.named_type('builtins.str')], + arg_kinds=[ARG_POS], + arg_names=[None], + ret_type=AnyType(TypeOfAny.implementation_artifact), + fallback=self.named_type('builtins.function'), + ) + # This has to be hard-coded, since it is a syntax pattern, not a function call. + if not is_subtype(write_type, required_type): + self.fail(message_registry.PYTHON2_PRINT_FILE_TYPE.format( + write_type, + required_type, + ), s.target) def visit_break_stmt(self, s: BreakStmt) -> None: self.binder.handle_break() @@ -3729,7 +3926,7 @@ def make_fake_typeinfo(self, return cdef, info def intersect_instances(self, - instances: Sequence[Instance], + instances: Tuple[Instance, Instance], ctx: Context, ) -> Optional[Instance]: """Try creating an ad-hoc intersection of the given instances. @@ -3757,34 +3954,51 @@ def intersect_instances(self, curr_module = self.scope.stack[0] assert isinstance(curr_module, MypyFile) - base_classes = [] - for inst in instances: - expanded = [inst] - if inst.type.is_intersection: - expanded = inst.type.bases - - for expanded_inst in expanded: - base_classes.append(expanded_inst) + def _get_base_classes(instances_: Tuple[Instance, Instance]) -> List[Instance]: + base_classes_ = [] + for inst in instances_: + if inst.type.is_intersection: + expanded = inst.type.bases + else: + expanded = [inst] + + for expanded_inst in expanded: + base_classes_.append(expanded_inst) + return base_classes_ + + def _make_fake_typeinfo_and_full_name( + base_classes_: List[Instance], + curr_module_: MypyFile, + ) -> Tuple[TypeInfo, str]: + names_list = pretty_seq([x.type.name for x in base_classes_], "and") + short_name = ''.format(names_list) + full_name_ = gen_unique_name(short_name, curr_module_.names) + cdef, info_ = self.make_fake_typeinfo( + curr_module_.fullname, + full_name_, + short_name, + base_classes_, + ) + return info_, full_name_ + old_msg = self.msg + new_msg = old_msg.clean_copy() + self.msg = new_msg + base_classes = _get_base_classes(instances) # We use the pretty_names_list for error messages but can't # use it for the real name that goes into the symbol table # because it can have dots in it. pretty_names_list = pretty_seq(format_type_distinctly(*base_classes, bare=True), "and") - names_list = pretty_seq([x.type.name for x in base_classes], "and") - short_name = ''.format(names_list) - full_name = gen_unique_name(short_name, curr_module.names) - - old_msg = self.msg - new_msg = self.msg.clean_copy() - self.msg = new_msg try: - cdef, info = self.make_fake_typeinfo( - curr_module.fullname, - full_name, - short_name, - base_classes, - ) + info, full_name = _make_fake_typeinfo_and_full_name(base_classes, curr_module) self.check_multiple_inheritance(info) + if new_msg.is_errors(): + # "class A(B, C)" unsafe, now check "class A(C, B)": + new_msg = new_msg.clean_copy() + self.msg = new_msg + base_classes = _get_base_classes(instances[::-1]) + info, full_name = _make_fake_typeinfo_and_full_name(base_classes, curr_module) + self.check_multiple_inheritance(info) info.is_intersection = True except MroError: if self.should_report_unreachable_issues(): @@ -3957,6 +4171,52 @@ def conditional_callable_type_map(self, expr: Expression, return None, {} + def _is_truthy_type(self, t: ProperType) -> bool: + return ( + ( + isinstance(t, Instance) and + bool(t.type) and + not t.type.has_readable_member('__bool__') and + not t.type.has_readable_member('__len__') + ) + or isinstance(t, FunctionLike) + or ( + isinstance(t, UnionType) and + all(self._is_truthy_type(t) for t in get_proper_types(t.items)) + ) + ) + + def _check_for_truthy_type(self, t: Type, expr: Expression) -> None: + if not state.strict_optional: + return # if everything can be None, all bets are off + + t = get_proper_type(t) + if not self._is_truthy_type(t): + return + + def format_expr_type() -> str: + typ = format_type(t) + if isinstance(expr, MemberExpr): + return f'Member "{expr.name}" has type {typ}' + elif isinstance(expr, RefExpr) and expr.fullname: + return f'"{expr.fullname}" has type {typ}' + elif isinstance(expr, CallExpr): + if isinstance(expr.callee, MemberExpr): + return f'"{expr.callee.name}" returns {typ}' + elif isinstance(expr.callee, RefExpr) and expr.callee.fullname: + return f'"{expr.callee.fullname}" returns {typ}' + return f'Call returns {typ}' + else: + return f'Expression has type {typ}' + + if isinstance(t, FunctionLike): + self.fail(message_registry.FUNCTION_ALWAYS_TRUE.format(format_type(t)), expr) + elif isinstance(t, UnionType): + self.fail(message_registry.TYPE_ALWAYS_TRUE_UNIONTYPE.format(format_expr_type()), + expr) + else: + self.fail(message_registry.TYPE_ALWAYS_TRUE.format(format_expr_type()), expr) + def find_type_equals_check(self, node: ComparisonExpr, expr_indices: List[int] ) -> Tuple[TypeMap, TypeMap]: """Narrow types based on any checks of the type ``type(x) == T`` @@ -3972,10 +4232,11 @@ def is_type_call(expr: CallExpr) -> bool: """Is expr a call to type with one argument?""" return (refers_to_fullname(expr.callee, 'builtins.type') and len(expr.args) == 1) + # exprs that are being passed into type - exprs_in_type_calls = [] # type: List[Expression] + exprs_in_type_calls: List[Expression] = [] # type that is being compared to type(expr) - type_being_compared = None # type: Optional[List[TypeRange]] + type_being_compared: Optional[List[TypeRange]] = None # whether the type being compared to is final is_final = False @@ -4004,8 +4265,8 @@ def is_type_call(expr: CallExpr) -> bool: if not exprs_in_type_calls: return {}, {} - if_maps = [] # type: List[TypeMap] - else_maps = [] # type: List[TypeMap] + if_maps: List[TypeMap] = [] + else_maps: List[TypeMap] = [] for expr in exprs_in_type_calls: current_if_map, current_else_map = self.conditional_type_map_with_intersection( expr, @@ -4022,6 +4283,7 @@ def combine_maps(list_maps: List[TypeMap]) -> TypeMap: if d is not None: result_map.update(d) return result_map + if_map = combine_maps(if_maps) # type(x) == T is only true when x has the same type as T, meaning # that it can be false if x is an instance of a subclass of T. That means @@ -4045,7 +4307,8 @@ def find_isinstance_check(self, node: Expression If either of the values in the tuple is None, then that particular branch can never occur. - Guaranteed to not return None, None. (But may return {}, {}) + May return {}, {}. + Can return None, None in situations involving NoReturn. """ if_map, else_map = self.find_isinstance_check_helper(node) new_if_map = self.propagate_up_typemap_info(self.type_map, if_map) @@ -4056,11 +4319,10 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM type_map = self.type_map if is_true_literal(node): return {}, None - elif is_false_literal(node): + if is_false_literal(node): return None, {} - elif isinstance(node, CallExpr): - if len(node.args) == 0: - return {}, {} + + if isinstance(node, CallExpr) and len(node.args) != 0: expr = collapse_walrus(node.args[0]) if refers_to_fullname(node.callee, 'builtins.isinstance'): if len(node.args) != 2: # the error will be reported elsewhere @@ -4086,10 +4348,15 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM if node.callee.type_guard is not None: # TODO: Follow keyword args or *args, **kwargs if node.arg_kinds[0] != nodes.ARG_POS: - self.fail("Type guard requires positional argument", node) + self.fail(message_registry.TYPE_GUARD_POS_ARG_REQUIRED, node) return {}, {} if literal(expr) == LITERAL_TYPE: - return {expr: TypeGuardType(node.callee.type_guard)}, {} + # Note: we wrap the target type, so that we can special case later. + # Namely, for isinstance() we use a normal meet, while TypeGuard is + # considered "always right" (i.e. even if the types are not overlapping). + # Also note that a care must be taken to unwrap this back at read places + # where we use this to narrow down declared type. + return {expr: TypeGuardedType(node.callee.type_guard)}, {} elif isinstance(node, ComparisonExpr): # Step 1: Obtain the types of each operand and whether or not we can # narrow their types. (For example, we shouldn't try narrowing the @@ -4157,7 +4424,7 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM # Set to 'false' only if the user defines custom __eq__ or __ne__ methods # that could cause identity-based narrowing to produce invalid results. if operator in {'is', 'is not'}: - is_valid_target = is_singleton_type # type: Callable[[Type], bool] + is_valid_target: Callable[[Type], bool] = is_singleton_type coerce_only_in_literal_context = False should_narrow_by_identity = True else: @@ -4174,8 +4441,8 @@ def has_no_custom_eq_checks(t: Type) -> bool: expr_types = [operand_types[i] for i in expr_indices] should_narrow_by_identity = all(map(has_no_custom_eq_checks, expr_types)) - if_map = {} # type: TypeMap - else_map = {} # type: TypeMap + if_map: TypeMap = {} + else_map: TypeMap = {} if should_narrow_by_identity: if_map, else_map = self.refine_identity_comparison_expression( operands, @@ -4236,42 +4503,67 @@ def has_no_custom_eq_checks(t: Type) -> bool: return reduce_conditional_maps(partial_type_maps) elif isinstance(node, AssignmentExpr): - return self.find_isinstance_check_helper(node.target) - elif isinstance(node, RefExpr): - # Restrict the type of the variable to True-ish/False-ish in the if and else branches - # respectively - vartype = type_map[node] - if_type = true_only(vartype) # type: Type - else_type = false_only(vartype) # type: Type - ref = node # type: Expression - if_map = ({ref: if_type} if not isinstance(get_proper_type(if_type), UninhabitedType) - else None) - else_map = ({ref: else_type} if not isinstance(get_proper_type(else_type), - UninhabitedType) - else None) - return if_map, else_map + if_map = {} + else_map = {} + + if_assignment_map, else_assignment_map = self.find_isinstance_check(node.target) + + if if_assignment_map is not None: + if_map.update(if_assignment_map) + if else_assignment_map is not None: + else_map.update(else_assignment_map) + + if_condition_map, else_condition_map = self.find_isinstance_check(node.value) + + if if_condition_map is not None: + if_map.update(if_condition_map) + if else_condition_map is not None: + else_map.update(else_condition_map) + + return ( + (None if if_assignment_map is None or if_condition_map is None else if_map), + (None if else_assignment_map is None or else_condition_map is None else else_map), + ) elif isinstance(node, OpExpr) and node.op == 'and': - left_if_vars, left_else_vars = self.find_isinstance_check_helper(node.left) - right_if_vars, right_else_vars = self.find_isinstance_check_helper(node.right) + left_if_vars, left_else_vars = self.find_isinstance_check(node.left) + right_if_vars, right_else_vars = self.find_isinstance_check(node.right) # (e1 and e2) is true if both e1 and e2 are true, # and false if at least one of e1 and e2 is false. return (and_conditional_maps(left_if_vars, right_if_vars), or_conditional_maps(left_else_vars, right_else_vars)) elif isinstance(node, OpExpr) and node.op == 'or': - left_if_vars, left_else_vars = self.find_isinstance_check_helper(node.left) - right_if_vars, right_else_vars = self.find_isinstance_check_helper(node.right) + left_if_vars, left_else_vars = self.find_isinstance_check(node.left) + right_if_vars, right_else_vars = self.find_isinstance_check(node.right) # (e1 or e2) is true if at least one of e1 or e2 is true, # and false if both e1 and e2 are false. return (or_conditional_maps(left_if_vars, right_if_vars), and_conditional_maps(left_else_vars, right_else_vars)) elif isinstance(node, UnaryExpr) and node.op == 'not': - left, right = self.find_isinstance_check_helper(node.expr) + left, right = self.find_isinstance_check(node.expr) return right, left - # Not a supported isinstance check - return {}, {} + # Restrict the type of the variable to True-ish/False-ish in the if and else branches + # respectively + original_vartype = type_map[node] + self._check_for_truthy_type(original_vartype, node) + vartype = try_expanding_sum_type_to_union(original_vartype, "builtins.bool") + + if_type = true_only(vartype) # type: Type + else_type = false_only(vartype) # type: Type + ref = node # type: Expression + if_map = ( + {ref: if_type} + if not isinstance(get_proper_type(if_type), UninhabitedType) + else None + ) + else_map = ( + {ref: else_type} + if not isinstance(get_proper_type(else_type), UninhabitedType) + else None + ) + return if_map, else_map def propagate_up_typemap_info(self, existing_types: Mapping[Expression, Type], @@ -4331,7 +4623,7 @@ def refine_parent_types(self, For more details about what a 'lookup operation' is and how we use the expr_type to refine the parent types of lookup_expr, see the docstring in 'propagate_up_typemap_info'. """ - output = {} # type: Dict[Expression, Type] + output: Dict[Expression, Type] = {} # Note: parent_expr and parent_type are progressively refined as we crawl up the # parent lookup chain. @@ -4347,7 +4639,6 @@ def refine_parent_types(self, def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: msg_copy = self.msg.clean_copy() - msg_copy.disable_count = 0 member_type = analyze_member_access( name=member_name, typ=new_parent_type, @@ -4419,8 +4710,7 @@ def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: # Take each element in the parent union and replay the original lookup procedure # to figure out which parents are compatible. new_parent_types = [] - for item in parent_type.items: - item = get_proper_type(item) + for item in union_items(parent_type): member_type = replay_lookup(item) if member_type is None: # We were unable to obtain the member type. So, we give up on refining this @@ -4439,8 +4729,6 @@ def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: expr = parent_expr expr_type = output[parent_expr] = make_simplified_union(new_parent_types) - return output - def refine_identity_comparison_expression(self, operands: List[Expression], operand_types: List[Type], @@ -4479,7 +4767,7 @@ def refine_identity_comparison_expression(self, if coerce_only_in_literal_context: should_coerce = any(is_literal_type_like(operand_types[i]) for i in chain_indices) - target = None # type: Optional[Type] + target: Optional[Type] = None possible_target_indices = [] for i in chain_indices: expr_type = operand_types[i] @@ -4534,10 +4822,11 @@ def refine_identity_comparison_expression(self, if singleton_index == -1: singleton_index = possible_target_indices[-1] - enum_name = None + sum_type_name = None target = get_proper_type(target) - if isinstance(target, LiteralType) and target.is_enum_literal(): - enum_name = target.fallback.type.fullname + if (isinstance(target, LiteralType) and + (target.is_enum_literal() or isinstance(target.value, bool))): + sum_type_name = target.fallback.type.fullname target_type = [TypeRange(target, is_upper_bound=False)] @@ -4558,8 +4847,8 @@ def refine_identity_comparison_expression(self, expr = operands[i] expr_type = coerce_to_literal(operand_types[i]) - if enum_name is not None: - expr_type = try_expanding_enum_to_union(expr_type, enum_name) + if sum_type_name is not None: + expr_type = try_expanding_sum_type_to_union(expr_type, sum_type_name) # We intentionally use 'conditional_type_map' directly here instead of # 'self.conditional_type_map_with_intersection': we only compute ad-hoc @@ -4607,7 +4896,7 @@ def check_subtype(self, subtype: Type, supertype: Type, context: Context, - msg: str = message_registry.INCOMPATIBLE_TYPES, + msg: Union[str, ErrorMessage] = message_registry.INCOMPATIBLE_TYPES, subtype_label: Optional[str] = None, supertype_label: Optional[str] = None, *, @@ -4617,16 +4906,21 @@ def check_subtype(self, if is_subtype(subtype, supertype): return True + if isinstance(msg, ErrorMessage): + msg_text = msg.value + code = msg.code + else: + msg_text = msg subtype = get_proper_type(subtype) supertype = get_proper_type(supertype) - if self.msg.try_report_long_tuple_assignment_error(subtype, supertype, context, msg, + if self.msg.try_report_long_tuple_assignment_error(subtype, supertype, context, msg_text, subtype_label, supertype_label, code=code): return False if self.should_suppress_optional_error([subtype]): return False - extra_info = [] # type: List[str] + extra_info: List[str] = [] note_msg = '' - notes = [] # type: List[str] + notes: List[str] = [] if subtype_label is not None or supertype_label is not None: subtype_str, supertype_str = format_type_distinctly(subtype, supertype) if subtype_label is not None: @@ -4638,8 +4932,9 @@ def check_subtype(self, if isinstance(subtype, Instance) and isinstance(supertype, Instance): notes = append_invariance_notes([], subtype, supertype) if extra_info: - msg += ' (' + ', '.join(extra_info) + ')' - self.fail(msg, context, code=code) + msg_text += ' (' + ', '.join(extra_info) + ')' + + self.fail(ErrorMessage(msg_text, code=code), context) for note in notes: self.msg.note(note, context, code=code) if note_msg: @@ -4728,9 +5023,8 @@ def in_checked_function(self) -> bool: or not self.dynamic_funcs or not self.dynamic_funcs[-1]) - def lookup(self, name: str, kind: int) -> SymbolTableNode: + def lookup(self, name: str) -> SymbolTableNode: """Look up a definition from the symbol table with the given name. - TODO remove kind argument """ if name in self.globals: return self.globals[name] @@ -4744,7 +5038,7 @@ def lookup(self, name: str, kind: int) -> SymbolTableNode: def lookup_qualified(self, name: str) -> SymbolTableNode: if '.' not in name: - return self.lookup(name, GDEF) # FIX kind + return self.lookup(name) else: parts = name.split('.') n = self.modules[parts[0]] @@ -4842,6 +5136,7 @@ def handle_partial_var_type( if is_local or not self.options.allow_untyped_globals: self.msg.need_annotation_for_var(node, context, self.options.python_version) + self.partial_reported.add(node) else: # Defer the node -- we might get a better type in the outer scope self.handle_cannot_determine_type(node.name, context) @@ -4910,8 +5205,12 @@ def temp_node(self, t: Type, context: Optional[Context] = None) -> TempNode: """Create a temporary node with the given, fixed type.""" return TempNode(t, context=context) - def fail(self, msg: str, context: Context, *, code: Optional[ErrorCode] = None) -> None: + def fail(self, msg: Union[str, ErrorMessage], context: Context, *, + code: Optional[ErrorCode] = None) -> None: """Produce an error message.""" + if isinstance(msg, ErrorMessage): + self.msg.fail(msg.value, context, code=msg.code) + return self.msg.fail(msg, context, code=code) def note(self, @@ -4993,8 +5292,8 @@ def conditional_type_map_with_intersection(self, # For some reason, doing "yes_map, no_map = conditional_type_maps(...)" # doesn't work: mypyc will decide that 'yes_map' is of type None if we try. initial_maps = conditional_type_map(expr, expr_type, type_ranges) - yes_map = initial_maps[0] # type: TypeMap - no_map = initial_maps[1] # type: TypeMap + yes_map: TypeMap = initial_maps[0] + no_map: TypeMap = initial_maps[1] if yes_map is not None or type_ranges is None: return yes_map, no_map @@ -5021,7 +5320,7 @@ def conditional_type_map_with_intersection(self, if not isinstance(v, Instance): return yes_map, no_map for t in possible_target_types: - intersection = self.intersect_instances([v, t], expr) + intersection = self.intersect_instances((v, t), expr) if intersection is None: continue out.append(intersection) @@ -5071,9 +5370,11 @@ def conditional_type_map(expr: Expression, return None, {} else: # we can only restrict when the type is precise, not bounded - proposed_precise_type = UnionType([type_range.item - for type_range in proposed_type_ranges - if not type_range.is_upper_bound]) + proposed_precise_type = UnionType.make_union([ + type_range.item + for type_range in proposed_type_ranges + if not type_range.is_upper_bound + ]) remaining_type = restrict_subtype_away(current_type, proposed_precise_type) return {expr: proposed_type}, {expr: remaining_type} else: @@ -5096,7 +5397,7 @@ def gen_unique_name(base: str, table: SymbolTable) -> str: def is_true_literal(n: Expression) -> bool: """Returns true if this expression is the 'True' literal/keyword.""" return (refers_to_fullname(n, 'builtins.True') - or isinstance(n, IntExpr) and n.value == 1) + or isinstance(n, IntExpr) and n.value != 0) def is_false_literal(n: Expression) -> bool: @@ -5115,7 +5416,7 @@ class Foo(Enum): B = 2 ...and if the expression 'Foo' referred to that enum within the current type context, - then the expression 'Foo.A' would be a a literal enum. However, if we did 'a = Foo.A', + then the expression 'Foo.A' would be a literal enum. However, if we did 'a = Foo.A', then the variable 'a' would *not* be a literal enum. We occasionally special-case expressions like 'Foo.A' and treat them as a single primitive @@ -5225,7 +5526,7 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: # expressions whose type is refined by both conditions. (We do not # learn anything about expressions whose type is refined by only # one condition.) - result = {} # type: Dict[Expression, Type] + result: Dict[Expression, Type] = {} for n1 in m1: for n2 in m2: if literal_hash(n1) == literal_hash(n2): @@ -5272,7 +5573,7 @@ def reduce_conditional_maps(type_maps: List[Tuple[TypeMap, TypeMap]], def convert_to_typetype(type_map: TypeMap) -> TypeMap: - converted_type_map = {} # type: Dict[Expression, Type] + converted_type_map: Dict[Expression, Type] = {} if type_map is None: return None for expr, typ in type_map.items(): @@ -5308,13 +5609,19 @@ def flatten_types(t: Type) -> List[Type]: def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> Optional[List[TypeRange]]: + if isinstance(expr, OpExpr) and expr.op == '|': + left = get_isinstance_type(expr.left, type_map) + right = get_isinstance_type(expr.right, type_map) + if left is None or right is None: + return None + return left + right all_types = get_proper_types(flatten_types(type_map[expr])) - types = [] # type: List[TypeRange] + types: List[TypeRange] = [] for typ in all_types: if isinstance(typ, FunctionLike) and typ.is_type_obj(): # Type variables may be present -- erase them, which is the best # we can do (outside disallowing them here). - erased_type = erase_typevars(typ.items()[0].ret_type) + erased_type = erase_typevars(typ.items[0].ret_type) types.append(TypeRange(erased_type, is_upper_bound=False)) elif isinstance(typ, TypeType): # Type[A] means "any type that is a subtype of A" rather than "precisely type A" @@ -5419,7 +5726,7 @@ def detach_callable(typ: CallableType) -> CallableType: from a class or not.""" type_list = typ.arg_types + [typ.ret_type] - appear_map = {} # type: Dict[str, List[int]] + appear_map: Dict[str, List[int]] = {} for i, inner_type in enumerate(type_list): typevars_available = get_type_vars(inner_type) for var in typevars_available: @@ -5436,7 +5743,7 @@ def detach_callable(typ: CallableType) -> CallableType: for var in set(all_type_vars): if var.fullname not in used_type_var_names: continue - new_variables.append(TypeVarDef( + new_variables.append(TypeVarType( name=var.name, fullname=var.fullname, id=var.id, @@ -5487,9 +5794,9 @@ def is_more_general_arg_prefix(t: FunctionLike, s: FunctionLike) -> bool: ignore_return=True) elif isinstance(t, FunctionLike): if isinstance(s, FunctionLike): - if len(t.items()) == len(s.items()): + if len(t.items) == len(s.items): return all(is_same_arg_prefix(items, itemt) - for items, itemt in zip(t.items(), s.items())) + for items, itemt in zip(t.items, s.items)) return False @@ -5508,9 +5815,9 @@ def infer_operator_assignment_method(typ: Type, operator: str) -> Tuple[bool, st depending on which method is supported by the type. """ typ = get_proper_type(typ) - method = nodes.op_methods[operator] + method = operators.op_methods[operator] if isinstance(typ, Instance): - if operator in nodes.ops_with_inplace_method: + if operator in operators.ops_with_inplace_method: inplace_method = '__i' + method[2:] if typ.type.has_readable_member(inplace_method): return True, inplace_method @@ -5573,7 +5880,7 @@ def is_node_static(node: Optional[Node]) -> Optional[bool]: class CheckerScope: # We keep two stacks combined, to maintain the relative order - stack = None # type: List[Union[TypeInfo, FuncItem, MypyFile]] + stack: List[Union[TypeInfo, FuncItem, MypyFile]] def __init__(self, module: MypyFile) -> None: self.stack = [module] @@ -5632,11 +5939,6 @@ def push_class(self, info: TypeInfo) -> Iterator[None]: self.stack.pop() -@contextmanager -def nothing() -> Iterator[None]: - yield - - TKey = TypeVar('TKey') TValue = TypeVar('TValue') @@ -5669,15 +5971,15 @@ class DisjointDict(Generic[TKey, TValue]): """ def __init__(self) -> None: # Each key maps to a unique ID - self._key_to_id = {} # type: Dict[TKey, int] + self._key_to_id: Dict[TKey, int] = {} # Each id points to the parent id, forming a forest of upwards-pointing trees. If the # current id already is the root, it points to itself. We gradually flatten these trees # as we perform root lookups: eventually all nodes point directly to its root. - self._id_to_parent_id = {} # type: Dict[int, int] + self._id_to_parent_id: Dict[int, int] = {} # Each root id in turn maps to the set of values. - self._root_id_to_values = {} # type: Dict[int, Set[TValue]] + self._root_id_to_values: Dict[int, Set[TValue]] = {} def add_mapping(self, keys: Set[TKey], values: Set[TValue]) -> None: """Adds a 'Set[TKey] -> Set[TValue]' mapping. If there already exists a mapping @@ -5701,7 +6003,7 @@ def add_mapping(self, keys: Set[TKey], values: Set[TValue]) -> None: def items(self) -> List[Tuple[Set[TKey], Set[TValue]]]: """Returns all disjoint mappings in key-value pairs.""" - root_id_to_keys = {} # type: Dict[int, Set[TKey]] + root_id_to_keys: Dict[int, Set[TKey]] = {} for key in self._key_to_id: root_id = self._lookup_root_id(key) if root_id not in root_id_to_keys: @@ -5782,14 +6084,12 @@ def group_comparison_operands(pairwise_comparisons: Iterable[Tuple[str, Expressi This function is currently only used to assist with type-narrowing refinements and is extracted out to a helper function so we can unit test it. """ - groups = { - op: DisjointDict() for op in operators_to_group - } # type: Dict[str, DisjointDict[Key, int]] - - simplified_operator_list = [] # type: List[Tuple[str, List[int]]] - last_operator = None # type: Optional[str] - current_indices = set() # type: Set[int] - current_hashes = set() # type: Set[Key] + groups: Dict[str, DisjointDict[Key, int]] = {op: DisjointDict() for op in operators_to_group} + + simplified_operator_list: List[Tuple[str, List[int]]] = [] + last_operator: Optional[str] = None + current_indices: Set[int] = set() + current_hashes: Set[Key] = set() for i, (operator, left_expr, right_expr) in enumerate(pairwise_comparisons): if last_operator is None: last_operator = operator @@ -5853,14 +6153,20 @@ def is_untyped_decorator(typ: Optional[Type]) -> bool: elif isinstance(typ, Instance): method = typ.type.get_method('__call__') if method: + if isinstance(method, Decorator): + return ( + is_untyped_decorator(method.func.type) + or is_untyped_decorator(method.var.type) + ) + if isinstance(method.type, Overloaded): - return any(is_untyped_decorator(item) for item in method.type.items()) + return any(is_untyped_decorator(item) for item in method.type.items) else: return not is_typed_callable(method.type) else: return False elif isinstance(typ, Overloaded): - return any(is_untyped_decorator(item) for item in typ.items()) + return any(is_untyped_decorator(item) for item in typ.items) return True diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 3bfe0a306446..dfac5be27d95 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,23 +1,24 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict, nullcontext from contextlib import contextmanager import itertools from typing import ( Any, cast, Dict, Set, List, Tuple, Callable, Union, Optional, Sequence, Iterator ) -from typing_extensions import ClassVar, Final, overload +from typing_extensions import ClassVar, Final, overload, TypeAlias as _TypeAlias from mypy.errors import report_internal_error from mypy.typeanal import ( has_any_from_unimported_type, check_for_explicit_any, set_any_tvars, expand_type_alias, make_optional_type, ) +from mypy.semanal_enum import ENUM_BASES from mypy.types import ( - Type, AnyType, CallableType, Overloaded, NoneType, TypeGuardType, TypeVarDef, - TupleType, TypedDictType, Instance, TypeVarType, ErasedType, UnionType, + Type, AnyType, CallableType, Overloaded, NoneType, TypeVarType, + TupleType, TypedDictType, Instance, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, LiteralType, LiteralValue, - is_named_instance, FunctionLike, + is_named_instance, FunctionLike, ParamSpecType, ParamSpecFlavor, StarType, is_optional, remove_optional, is_generic_instance, get_proper_type, ProperType, get_proper_types, flatten_nested_unions ) @@ -32,10 +33,11 @@ YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr, TypeAliasExpr, BackquoteExpr, EnumCallExpr, TypeAlias, SymbolNode, PlaceholderNode, ParamSpecExpr, - ARG_POS, ARG_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE, + ArgKind, ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE, ) from mypy.literals import literal from mypy import nodes +from mypy import operators import mypy.checker from mypy import types from mypy.sametypes import is_same_type @@ -43,7 +45,9 @@ from mypy.maptype import map_instance_to_supertype from mypy.messages import MessageBuilder from mypy import message_registry -from mypy.infer import infer_type_arguments, infer_function_type_arguments +from mypy.infer import ( + ArgumentInferContext, infer_type_arguments, infer_function_type_arguments, +) from mypy import join from mypy.meet import narrow_declared_type, is_overlapping_types from mypy.subtypes import is_subtype, is_proper_subtype, is_equivalent, non_method_protocol_members @@ -62,38 +66,51 @@ FunctionContext, FunctionSigContext, ) from mypy.typeops import ( - tuple_fallback, make_simplified_union, true_only, false_only, erase_to_union_or_bound, - function_type, callable_type, try_getting_str_literals, custom_special_method, + try_expanding_sum_type_to_union, tuple_fallback, make_simplified_union, + true_only, false_only, erase_to_union_or_bound, function_type, + callable_type, try_getting_str_literals, custom_special_method, is_literal_type_like, ) +from mypy.message_registry import ErrorMessage import mypy.errorcodes as codes # Type of callback user for checking individual function arguments. See # check_args() below for details. -ArgChecker = Callable[[Type, - Type, - int, - Type, - int, - int, - CallableType, - Optional[Type], - Context, - Context, - MessageBuilder], - None] +ArgChecker: _TypeAlias = Callable[[ + Type, + Type, + ArgKind, + Type, + int, + int, + CallableType, + Optional[Type], + Context, + Context, + MessageBuilder, + ], + None, +] # Maximum nesting level for math union in overloads, setting this to large values # may cause performance issues. The reason is that although union math algorithm we use # nicely captures most corner cases, its worst case complexity is exponential, # see https://github.com/python/mypy/pull/5255#discussion_r196896335 for discussion. -MAX_UNIONS = 5 # type: Final +MAX_UNIONS: Final = 5 # Types considered safe for comparisons with --strict-equality due to known behaviour of __eq__. # NOTE: All these types are subtypes of AbstractSet. -OVERLAPPING_TYPES_WHITELIST = ['builtins.set', 'builtins.frozenset', - 'typing.KeysView', 'typing.ItemsView'] # type: Final +OVERLAPPING_TYPES_ALLOWLIST: Final = [ + "builtins.set", + "builtins.frozenset", + "typing.KeysView", + "typing.ItemsView", + "builtins._dict_keys", + "builtins._dict_items", + "_collections_abc.dict_keys", + "_collections_abc.dict_items", +] class TooManyUnions(Exception): @@ -107,7 +124,7 @@ def extract_refexpr_names(expr: RefExpr) -> Set[str]: Note that currently, the only two subclasses of RefExpr are NameExpr and MemberExpr.""" - output = set() # type: Set[str] + output: Set[str] = set() while isinstance(expr.node, MypyFile) or expr.fullname is not None: if isinstance(expr.node, MypyFile) and expr.fullname is not None: # If it's None, something's wrong (perhaps due to an @@ -145,14 +162,14 @@ class ExpressionChecker(ExpressionVisitor[Type]): """ # Some services are provided by a TypeChecker instance. - chk = None # type: mypy.checker.TypeChecker + chk: "mypy.checker.TypeChecker" # This is shared with TypeChecker, but stored also here for convenience. - msg = None # type: MessageBuilder + msg: MessageBuilder # Type context for type inference - type_context = None # type: List[Optional[Type]] + type_context: List[Optional[Type]] - strfrm_checker = None # type: StringFormatterChecker - plugin = None # type: Plugin + strfrm_checker: StringFormatterChecker + plugin: Plugin def __init__(self, chk: 'mypy.checker.TypeChecker', @@ -168,7 +185,7 @@ def __init__(self, # used by the union math in overloads. # TODO: refactor this to use a pattern similar to one in # multiassign_from_union, or maybe even combine the two? - self.type_overrides = {} # type: Dict[Expression, Type] + self.type_overrides: Dict[Expression, Type] = {} self.strfrm_checker = StringFormatterChecker(self, self.chk, self.msg) def visit_name_expr(self, e: NameExpr) -> Type: @@ -181,7 +198,7 @@ def visit_name_expr(self, e: NameExpr) -> Type: return self.narrow_type_from_binder(e, result) def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: - result = None # type: Optional[Type] + result: Optional[Type] = None node = e.node if isinstance(e, NameExpr) and e.is_special_form: @@ -328,6 +345,7 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> isinstance(callee_type, CallableType) and callee_type.implicit): self.msg.untyped_function_call(callee_type, e) + # Figure out the full name of the callee for plugin lookup. object_type = None member = None @@ -471,7 +489,7 @@ def check_protocol_issubclass(self, e: CallExpr) -> None: attr_members, e) def check_typeddict_call(self, callee: TypedDictType, - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Sequence[Optional[str]], args: List[Expression], context: Context) -> Type: @@ -589,14 +607,16 @@ def get_partial_self_var(self, expr: MemberExpr) -> Optional[Var]: return None # Types and methods that can be used to infer partial types. - item_args = {'builtins.list': ['append'], - 'builtins.set': ['add', 'discard'], - } # type: ClassVar[Dict[str, List[str]]] - container_args = {'builtins.list': {'extend': ['builtins.list']}, - 'builtins.dict': {'update': ['builtins.dict']}, - 'collections.OrderedDict': {'update': ['builtins.dict']}, - 'builtins.set': {'update': ['builtins.set', 'builtins.list']}, - } # type: ClassVar[Dict[str, Dict[str, List[str]]]] + item_args: ClassVar[Dict[str, List[str]]] = { + "builtins.list": ["append"], + "builtins.set": ["add", "discard"], + } + container_args: ClassVar[Dict[str, Dict[str, List[str]]]] = { + "builtins.list": {"extend": ["builtins.list"]}, + "builtins.dict": {"update": ["builtins.dict"]}, + "collections.OrderedDict": {"update": ["builtins.dict"]}, + "builtins.set": {"update": ["builtins.set", "builtins.list"]}, + } def try_infer_partial_type(self, e: CallExpr) -> None: """Try to make partial type precise from a call.""" @@ -690,7 +710,7 @@ def try_infer_partial_value_type_from_call( def apply_function_plugin(self, callee: CallableType, - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_types: List[Type], arg_names: Optional[Sequence[Optional[str]]], formal_to_actual: List[List[int]], @@ -710,10 +730,10 @@ def apply_function_plugin(self, Return the inferred return type. """ num_formals = len(callee.arg_types) - formal_arg_types = [[] for _ in range(num_formals)] # type: List[List[Type]] - formal_arg_exprs = [[] for _ in range(num_formals)] # type: List[List[Expression]] - formal_arg_names = [[] for _ in range(num_formals)] # type: List[List[Optional[str]]] - formal_arg_kinds = [[] for _ in range(num_formals)] # type: List[List[int]] + formal_arg_types: List[List[Type]] = [[] for _ in range(num_formals)] + formal_arg_exprs: List[List[Expression]] = [[] for _ in range(num_formals)] + formal_arg_names: List[List[Optional[str]]] = [[] for _ in range(num_formals)] + formal_arg_kinds: List[List[ArgKind]] = [[] for _ in range(num_formals)] for formal, actuals in enumerate(formal_to_actual): for actual in actuals: formal_arg_types[formal].append(arg_types[actual]) @@ -742,11 +762,11 @@ def apply_function_plugin(self, def apply_signature_hook( self, callee: FunctionLike, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], hook: Callable[ [List[List[Expression]], CallableType], - CallableType, + FunctionLike, ]) -> FunctionLike: """Helper to apply a signature hook for either a function or method""" if isinstance(callee, CallableType): @@ -755,7 +775,7 @@ def apply_signature_hook( arg_kinds, arg_names, callee.arg_kinds, callee.arg_names, lambda i: self.accept(args[i])) - formal_arg_exprs = [[] for _ in range(num_formals)] # type: List[List[Expression]] + formal_arg_exprs: List[List[Expression]] = [[] for _ in range(num_formals)] for formal, actuals in enumerate(formal_to_actual): for actual in actuals: formal_arg_exprs[formal].append(args[actual]) @@ -763,7 +783,7 @@ def apply_signature_hook( else: assert isinstance(callee, Overloaded) items = [] - for item in callee.items(): + for item in callee.items: adjusted = self.apply_signature_hook( item, args, arg_kinds, arg_names, hook) assert isinstance(adjusted, CallableType) @@ -772,9 +792,9 @@ def apply_signature_hook( def apply_function_signature_hook( self, callee: FunctionLike, args: List[Expression], - arg_kinds: List[int], context: Context, + arg_kinds: List[ArgKind], context: Context, arg_names: Optional[Sequence[Optional[str]]], - signature_hook: Callable[[FunctionSigContext], CallableType]) -> FunctionLike: + signature_hook: Callable[[FunctionSigContext], FunctionLike]) -> FunctionLike: """Apply a plugin hook that may infer a more precise signature for a function.""" return self.apply_signature_hook( callee, args, arg_kinds, arg_names, @@ -783,9 +803,9 @@ def apply_function_signature_hook( def apply_method_signature_hook( self, callee: FunctionLike, args: List[Expression], - arg_kinds: List[int], context: Context, + arg_kinds: List[ArgKind], context: Context, arg_names: Optional[Sequence[Optional[str]]], object_type: Type, - signature_hook: Callable[[MethodSigContext], CallableType]) -> FunctionLike: + signature_hook: Callable[[MethodSigContext], FunctionLike]) -> FunctionLike: """Apply a plugin hook that may infer a more precise signature for a method.""" pobject_type = get_proper_type(object_type) return self.apply_signature_hook( @@ -795,7 +815,7 @@ def apply_method_signature_hook( def transform_callee_type( self, callable_name: Optional[str], callee: Type, args: List[Expression], - arg_kinds: List[int], context: Context, + arg_kinds: List[ArgKind], context: Context, arg_names: Optional[Sequence[Optional[str]]] = None, object_type: Optional[Type] = None) -> Type: """Attempt to determine a more accurate signature for a method call. @@ -862,15 +882,14 @@ def check_call_expr_with_callee_type(self, def check_union_call_expr(self, e: CallExpr, object_type: UnionType, member: str) -> Type: """"Type check calling a member expression where the base type is a union.""" - res = [] # type: List[Type] + res: List[Type] = [] for typ in object_type.relevant_items(): # Member access errors are already reported when visiting the member expression. - self.msg.disable_errors() - item = analyze_member_access(member, typ, e, False, False, False, - self.msg, original_type=object_type, chk=self.chk, - in_literal_context=self.is_literal_context(), - self_type=typ) - self.msg.enable_errors() + with self.msg.disable_errors(): + item = analyze_member_access(member, typ, e, False, False, False, + self.msg, original_type=object_type, chk=self.chk, + in_literal_context=self.is_literal_context(), + self_type=typ) narrowed = self.narrow_type_from_binder(e.callee, item, skip_non_overlapping=True) if narrowed is None: continue @@ -883,7 +902,7 @@ def check_union_call_expr(self, e: CallExpr, object_type: UnionType, member: str def check_call(self, callee: Type, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], context: Context, arg_names: Optional[Sequence[Optional[str]]] = None, callable_node: Optional[Expression] = None, @@ -901,10 +920,12 @@ def check_call(self, args: actual argument expressions arg_kinds: contains nodes.ARG_* constant for each argument in args describing whether the argument is positional, *arg, etc. + context: current expression context, used for inference. arg_names: names of arguments (optional) callable_node: associate the inferred callable type to this node, if specified - arg_messages: TODO + arg_messages: utility for generating messages, can be swapped to suppress errors, + by default uses 'self.msg' to show errors callable_name: Fully-qualified name of the function/method to call, or None if unavailable (examples: 'builtins.open', 'typing.Mapping.get') object_type: If callable_name refers to a method, the type of the object @@ -957,7 +978,7 @@ def check_call(self, def check_callable_call(self, callee: CallableType, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], context: Context, arg_names: Optional[Sequence[Optional[str]]], callable_node: Optional[Expression], @@ -973,9 +994,7 @@ def check_callable_call(self, ret_type = get_proper_type(callee.ret_type) if callee.is_type_obj() and isinstance(ret_type, Instance): callable_name = ret_type.type.fullname - if (isinstance(callable_node, RefExpr) - and callable_node.fullname in ('enum.Enum', 'enum.IntEnum', - 'enum.Flag', 'enum.IntFlag')): + if isinstance(callable_node, RefExpr) and callable_node.fullname in ENUM_BASES: # An Enum() call that failed SemanticAnalyzerPass2.check_enum_call(). return callee.ret_type, callee @@ -999,11 +1018,31 @@ def check_callable_call(self, lambda i: self.accept(args[i])) if callee.is_generic(): + need_refresh = any(isinstance(v, ParamSpecType) for v in callee.variables) callee = freshen_function_type_vars(callee) callee = self.infer_function_type_arguments_using_context( callee, context) callee = self.infer_function_type_arguments( callee, args, arg_kinds, formal_to_actual, context) + if need_refresh: + # Argument kinds etc. may have changed due to + # ParamSpec variables being replaced with an arbitrary + # number of arguments; recalculate actual-to-formal map + formal_to_actual = map_actuals_to_formals( + arg_kinds, arg_names, + callee.arg_kinds, callee.arg_names, + lambda i: self.accept(args[i])) + + param_spec = callee.param_spec() + if param_spec is not None and arg_kinds == [ARG_STAR, ARG_STAR2]: + arg1 = self.accept(args[0]) + arg2 = self.accept(args[1]) + if (isinstance(arg1, ParamSpecType) + and isinstance(arg2, ParamSpecType) + and arg1.flavor == ParamSpecFlavor.ARGS + and arg2.flavor == ParamSpecFlavor.KWARGS + and arg1.id == arg2.id == param_spec.id): + return callee.ret_type, callee arg_types = self.infer_arg_types_in_context( callee, args, arg_kinds, formal_to_actual) @@ -1063,7 +1102,7 @@ def analyze_type_type_callee(self, item: ProperType, context: Context) -> Type: callee = callee.copy_modified(ret_type=item) elif isinstance(callee, Overloaded): callee = Overloaded([c.copy_modified(ret_type=item) - for c in callee.items()]) + for c in callee.items]) return callee # We support Type of namedtuples but not of tuples in general if (isinstance(item, TupleType) @@ -1079,7 +1118,7 @@ def infer_arg_types_in_empty_context(self, args: List[Expression]) -> List[Type] In short, we basically recurse on each argument without considering in what context the argument was called. """ - res = [] # type: List[Type] + res: List[Type] = [] for arg in args: arg_type = self.accept(arg) @@ -1090,7 +1129,7 @@ def infer_arg_types_in_empty_context(self, args: List[Expression]) -> List[Type] return res def infer_arg_types_in_context( - self, callee: CallableType, args: List[Expression], arg_kinds: List[int], + self, callee: CallableType, args: List[Expression], arg_kinds: List[ArgKind], formal_to_actual: List[List[int]]) -> List[Type]: """Infer argument expression types using a callable type as context. @@ -1099,11 +1138,11 @@ def infer_arg_types_in_context( Returns the inferred types of *actual arguments*. """ - res = [None] * len(args) # type: List[Optional[Type]] + res: List[Optional[Type]] = [None] * len(args) for i, actuals in enumerate(formal_to_actual): for ai in actuals: - if arg_kinds[ai] not in (nodes.ARG_STAR, nodes.ARG_STAR2): + if not arg_kinds[ai].is_star(): res[ai] = self.accept(args[ai], callee.arg_types[i]) # Fill in the rest of the argument types. @@ -1176,7 +1215,7 @@ def infer_function_type_arguments_using_context( return callable.copy_modified() args = infer_type_arguments(callable.type_var_ids(), ret_type, erased_ctx) # Only substitute non-Uninhabited and non-erased types. - new_args = [] # type: List[Optional[Type]] + new_args: List[Optional[Type]] = [] for arg in args: if has_uninhabited_component(arg) or has_erased_component(arg): new_args.append(None) @@ -1189,7 +1228,7 @@ def infer_function_type_arguments_using_context( def infer_function_type_arguments(self, callee_type: CallableType, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], formal_to_actual: List[List[int]], context: Context) -> CallableType: """Infer the type arguments for a generic callee type. @@ -1203,17 +1242,14 @@ def infer_function_type_arguments(self, callee_type: CallableType, # due to partial available context information at this time, but # these errors can be safely ignored as the arguments will be # inferred again later. - self.msg.disable_errors() - - arg_types = self.infer_arg_types_in_context( - callee_type, args, arg_kinds, formal_to_actual) - - self.msg.enable_errors() + with self.msg.disable_errors(): + arg_types = self.infer_arg_types_in_context( + callee_type, args, arg_kinds, formal_to_actual) arg_pass_nums = self.get_arg_infer_passes( callee_type.arg_types, formal_to_actual, len(args)) - pass1_args = [] # type: List[Optional[Type]] + pass1_args: List[Optional[Type]] = [] for i, arg in enumerate(arg_types): if arg_pass_nums[i] > 1: pass1_args.append(None) @@ -1222,6 +1258,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, inferred_args = infer_function_type_arguments( callee_type, pass1_args, arg_kinds, formal_to_actual, + context=self.argument_infer_context(), strict=self.chk.in_checked_function()) if 2 in arg_pass_nums: @@ -1243,7 +1280,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, if isinstance(first_arg, (NoneType, UninhabitedType)): inferred_args[0] = self.named_type('builtins.str') elif not first_arg or not is_subtype(self.named_type('builtins.str'), first_arg): - self.msg.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, + self.chk.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, context) else: # In dynamically typed functions use implicit 'Any' types for @@ -1255,7 +1292,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, def infer_function_type_arguments_pass2( self, callee_type: CallableType, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], formal_to_actual: List[List[int]], old_inferred_args: Sequence[Optional[Type]], context: Context) -> Tuple[CallableType, List[Optional[Type]]]: @@ -1283,10 +1320,18 @@ def infer_function_type_arguments_pass2( callee_type, args, arg_kinds, formal_to_actual) inferred_args = infer_function_type_arguments( - callee_type, arg_types, arg_kinds, formal_to_actual) + callee_type, arg_types, arg_kinds, formal_to_actual, + context=self.argument_infer_context(), + ) return callee_type, inferred_args + def argument_infer_context(self) -> ArgumentInferContext: + return ArgumentInferContext( + self.chk.named_type('typing.Mapping'), + self.chk.named_type('typing.Iterable'), + ) + def get_arg_infer_passes(self, arg_types: List[Type], formal_to_actual: List[List[int]], num_actuals: int) -> List[int]: @@ -1329,7 +1374,7 @@ def apply_inferred_arguments(self, callee_type: CallableType, def check_argument_count(self, callee: CallableType, actual_types: List[Type], - actual_kinds: List[int], + actual_kinds: List[ArgKind], actual_names: Optional[Sequence[Optional[str]]], formal_to_actual: List[List[int]], context: Optional[Context], @@ -1350,7 +1395,7 @@ def check_argument_count(self, # TODO(jukka): We could return as soon as we find an error if messages is None. # Collect list of all actual arguments matched to formal arguments. - all_actuals = [] # type: List[int] + all_actuals: List[int] = [] for actuals in formal_to_actual: all_actuals.extend(actuals) @@ -1359,21 +1404,16 @@ def check_argument_count(self, # Check for too many or few values for formals. for i, kind in enumerate(callee.arg_kinds): - if kind == nodes.ARG_POS and (not formal_to_actual[i] and - not is_unexpected_arg_error): - # No actual for a mandatory positional formal. + if kind.is_required() and not formal_to_actual[i] and not is_unexpected_arg_error: + # No actual for a mandatory formal if messages: - messages.too_few_arguments(callee, context, actual_names) - ok = False - elif kind == nodes.ARG_NAMED and (not formal_to_actual[i] and - not is_unexpected_arg_error): - # No actual for a mandatory named formal - if messages: - argname = callee.arg_names[i] or "?" - messages.missing_named_argument(callee, context, argname) + if kind.is_positional(): + messages.too_few_arguments(callee, context, actual_names) + else: + argname = callee.arg_names[i] or "?" + messages.missing_named_argument(callee, context, argname) ok = False - elif kind in [nodes.ARG_POS, nodes.ARG_OPT, - nodes.ARG_NAMED, nodes.ARG_NAMED_OPT] and is_duplicate_mapping( + elif not kind.is_star() and is_duplicate_mapping( formal_to_actual[i], actual_types, actual_kinds): if (self.chk.in_checked_function() or isinstance(get_proper_type(actual_types[formal_to_actual[i][0]]), @@ -1381,7 +1421,7 @@ def check_argument_count(self, if messages: messages.duplicate_argument_value(callee, i, context) ok = False - elif (kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT) and formal_to_actual[i] and + elif (kind.is_named() and formal_to_actual[i] and actual_kinds[formal_to_actual[i][0]] not in [nodes.ARG_NAMED, nodes.ARG_STAR2]): # Positional argument when expecting a keyword argument. if messages: @@ -1392,7 +1432,7 @@ def check_argument_count(self, def check_for_extra_actual_arguments(self, callee: CallableType, actual_types: List[Type], - actual_kinds: List[int], + actual_kinds: List[ArgKind], actual_names: Optional[Sequence[Optional[str]]], all_actuals: List[int], context: Context, @@ -1407,11 +1447,13 @@ def check_for_extra_actual_arguments(self, ok = True # False if we've found any error for i, kind in enumerate(actual_kinds): - if i not in all_actuals and ( - kind != nodes.ARG_STAR or + if (i not in all_actuals and # We accept the other iterables than tuple (including Any) # as star arguments because they could be empty, resulting no arguments. - is_non_empty_tuple(actual_types[i])): + (kind != nodes.ARG_STAR or is_non_empty_tuple(actual_types[i])) and + # Accept all types for double-starred arguments, because they could be empty + # dictionaries and we can't tell it from their types + kind != nodes.ARG_STAR2): # Extra actual: not matched by a formal argument. ok = False if kind != nodes.ARG_NAMED: @@ -1447,7 +1489,7 @@ def check_for_extra_actual_arguments(self, def check_argument_types(self, arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], args: List[Expression], callee: CallableType, formal_to_actual: List[List[int]], @@ -1464,7 +1506,7 @@ def check_argument_types(self, messages = messages or self.msg check_arg = check_arg or self.check_arg # Keep track of consumed tuple *arg items. - mapper = ArgTypeExpander() + mapper = ArgTypeExpander(self.argument_infer_context()) for i, actuals in enumerate(formal_to_actual): for actual in actuals: actual_type = arg_types[actual] @@ -1489,7 +1531,7 @@ def check_argument_types(self, def check_arg(self, caller_type: Type, original_caller_type: Type, - caller_kind: int, + caller_kind: ArgKind, callee_type: Type, n: int, m: int, @@ -1529,7 +1571,7 @@ def check_arg(self, def check_overload_call(self, callee: Overloaded, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], callable_name: Optional[str], object_type: Optional[Type], @@ -1546,8 +1588,8 @@ def check_overload_call(self, # This is because picking the first overload often ends up being too greedy: # for example, when we have a fallback alternative that accepts an unrestricted # typevar. See https://github.com/python/mypy/issues/4063 for related discussion. - erased_targets = None # type: Optional[List[CallableType]] - unioned_result = None # type: Optional[Tuple[Type, Type]] + erased_targets: Optional[List[CallableType]] = None + unioned_result: Optional[Tuple[Type, Type]] = None union_interrupted = False # did we try all union combinations? if any(self.real_union(arg) for arg in arg_types): unioned_errors = arg_messages.clean_copy() @@ -1611,7 +1653,7 @@ def check_overload_call(self, # a note with whatever error message 'self.check_call' will generate. # In particular, the note's line and column numbers need to be the same # as the error's. - target = erased_targets[0] # type: Type + target: Type = erased_targets[0] else: # There was no plausible match: give up target = AnyType(TypeOfAny.from_error) @@ -1622,20 +1664,19 @@ def check_overload_call(self, else: code = codes.OPERATOR arg_messages.no_variant_matches_arguments( - plausible_targets, callee, arg_types, context, code=code) + callee, arg_types, context, code=code) result = self.check_call(target, args, arg_kinds, context, arg_names, arg_messages=arg_messages, callable_name=callable_name, object_type=object_type) if union_interrupted: - self.chk.fail("Not all union combinations were tried" - " because there are too many unions", context) + self.chk.fail(message_registry.TOO_MANY_UNION_COMBINATIONS, context) return result def plausible_overload_call_targets(self, arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], overload: Overloaded) -> List[CallableType]: """Returns all overload call targets that having matching argument counts. @@ -1654,8 +1695,8 @@ def has_shape(typ: Type) -> bool: return (isinstance(typ, TupleType) or isinstance(typ, TypedDictType) or (isinstance(typ, Instance) and typ.type.is_named_tuple)) - matches = [] # type: List[CallableType] - star_matches = [] # type: List[CallableType] + matches: List[CallableType] = [] + star_matches: List[CallableType] = [] args_have_var_arg = False args_have_kw_arg = False @@ -1665,7 +1706,7 @@ def has_shape(typ: Type) -> bool: if kind == ARG_STAR2 and not has_shape(typ): args_have_kw_arg = True - for typ in overload.items(): + for typ in overload.items: formal_to_actual = map_actuals_to_formals(arg_kinds, arg_names, typ.arg_kinds, typ.arg_names, lambda i: arg_types[i]) @@ -1685,7 +1726,7 @@ def infer_overload_return_type(self, plausible_targets: List[CallableType], args: List[Expression], arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], callable_name: Optional[str], object_type: Optional[Type], @@ -1703,9 +1744,9 @@ def infer_overload_return_type(self, """ arg_messages = self.msg if arg_messages is None else arg_messages - matches = [] # type: List[CallableType] - return_types = [] # type: List[Type] - inferred_types = [] # type: List[Type] + matches: List[CallableType] = [] + return_types: List[Type] = [] + inferred_types: List[Type] = [] args_contain_any = any(map(has_any_type, arg_types)) for typ in plausible_targets: @@ -1767,7 +1808,7 @@ def infer_overload_return_type(self, def overload_erased_call_targets(self, plausible_targets: List[CallableType], arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], args: List[Expression], context: Context) -> List[CallableType]: @@ -1775,7 +1816,7 @@ def overload_erased_call_targets(self, Assumes all of the given targets have argument counts compatible with the caller. """ - matches = [] # type: List[CallableType] + matches: List[CallableType] = [] for typ in plausible_targets: if self.erased_signature_similarity(arg_types, arg_kinds, arg_names, args, typ, context): @@ -1786,7 +1827,7 @@ def union_overload_result(self, plausible_targets: List[CallableType], args: List[Expression], arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], callable_name: Optional[str], object_type: Optional[Type], @@ -1851,7 +1892,7 @@ def union_overload_result(self, return None # Step 5: If splitting succeeded, then filter out duplicate items before returning. - seen = set() # type: Set[Tuple[Type, Type]] + seen: Set[Tuple[Type, Type]] = set() result = [] for pair in res_items: if pair not in seen: @@ -1896,17 +1937,17 @@ def combine_function_signatures(self, types: Sequence[Type]) -> Union[AnyType, C # same thing. # # This function will make sure that all instances of that TypeVar 'T' - # refer to the same underlying TypeVarType and TypeVarDef objects to - # simplify the union-ing logic below. + # refer to the same underlying TypeVarType objects to simplify the union-ing + # logic below. # # (If the user did *not* mean for 'T' to be consistently bound to the # same type in their overloads, well, their code is probably too # confusing and ought to be re-written anyways.) callables, variables = merge_typevars_in_callables_by_name(callables) - new_args = [[] for _ in range(len(callables[0].arg_types))] # type: List[List[Type]] + new_args: List[List[Type]] = [[] for _ in range(len(callables[0].arg_types))] new_kinds = list(callables[0].arg_kinds) - new_returns = [] # type: List[Type] + new_returns: List[Type] = [] too_complex = False for target in callables: @@ -1921,7 +1962,7 @@ def combine_function_signatures(self, types: Sequence[Type]) -> Union[AnyType, C for i, (new_kind, target_kind) in enumerate(zip(new_kinds, target.arg_kinds)): if new_kind == target_kind: continue - elif new_kind in (ARG_POS, ARG_OPT) and target_kind in (ARG_POS, ARG_OPT): + elif new_kind.is_positional() and target_kind.is_positional(): new_kinds[i] = ARG_POS else: too_complex = True @@ -1959,7 +2000,7 @@ def combine_function_signatures(self, types: Sequence[Type]) -> Union[AnyType, C def erased_signature_similarity(self, arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], args: List[Expression], callee: CallableType, @@ -1979,7 +2020,7 @@ def erased_signature_similarity(self, def check_arg(caller_type: Type, original_ccaller_type: Type, - caller_kind: int, + caller_kind: ArgKind, callee_type: Type, n: int, m: int, @@ -2019,7 +2060,7 @@ def check_any_type_call(self, args: List[Expression], callee: Type) -> Tuple[Typ def check_union_call(self, callee: UnionType, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], context: Context, arg_messages: MessageBuilder) -> Tuple[Type, Type]: @@ -2171,7 +2212,7 @@ def visit_op_expr(self, e: OpExpr) -> Type: if right_radd_method is None: return self.concat_tuples(proper_left_type, proper_right_type) - if e.op in nodes.op_methods: + if e.op in operators.op_methods: method = self.get_operator_method(e.op) result, method_type = self.check_op(method, left_type, e.right, e, allow_reverse=True) @@ -2186,14 +2227,14 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: Comparison expressions are type checked consecutive-pair-wise That is, 'a < b > c == d' is check as 'a < b and b > c and c == d' """ - result = None # type: Optional[Type] - sub_result = None # type: Optional[Type] + result: Optional[Type] = None + sub_result: Optional[Type] = None # Check each consecutive operand pair and their operator for left, right, operator in zip(e.operands, e.operands[1:], e.operators): left_type = self.accept(left) - method_type = None # type: Optional[mypy.types.Type] + method_type: Optional[mypy.types.Type] = None if operator == 'in' or operator == 'not in': # If the right operand has partial type, look it up without triggering @@ -2204,10 +2245,15 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: # Keep track of whether we get type check errors (these won't be reported, they # are just to verify whether something is valid typing wise). - local_errors = self.msg.copy() - local_errors.disable_count = 0 + local_errors = self.msg.clean_copy() _, method_type = self.check_method_call_by_name( - '__contains__', right_type, [left], [ARG_POS], e, local_errors) + method='__contains__', + base_type=right_type, + args=[left], + arg_kinds=[ARG_POS], + context=e, + local_errors=local_errors, + ) sub_result = self.bool_type() # Container item type for strict type overlap checks. Note: we need to only # check for nominal type, because a usual "Unsupported operands for in" @@ -2236,7 +2282,7 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: self.msg.dangerous_comparison(left_type, cont_type, 'container', e) else: self.msg.add_errors(local_errors) - elif operator in nodes.op_methods: + elif operator in operators.op_methods: method = self.get_operator_method(operator) err_count = self.msg.errors.total_errors() sub_result, method_type = self.check_op(method, left_type, right, e, @@ -2347,8 +2393,8 @@ def dangerous_comparison(self, left: Type, right: Type, return False if isinstance(left, Instance) and isinstance(right, Instance): # Special case some builtin implementations of AbstractSet. - if (left.type.fullname in OVERLAPPING_TYPES_WHITELIST and - right.type.fullname in OVERLAPPING_TYPES_WHITELIST): + if (left.type.fullname in OVERLAPPING_TYPES_ALLOWLIST and + right.type.fullname in OVERLAPPING_TYPES_ALLOWLIST): abstract_set = self.chk.lookup_typeinfo('typing.AbstractSet') left = map_instance_to_supertype(left, abstract_set) right = map_instance_to_supertype(right, abstract_set) @@ -2364,13 +2410,13 @@ def get_operator_method(self, op: str) -> str: # TODO also check for "from __future__ import division" return '__div__' else: - return nodes.op_methods[op] + return operators.op_methods[op] def check_method_call_by_name(self, method: str, base_type: Type, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], context: Context, local_errors: Optional[MessageBuilder] = None, original_type: Optional[Type] = None @@ -2400,7 +2446,7 @@ def check_union_method_call_by_name(self, method: str, base_type: UnionType, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], context: Context, local_errors: MessageBuilder, original_type: Optional[Type] = None @@ -2411,8 +2457,8 @@ def check_union_method_call_by_name(self, union item and unions the result. We do this to allow plugins to act on individual union items. """ - res = [] # type: List[Type] - meth_res = [] # type: List[Type] + res: List[Type] = [] + meth_res: List[Type] = [] for typ in base_type.relevant_items(): # Format error messages consistently with # mypy.checkmember.analyze_union_member_access(). @@ -2430,7 +2476,7 @@ def check_method_call(self, base_type: Type, method_type: Type, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], context: Context, local_errors: Optional[MessageBuilder] = None) -> Tuple[Type, Type]: """Type check a call to a method with the given name and type on an object. @@ -2456,12 +2502,6 @@ def check_op_reversible(self, right_expr: Expression, context: Context, msg: MessageBuilder) -> Tuple[Type, Type]: - def make_local_errors() -> MessageBuilder: - """Creates a new MessageBuilder object.""" - local_errors = msg.clean_copy() - local_errors.disable_count = 0 - return local_errors - def lookup_operator(op_name: str, base_type: Type) -> Optional[Type]: """Looks up the given operator and returns the corresponding type, if it exists.""" @@ -2473,7 +2513,7 @@ def lookup_operator(op_name: str, base_type: Type) -> Optional[Type]: if not self.has_member(base_type, op_name): return None - local_errors = make_local_errors() + local_errors = msg.clean_copy() member = analyze_member_access( name=op_name, @@ -2539,7 +2579,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: # which records tuples containing the method, base type, and the argument. bias_right = is_proper_subtype(right_type, left_type) - if op_name in nodes.op_methods_that_shortcut and is_same_type(left_type, right_type): + if op_name in operators.op_methods_that_shortcut and is_same_type(left_type, right_type): # When we do "A() + A()", for example, Python will only call the __add__ method, # never the __radd__ method. # @@ -2577,8 +2617,8 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: # When running Python 2, we might also try calling the __cmp__ method. is_python_2 = self.chk.options.python_version[0] == 2 - if is_python_2 and op_name in nodes.ops_falling_back_to_cmp: - cmp_method = nodes.comparison_fallback_method + if is_python_2 and op_name in operators.ops_falling_back_to_cmp: + cmp_method = operators.comparison_fallback_method left_cmp_op = lookup_operator(cmp_method, left_type) right_cmp_op = lookup_operator(cmp_method, right_type) @@ -2604,7 +2644,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: errors = [] results = [] for method, obj, arg in variants: - local_errors = make_local_errors() + local_errors = msg.clean_copy() result = self.check_method_call( op_name, obj, method, [arg], [ARG_POS], context, local_errors) if local_errors.is_errors(): @@ -2626,7 +2666,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: # call the __op__ method (even though it's missing). if not variants: - local_errors = make_local_errors() + local_errors = msg.clean_copy() result = self.check_method_call_by_name( op_name, left_type, [right_expr], [ARG_POS], context, local_errors) @@ -2673,7 +2713,6 @@ def check_op(self, method: str, base_type: Type, # just the left ones. (Mypy can sometimes perform some more precise inference # if we leave the right operands a union -- see testOperatorWithEmptyListAndSum.) msg = self.msg.clean_copy() - msg.disable_count = 0 all_results = [] all_inferred = [] @@ -2708,11 +2747,13 @@ def check_op(self, method: str, base_type: Type, right_variants = [(right_type, arg)] right_type = get_proper_type(right_type) if isinstance(right_type, UnionType): - right_variants = [(item, TempNode(item, context=context)) - for item in flatten_nested_unions(right_type.relevant_items(), - handle_type_alias_type=True)] + right_variants = [ + (item, TempNode(item, context=context)) + for item in flatten_nested_unions(right_type.relevant_items(), + handle_type_alias_type=True) + ] + msg = self.msg.clean_copy() - msg.disable_count = 0 all_results = [] all_inferred = [] @@ -2762,7 +2803,7 @@ def get_reverse_op_method(self, method: str) -> str: if method == '__div__' and self.chk.options.python_version[0] == 2: return '__rdiv__' else: - return nodes.reverse_op_methods[method] + return operators.reverse_op_methods[method] def check_boolean_op(self, e: OpExpr, context: Context) -> Type: """Type check a boolean operation ('and' or 'or').""" @@ -2775,63 +2816,64 @@ def check_boolean_op(self, e: OpExpr, context: Context) -> Type: # '[1] or []' are inferred correctly. ctx = self.type_context[-1] left_type = self.accept(e.left, ctx) + expanded_left_type = try_expanding_sum_type_to_union( + self.accept(e.left, ctx), "builtins.bool" + ) assert e.op in ('and', 'or') # Checked by visit_op_expr - if e.op == 'and': + if e.right_always: + left_map, right_map = None, {} # type: mypy.checker.TypeMap, mypy.checker.TypeMap + elif e.right_unreachable: + left_map, right_map = {}, None + elif e.op == 'and': right_map, left_map = self.chk.find_isinstance_check(e.left) - restricted_left_type = false_only(left_type) - result_is_left = not left_type.can_be_true elif e.op == 'or': left_map, right_map = self.chk.find_isinstance_check(e.left) - restricted_left_type = true_only(left_type) - result_is_left = not left_type.can_be_false # If left_map is None then we know mypy considers the left expression # to be redundant. - # - # Note that we perform these checks *before* we take into account - # the analysis from the semanal phase below. We assume that nodes - # marked as unreachable during semantic analysis were done so intentionally. - # So, we shouldn't report an error. - if codes.REDUNDANT_EXPR in self.chk.options.enabled_error_codes: - if left_map is None: - self.msg.redundant_left_operand(e.op, e.left) + if ( + codes.REDUNDANT_EXPR in self.chk.options.enabled_error_codes + and left_map is None + # don't report an error if it's intentional + and not e.right_always + ): + self.msg.redundant_left_operand(e.op, e.left) + + if ( + self.chk.should_report_unreachable_issues() + and right_map is None + # don't report an error if it's intentional + and not e.right_unreachable + ): + self.msg.unreachable_right_operand(e.op, e.right) # If right_map is None then we know mypy considers the right branch # to be unreachable and therefore any errors found in the right branch # should be suppressed. - # - # Note that we perform these checks *before* we take into account - # the analysis from the semanal phase below. We assume that nodes - # marked as unreachable during semantic analysis were done so intentionally. - # So, we shouldn't report an error. - if self.chk.should_report_unreachable_issues(): - if right_map is None: - self.msg.unreachable_right_operand(e.op, e.right) - - if e.right_unreachable: - right_map = None - elif e.right_always: - left_map = None + with (self.msg.disable_errors() if right_map is None else nullcontext()): + right_type = self.analyze_cond_branch(right_map, e.right, expanded_left_type) - if right_map is None: - self.msg.disable_errors() - try: - right_type = self.analyze_cond_branch(right_map, e.right, left_type) - finally: - if right_map is None: - self.msg.enable_errors() + if left_map is None and right_map is None: + return UninhabitedType() if right_map is None: # The boolean expression is statically known to be the left value - assert left_map is not None # find_isinstance_check guarantees this + assert left_map is not None return left_type if left_map is None: # The boolean expression is statically known to be the right value - assert right_map is not None # find_isinstance_check guarantees this + assert right_map is not None return right_type + if e.op == 'and': + restricted_left_type = false_only(expanded_left_type) + result_is_left = not expanded_left_type.can_be_true + elif e.op == 'or': + restricted_left_type = true_only(expanded_left_type) + result_is_left = not expanded_left_type.can_be_false + if isinstance(restricted_left_type, UninhabitedType): # The left operand can never be the result return right_type @@ -2870,9 +2912,9 @@ def visit_unary_expr(self, e: UnaryExpr) -> Type: operand_type = self.accept(e.expr) op = e.op if op == 'not': - result = self.bool_type() # type: Type + result: Type = self.bool_type() else: - method = nodes.unary_op_methods[op] + method = operators.unary_op_methods[op] result, method_type = self.check_method_call_by_name(method, operand_type, [], [], e) e.method_type = method_type return result @@ -2940,6 +2982,9 @@ def visit_index_with_type(self, left_type: Type, e: IndexExpr, elif (isinstance(left_type, CallableType) and left_type.is_type_obj() and left_type.type_object().is_enum): return self.visit_enum_index_expr(left_type.type_object(), e.index, e) + elif (isinstance(left_type, TypeVarType) + and not self.has_member(left_type.upper_bound, "__getitem__")): + return self.visit_index_with_type(left_type.upper_bound, e, original_type) else: result, method_type = self.check_method_call_by_name( '__getitem__', left_type, [e.index], [ARG_POS], e, @@ -2948,9 +2993,9 @@ def visit_index_with_type(self, left_type: Type, e: IndexExpr, return result def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Type: - begin = [None] # type: Sequence[Optional[int]] - end = [None] # type: Sequence[Optional[int]] - stride = [None] # type: Sequence[Optional[int]] + begin: Sequence[Optional[int]] = [None] + end: Sequence[Optional[int]] = [None] + stride: Sequence[Optional[int]] = [None] if slic.begin_index: begin_raw = self.try_getting_int_literals(slic.begin_index) @@ -2970,7 +3015,7 @@ def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Typ return self.nonliteral_tuple_index_helper(left_type, slic) stride = stride_raw - items = [] # type: List[Type] + items: List[Type] = [] for b, e, s in itertools.product(begin, end, stride): items.append(left_type.slice(b, e, s)) return make_simplified_union(items) @@ -3030,7 +3075,7 @@ def visit_typeddict_index_expr(self, td_type: TypedDictType, index: Expression) else: typ = get_proper_type(self.accept(index)) if isinstance(typ, UnionType): - key_types = list(typ.items) # type: List[Type] + key_types: List[Type] = list(typ.items) else: key_types = [typ] @@ -3057,9 +3102,10 @@ def visit_typeddict_index_expr(self, td_type: TypedDictType, index: Expression) value_types.append(value_type) return make_simplified_union(value_types) - def visit_enum_index_expr(self, enum_type: TypeInfo, index: Expression, - context: Context) -> Type: - string_type = self.named_type('builtins.str') # type: Type + def visit_enum_index_expr( + self, enum_type: TypeInfo, index: Expression, context: Context + ) -> Type: + string_type: Type = self.named_type("builtins.str") if self.chk.options.python_version[0] < 3: string_type = UnionType.make_union([string_type, self.named_type('builtins.unicode')]) @@ -3217,13 +3263,13 @@ def apply_type_arguments_to_callable( return AnyType(TypeOfAny.from_error) return self.apply_generic_arguments(tp, args, ctx) if isinstance(tp, Overloaded): - for it in tp.items(): + for it in tp.items: if len(it.variables) != len(args): self.msg.incompatible_type_application(len(it.variables), len(args), ctx) return AnyType(TypeOfAny.from_error) return Overloaded([self.apply_generic_arguments(it, args, ctx) - for it in tp.items()]) + for it in tp.items]) return AnyType(TypeOfAny.special_form) def visit_list_expr(self, e: ListExpr) -> Type: @@ -3249,7 +3295,7 @@ def fast_container_type( ctx = self.type_context[-1] if ctx: return None - values = [] # type: List[Type] + values: List[Type] = [] for item in items: if isinstance(item, StarExpr): # fallback to slow path @@ -3273,8 +3319,7 @@ def check_lst_expr(self, items: List[Expression], fullname: str, # Used for list and set expressions, as well as for tuples # containing star expressions that don't refer to a # Tuple. (Note: "lst" stands for list-set-tuple. :-) - tvdef = TypeVarDef('T', 'T', -1, [], self.object_type()) - tv = TypeVarType(tvdef) + tv = TypeVarType('T', 'T', -1, [], self.object_type()) constructor = CallableType( [tv], [nodes.ARG_STAR], @@ -3282,7 +3327,7 @@ def check_lst_expr(self, items: List[Expression], fullname: str, self.chk.named_generic_type(fullname, [tv]), self.named_type('builtins.function'), name=tag, - variables=[tvdef]) + variables=[tv]) out = self.check_call(constructor, [(i.expr if isinstance(i, StarExpr) else i) for i in items], @@ -3320,7 +3365,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type: # Infer item types. Give up if there's a star expression # that's not a Tuple. - items = [] # type: List[Type] + items: List[Type] = [] j = 0 # Index into type_context_items; irrelevant if type_context_items is none for i in range(len(e.items)): item = e.items[i] @@ -3364,9 +3409,9 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: ctx = self.type_context[-1] if ctx: return None - keys = [] # type: List[Type] - values = [] # type: List[Type] - stargs = None # type: Optional[Tuple[Type, Type]] + keys: List[Type] = [] + values: List[Type] = [] + stargs: Optional[Tuple[Type, Type]] = None for key, value in e.items: if key is None: st = get_proper_type(self.accept(value)) @@ -3416,8 +3461,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type: return dt # Collect function arguments, watching out for **expr. - args = [] # type: List[Expression] # Regular "key: value" - stargs = [] # type: List[Expression] # For "**expr" + args: List[Expression] = [] # Regular "key: value" + stargs: List[Expression] = [] # For "**expr" for key, value in e.items: if key is None: stargs.append(value) @@ -3431,10 +3476,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type: tup.column = value.column args.append(tup) # Define type variables (used in constructors below). - ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type()) - vtdef = TypeVarDef('VT', 'VT', -2, [], self.object_type()) - kt = TypeVarType(ktdef) - vt = TypeVarType(vtdef) + kt = TypeVarType('KT', 'KT', -1, [], self.object_type()) + vt = TypeVarType('VT', 'VT', -2, [], self.object_type()) rv = None # Call dict(*args), unless it's empty and stargs is not. if args or not stargs: @@ -3448,7 +3491,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type: self.chk.named_generic_type('builtins.dict', [kt, vt]), self.named_type('builtins.function'), name='', - variables=[ktdef, vtdef]) + variables=[kt, vt]) rv = self.check_call(constructor, args, [nodes.ARG_POS] * len(args), e)[0] else: # dict(...) will be called below. @@ -3465,7 +3508,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type: self.chk.named_generic_type('builtins.dict', [kt, vt]), self.named_type('builtins.function'), name='', - variables=[ktdef, vtdef]) + variables=[kt, vt]) rv = self.check_call(constructor, [arg], [nodes.ARG_POS], arg)[0] else: self.check_method_call_by_name('update', rv, [arg], [nodes.ARG_POS], arg) @@ -3503,6 +3546,9 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type: # Type check everything in the body except for the final return # statement (it can contain tuple unpacking before return). with self.chk.scope.push_function(e): + # Lambdas can have more than one element in body, + # when we add "fictional" AssigmentStatement nodes, like in: + # `lambda (a, b): a` for stmt in e.body.body[:-1]: stmt.accept(self.chk) # Only type check the return expression, not the return statement. @@ -3550,20 +3596,27 @@ def infer_lambda_type_using_context(self, e: LambdaExpr) -> Tuple[Optional[Calla callable_ctx = get_proper_type(replace_meta_vars(ctx, ErasedType())) assert isinstance(callable_ctx, CallableType) + if callable_ctx.type_guard is not None: + # Lambda's return type cannot be treated as a `TypeGuard`, + # because it is implicit. And `TypeGuard`s must be explicit. + # See https://github.com/python/mypy/issues/9927 + return None, None + arg_kinds = [arg.kind for arg in e.arguments] - if callable_ctx.is_ellipsis_args: + if callable_ctx.is_ellipsis_args or ctx.param_spec() is not None: # Fill in Any arguments to match the arguments of the lambda. callable_ctx = callable_ctx.copy_modified( is_ellipsis_args=False, arg_types=[AnyType(TypeOfAny.special_form)] * len(arg_kinds), arg_kinds=arg_kinds, - arg_names=[None] * len(arg_kinds) + arg_names=e.arg_names[:], ) if ARG_STAR in arg_kinds or ARG_STAR2 in arg_kinds: # TODO treat this case appropriately return callable_ctx, None + if callable_ctx.arg_kinds != arg_kinds: # Incompatible context; cannot use it to infer types. self.chk.fail(message_registry.CANNOT_INFER_LAMBDA_TYPE, e) @@ -3640,7 +3693,7 @@ def _super_arg_types(self, e: SuperExpr) -> Union[Type, Tuple[Type, Type]]: return AnyType(TypeOfAny.unannotated) elif len(e.call.args) == 0: if self.chk.options.python_version[0] == 2: - self.chk.fail(message_registry.TOO_FEW_ARGS_FOR_SUPER, e, code=codes.CALL_ARG) + self.chk.fail(message_registry.TOO_FEW_ARGS_FOR_SUPER, e) return AnyType(TypeOfAny.from_error) elif not e.info: # This has already been reported by the semantic analyzer. @@ -3651,13 +3704,13 @@ def _super_arg_types(self, e: SuperExpr) -> Union[Type, Tuple[Type, Type]]: # Zero-argument super() is like super(, ) current_type = fill_typevars(e.info) - type_type = TypeType(current_type) # type: ProperType + type_type: ProperType = TypeType(current_type) # Use the type of the self argument, in case it was annotated method = self.chk.scope.top_function() assert method is not None if method.arguments: - instance_type = method.arguments[0].variable.type or current_type # type: Type + instance_type: Type = method.arguments[0].variable.type or current_type else: self.chk.fail(message_registry.SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED, e) return AnyType(TypeOfAny.from_error) @@ -3736,7 +3789,7 @@ def visit_generator_expr(self, e: GeneratorExpr) -> Type: if any(e.is_async): typ = 'typing.AsyncGenerator' # received type is always None in async generator expressions - additional_args = [NoneType()] # type: List[Type] + additional_args: List[Type] = [NoneType()] else: typ = 'typing.Generator' # received type and returned type are None @@ -3755,8 +3808,8 @@ def check_generator_or_comprehension(self, gen: GeneratorExpr, # Infer the type of the list comprehension by using a synthetic generic # callable type. - tvdef = TypeVarDef('T', 'T', -1, [], self.object_type()) - tv_list = [TypeVarType(tvdef)] # type: List[Type] + tv = TypeVarType('T', 'T', -1, [], self.object_type()) + tv_list: List[Type] = [tv] constructor = CallableType( tv_list, [nodes.ARG_POS], @@ -3764,7 +3817,7 @@ def check_generator_or_comprehension(self, gen: GeneratorExpr, self.chk.named_generic_type(type_name, tv_list + additional_args), self.chk.named_type('builtins.function'), name=id_for_messages, - variables=[tvdef]) + variables=[tv]) return self.check_call(constructor, [gen.left_expr], [nodes.ARG_POS], gen)[0] @@ -3775,15 +3828,13 @@ def visit_dictionary_comprehension(self, e: DictionaryComprehension) -> Type: # Infer the type of the list comprehension by using a synthetic generic # callable type. - ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type()) - vtdef = TypeVarDef('VT', 'VT', -2, [], self.object_type()) - kt = TypeVarType(ktdef) - vt = TypeVarType(vtdef) + ktdef = TypeVarType('KT', 'KT', -1, [], self.object_type()) + vtdef = TypeVarType('VT', 'VT', -2, [], self.object_type()) constructor = CallableType( - [kt, vt], + [ktdef, vtdef], [nodes.ARG_POS, nodes.ARG_POS], [None, None], - self.chk.named_generic_type('builtins.dict', [kt, vt]), + self.chk.named_generic_type('builtins.dict', [ktdef, vtdef]), self.chk.named_type('builtins.function'), name='', variables=[ktdef, vtdef]) @@ -3941,25 +3992,22 @@ def is_valid_var_arg(self, typ: Type) -> bool: return (isinstance(typ, TupleType) or is_subtype(typ, self.chk.named_generic_type('typing.Iterable', [AnyType(TypeOfAny.special_form)])) or - isinstance(typ, AnyType)) + isinstance(typ, AnyType) or + isinstance(typ, ParamSpecType)) def is_valid_keyword_var_arg(self, typ: Type) -> bool: """Is a type valid as a **kwargs argument?""" - if self.chk.options.python_version[0] >= 3: - return is_subtype(typ, self.chk.named_generic_type( - 'typing.Mapping', [self.named_type('builtins.str'), - AnyType(TypeOfAny.special_form)])) - else: - return ( - is_subtype(typ, self.chk.named_generic_type( - 'typing.Mapping', - [self.named_type('builtins.str'), - AnyType(TypeOfAny.special_form)])) - or - is_subtype(typ, self.chk.named_generic_type( - 'typing.Mapping', - [self.named_type('builtins.unicode'), - AnyType(TypeOfAny.special_form)]))) + ret = ( + is_subtype(typ, self.chk.named_generic_type('typing.Mapping', + [self.named_type('builtins.str'), AnyType(TypeOfAny.special_form)])) or + is_subtype(typ, self.chk.named_generic_type('typing.Mapping', + [UninhabitedType(), UninhabitedType()])) or + isinstance(typ, ParamSpecType) + ) + if self.chk.options.python_version[0] < 3: + ret = ret or is_subtype(typ, self.chk.named_generic_type('typing.Mapping', + [self.named_type('builtins.unicode'), AnyType(TypeOfAny.special_form)])) + return ret def has_member(self, typ: Type, member: str) -> bool: """Does type have member with the given name?""" @@ -4032,7 +4080,7 @@ def visit_await_expr(self, e: AwaitExpr) -> Type: return self.check_awaitable_expr(actual_type, e, message_registry.INCOMPATIBLE_TYPES_IN_AWAIT) - def check_awaitable_expr(self, t: Type, ctx: Context, msg: str) -> Type: + def check_awaitable_expr(self, t: Type, ctx: Context, msg: Union[str, ErrorMessage]) -> Type: """Check the argument to `await` and extract the type of value. Also used by `async for` and `async with`. @@ -4064,7 +4112,7 @@ def visit_yield_from_expr(self, e: YieldFromExpr, allow_none_return: bool = Fals # Check that the expr is an instance of Iterable and get the type of the iterator produced # by __iter__. if isinstance(subexpr_type, AnyType): - iter_type = AnyType(TypeOfAny.from_another_any, source_any=subexpr_type) # type: Type + iter_type: Type = AnyType(TypeOfAny.from_another_any, source_any=subexpr_type) elif self.chk.type_is_iterable(subexpr_type): if is_async_def(subexpr_type) and not has_coroutine_decorator(return_type): self.chk.msg.yield_from_invalid_operand_type(subexpr_type, e) @@ -4180,10 +4228,6 @@ def narrow_type_from_binder(self, expr: Expression, known_type: Type, """ if literal(expr) >= LITERAL_TYPE: restriction = self.chk.binder.get(expr) - # Ignore the error about using get_proper_type(). - if isinstance(restriction, TypeGuardType): # type: ignore[misc] - # A type guard forces the new type even if it doesn't overlap the old. - return restriction.type_guard # If the current node is deferred, some variables may get Any types that they # otherwise wouldn't have. We don't want to narrow down these since it may # produce invalid inferred Optional[Any] types, at least. @@ -4198,18 +4242,24 @@ def narrow_type_from_binder(self, expr: Expression, known_type: Type, return known_type -def has_any_type(t: Type) -> bool: +def has_any_type(t: Type, ignore_in_type_obj: bool = False) -> bool: """Whether t contains an Any type""" - return t.accept(HasAnyType()) + return t.accept(HasAnyType(ignore_in_type_obj)) class HasAnyType(types.TypeQuery[bool]): - def __init__(self) -> None: + def __init__(self, ignore_in_type_obj: bool) -> None: super().__init__(any) + self.ignore_in_type_obj = ignore_in_type_obj def visit_any(self, t: AnyType) -> bool: return t.type_of_any != TypeOfAny.special_form # special forms are not real Any types + def visit_callable_type(self, t: CallableType) -> bool: + if self.ignore_in_type_obj and t.is_type_obj(): + return False + return super().visit_callable_type(t) + def has_coroutine_decorator(t: Type) -> bool: """Whether t came from a function decorated with `@coroutine`.""" @@ -4246,7 +4296,7 @@ def is_non_empty_tuple(t: Type) -> bool: def is_duplicate_mapping(mapping: List[int], actual_types: List[Type], - actual_kinds: List[int]) -> bool: + actual_kinds: List[ArgKind]) -> bool: return ( len(mapping) > 1 # Multiple actuals can map to the same formal if they both come from @@ -4369,7 +4419,7 @@ def is_typetype_like(typ: ProperType) -> bool: if isinstance(actual, CallableType): actual = actual.fallback if isinstance(actual, Overloaded): - actual = actual.items()[0].fallback + actual = actual.items[0].fallback if isinstance(actual, TupleType): actual = tuple_fallback(actual) if isinstance(actual, Instance) and formal.type in actual.type.mro: @@ -4383,7 +4433,7 @@ def is_typetype_like(typ: ProperType) -> bool: def any_causes_overload_ambiguity(items: List[CallableType], return_types: List[Type], arg_types: List[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]]) -> bool: """May an argument containing 'Any' cause ambiguous result type on call to overloaded function? @@ -4407,7 +4457,10 @@ def any_causes_overload_ambiguity(items: List[CallableType], ] for arg_idx, arg_type in enumerate(arg_types): - if has_any_type(arg_type): + # We ignore Anys in type object callables as ambiguity + # creators, since that can lead to falsely claiming ambiguity + # for overloads between Type and Callable. + if has_any_type(arg_type, ignore_in_type_obj=True): matching_formals_unfiltered = [(item_idx, lookup[arg_idx]) for item_idx, lookup in enumerate(actual_to_formal) if lookup[arg_idx]] @@ -4437,7 +4490,7 @@ def all_same_types(types: List[Type]) -> bool: def merge_typevars_in_callables_by_name( - callables: Sequence[CallableType]) -> Tuple[List[CallableType], List[TypeVarDef]]: + callables: Sequence[CallableType]) -> Tuple[List[CallableType], List[TypeVarType]]: """Takes all the typevars present in the callables and 'combines' the ones with the same name. For example, suppose we have two callables with signatures "f(x: T, y: S) -> T" and @@ -4445,33 +4498,34 @@ def merge_typevars_in_callables_by_name( "S", but we treat them as distinct, unrelated typevars. (E.g. they could both have distinct ids.) - If we pass in both callables into this function, it returns a a list containing two - new callables that are identical in signature, but use the same underlying TypeVarDef - and TypeVarType objects for T and S. + If we pass in both callables into this function, it returns a list containing two + new callables that are identical in signature, but use the same underlying TypeVarType + for T and S. This is useful if we want to take the output lists and "merge" them into one callable in some way -- for example, when unioning together overloads. - Returns both the new list of callables and a list of all distinct TypeVarDef objects used. + Returns both the new list of callables and a list of all distinct TypeVarType objects used. """ - - output = [] # type: List[CallableType] - unique_typevars = {} # type: Dict[str, TypeVarType] - variables = [] # type: List[TypeVarDef] + output: List[CallableType] = [] + unique_typevars: Dict[str, TypeVarType] = {} + variables: List[TypeVarType] = [] for target in callables: if target.is_generic(): target = freshen_function_type_vars(target) rename = {} # Dict[TypeVarId, TypeVar] - for tvdef in target.variables: - name = tvdef.fullname + for tv in target.variables: + name = tv.fullname if name not in unique_typevars: - # TODO(shantanu): fix for ParamSpecDef - assert isinstance(tvdef, TypeVarDef) - unique_typevars[name] = TypeVarType(tvdef) - variables.append(tvdef) - rename[tvdef.id] = unique_typevars[name] + # TODO(PEP612): fix for ParamSpecType + if isinstance(tv, ParamSpecType): + continue + assert isinstance(tv, TypeVarType) + unique_typevars[name] = tv + variables.append(tv) + rename[tv.id] = unique_typevars[name] target = cast(CallableType, expand_type(target, rename)) output.append(target) @@ -4538,9 +4592,9 @@ def is_operator_method(fullname: Optional[str]) -> bool: return False short_name = fullname.split('.')[-1] return ( - short_name in nodes.op_methods.values() or - short_name in nodes.reverse_op_methods.values() or - short_name in nodes.unary_op_methods.values()) + short_name in operators.op_methods.values() or + short_name in operators.reverse_op_methods.values() or + short_name in operators.unary_op_methods.values()) def get_partial_instance_type(t: Optional[Type]) -> Optional[PartialType]: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 64e693d52c96..c01f52de5a77 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -5,14 +5,14 @@ from mypy.types import ( Type, Instance, AnyType, TupleType, TypedDictType, CallableType, FunctionLike, - TypeVarLikeDef, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType, - DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType + TypeVarLikeType, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType, + DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType, ParamSpecType ) from mypy.nodes import ( TypeInfo, FuncBase, Var, FuncDef, SymbolNode, SymbolTable, Context, MypyFile, TypeVarExpr, ARG_POS, ARG_STAR, ARG_STAR2, Decorator, OverloadedFuncDef, TypeAlias, TempNode, is_final_node, - SYMBOL_FUNCBASE_TYPES, + SYMBOL_FUNCBASE_TYPES, IndexExpr ) from mypy.messages import MessageBuilder from mypy.maptype import map_instance_to_supertype @@ -60,14 +60,15 @@ def __init__(self, self.chk = chk self.module_symbol_table = module_symbol_table - def builtin_type(self, name: str) -> Instance: + def named_type(self, name: str) -> Instance: return self.chk.named_type(name) def not_ready_callback(self, name: str, context: Context) -> None: self.chk.handle_cannot_determine_type(name, context) def copy_modified(self, *, messages: Optional[MessageBuilder] = None, - self_type: Optional[Type] = None) -> 'MemberContext': + self_type: Optional[Type] = None, + is_lvalue: Optional[bool] = None) -> 'MemberContext': mx = MemberContext(self.is_lvalue, self.is_super, self.is_operator, self.original_type, self.context, self.msg, self.chk, self.self_type, self.module_symbol_table) @@ -75,6 +76,8 @@ def copy_modified(self, *, messages: Optional[MessageBuilder] = None, mx.msg = messages if self_type is not None: mx.self_type = self_type + if is_lvalue is not None: + mx.is_lvalue = is_lvalue return mx @@ -153,9 +156,11 @@ def _analyze_member_access(name: str, elif isinstance(typ, TupleType): # Actually look up from the fallback instance type. return _analyze_member_access(name, tuple_fallback(typ), mx, override_info) - elif isinstance(typ, (TypedDictType, LiteralType, FunctionLike)): + elif isinstance(typ, (LiteralType, FunctionLike)): # Actually look up from the fallback instance type. return _analyze_member_access(name, typ.fallback, mx, override_info) + elif isinstance(typ, TypedDictType): + return analyze_typeddict_access(name, typ, mx, override_info) elif isinstance(typ, NoneType): return analyze_none_member_access(name, typ, mx) elif isinstance(typ, TypeVarType): @@ -195,14 +200,14 @@ def analyze_instance_member_access(name: str, # Look up the member. First look up the method dictionary. method = info.get_method(name) - if method: + if method and not isinstance(method, Decorator): if method.is_property: assert isinstance(method, OverloadedFuncDef) first_item = cast(Decorator, method.items[0]) return analyze_var(name, first_item.var, typ, info, mx) if mx.is_lvalue: mx.msg.cant_assign_to_method(mx.context) - signature = function_type(method, mx.builtin_type('builtins.function')) + signature = function_type(method, mx.named_type('builtins.function')) signature = freshen_function_type_vars(signature) if name == '__new__': # __new__ is special and behaves like a static method -- don't strip @@ -230,7 +235,7 @@ def analyze_type_callable_member_access(name: str, mx: MemberContext) -> Type: # Class attribute. # TODO super? - ret_type = typ.items()[0].ret_type + ret_type = typ.items[0].ret_type assert isinstance(ret_type, ProperType) if isinstance(ret_type, TupleType): ret_type = tuple_fallback(ret_type) @@ -251,7 +256,7 @@ def analyze_type_callable_member_access(name: str, # See https://github.com/python/mypy/pull/1787 for more info. # TODO: do not rely on same type variables being present in all constructor overloads. result = analyze_class_attribute_access(ret_type, name, mx, - original_vars=typ.items()[0].variables) + original_vars=typ.items[0].variables) if result: return result # Look up from the 'type' type. @@ -266,9 +271,9 @@ def analyze_type_type_member_access(name: str, override_info: Optional[TypeInfo]) -> Type: # Similar to analyze_type_callable_attribute_access. item = None - fallback = mx.builtin_type('builtins.type') + fallback = mx.named_type('builtins.type') ignore_messages = mx.msg.copy() - ignore_messages.disable_errors() + ignore_messages.disable_errors().__enter__() if isinstance(typ.item, Instance): item = typ.item elif isinstance(typ.item, AnyType): @@ -317,19 +322,20 @@ def analyze_union_member_access(name: str, typ: UnionType, mx: MemberContext) -> def analyze_none_member_access(name: str, typ: NoneType, mx: MemberContext) -> Type: - if mx.chk.should_suppress_optional_error([typ]): - return AnyType(TypeOfAny.from_error) is_python_3 = mx.chk.options.python_version[0] >= 3 # In Python 2 "None" has exactly the same attributes as "object". Python 3 adds a single # extra attribute, "__bool__". if is_python_3 and name == '__bool__': + literal_false = LiteralType(False, fallback=mx.named_type('builtins.bool')) return CallableType(arg_types=[], arg_kinds=[], arg_names=[], - ret_type=mx.builtin_type('builtins.bool'), - fallback=mx.builtin_type('builtins.function')) + ret_type=literal_false, + fallback=mx.named_type('builtins.function')) + elif mx.chk.should_suppress_optional_error([typ]): + return AnyType(TypeOfAny.from_error) else: - return _analyze_member_access(name, mx.builtin_type('builtins.object'), mx) + return _analyze_member_access(name, mx.named_type('builtins.object'), mx) def analyze_member_var_access(name: str, @@ -354,7 +360,7 @@ def analyze_member_var_access(name: str, # If the associated variable is a TypeInfo synthesize a Var node for # the purposes of type checking. This enables us to type check things # like accessing class attributes on an inner class. - v = Var(name, type=type_object_type(vv, mx.builtin_type)) + v = Var(name, type=type_object_type(vv, mx.named_type)) v.info = info if isinstance(vv, TypeAlias) and isinstance(get_proper_type(vv.target), Instance): @@ -364,7 +370,7 @@ def analyze_member_var_access(name: str, # class C: # A = List[int] # x = C.A() <- this is OK - typ = instance_alias_type(vv, mx.builtin_type) + typ = instance_alias_type(vv, mx.named_type) v = Var(name, type=typ) v.info = info @@ -380,33 +386,42 @@ def analyze_member_var_access(name: str, elif isinstance(v, FuncDef): assert False, "Did not expect a function" elif (not v and name not in ['__getattr__', '__setattr__', '__getattribute__'] and - not mx.is_operator): + not mx.is_operator and mx.module_symbol_table is None): + # Above we skip ModuleType.__getattr__ etc. if we have a + # module symbol table, since the symbol table allows precise + # checking. if not mx.is_lvalue: for method_name in ('__getattribute__', '__getattr__'): method = info.get_method(method_name) + # __getattribute__ is defined on builtins.object and returns Any, so without # the guard this search will always find object.__getattribute__ and conclude # that the attribute exists if method and method.info.fullname != 'builtins.object': - function = function_type(method, mx.builtin_type('builtins.function')) - bound_method = bind_self(function, mx.self_type) + bound_method = analyze_decorator_or_funcbase_access( + defn=method, itype=itype, info=info, + self_type=mx.self_type, name=method_name, mx=mx) typ = map_instance_to_supertype(itype, method.info) getattr_type = get_proper_type(expand_type_by_instance(bound_method, typ)) if isinstance(getattr_type, CallableType): result = getattr_type.ret_type - - # Call the attribute hook before returning. - fullname = '{}.{}'.format(method.info.fullname, name) - hook = mx.chk.plugin.get_attribute_hook(fullname) - if hook: - result = hook(AttributeContext(get_proper_type(mx.original_type), - result, mx.context, mx.chk)) - return result + else: + result = getattr_type + + # Call the attribute hook before returning. + fullname = '{}.{}'.format(method.info.fullname, name) + hook = mx.chk.plugin.get_attribute_hook(fullname) + if hook: + result = hook(AttributeContext(get_proper_type(mx.original_type), + result, mx.context, mx.chk)) + return result else: setattr_meth = info.get_method('__setattr__') if setattr_meth and setattr_meth.info.fullname != 'builtins.object': - setattr_func = function_type(setattr_meth, mx.builtin_type('builtins.function')) - bound_type = bind_self(setattr_func, mx.self_type) + bound_type = analyze_decorator_or_funcbase_access( + defn=setattr_meth, itype=itype, info=info, + self_type=mx.self_type, name=name, + mx=mx.copy_modified(is_lvalue=False)) typ = map_instance_to_supertype(itype, setattr_meth.info) setattr_type = get_proper_type(expand_type_by_instance(bound_type, typ)) if isinstance(setattr_type, CallableType) and len(setattr_type.arg_types) > 0: @@ -435,32 +450,24 @@ def check_final_member(name: str, info: TypeInfo, msg: MessageBuilder, ctx: Cont msg.cant_assign_to_final(name, attr_assign=True, ctx=ctx) -def analyze_descriptor_access(instance_type: Type, - descriptor_type: Type, - builtin_type: Callable[[str], Instance], - msg: MessageBuilder, - context: Context, *, - chk: 'mypy.checker.TypeChecker') -> Type: +def analyze_descriptor_access(descriptor_type: Type, + mx: MemberContext) -> Type: """Type check descriptor access. Arguments: - instance_type: The type of the instance on which the descriptor - attribute is being accessed (the type of ``a`` in ``a.f`` when - ``f`` is a descriptor). descriptor_type: The type of the descriptor attribute being accessed (the type of ``f`` in ``a.f`` when ``f`` is a descriptor). - context: The node defining the context of this inference. + mx: The current member access context. Return: The return type of the appropriate ``__get__`` overload for the descriptor. """ - instance_type = get_proper_type(instance_type) + instance_type = get_proper_type(mx.original_type) descriptor_type = get_proper_type(descriptor_type) if isinstance(descriptor_type, UnionType): # Map the access over union types return make_simplified_union([ - analyze_descriptor_access(instance_type, typ, builtin_type, - msg, context, chk=chk) + analyze_descriptor_access(typ, mx) for typ in descriptor_type.items ]) elif not isinstance(descriptor_type, Instance): @@ -470,18 +477,20 @@ def analyze_descriptor_access(instance_type: Type, return descriptor_type dunder_get = descriptor_type.type.get_method('__get__') - if dunder_get is None: - msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context) + mx.msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), + mx.context) return AnyType(TypeOfAny.from_error) - function = function_type(dunder_get, builtin_type('builtins.function')) - bound_method = bind_self(function, descriptor_type) + bound_method = analyze_decorator_or_funcbase_access( + defn=dunder_get, itype=descriptor_type, info=descriptor_type.type, + self_type=descriptor_type, name='__set__', mx=mx) + typ = map_instance_to_supertype(descriptor_type, dunder_get.info) dunder_get_type = expand_type_by_instance(bound_method, typ) if isinstance(instance_type, FunctionLike) and instance_type.is_type_obj(): - owner_type = instance_type.items()[0].ret_type + owner_type = instance_type.items[0].ret_type instance_type = NoneType() elif isinstance(instance_type, TypeType): owner_type = instance_type.item @@ -489,19 +498,19 @@ def analyze_descriptor_access(instance_type: Type, else: owner_type = instance_type - callable_name = chk.expr_checker.method_fullname(descriptor_type, "__get__") - dunder_get_type = chk.expr_checker.transform_callee_type( + callable_name = mx.chk.expr_checker.method_fullname(descriptor_type, "__get__") + dunder_get_type = mx.chk.expr_checker.transform_callee_type( callable_name, dunder_get_type, - [TempNode(instance_type, context=context), - TempNode(TypeType.make_normalized(owner_type), context=context)], - [ARG_POS, ARG_POS], context, object_type=descriptor_type, + [TempNode(instance_type, context=mx.context), + TempNode(TypeType.make_normalized(owner_type), context=mx.context)], + [ARG_POS, ARG_POS], mx.context, object_type=descriptor_type, ) - _, inferred_dunder_get_type = chk.expr_checker.check_call( + _, inferred_dunder_get_type = mx.chk.expr_checker.check_call( dunder_get_type, - [TempNode(instance_type, context=context), - TempNode(TypeType.make_normalized(owner_type), context=context)], - [ARG_POS, ARG_POS], context, object_type=descriptor_type, + [TempNode(instance_type, context=mx.context), + TempNode(TypeType.make_normalized(owner_type), context=mx.context)], + [ARG_POS, ARG_POS], mx.context, object_type=descriptor_type, callable_name=callable_name) inferred_dunder_get_type = get_proper_type(inferred_dunder_get_type) @@ -510,24 +519,25 @@ def analyze_descriptor_access(instance_type: Type, return inferred_dunder_get_type if not isinstance(inferred_dunder_get_type, CallableType): - msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context) + mx.msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), + mx.context) return AnyType(TypeOfAny.from_error) return inferred_dunder_get_type.ret_type def instance_alias_type(alias: TypeAlias, - builtin_type: Callable[[str], Instance]) -> Type: + named_type: Callable[[str], Instance]) -> Type: """Type of a type alias node targeting an instance, when appears in runtime context. As usual, we first erase any unbound type variables to Any. """ - target = get_proper_type(alias.target) # type: Type + target: Type = get_proper_type(alias.target) assert isinstance(get_proper_type(target), Instance), "Must be called only with aliases to classes" target = get_proper_type(set_any_tvars(alias, alias.line, alias.column)) assert isinstance(target, Instance) - tp = type_object_type(target.type, builtin_type) + tp = type_object_type(target.type, named_type) return expand_type_by_instance(tp, target) @@ -557,7 +567,7 @@ def analyze_var(name: str, if mx.is_lvalue and var.is_classvar: mx.msg.cant_assign_to_classvar(name, mx.context) t = get_proper_type(expand_type_by_instance(typ, itype)) - result = t # type: Type + result: Type = t typ = get_proper_type(typ) if var.is_initialized_in_class and isinstance(typ, FunctionLike) and not typ.is_type_obj(): if mx.is_lvalue: @@ -599,8 +609,7 @@ def analyze_var(name: str, fullname = '{}.{}'.format(var.info.fullname, name) hook = mx.chk.plugin.get_attribute_hook(fullname) if result and not mx.is_lvalue and not implicit: - result = analyze_descriptor_access(mx.original_type, result, mx.builtin_type, - mx.msg, mx.context, chk=mx.chk) + result = analyze_descriptor_access(result, mx) if hook: result = hook(AttributeContext(get_proper_type(mx.original_type), result, mx.context, mx.chk)) @@ -614,7 +623,7 @@ def freeze_type_vars(member_type: Type) -> None: for v in member_type.variables: v.id.meta_level = 0 if isinstance(member_type, Overloaded): - for it in member_type.items(): + for it in member_type.items: for v in it.variables: v.id.meta_level = 0 @@ -648,7 +657,7 @@ def f(self: S) -> T: ... original type of 'x' is a union. This is done because several special methods treat union types in ad-hoc manner, so we can't use MemberContext.self_type yet. """ - items = functype.items() + items = functype.items if not items: return functype new_items = [] @@ -665,6 +674,9 @@ def f(self: S) -> T: ... selfarg = item.arg_types[0] if subtypes.is_subtype(dispatched_arg_type, erase_typevars(erase_to_bound(selfarg))): new_items.append(item) + elif isinstance(selfarg, ParamSpecType): + # TODO: This is not always right. What's the most reasonable thing to do here? + new_items.append(item) if not new_items: # Choose first item for the message (it may be not very helpful for overloads). msg.incompatible_self_argument(name, dispatched_arg_type, items[0], @@ -679,7 +691,7 @@ def analyze_class_attribute_access(itype: Instance, name: str, mx: MemberContext, override_info: Optional[TypeInfo] = None, - original_vars: Optional[Sequence[TypeVarLikeDef]] = None + original_vars: Optional[Sequence[TypeVarLikeType]] = None ) -> Optional[Type]: """Analyze access to an attribute on a class object. @@ -730,7 +742,7 @@ def analyze_class_attribute_access(itype: Instance, # Find the class where method/variable was defined. if isinstance(node.node, Decorator): - super_info = node.node.var.info # type: Optional[TypeInfo] + super_info: Optional[TypeInfo] = node.node.var.info elif isinstance(node.node, (Var, SYMBOL_FUNCBASE_TYPES)): super_info = node.node.info else: @@ -776,8 +788,7 @@ def analyze_class_attribute_access(itype: Instance, result = add_class_tvars(t, isuper, is_classmethod, mx.self_type, original_vars=original_vars) if not mx.is_lvalue: - result = analyze_descriptor_access(mx.original_type, result, mx.builtin_type, - mx.msg, mx.context, chk=mx.chk) + result = analyze_descriptor_access(result, mx) return result elif isinstance(node.node, Var): mx.not_ready_callback(name, mx.context) @@ -789,15 +800,15 @@ def analyze_class_attribute_access(itype: Instance, return AnyType(TypeOfAny.from_error) if isinstance(node.node, TypeInfo): - return type_object_type(node.node, mx.builtin_type) + return type_object_type(node.node, mx.named_type) if isinstance(node.node, MypyFile): # Reference to a module object. - return mx.builtin_type('types.ModuleType') + return mx.named_type('types.ModuleType') if (isinstance(node.node, TypeAlias) and isinstance(get_proper_type(node.node.target), Instance)): - return instance_alias_type(node.node, mx.builtin_type) + return instance_alias_type(node.node, mx.named_type) if is_decorated: assert isinstance(node.node, Decorator) @@ -808,7 +819,7 @@ def analyze_class_attribute_access(itype: Instance, return AnyType(TypeOfAny.from_error) else: assert isinstance(node.node, FuncBase) - typ = function_type(node.node, mx.builtin_type('builtins.function')) + typ = function_type(node.node, mx.named_type('builtins.function')) # Note: if we are accessing class method on class object, the cls argument is bound. # Annotated and/or explicit class methods go through other code paths above, for # unannotated implicit class methods we do this here. @@ -839,10 +850,44 @@ def analyze_enum_class_attribute_access(itype: Instance, return itype.copy_modified(erased=False, last_known_value=enum_literal) +def analyze_typeddict_access(name: str, typ: TypedDictType, + mx: MemberContext, override_info: Optional[TypeInfo]) -> Type: + if name == '__setitem__': + if isinstance(mx.context, IndexExpr): + # Since we can get this during `a['key'] = ...` + # it is safe to assume that the context is `IndexExpr`. + item_type = mx.chk.expr_checker.visit_typeddict_index_expr( + typ, mx.context.index) + else: + # It can also be `a.__setitem__(...)` direct call. + # In this case `item_type` can be `Any`, + # because we don't have args available yet. + # TODO: check in `default` plugin that `__setitem__` is correct. + item_type = AnyType(TypeOfAny.implementation_artifact) + return CallableType( + arg_types=[mx.chk.named_type('builtins.str'), item_type], + arg_kinds=[ARG_POS, ARG_POS], + arg_names=[None, None], + ret_type=NoneType(), + fallback=mx.chk.named_type('builtins.function'), + name=name, + ) + elif name == '__delitem__': + return CallableType( + arg_types=[mx.chk.named_type('builtins.str')], + arg_kinds=[ARG_POS], + arg_names=[None], + ret_type=NoneType(), + fallback=mx.chk.named_type('builtins.function'), + name=name, + ) + return _analyze_member_access(name, typ.fallback, mx, override_info) + + def add_class_tvars(t: ProperType, isuper: Optional[Instance], is_classmethod: bool, original_type: Type, - original_vars: Optional[Sequence[TypeVarLikeDef]] = None) -> Type: + original_vars: Optional[Sequence[TypeVarLikeType]] = None) -> Type: """Instantiate type variables during analyze_class_attribute_access, e.g T and Q in the following: @@ -891,13 +936,13 @@ class B(A[str]): pass return Overloaded([cast(CallableType, add_class_tvars(item, isuper, is_classmethod, original_type, original_vars=original_vars)) - for item in t.items()]) + for item in t.items]) if isuper is not None: t = cast(ProperType, expand_type_by_instance(t, isuper)) return t -def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> ProperType: +def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> ProperType: """Return the type of a type object. For a generic type G with type variables T and S the type is generally of form @@ -929,9 +974,9 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> init_index = info.mro.index(init_method.node.info) new_index = info.mro.index(new_method.node.info) - fallback = info.metaclass_type or builtin_type('builtins.type') + fallback = info.metaclass_type or named_type('builtins.type') if init_index < new_index: - method = init_method.node # type: Union[FuncBase, Decorator] + method: Union[FuncBase, Decorator] = init_method.node is_new = False elif init_index > new_index: method = new_method.node @@ -947,7 +992,7 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> arg_kinds=[ARG_STAR, ARG_STAR2], arg_names=["_args", "_kwds"], ret_type=any_type, - fallback=builtin_type('builtins.function')) + fallback=named_type('builtins.function')) return class_callable(sig, info, fallback, None, is_new=False) # Otherwise prefer __init__ in a tie. It isn't clear that this @@ -966,6 +1011,27 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) -> return type_object_type_from_function(t, info, method.info, fallback, is_new) +def analyze_decorator_or_funcbase_access( + defn: Union[Decorator, FuncBase], + itype: Instance, + info: TypeInfo, + self_type: Optional[Type], + name: str, + mx: MemberContext, +) -> Type: + """Analyzes the type behind method access. + + The function itself can possibly be decorated. + See: https://github.com/python/mypy/issues/10409 + """ + if isinstance(defn, Decorator): + return analyze_var(name, defn.var, itype, info, mx) + return bind_self( + function_type(defn, mx.chk.named_type('builtins.function')), + original_type=self_type, + ) + + def is_valid_constructor(n: Optional[SymbolNode]) -> bool: """Does this node represents a valid constructor method? diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index b09ff496de4d..dcb711150870 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -13,9 +13,9 @@ import re from typing import ( - cast, List, Tuple, Dict, Callable, Union, Optional, Pattern, Match, Set, Any + cast, List, Tuple, Dict, Callable, Union, Optional, Pattern, Match, Set ) -from typing_extensions import Final, TYPE_CHECKING +from typing_extensions import Final, TYPE_CHECKING, TypeAlias as _TypeAlias from mypy.types import ( Type, AnyType, TupleType, Instance, UnionType, TypeOfAny, get_proper_type, TypeVarType, @@ -39,9 +39,9 @@ from mypy.subtypes import is_subtype from mypy.parse import parse -FormatStringExpr = Union[StrExpr, BytesExpr, UnicodeExpr] -Checkers = Tuple[Callable[[Expression], None], Callable[[Type], None]] -MatchMap = Dict[Tuple[int, int], Match[str]] # span -> match +FormatStringExpr: _TypeAlias = Union[StrExpr, BytesExpr, UnicodeExpr] +Checkers: _TypeAlias = Tuple[Callable[[Expression], None], Callable[[Type], bool]] +MatchMap: _TypeAlias = Dict[Tuple[int, int], Match[str]] # span -> match def compile_format_re() -> Pattern[str]: @@ -50,12 +50,12 @@ def compile_format_re() -> Pattern[str]: See https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting The regexp is intentionally a bit wider to report better errors. """ - key_re = r'(\(([^()]*)\))?' # (optional) parenthesised sequence of characters. - flags_re = r'([#0\-+ ]*)' # (optional) sequence of flags. - width_re = r'(\*|[1-9][0-9]*)?' # (optional) minimum field width (* or numbers). - precision_re = r'(?:\.(\*|[0-9]+)?)?' # (optional) . followed by * of numbers. + key_re = r'(\((?P[^)]*)\))?' # (optional) parenthesised sequence of characters. + flags_re = r'(?P[#0\-+ ]*)' # (optional) sequence of flags. + width_re = r'(?P[1-9][0-9]*|\*)?' # (optional) minimum field width (* or numbers). + precision_re = r'(?:\.(?P\*|[0-9]+)?)?' # (optional) . followed by * of numbers. length_mod_re = r'[hlL]?' # (optional) length modifier (unused). - type_re = r'(.)?' # conversion type. + type_re = r'(?P.)?' # conversion type. format_re = '%' + key_re + flags_re + width_re + precision_re + length_mod_re + type_re return re.compile(format_re) @@ -83,8 +83,8 @@ def compile_new_format_re(custom_spec: bool) -> Pattern[str]: # This contains sign, flags (sign, # and/or 0), width, grouping (_ or ,) and precision. num_spec = r'(?P[+\- ]?#?0?)(?P\d+)?[_,]?(?P\.\d+)?' # The last element is type. - type = r'(?P.)?' # only some are supported, but we want to give a better error - format_spec = r'(?P:' + fill_align + num_spec + type + r')?' + conv_type = r'(?P.)?' # only some are supported, but we want to give a better error + format_spec = r'(?P:' + fill_align + num_spec + conv_type + r')?' else: # Custom types can define their own form_spec using __format__(). format_spec = r'(?P:.*)?' @@ -92,69 +92,52 @@ def compile_new_format_re(custom_spec: bool) -> Pattern[str]: return re.compile(field + conversion + format_spec) -FORMAT_RE = compile_format_re() # type: Final -FORMAT_RE_NEW = compile_new_format_re(False) # type: Final -FORMAT_RE_NEW_CUSTOM = compile_new_format_re(True) # type: Final -DUMMY_FIELD_NAME = '__dummy_name__' # type: Final +FORMAT_RE: Final = compile_format_re() +FORMAT_RE_NEW: Final = compile_new_format_re(False) +FORMAT_RE_NEW_CUSTOM: Final = compile_new_format_re(True) +DUMMY_FIELD_NAME: Final = "__dummy_name__" # Format types supported by str.format() for builtin classes. -SUPPORTED_TYPES_NEW = {'b', 'c', 'd', 'e', 'E', 'f', 'F', - 'g', 'G', 'n', 'o', 's', 'x', 'X', '%'} # type: Final +SUPPORTED_TYPES_NEW: Final = {"b", "c", "d", "e", "E", "f", "F", + "g", "G", "n", "o", "s", "x", "X", "%"} # Types that require either int or float. -NUMERIC_TYPES_OLD = {'d', 'i', 'o', 'u', 'x', 'X', - 'e', 'E', 'f', 'F', 'g', 'G'} # type: Final -NUMERIC_TYPES_NEW = {'b', 'd', 'o', 'e', 'E', 'f', 'F', - 'g', 'G', 'n', 'x', 'X', '%'} # type: Final +NUMERIC_TYPES_OLD: Final = {"d", "i", "o", "u", "x", "X", "e", "E", "f", "F", "g", "G"} +NUMERIC_TYPES_NEW: Final = {"b", "d", "o", "e", "E", "f", "F", "g", "G", "n", "x", "X", "%"} # These types accept _only_ int. -REQUIRE_INT_OLD = {'o', 'x', 'X'} # type: Final -REQUIRE_INT_NEW = {'b', 'd', 'o', 'x', 'X'} # type: Final +REQUIRE_INT_OLD: Final = {"o", "x", "X"} +REQUIRE_INT_NEW: Final = {"b", "d", "o", "x", "X"} # These types fall back to SupportsFloat with % (other fall back to SupportsInt) -FLOAT_TYPES = {'e', 'E', 'f', 'F', 'g', 'G'} # type: Final +FLOAT_TYPES: Final = {"e", "E", "f", "F", "g", "G"} class ConversionSpecifier: - def __init__(self, key: Optional[str], - flags: str, width: str, precision: str, type: str, - format_spec: Optional[str] = None, - conversion: Optional[str] = None, - field: Optional[str] = None) -> None: - self.key = key - self.flags = flags - self.width = width - self.precision = precision - self.type = type + def __init__(self, match: Match[str], + start_pos: int = -1, + non_standard_format_spec: bool = False) -> None: + + self.whole_seq = match.group() + self.start_pos = start_pos + + m_dict = match.groupdict() + self.key = m_dict.get('key') + + # Replace unmatched optional groups with empty matches (for convenience). + self.conv_type = m_dict.get('type', '') + self.flags = m_dict.get('flags', '') + self.width = m_dict.get('width', '') + self.precision = m_dict.get('precision', '') + # Used only for str.format() calls (it may be custom for types with __format__()). - self.format_spec = format_spec - self.non_standard_format_spec = False + self.format_spec = m_dict.get('format_spec') + self.non_standard_format_spec = non_standard_format_spec # Used only for str.format() calls. - self.conversion = conversion + self.conversion = m_dict.get('conversion') # Full formatted expression (i.e. key plus following attributes and/or indexes). # Used only for str.format() calls. - self.field = field - - @classmethod - def from_match(cls, match_obj: Match[str], - non_standard_spec: bool = False) -> 'ConversionSpecifier': - """Construct specifier from match object resulted from parsing str.format() call.""" - match = cast(Any, match_obj) # TODO: remove this once typeshed is fixed. - if non_standard_spec: - spec = cls(match.group('key'), - flags='', width='', precision='', type='', - format_spec=match.group('format_spec'), - conversion=match.group('conversion'), - field=match.group('field')) - spec.non_standard_format_spec = True - return spec - # Replace unmatched optional groups with empty matches (for convenience). - return cls(match.group('key'), - flags=match.group('flags') or '', width=match.group('width') or '', - precision=match.group('precision') or '', type=match.group('type') or '', - format_spec=match.group('format_spec'), - conversion=match.group('conversion'), - field=match.group('field')) + self.field = m_dict.get('field') def has_key(self) -> bool: return self.key is not None @@ -163,6 +146,112 @@ def has_star(self) -> bool: return self.width == '*' or self.precision == '*' +def parse_conversion_specifiers(format_str: str) -> List[ConversionSpecifier]: + """Parse c-printf-style format string into list of conversion specifiers.""" + specifiers: List[ConversionSpecifier] = [] + for m in re.finditer(FORMAT_RE, format_str): + specifiers.append(ConversionSpecifier(m, start_pos=m.start())) + return specifiers + + +def parse_format_value(format_value: str, ctx: Context, msg: MessageBuilder, + nested: bool = False) -> Optional[List[ConversionSpecifier]]: + """Parse format string into list of conversion specifiers. + + The specifiers may be nested (two levels maximum), in this case they are ordered as + '{0:{1}}, {2:{3}{4}}'. Return None in case of an error. + """ + top_targets = find_non_escaped_targets(format_value, ctx, msg) + if top_targets is None: + return None + + result: List[ConversionSpecifier] = [] + for target, start_pos in top_targets: + match = FORMAT_RE_NEW.fullmatch(target) + if match: + conv_spec = ConversionSpecifier(match, start_pos=start_pos) + else: + custom_match = FORMAT_RE_NEW_CUSTOM.fullmatch(target) + if custom_match: + conv_spec = ConversionSpecifier( + custom_match, start_pos=start_pos, + non_standard_format_spec=True) + else: + msg.fail('Invalid conversion specifier in format string', + ctx, code=codes.STRING_FORMATTING) + return None + + if conv_spec.key and ('{' in conv_spec.key or '}' in conv_spec.key): + msg.fail('Conversion value must not contain { or }', + ctx, code=codes.STRING_FORMATTING) + return None + result.append(conv_spec) + + # Parse nested conversions that are allowed in format specifier. + if (conv_spec.format_spec and conv_spec.non_standard_format_spec and + ('{' in conv_spec.format_spec or '}' in conv_spec.format_spec)): + if nested: + msg.fail('Formatting nesting must be at most two levels deep', + ctx, code=codes.STRING_FORMATTING) + return None + sub_conv_specs = parse_format_value(conv_spec.format_spec, ctx, msg, + nested=True) + if sub_conv_specs is None: + return None + result.extend(sub_conv_specs) + return result + + +def find_non_escaped_targets(format_value: str, ctx: Context, + msg: MessageBuilder) -> Optional[List[Tuple[str, int]]]: + """Return list of raw (un-parsed) format specifiers in format string. + + Format specifiers don't include enclosing braces. We don't use regexp for + this because they don't work well with nested/repeated patterns + (both greedy and non-greedy), and these are heavily used internally for + representation of f-strings. + + Return None in case of an error. + """ + result = [] + next_spec = '' + pos = 0 + nesting = 0 + while pos < len(format_value): + c = format_value[pos] + if not nesting: + # Skip any paired '{{' and '}}', enter nesting on '{', report error on '}'. + if c == '{': + if pos < len(format_value) - 1 and format_value[pos + 1] == '{': + pos += 1 + else: + nesting = 1 + if c == '}': + if pos < len(format_value) - 1 and format_value[pos + 1] == '}': + pos += 1 + else: + msg.fail('Invalid conversion specifier in format string:' + ' unexpected }', ctx, code=codes.STRING_FORMATTING) + return None + else: + # Adjust nesting level, then either continue adding chars or move on. + if c == '{': + nesting += 1 + if c == '}': + nesting -= 1 + if nesting: + next_spec += c + else: + result.append((next_spec, pos - len(next_spec))) + next_spec = '' + pos += 1 + if nesting: + msg.fail('Invalid conversion specifier in format string:' + ' unmatched {', ctx, code=codes.STRING_FORMATTING) + return None + return result + + class StringFormatterChecker: """String interpolation/formatter type checker. @@ -170,11 +259,11 @@ class StringFormatterChecker: """ # Some services are provided by a TypeChecker instance. - chk = None # type: mypy.checker.TypeChecker + chk: "mypy.checker.TypeChecker" # This is shared with TypeChecker, but stored also here for convenience. - msg = None # type: MessageBuilder + msg: MessageBuilder # Some services are provided by a ExpressionChecker instance. - exprchk = None # type: mypy.checkexpr.ExpressionChecker + exprchk: "mypy.checkexpr.ExpressionChecker" def __init__(self, exprchk: 'mypy.checkexpr.ExpressionChecker', @@ -209,107 +298,13 @@ def check_str_format_call(self, call: CallExpr, format_value: str) -> None: - 's' must not accept bytes - non-empty flags are only allowed for numeric types """ - conv_specs = self.parse_format_value(format_value, call) + conv_specs = parse_format_value(format_value, call, self.msg) if conv_specs is None: return if not self.auto_generate_keys(conv_specs, call): return self.check_specs_in_format_call(call, conv_specs, format_value) - def parse_format_value(self, format_value: str, ctx: Context, - nested: bool = False) -> Optional[List[ConversionSpecifier]]: - """Parse format string into list of conversion specifiers. - - The specifiers may be nested (two levels maximum), in this case they are ordered as - '{0:{1}}, {2:{3}{4}}'. Return None in case of an error. - """ - top_targets = self.find_non_escaped_targets(format_value, ctx) - if top_targets is None: - return None - - result = [] # type: List[ConversionSpecifier] - for target in top_targets: - match = FORMAT_RE_NEW.fullmatch(target) - if match: - conv_spec = ConversionSpecifier.from_match(match) - else: - custom_match = FORMAT_RE_NEW_CUSTOM.fullmatch(target) - if custom_match: - conv_spec = ConversionSpecifier.from_match(custom_match, - non_standard_spec=True) - else: - self.msg.fail('Invalid conversion specifier in format string', - ctx, code=codes.STRING_FORMATTING) - return None - - if conv_spec.key and ('{' in conv_spec.key or '}' in conv_spec.key): - self.msg.fail('Conversion value must not contain { or }', - ctx, code=codes.STRING_FORMATTING) - return None - result.append(conv_spec) - - # Parse nested conversions that are allowed in format specifier. - if (conv_spec.format_spec and conv_spec.non_standard_format_spec and - ('{' in conv_spec.format_spec or '}' in conv_spec.format_spec)): - if nested: - self.msg.fail('Formatting nesting must be at most two levels deep', - ctx, code=codes.STRING_FORMATTING) - return None - sub_conv_specs = self.parse_format_value(conv_spec.format_spec, ctx=ctx, - nested=True) - if sub_conv_specs is None: - return None - result.extend(sub_conv_specs) - return result - - def find_non_escaped_targets(self, format_value: str, ctx: Context) -> Optional[List[str]]: - """Return list of raw (un-parsed) format specifiers in format string. - - Format specifiers don't include enclosing braces. We don't use regexp for - this because they don't work well with nested/repeated patterns - (both greedy and non-greedy), and these are heavily used internally for - representation of f-strings. - - Return None in case of an error. - """ - result = [] - next_spec = '' - pos = 0 - nesting = 0 - while pos < len(format_value): - c = format_value[pos] - if not nesting: - # Skip any paired '{{' and '}}', enter nesting on '{', report error on '}'. - if c == '{': - if pos < len(format_value) - 1 and format_value[pos + 1] == '{': - pos += 1 - else: - nesting = 1 - if c == '}': - if pos < len(format_value) - 1 and format_value[pos + 1] == '}': - pos += 1 - else: - self.msg.fail('Invalid conversion specifier in format string:' - ' unexpected }', ctx, code=codes.STRING_FORMATTING) - return None - else: - # Adjust nesting level, then either continue adding chars or move on. - if c == '{': - nesting += 1 - if c == '}': - nesting -= 1 - if nesting: - next_spec += c - else: - result.append(next_spec) - next_spec = '' - pos += 1 - if nesting: - self.msg.fail('Invalid conversion specifier in format string:' - ' unmatched {', ctx, code=codes.STRING_FORMATTING) - return None - return result - def check_specs_in_format_call(self, call: CallExpr, specs: List[ConversionSpecifier], format_value: str) -> None: """Perform pairwise checks for conversion specifiers vs their replacements. @@ -336,15 +331,15 @@ def check_specs_in_format_call(self, call: CallExpr, call, code=codes.STRING_FORMATTING) continue # Adjust expected and actual types. - if not spec.type: - expected_type = AnyType(TypeOfAny.special_form) # type: Optional[Type] + if not spec.conv_type: + expected_type: Optional[Type] = AnyType(TypeOfAny.special_form) else: assert isinstance(call.callee, MemberExpr) if isinstance(call.callee.expr, (StrExpr, UnicodeExpr)): format_str = call.callee.expr else: format_str = StrExpr(format_value) - expected_type = self.conversion_type(spec.type, call, format_str, + expected_type = self.conversion_type(spec.conv_type, call, format_str, format_call=True) if spec.conversion is not None: # If the explicit conversion is given, then explicit conversion is called _first_. @@ -371,7 +366,7 @@ def perform_special_format_checks(self, spec: ConversionSpecifier, call: CallExp repl: Expression, actual_type: Type, expected_type: Type) -> None: # TODO: try refactoring to combine this logic with % formatting. - if spec.type == 'c': + if spec.conv_type == 'c': if isinstance(repl, (StrExpr, BytesExpr)) and len(repl.value) != 1: self.msg.requires_int_or_char(call, format_call=True) c_typ = get_proper_type(self.chk.type_map[repl]) @@ -380,19 +375,20 @@ def perform_special_format_checks(self, spec: ConversionSpecifier, call: CallExp if isinstance(c_typ, LiteralType) and isinstance(c_typ.value, str): if len(c_typ.value) != 1: self.msg.requires_int_or_char(call, format_call=True) - if (not spec.type or spec.type == 's') and not spec.conversion: + if (not spec.conv_type or spec.conv_type == 's') and not spec.conversion: if self.chk.options.python_version >= (3, 0): if (has_type_component(actual_type, 'builtins.bytes') and not custom_special_method(actual_type, '__str__')): self.msg.fail( - "On Python 3 '{}'.format(b'abc') produces \"b'abc'\", not 'abc'; " - "use '{!r}'.format(b'abc') if this is desired behavior", + 'On Python 3 formatting "b\'abc\'" with "{}" ' + 'produces "b\'abc\'", not "abc"; ' + 'use "{!r}" if this is desired behavior', call, code=codes.STR_BYTES_PY3) if spec.flags: numeric_types = UnionType([self.named_type('builtins.int'), self.named_type('builtins.float')]) - if (spec.type and spec.type not in NUMERIC_TYPES_NEW or - not spec.type and not is_subtype(actual_type, numeric_types) and + if (spec.conv_type and spec.conv_type not in NUMERIC_TYPES_NEW or + not spec.conv_type and not is_subtype(actual_type, numeric_types) and not custom_special_method(actual_type, '__format__')): self.msg.fail('Numeric flags are only allowed for numeric types', call, code=codes.STRING_FORMATTING) @@ -403,8 +399,8 @@ def find_replacements_in_call(self, call: CallExpr, In case of an error use TempNode(AnyType). """ - result = [] # type: List[Expression] - used = set() # type: Set[Expression] + result: List[Expression] = [] + used: Set[Expression] = set() for key in keys: if key.isdecimal(): expr = self.get_expr_by_position(int(key), call) @@ -519,8 +515,9 @@ def apply_field_accessors(self, spec: ConversionSpecifier, repl: Expression, # This is a bit of a dirty trick, but it looks like this is the simplest way. temp_errors = self.msg.clean_copy().errors dummy = DUMMY_FIELD_NAME + spec.field[len(spec.key):] - temp_ast = parse(dummy, fnam='', module=None, - options=self.chk.options, errors=temp_errors) # type: Node + temp_ast: Node = parse( + dummy, fnam="", module=None, options=self.chk.options, errors=temp_errors + ) if temp_errors.is_errors(): self.msg.fail('Syntax error in format specifier "{}"'.format(spec.field), ctx, code=codes.STRING_FORMATTING) @@ -587,7 +584,7 @@ class User(TypedDict): spec=spec, ctx=ctx) # TODO: In Python 3, the bytes formatting has a more restricted set of options - # compared to string formatting. + # compared to string formatting. def check_str_interpolation(self, expr: FormatStringExpr, replacements: Expression) -> Type: @@ -595,7 +592,7 @@ def check_str_interpolation(self, expression: str % replacements. """ self.exprchk.accept(expr) - specifiers = self.parse_conversion_specifiers(expr.value) + specifiers = parse_conversion_specifiers(expr.value) has_mapping_keys = self.analyze_conversion_specifiers(specifiers, expr) if isinstance(expr, BytesExpr) and (3, 0) <= self.chk.options.python_version < (3, 5): self.msg.fail('Bytes formatting is only supported in Python 3.5 and later', @@ -621,20 +618,12 @@ def check_str_interpolation(self, else: assert False - def parse_conversion_specifiers(self, format: str) -> List[ConversionSpecifier]: - specifiers = [] # type: List[ConversionSpecifier] - for parens_key, key, flags, width, precision, type in FORMAT_RE.findall(format): - if parens_key == '': - key = None - specifiers.append(ConversionSpecifier(key, flags, width, precision, type)) - return specifiers - def analyze_conversion_specifiers(self, specifiers: List[ConversionSpecifier], context: Context) -> Optional[bool]: has_star = any(specifier.has_star() for specifier in specifiers) has_key = any(specifier.has_key() for specifier in specifiers) all_have_keys = all( - specifier.has_key() or specifier.type == '%' for specifier in specifiers + specifier.has_key() or specifier.conv_type == '%' for specifier in specifiers ) if has_key and has_star: @@ -653,7 +642,7 @@ def check_simple_str_interpolation(self, specifiers: List[ConversionSpecifier], return rhs_type = get_proper_type(self.accept(replacements)) - rep_types = [] # type: List[Type] + rep_types: List[Type] = [] if isinstance(rhs_type, TupleType): rep_types = rhs_type.items elif isinstance(rhs_type, AnyType): @@ -671,7 +660,12 @@ def check_simple_str_interpolation(self, specifiers: List[ConversionSpecifier], rep_types = [rhs_type] if len(checkers) > len(rep_types): - self.msg.too_few_string_formatting_arguments(replacements) + # Only check the fix-length Tuple type. Other Iterable types would skip. + if (is_subtype(rhs_type, self.chk.named_type("typing.Iterable")) and + not isinstance(rhs_type, TupleType)): + return + else: + self.msg.too_few_string_formatting_arguments(replacements) elif len(checkers) < len(rep_types): self.msg.too_many_string_formatting_arguments(replacements) else: @@ -698,7 +692,7 @@ def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], if (isinstance(replacements, DictExpr) and all(isinstance(k, (StrExpr, BytesExpr, UnicodeExpr)) for k, v in replacements.items)): - mapping = {} # type: Dict[str, Type] + mapping: Dict[str, Type] = {} for k, v in replacements.items: if self.chk.options.python_version >= (3, 0) and isinstance(expr, BytesExpr): # Special case: for bytes formatting keys must be bytes. @@ -709,7 +703,7 @@ def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], mapping[key_str] = self.accept(v) for specifier in specifiers: - if specifier.type == '%': + if specifier.conv_type == '%': # %% is allowed in mappings, no checking is required continue assert specifier.key is not None @@ -717,7 +711,8 @@ def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], self.msg.key_not_in_mapping(specifier.key, replacements) return rep_type = mapping[specifier.key] - expected_type = self.conversion_type(specifier.type, replacements, expr) + assert specifier.conv_type is not None + expected_type = self.conversion_type(specifier.conv_type, replacements, expr) if expected_type is None: return self.chk.check_subtype(rep_type, expected_type, replacements, @@ -725,7 +720,7 @@ def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], 'expression has type', 'placeholder with key \'%s\' has type' % specifier.key, code=codes.STRING_FORMATTING) - if specifier.type == 's': + if specifier.conv_type == 's': self.check_s_special_cases(expr, rep_type, expr) else: rep_type = self.accept(replacements) @@ -761,7 +756,7 @@ def build_dict_type(self, expr: FormatStringExpr) -> Type: def build_replacement_checkers(self, specifiers: List[ConversionSpecifier], context: Context, expr: FormatStringExpr ) -> Optional[List[Checkers]]: - checkers = [] # type: List[Checkers] + checkers: List[Checkers] = [] for specifier in specifiers: checker = self.replacement_checkers(specifier, context, expr) if checker is None: @@ -772,22 +767,23 @@ def build_replacement_checkers(self, specifiers: List[ConversionSpecifier], def replacement_checkers(self, specifier: ConversionSpecifier, context: Context, expr: FormatStringExpr) -> Optional[List[Checkers]]: """Returns a list of tuples of two functions that check whether a replacement is - of the right type for the specifier. The first functions take a node and checks + of the right type for the specifier. The first function takes a node and checks its type in the right type context. The second function just checks a type. """ - checkers = [] # type: List[Checkers] + checkers: List[Checkers] = [] if specifier.width == '*': checkers.append(self.checkers_for_star(context)) if specifier.precision == '*': checkers.append(self.checkers_for_star(context)) - if specifier.type == 'c': - c = self.checkers_for_c_type(specifier.type, context, expr) + + if specifier.conv_type == 'c': + c = self.checkers_for_c_type(specifier.conv_type, context, expr) if c is None: return None checkers.append(c) - elif specifier.type != '%': - c = self.checkers_for_regular_type(specifier.type, context, expr) + elif specifier.conv_type is not None and specifier.conv_type != '%': + c = self.checkers_for_regular_type(specifier.conv_type, context, expr) if c is None: return None checkers.append(c) @@ -799,10 +795,10 @@ def checkers_for_star(self, context: Context) -> Checkers: """ expected = self.named_type('builtins.int') - def check_type(type: Type) -> None: + def check_type(type: Type) -> bool: expected = self.named_type('builtins.int') - self.chk.check_subtype(type, expected, context, '* wants int', - code=codes.STRING_FORMATTING) + return self.chk.check_subtype(type, expected, context, '* wants int', + code=codes.STRING_FORMATTING) def check_expr(expr: Expression) -> None: type = self.accept(expr, expected) @@ -810,27 +806,28 @@ def check_expr(expr: Expression) -> None: return check_expr, check_type - def check_placeholder_type(self, typ: Type, expected_type: Type, context: Context) -> None: - self.chk.check_subtype(typ, expected_type, context, - message_registry.INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION, - 'expression has type', 'placeholder has type', - code=codes.STRING_FORMATTING) + def check_placeholder_type(self, typ: Type, expected_type: Type, context: Context) -> bool: + return self.chk.check_subtype(typ, expected_type, context, + message_registry.INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION, + 'expression has type', 'placeholder has type', + code=codes.STRING_FORMATTING) - def checkers_for_regular_type(self, type: str, + def checkers_for_regular_type(self, conv_type: str, context: Context, expr: FormatStringExpr) -> Optional[Checkers]: """Returns a tuple of check functions that check whether, respectively, a node or a type is compatible with 'type'. Return None in case of an error. """ - expected_type = self.conversion_type(type, context, expr) + expected_type = self.conversion_type(conv_type, context, expr) if expected_type is None: return None - def check_type(typ: Type) -> None: + def check_type(typ: Type) -> bool: assert expected_type is not None - self.check_placeholder_type(typ, expected_type, context) - if type == 's': - self.check_s_special_cases(expr, typ, context) + ret = self.check_placeholder_type(typ, expected_type, context) + if ret and conv_type == 's': + ret = self.check_s_special_cases(expr, typ, context) + return ret def check_expr(expr: Expression) -> None: type = self.accept(expr, expected_type) @@ -838,16 +835,18 @@ def check_expr(expr: Expression) -> None: return check_expr, check_type - def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Context) -> None: + def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Context) -> bool: """Additional special cases for %s in bytes vs string context.""" if isinstance(expr, StrExpr): # Couple special cases for string formatting. if self.chk.options.python_version >= (3, 0): if has_type_component(typ, 'builtins.bytes'): self.msg.fail( - "On Python 3 '%s' % b'abc' produces \"b'abc'\", not 'abc'; " - "use '%r' % b'abc' if this is desired behavior", + 'On Python 3 formatting "b\'abc\'" with "%s" ' + 'produces "b\'abc\'", not "abc"; ' + 'use "%r" if this is desired behavior', context, code=codes.STR_BYTES_PY3) + return False if self.chk.options.python_version < (3, 0): if has_type_component(typ, 'builtins.unicode'): self.unicode_upcast = True @@ -857,27 +856,43 @@ def check_s_special_cases(self, expr: FormatStringExpr, typ: Type, context: Cont if has_type_component(typ, 'builtins.str'): self.msg.fail("On Python 3 b'%s' requires bytes, not string", context, code=codes.STRING_FORMATTING) + return False + return True def checkers_for_c_type(self, type: str, context: Context, - expr: FormatStringExpr) -> Optional[Checkers]: + format_expr: FormatStringExpr) -> Optional[Checkers]: """Returns a tuple of check functions that check whether, respectively, a node or a type is compatible with 'type' that is a character type. """ - expected_type = self.conversion_type(type, context, expr) + expected_type = self.conversion_type(type, context, format_expr) if expected_type is None: return None - def check_type(type: Type) -> None: + def check_type(type: Type) -> bool: assert expected_type is not None - self.check_placeholder_type(type, expected_type, context) + if self.chk.options.python_version >= (3, 0) and isinstance(format_expr, BytesExpr): + err_msg = '"%c" requires an integer in range(256) or a single byte' + else: + err_msg = '"%c" requires int or char' + return self.chk.check_subtype(type, expected_type, context, err_msg, + 'expression has type', + code=codes.STRING_FORMATTING) def check_expr(expr: Expression) -> None: """int, or str with length 1""" type = self.accept(expr, expected_type) - if isinstance(expr, (StrExpr, BytesExpr)) and len(cast(StrExpr, expr).value) != 1: - self.msg.requires_int_or_char(context) - check_type(type) + # We need further check with expr to make sure that + # it has exact one char or one single byte. + if check_type(type): + # Python 3 doesn't support b'%c' % str + if (self.chk.options.python_version >= (3, 0) + and isinstance(format_expr, BytesExpr) + and isinstance(expr, BytesExpr) and len(expr.value) != 1): + self.msg.requires_int_or_single_byte(context) + # In Python 2, b'%c' is the same as '%c' + elif isinstance(expr, (StrExpr, BytesExpr)) and len(expr.value) != 1: + self.msg.requires_int_or_char(context) return check_expr, check_type @@ -925,9 +940,12 @@ def conversion_type(self, p: str, context: Context, expr: FormatStringExpr, numeric_types.append(self.named_type('typing.SupportsInt')) return UnionType.make_union(numeric_types) elif p in ['c']: - return UnionType([self.named_type('builtins.int'), - self.named_type('builtins.float'), - self.named_type('builtins.str')]) + if isinstance(expr, BytesExpr): + return UnionType([self.named_type('builtins.int'), + self.named_type('builtins.bytes')]) + else: + return UnionType([self.named_type('builtins.int'), + self.named_type('builtins.str')]) else: self.msg.unsupported_placeholder(p, context) return None diff --git a/mypy/config_parser.py b/mypy/config_parser.py index c60097174234..24e61df0441c 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -1,5 +1,4 @@ import argparse -from collections import OrderedDict import configparser import glob as fileglob from io import StringIO @@ -7,16 +6,18 @@ import re import sys -import toml +import tomli from typing import (Any, Callable, Dict, List, Mapping, MutableMapping, Optional, Sequence, - TextIO, Tuple, Union, cast) -from typing_extensions import Final + TextIO, Tuple, Union) +from typing_extensions import Final, TypeAlias as _TypeAlias from mypy import defaults from mypy.options import Options, PER_MODULE_OPTIONS -_CONFIG_VALUE_TYPES = Union[str, bool, int, float, Dict[str, str], List[str], Tuple[int, int]] -_INI_PARSER_CALLABLE = Callable[[Any], _CONFIG_VALUE_TYPES] +_CONFIG_VALUE_TYPES: _TypeAlias = Union[ + str, bool, int, float, Dict[str, str], List[str], Tuple[int, int], +] +_INI_PARSER_CALLABLE: _TypeAlias = Callable[[Any], _CONFIG_VALUE_TYPES] def parse_version(v: str) -> Tuple[int, int]: @@ -102,7 +103,7 @@ def check_follow_imports(choice: str) -> str: # sufficient, and we don't have to do anything here. This table # exists to specify types for values initialized to None or container # types. -ini_config_types = { +ini_config_types: Final[Dict[str, _INI_PARSER_CALLABLE]] = { 'python_version': parse_version, 'strict_optional_whitelist': lambda s: s.split(), 'custom_typing_module': str, @@ -125,10 +126,11 @@ def check_follow_imports(choice: str) -> str: 'cache_dir': expand_path, 'python_executable': expand_path, 'strict': bool, -} # type: Final[Dict[str, _INI_PARSER_CALLABLE]] + 'exclude': lambda s: [p.strip() for p in s.split('\n') if p.strip()], +} # Reuse the ini_config_types and overwrite the diff -toml_config_types = ini_config_types.copy() # type: Final[Dict[str, _INI_PARSER_CALLABLE]] +toml_config_types: Final[Dict[str, _INI_PARSER_CALLABLE]] = ini_config_types.copy() toml_config_types.update({ 'python_version': lambda s: parse_version(str(s)), 'strict_optional_whitelist': try_split, @@ -158,7 +160,7 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], stderr = stderr or sys.stderr if filename is not None: - config_files = (filename,) # type: Tuple[str, ...] + config_files: Tuple[str, ...] = (filename,) else: config_files = tuple(map(os.path.expanduser, defaults.CONFIG_FILES)) @@ -169,20 +171,20 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], continue try: if is_toml(config_file): - toml_data = cast("OrderedDict[str, Any]", - toml.load(config_file, _dict=OrderedDict)) + with open(config_file, encoding="utf-8") as f: + toml_data = tomli.loads(f.read()) # Filter down to just mypy relevant toml keys toml_data = toml_data.get('tool', {}) if 'mypy' not in toml_data: continue - toml_data = OrderedDict({'mypy': toml_data['mypy']}) - parser = destructure_overrides(toml_data) # type: MutableMapping[str, Any] + toml_data = {'mypy': toml_data['mypy']} + parser: MutableMapping[str, Any] = destructure_overrides(toml_data) config_types = toml_config_types else: config_parser.read(config_file) parser = config_parser config_types = ini_config_types - except (toml.TomlDecodeError, configparser.Error, ConfigTOMLValueError) as err: + except (tomli.TOMLDecodeError, configparser.Error, ConfigTOMLValueError) as err: print("%s: %s" % (config_file, err), file=stderr) else: if config_file in defaults.SHARED_CONFIG_FILES and 'mypy' not in parser: @@ -252,7 +254,7 @@ def is_toml(filename: str) -> bool: return filename.lower().endswith('.toml') -def destructure_overrides(toml_data: "OrderedDict[str, Any]") -> "OrderedDict[str, Any]": +def destructure_overrides(toml_data: Dict[str, Any]) -> Dict[str, Any]: """Take the new [[tool.mypy.overrides]] section array in the pyproject.toml file, and convert it back to a flatter structure that the existing config_parser can handle. @@ -336,8 +338,8 @@ def parse_section(prefix: str, template: Options, Returns a dict of option values encountered, and a dict of report directories. """ - results = {} # type: Dict[str, object] - report_dirs = {} # type: Dict[str, str] + results: Dict[str, object] = {} + report_dirs: Dict[str, str] = {} for key in section: invert = False options_key = key @@ -380,7 +382,7 @@ def parse_section(prefix: str, template: Options, else: continue ct = type(dv) - v = None # type: Any + v: Any = None try: if ct is bool: if isinstance(section, dict): @@ -443,7 +445,7 @@ def split_directive(s: str) -> Tuple[List[str], List[str]]: Returns the parts and a list of error messages.""" parts = [] - cur = [] # type: List[str] + cur: List[str] = [] errors = [] i = 0 while i < len(s): @@ -499,7 +501,7 @@ def parse_mypy_comments( generated. """ - errors = [] # type: List[Tuple[int, str]] + errors: List[Tuple[int, str]] = [] sections = {} for lineno, line in args: diff --git a/mypy/constraints.py b/mypy/constraints.py index 074f038a30bc..5a78cdb94e93 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -1,25 +1,29 @@ """Type inference constraints.""" -from typing import Iterable, List, Optional, Sequence +from typing import TYPE_CHECKING, Iterable, List, Optional, Sequence from typing_extensions import Final from mypy.types import ( CallableType, Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarType, Instance, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType, - ProperType, get_proper_type, TypeAliasType, TypeGuardType + ProperType, ParamSpecType, get_proper_type, TypeAliasType, is_union_with_any, + callable_with_ellipsis ) from mypy.maptype import map_instance_to_supertype import mypy.subtypes import mypy.sametypes import mypy.typeops from mypy.erasetype import erase_typevars -from mypy.nodes import COVARIANT, CONTRAVARIANT +from mypy.nodes import COVARIANT, CONTRAVARIANT, ArgKind from mypy.argmap import ArgTypeExpander from mypy.typestate import TypeState -SUBTYPE_OF = 0 # type: Final -SUPERTYPE_OF = 1 # type: Final +if TYPE_CHECKING: + from mypy.infer import ArgumentInferContext + +SUBTYPE_OF: Final = 0 +SUPERTYPE_OF: Final = 1 class Constraint: @@ -28,9 +32,9 @@ class Constraint: It can be either T <: type or T :> type (T is a type variable). """ - type_var = None # type: TypeVarId + type_var: TypeVarId op = 0 # SUBTYPE_OF or SUPERTYPE_OF - target = None # type: Type + target: Type def __init__(self, type_var: TypeVarId, op: int, target: Type) -> None: self.type_var = type_var @@ -45,14 +49,17 @@ def __repr__(self) -> str: def infer_constraints_for_callable( - callee: CallableType, arg_types: Sequence[Optional[Type]], arg_kinds: List[int], - formal_to_actual: List[List[int]]) -> List[Constraint]: + callee: CallableType, + arg_types: Sequence[Optional[Type]], + arg_kinds: List[ArgKind], + formal_to_actual: List[List[int]], + context: 'ArgumentInferContext') -> List[Constraint]: """Infer type variable constraints for a callable and actual arguments. Return a list of constraints. """ - constraints = [] # type: List[Constraint] - mapper = ArgTypeExpander() + constraints: List[Constraint] = [] + mapper = ArgTypeExpander(context) for i, actuals in enumerate(formal_to_actual): for actual in actuals: @@ -195,6 +202,32 @@ def infer_constraints_if_possible(template: Type, actual: Type, return infer_constraints(template, actual, direction) +def select_trivial(options: Sequence[Optional[List[Constraint]]]) -> List[List[Constraint]]: + """Select only those lists where each item is a constraint against Any.""" + res = [] + for option in options: + if option is None: + continue + if all(isinstance(get_proper_type(c.target), AnyType) for c in option): + res.append(option) + return res + + +def merge_with_any(constraint: Constraint) -> Constraint: + """Transform a constraint target into a union with given Any type.""" + target = constraint.target + if is_union_with_any(target): + # Do not produce redundant unions. + return constraint + # TODO: if we will support multiple sources Any, use this here instead. + any_type = AnyType(TypeOfAny.implementation_artifact) + return Constraint( + constraint.type_var, + constraint.op, + UnionType.make_union([target, any_type], target.line, target.column), + ) + + def any_constraints(options: List[Optional[List[Constraint]]], eager: bool) -> List[Constraint]: """Deduce what we can from a collection of constraint lists. @@ -207,16 +240,36 @@ def any_constraints(options: List[Optional[List[Constraint]]], eager: bool) -> L valid_options = [option for option in options if option] else: valid_options = [option for option in options if option is not None] + + if not valid_options: + return [] + if len(valid_options) == 1: return valid_options[0] - elif (len(valid_options) > 1 and - all(is_same_constraints(valid_options[0], c) - for c in valid_options[1:])): + + if all(is_same_constraints(valid_options[0], c) for c in valid_options[1:]): # Multiple sets of constraints that are all the same. Just pick any one of them. - # TODO: More generally, if a given (variable, direction) pair appears in - # every option, combine the bounds with meet/join. return valid_options[0] + if all(is_similar_constraints(valid_options[0], c) for c in valid_options[1:]): + # All options have same structure. In this case we can merge-in trivial + # options (i.e. those that only have Any) and try again. + # TODO: More generally, if a given (variable, direction) pair appears in + # every option, combine the bounds with meet/join always, not just for Any. + trivial_options = select_trivial(valid_options) + if trivial_options and len(trivial_options) < len(valid_options): + merged_options = [] + for option in valid_options: + if option in trivial_options: + continue + if option is not None: + merged_option: Optional[List[Constraint]] = [ + merge_with_any(c) for c in option + ] + else: + merged_option = None + merged_options.append(merged_option) + return any_constraints([option for option in merged_options], eager) # Otherwise, there are either no valid options or multiple, inconsistent valid # options. Give up and deduce nothing. return [] @@ -233,11 +286,47 @@ def is_same_constraints(x: List[Constraint], y: List[Constraint]) -> bool: def is_same_constraint(c1: Constraint, c2: Constraint) -> bool: + # Ignore direction when comparing constraints against Any. + skip_op_check = ( + isinstance(get_proper_type(c1.target), AnyType) and + isinstance(get_proper_type(c2.target), AnyType) + ) return (c1.type_var == c2.type_var - and c1.op == c2.op + and (c1.op == c2.op or skip_op_check) and mypy.sametypes.is_same_type(c1.target, c2.target)) +def is_similar_constraints(x: List[Constraint], y: List[Constraint]) -> bool: + """Check that two lists of constraints have similar structure. + + This means that each list has same type variable plus direction pairs (i.e we + ignore the target). Except for constraints where target is Any type, there + we ignore direction as well. + """ + return _is_similar_constraints(x, y) and _is_similar_constraints(y, x) + + +def _is_similar_constraints(x: List[Constraint], y: List[Constraint]) -> bool: + """Check that every constraint in the first list has a similar one in the second. + + See docstring above for definition of similarity. + """ + for c1 in x: + has_similar = False + for c2 in y: + # Ignore direction when either constraint is against Any. + skip_op_check = ( + isinstance(get_proper_type(c1.target), AnyType) or + isinstance(get_proper_type(c2.target), AnyType) + ) + if c1.type_var == c2.type_var and (c1.op == c2.op or skip_op_check): + has_similar = True + break + if not has_similar: + return False + return True + + def simplify_away_incomplete_types(types: Iterable[Type]) -> List[Type]: complete = [typ for typ in types if is_complete_type(typ)] if complete: @@ -268,7 +357,7 @@ class ConstraintBuilderVisitor(TypeVisitor[List[Constraint]]): # The type that is compared against a template # TODO: The value may be None. Is that actually correct? - actual = None # type: ProperType + actual: ProperType def __init__(self, actual: ProperType, direction: int) -> None: # Direction must be SUBTYPE_OF or SUPERTYPE_OF. @@ -310,11 +399,15 @@ def visit_type_var(self, template: TypeVarType) -> List[Constraint]: assert False, ("Unexpected TypeVarType in ConstraintBuilderVisitor" " (should have been handled in infer_constraints)") + def visit_param_spec(self, template: ParamSpecType) -> List[Constraint]: + # Can't infer ParamSpecs from component values (only via Callable[P, T]). + return [] + # Non-leaf types def visit_instance(self, template: Instance) -> List[Constraint]: original_actual = actual = self.actual - res = [] # type: List[Constraint] + res: List[Constraint] = [] if isinstance(actual, (CallableType, Overloaded)) and template.type.is_protocol: if template.type.protocol_members == ['__call__']: # Special case: a generic callback protocol @@ -350,14 +443,16 @@ def visit_instance(self, template: Instance) -> List[Constraint]: # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for tvar, mapped_arg, instance_arg in zip(tvars, mapped.args, instance.args): - # The constraints for generic type parameters depend on variance. - # Include constraints from both directions if invariant. - if tvar.variance != CONTRAVARIANT: - res.extend(infer_constraints( - mapped_arg, instance_arg, self.direction)) - if tvar.variance != COVARIANT: - res.extend(infer_constraints( - mapped_arg, instance_arg, neg_op(self.direction))) + # TODO: ParamSpecType + if isinstance(tvar, TypeVarType): + # The constraints for generic type parameters depend on variance. + # Include constraints from both directions if invariant. + if tvar.variance != CONTRAVARIANT: + res.extend(infer_constraints( + mapped_arg, instance_arg, self.direction)) + if tvar.variance != COVARIANT: + res.extend(infer_constraints( + mapped_arg, instance_arg, neg_op(self.direction))) return res elif (self.direction == SUPERTYPE_OF and instance.type.has_base(template.type.fullname)): @@ -366,19 +461,21 @@ def visit_instance(self, template: Instance) -> List[Constraint]: # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for tvar, mapped_arg, template_arg in zip(tvars, mapped.args, template.args): - # The constraints for generic type parameters depend on variance. - # Include constraints from both directions if invariant. - if tvar.variance != CONTRAVARIANT: - res.extend(infer_constraints( - template_arg, mapped_arg, self.direction)) - if tvar.variance != COVARIANT: - res.extend(infer_constraints( - template_arg, mapped_arg, neg_op(self.direction))) + # TODO: ParamSpecType + if isinstance(tvar, TypeVarType): + # The constraints for generic type parameters depend on variance. + # Include constraints from both directions if invariant. + if tvar.variance != CONTRAVARIANT: + res.extend(infer_constraints( + template_arg, mapped_arg, self.direction)) + if tvar.variance != COVARIANT: + res.extend(infer_constraints( + template_arg, mapped_arg, neg_op(self.direction))) return res if (template.type.is_protocol and self.direction == SUPERTYPE_OF and # We avoid infinite recursion for structural subtypes by checking # whether this type already appeared in the inference chain. - # This is a conservative way break the inference cycles. + # This is a conservative way to break the inference cycles. # It never produces any "false" constraints but gives up soon # on purely structural inference cycles, see #3829. # Note that we use is_protocol_implementation instead of is_subtype @@ -388,8 +485,8 @@ def visit_instance(self, template: Instance) -> List[Constraint]: for t in template.type.inferring) and mypy.subtypes.is_protocol_implementation(instance, erased)): template.type.inferring.append(template) - self.infer_constraints_from_protocol_members(res, instance, template, - original_actual, template) + res.extend(self.infer_constraints_from_protocol_members( + instance, template, original_actual, template)) template.type.inferring.pop() return res elif (instance.type.is_protocol and self.direction == SUBTYPE_OF and @@ -398,12 +495,11 @@ def visit_instance(self, template: Instance) -> List[Constraint]: for i in instance.type.inferring) and mypy.subtypes.is_protocol_implementation(erased, instance)): instance.type.inferring.append(instance) - self.infer_constraints_from_protocol_members(res, instance, template, - template, instance) + res.extend(self.infer_constraints_from_protocol_members( + instance, template, template, instance)) instance.type.inferring.pop() return res if isinstance(actual, AnyType): - # IDEA: Include both ways, i.e. add negation as well? return self.infer_against_any(template.args, actual) if (isinstance(actual, TupleType) and (is_named_instance(template, 'typing.Iterable') or @@ -422,19 +518,22 @@ def visit_instance(self, template: Instance) -> List[Constraint]: else: return [] - def infer_constraints_from_protocol_members(self, res: List[Constraint], + def infer_constraints_from_protocol_members(self, instance: Instance, template: Instance, - subtype: Type, protocol: Instance) -> None: + subtype: Type, protocol: Instance, + ) -> List[Constraint]: """Infer constraints for situations where either 'template' or 'instance' is a protocol. The 'protocol' is the one of two that is an instance of protocol type, 'subtype' is the type used to bind self during inference. Currently, we just infer constrains for every protocol member type (both ways for settable members). """ + res = [] for member in protocol.type.protocol_members: inst = mypy.subtypes.find_member(member, instance, subtype) temp = mypy.subtypes.find_member(member, template, subtype) - assert inst is not None and temp is not None + if inst is None or temp is None: + return [] # See #11020 # The above is safe since at this point we know that 'instance' is a subtype # of (erased) 'template', therefore it defines all protocol members res.extend(infer_constraints(temp, inst, self.direction)) @@ -442,33 +541,50 @@ def infer_constraints_from_protocol_members(self, res: List[Constraint], mypy.subtypes.get_member_flags(member, protocol.type)): # Settable members are invariant, add opposite constraints res.extend(infer_constraints(temp, inst, neg_op(self.direction))) + return res def visit_callable_type(self, template: CallableType) -> List[Constraint]: if isinstance(self.actual, CallableType): + res: List[Constraint] = [] cactual = self.actual - # FIX verify argument counts - # FIX what if one of the functions is generic - res = [] # type: List[Constraint] - - # We can't infer constraints from arguments if the template is Callable[..., T] (with - # literal '...'). - if not template.is_ellipsis_args: - # The lengths should match, but don't crash (it will error elsewhere). - for t, a in zip(template.arg_types, cactual.arg_types): - # Negate direction due to function argument type contravariance. - res.extend(infer_constraints(t, a, neg_op(self.direction))) + param_spec = template.param_spec() + if param_spec is None: + # FIX verify argument counts + # FIX what if one of the functions is generic + + # We can't infer constraints from arguments if the template is Callable[..., T] + # (with literal '...'). + if not template.is_ellipsis_args: + # The lengths should match, but don't crash (it will error elsewhere). + for t, a in zip(template.arg_types, cactual.arg_types): + # Negate direction due to function argument type contravariance. + res.extend(infer_constraints(t, a, neg_op(self.direction))) + else: + # TODO: Direction + # TODO: Deal with arguments that come before param spec ones? + res.append(Constraint(param_spec.id, + SUBTYPE_OF, + cactual.copy_modified(ret_type=NoneType()))) + template_ret_type, cactual_ret_type = template.ret_type, cactual.ret_type if template.type_guard is not None: template_ret_type = template.type_guard if cactual.type_guard is not None: cactual_ret_type = cactual.type_guard + res.extend(infer_constraints(template_ret_type, cactual_ret_type, self.direction)) return res elif isinstance(self.actual, AnyType): - # FIX what if generic - res = self.infer_against_any(template.arg_types, self.actual) + param_spec = template.param_spec() any_type = AnyType(TypeOfAny.from_another_any, source_any=self.actual) + if param_spec is None: + # FIX what if generic + res = self.infer_against_any(template.arg_types, self.actual) + else: + res = [Constraint(param_spec.id, + SUBTYPE_OF, + callable_with_ellipsis(any_type, any_type, template.fallback))] res.extend(infer_constraints(template.ret_type, any_type, self.direction)) return res elif isinstance(self.actual, Overloaded): @@ -500,7 +616,7 @@ def infer_against_overloaded(self, overloaded: Overloaded, def visit_tuple_type(self, template: TupleType) -> List[Constraint]: actual = self.actual if isinstance(actual, TupleType) and len(actual.items) == len(template.items): - res = [] # type: List[Constraint] + res: List[Constraint] = [] for i in range(len(template.items)): res.extend(infer_constraints(template.items[i], actual.items[i], @@ -514,7 +630,7 @@ def visit_tuple_type(self, template: TupleType) -> List[Constraint]: def visit_typeddict_type(self, template: TypedDictType) -> List[Constraint]: actual = self.actual if isinstance(actual, TypedDictType): - res = [] # type: List[Constraint] + res: List[Constraint] = [] # NOTE: Non-matching keys are ignored. Compatibility is checked # elsewhere so this shouldn't be unsafe. for (item_name, template_item_type, actual_item_type) in template.zip(actual): @@ -534,18 +650,18 @@ def visit_union_type(self, template: UnionType) -> List[Constraint]: def visit_type_alias_type(self, template: TypeAliasType) -> List[Constraint]: assert False, "This should be never called, got {}".format(template) - def visit_type_guard_type(self, template: TypeGuardType) -> List[Constraint]: - assert False, "This should be never called, got {}".format(template) - def infer_against_any(self, types: Iterable[Type], any_type: AnyType) -> List[Constraint]: - res = [] # type: List[Constraint] + res: List[Constraint] = [] for t in types: + # Note that we ignore variance and simply always use the + # original direction. This is because for Any targets direction is + # irrelevant in most cases, see e.g. is_same_constraint(). res.extend(infer_constraints(t, any_type, self.direction)) return res def visit_overloaded(self, template: Overloaded) -> List[Constraint]: - res = [] # type: List[Constraint] - for t in template.items(): + res: List[Constraint] = [] + for t in template.items: res.extend(infer_constraints(t, self.actual, self.direction)) return res @@ -553,7 +669,7 @@ def visit_type_type(self, template: TypeType) -> List[Constraint]: if isinstance(self.actual, CallableType): return infer_constraints(template.item, self.actual.ret_type, self.direction) elif isinstance(self.actual, Overloaded): - return infer_constraints(template.item, self.actual.items()[0].ret_type, + return infer_constraints(template.item, self.actual.items[0].ret_type, self.direction) elif isinstance(self.actual, TypeType): return infer_constraints(template.item, self.actual.item, self.direction) @@ -576,7 +692,7 @@ def neg_op(op: int) -> int: def find_matching_overload_item(overloaded: Overloaded, template: CallableType) -> CallableType: """Disambiguate overload item against a template.""" - items = overloaded.items() + items = overloaded.items for item in items: # Return type may be indeterminate in the template, so ignore it when performing a # subtype check. diff --git a/mypy/defaults.py b/mypy/defaults.py index 7e19bfe4a56f..dc9e49c2e9c6 100644 --- a/mypy/defaults.py +++ b/mypy/defaults.py @@ -2,31 +2,45 @@ from typing_extensions import Final -PYTHON2_VERSION = (2, 7) # type: Final -PYTHON3_VERSION = (3, 6) # type: Final -PYTHON3_VERSION_MIN = (3, 4) # type: Final -CACHE_DIR = '.mypy_cache' # type: Final -CONFIG_FILE = ['mypy.ini', '.mypy.ini'] # type: Final -PYPROJECT_CONFIG_FILES = ['pyproject.toml', ] # type: Final -SHARED_CONFIG_FILES = ['setup.cfg', ] # type: Final -USER_CONFIG_FILES = ['~/.config/mypy/config', '~/.mypy.ini', ] # type: Final -if os.environ.get('XDG_CONFIG_HOME'): - USER_CONFIG_FILES.insert(0, os.path.join(os.environ['XDG_CONFIG_HOME'], 'mypy/config')) +PYTHON2_VERSION: Final = (2, 7) +PYTHON3_VERSION: Final = (3, 6) +PYTHON3_VERSION_MIN: Final = (3, 4) +CACHE_DIR: Final = ".mypy_cache" +CONFIG_FILE: Final = ["mypy.ini", ".mypy.ini"] +PYPROJECT_CONFIG_FILES: Final = [ + "pyproject.toml", +] +SHARED_CONFIG_FILES: Final = [ + "setup.cfg", +] +USER_CONFIG_FILES: Final = [ + "~/.config/mypy/config", + "~/.mypy.ini", +] +if os.environ.get("XDG_CONFIG_HOME"): + USER_CONFIG_FILES.insert(0, os.path.join(os.environ["XDG_CONFIG_HOME"], "mypy/config")) -CONFIG_FILES = (CONFIG_FILE + PYPROJECT_CONFIG_FILES + SHARED_CONFIG_FILES + - USER_CONFIG_FILES) # type: Final +CONFIG_FILES: Final = ( + CONFIG_FILE + PYPROJECT_CONFIG_FILES + SHARED_CONFIG_FILES + USER_CONFIG_FILES +) # This must include all reporters defined in mypy.report. This is defined here # to make reporter names available without importing mypy.report -- this speeds # up startup. -REPORTER_NAMES = ['linecount', - 'any-exprs', - 'linecoverage', - 'memory-xml', - 'cobertura-xml', - 'xml', - 'xslt-html', - 'xslt-txt', - 'html', - 'txt', - 'lineprecision'] # type: Final +REPORTER_NAMES: Final = [ + "linecount", + "any-exprs", + "linecoverage", + "memory-xml", + "cobertura-xml", + "xml", + "xslt-html", + "xslt-txt", + "html", + "txt", + "lineprecision", +] + +# Threshold after which we sometimes filter out most errors to avoid very +# verbose output +MANY_ERRORS_THRESHOLD: Final = 200 diff --git a/mypy/dmypy/client.py b/mypy/dmypy/client.py index 141c18993fcc..3629372d1a85 100644 --- a/mypy/dmypy/client.py +++ b/mypy/dmypy/client.py @@ -469,7 +469,7 @@ def request(status_file: str, command: str, *, timeout: Optional[int] = None, raised OSError. This covers cases such as connection refused or closed prematurely as well as invalid JSON received. """ - response = {} # type: Dict[str, str] + response: Dict[str, str] = {} args = dict(kwds) args['command'] = command # Tell the server whether this request was initiated from a human-facing terminal, diff --git a/mypy/dmypy_os.py b/mypy/dmypy_os.py index 77cf963ad612..3168f7566a27 100644 --- a/mypy/dmypy_os.py +++ b/mypy/dmypy_os.py @@ -10,8 +10,8 @@ PROCESS_QUERY_LIMITED_INFORMATION = ctypes.c_ulong(0x1000) kernel32 = ctypes.windll.kernel32 - OpenProcess = kernel32.OpenProcess # type: Callable[[DWORD, int, int], HANDLE] - GetExitCodeProcess = kernel32.GetExitCodeProcess # type: Callable[[HANDLE, Any], int] + OpenProcess: Callable[[DWORD, int, int], HANDLE] = kernel32.OpenProcess + GetExitCodeProcess: Callable[[HANDLE, Any], int] = kernel32.GetExitCodeProcess else: import os import signal diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index c6a23a47b49e..2f8fc7f119ba 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -35,7 +35,7 @@ from mypy.version import __version__ from mypy.util import FancyFormatter, count_stats -MEM_PROFILE = False # type: Final # If True, dump memory profile after initialization +MEM_PROFILE: Final = False # If True, dump memory profile after initialization if sys.platform == 'win32': from subprocess import STARTUPINFO @@ -127,7 +127,7 @@ def daemonize(options: Options, # Server code. -CONNECTION_NAME = 'dmypy' # type: Final +CONNECTION_NAME: Final = "dmypy" def process_start_options(flags: List[str], allow_sources: bool) -> Options: @@ -172,7 +172,7 @@ def __init__(self, options: Options, # Snapshot the options info before we muck with it, to detect changes self.options_snapshot = options.snapshot() self.timeout = timeout - self.fine_grained_manager = None # type: Optional[FineGrainedBuildManager] + self.fine_grained_manager: Optional[FineGrainedBuildManager] = None if os.path.isfile(status_file): os.unlink(status_file) @@ -216,7 +216,7 @@ def serve(self) -> None: while True: with server: data = receive(server) - resp = {} # type: Dict[str, Any] + resp: Dict[str, Any] = {} if 'command' not in data: resp = {'error': "No command found in request"} else: @@ -275,7 +275,7 @@ def run_command(self, command: str, data: Dict[str, object]) -> Dict[str, object def cmd_status(self, fswatcher_dump_file: Optional[str] = None) -> Dict[str, object]: """Return daemon status.""" - res = {} # type: Dict[str, object] + res: Dict[str, object] = {} res.update(get_meminfo()) if fswatcher_dump_file: data = self.fswatcher.dump_file_data() if hasattr(self, 'fswatcher') else {} @@ -771,7 +771,7 @@ def pretty_messages(self, messages: List[str], n_sources: int, messages = self.formatter.fit_in_terminal(messages, fixed_terminal_width=terminal_width) if self.options.error_summary: - summary = None # type: Optional[str] + summary: Optional[str] = None if messages: n_errors, n_files = count_stats(messages) if n_errors: @@ -868,11 +868,11 @@ def cmd_hang(self) -> Dict[str, object]: # Misc utilities. -MiB = 2**20 # type: Final +MiB: Final = 2 ** 20 def get_meminfo() -> Dict[str, Any]: - res = {} # type: Dict[str, Any] + res: Dict[str, Any] = {} try: import psutil # type: ignore # It's not in typeshed yet except ImportError: diff --git a/mypy/dmypy_util.py b/mypy/dmypy_util.py index f598742d2474..8a527afe5762 100644 --- a/mypy/dmypy_util.py +++ b/mypy/dmypy_util.py @@ -10,7 +10,7 @@ from mypy.ipc import IPCBase -DEFAULT_STATUS_FILE = '.dmypy.json' # type: Final +DEFAULT_STATUS_FILE: Final = ".dmypy.json" def receive(connection: IPCBase) -> Any: diff --git a/mypy/erasetype.py b/mypy/erasetype.py index 70b7c3b6de32..8acebbd783d8 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -4,7 +4,7 @@ Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarId, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType, ProperType, - get_proper_type, TypeAliasType, TypeGuardType + get_proper_type, TypeAliasType, ParamSpecType ) from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -57,6 +57,9 @@ def visit_instance(self, t: Instance) -> ProperType: def visit_type_var(self, t: TypeVarType) -> ProperType: return AnyType(TypeOfAny.special_form) + def visit_param_spec(self, t: ParamSpecType) -> ProperType: + return AnyType(TypeOfAny.special_form) + def visit_callable_type(self, t: CallableType) -> ProperType: # We must preserve the fallback type for overload resolution to work. any_type = AnyType(TypeOfAny.special_form) @@ -90,9 +93,6 @@ def visit_union_type(self, t: UnionType) -> ProperType: from mypy.typeops import make_simplified_union return make_simplified_union(erased_items) - def visit_type_guard_type(self, t: TypeGuardType) -> ProperType: - return TypeGuardType(t.type_guard.accept(self)) - def visit_type_type(self, t: TypeType) -> ProperType: return TypeType.make_normalized(t.item.accept(self), line=t.line) @@ -128,6 +128,11 @@ def visit_type_var(self, t: TypeVarType) -> Type: return self.replacement return t + def visit_param_spec(self, t: ParamSpecType) -> Type: + if self.erase_id(t.id): + return self.replacement + return t + def visit_type_alias_type(self, t: TypeAliasType) -> Type: # Type alias target can't contain bound type variables, so # it is safe to just erase the arguments. diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 01b946c46747..2a07bbb8597b 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -8,9 +8,9 @@ # All created error codes are implicitly stored in this list. -all_error_codes = [] # type: List[ErrorCode] +all_error_codes: List["ErrorCode"] = [] -error_codes = {} # type: Dict[str, ErrorCode] +error_codes: Dict[str, "ErrorCode"] = {} class ErrorCode: @@ -28,103 +28,115 @@ def __str__(self) -> str: return ''.format(self.code) -ATTR_DEFINED = ErrorCode( - 'attr-defined', "Check that attribute exists", 'General') # type: Final -NAME_DEFINED = ErrorCode( - 'name-defined', "Check that name is defined", 'General') # type: Final -CALL_ARG = ErrorCode( - 'call-arg', "Check number, names and kinds of arguments in calls", 'General') # type: Final -ARG_TYPE = ErrorCode( - 'arg-type', "Check argument types in calls", 'General') # type: Final -CALL_OVERLOAD = ErrorCode( - 'call-overload', "Check that an overload variant matches arguments", 'General') # type: Final -VALID_TYPE = ErrorCode( - 'valid-type', "Check that type (annotation) is valid", 'General') # type: Final -VAR_ANNOTATED = ErrorCode( - 'var-annotated', "Require variable annotation if type can't be inferred", - 'General') # type: Final -OVERRIDE = ErrorCode( - 'override', "Check that method override is compatible with base class", - 'General') # type: Final -RETURN = ErrorCode( - 'return', "Check that function always returns a value", 'General') # type: Final -RETURN_VALUE = ErrorCode( - 'return-value', "Check that return value is compatible with signature", - 'General') # type: Final -ASSIGNMENT = ErrorCode( - 'assignment', "Check that assigned value is compatible with target", 'General') # type: Final -TYPE_ARG = ErrorCode( - 'type-arg', "Check that generic type arguments are present", 'General') # type: Final -TYPE_VAR = ErrorCode( - 'type-var', "Check that type variable values are valid", 'General') # type: Final -UNION_ATTR = ErrorCode( - 'union-attr', "Check that attribute exists in each item of a union", 'General') # type: Final -INDEX = ErrorCode( - 'index', "Check indexing operations", 'General') # type: Final -OPERATOR = ErrorCode( - 'operator', "Check that operator is valid for operands", 'General') # type: Final -LIST_ITEM = ErrorCode( - 'list-item', "Check list items in a list expression [item, ...]", 'General') # type: Final -DICT_ITEM = ErrorCode( - 'dict-item', - "Check dict items in a dict expression {key: value, ...}", 'General') # type: Final -TYPEDDICT_ITEM = ErrorCode( - 'typeddict-item', "Check items when constructing TypedDict", 'General') # type: Final -HAS_TYPE = ErrorCode( - 'has-type', "Check that type of reference can be determined", 'General') # type: Final -IMPORT = ErrorCode( - 'import', "Require that imported module can be found or has stubs", 'General') # type: Final -NO_REDEF = ErrorCode( - 'no-redef', "Check that each name is defined once", 'General') # type: Final -FUNC_RETURNS_VALUE = ErrorCode( - 'func-returns-value', "Check that called function returns a value in value context", - 'General') # type: Final -ABSTRACT = ErrorCode( - 'abstract', "Prevent instantiation of classes with abstract attributes", - 'General') # type: Final -VALID_NEWTYPE = ErrorCode( - 'valid-newtype', "Check that argument 2 to NewType is valid", 'General') # type: Final -STRING_FORMATTING = ErrorCode( - 'str-format', "Check that string formatting/interpolation is type-safe", - 'General') # type: Final -STR_BYTES_PY3 = ErrorCode( - 'str-bytes-safe', "Warn about dangerous coercions related to bytes and string types", - 'General') # type: Final -EXIT_RETURN = ErrorCode( - 'exit-return', "Warn about too general return type for '__exit__'", 'General') # type: Final +ATTR_DEFINED: Final = ErrorCode("attr-defined", "Check that attribute exists", "General") +NAME_DEFINED: Final = ErrorCode("name-defined", "Check that name is defined", "General") +CALL_ARG: Final[ErrorCode] = ErrorCode( + "call-arg", "Check number, names and kinds of arguments in calls", "General" +) +ARG_TYPE: Final = ErrorCode("arg-type", "Check argument types in calls", "General") +CALL_OVERLOAD: Final = ErrorCode( + "call-overload", "Check that an overload variant matches arguments", "General" +) +VALID_TYPE: Final = ErrorCode("valid-type", "Check that type (annotation) is valid", "General") +VAR_ANNOTATED: Final = ErrorCode( + "var-annotated", "Require variable annotation if type can't be inferred", "General" +) +OVERRIDE: Final = ErrorCode( + "override", "Check that method override is compatible with base class", "General" +) +RETURN: Final[ErrorCode] = ErrorCode( + "return", "Check that function always returns a value", "General" +) +RETURN_VALUE: Final[ErrorCode] = ErrorCode( + "return-value", "Check that return value is compatible with signature", "General" +) +ASSIGNMENT: Final = ErrorCode( + "assignment", "Check that assigned value is compatible with target", "General" +) +TYPE_ARG: Final = ErrorCode("type-arg", "Check that generic type arguments are present", "General") +TYPE_VAR: Final = ErrorCode("type-var", "Check that type variable values are valid", "General") +UNION_ATTR: Final = ErrorCode( + "union-attr", "Check that attribute exists in each item of a union", "General" +) +INDEX: Final = ErrorCode("index", "Check indexing operations", "General") +OPERATOR: Final = ErrorCode("operator", "Check that operator is valid for operands", "General") +LIST_ITEM: Final = ErrorCode( + "list-item", "Check list items in a list expression [item, ...]", "General" +) +DICT_ITEM: Final = ErrorCode( + "dict-item", "Check dict items in a dict expression {key: value, ...}", "General" +) +TYPEDDICT_ITEM: Final = ErrorCode( + "typeddict-item", "Check items when constructing TypedDict", "General" +) +HAS_TYPE: Final = ErrorCode( + "has-type", "Check that type of reference can be determined", "General" +) +IMPORT: Final = ErrorCode( + "import", "Require that imported module can be found or has stubs", "General" +) +NO_REDEF: Final = ErrorCode("no-redef", "Check that each name is defined once", "General") +FUNC_RETURNS_VALUE: Final = ErrorCode( + "func-returns-value", "Check that called function returns a value in value context", "General" +) +ABSTRACT: Final = ErrorCode( + "abstract", "Prevent instantiation of classes with abstract attributes", "General" +) +VALID_NEWTYPE: Final = ErrorCode( + "valid-newtype", "Check that argument 2 to NewType is valid", "General" +) +STRING_FORMATTING: Final = ErrorCode( + "str-format", "Check that string formatting/interpolation is type-safe", "General" +) +STR_BYTES_PY3: Final = ErrorCode( + "str-bytes-safe", "Warn about dangerous coercions related to bytes and string types", "General" +) +EXIT_RETURN: Final = ErrorCode( + "exit-return", "Warn about too general return type for '__exit__'", "General" +) # These error codes aren't enabled by default. -NO_UNTYPED_DEF = ErrorCode( - 'no-untyped-def', "Check that every function has an annotation", 'General') # type: Final -NO_UNTYPED_CALL = ErrorCode( - 'no-untyped-call', +NO_UNTYPED_DEF: Final[ErrorCode] = ErrorCode( + "no-untyped-def", "Check that every function has an annotation", "General" +) +NO_UNTYPED_CALL: Final = ErrorCode( + "no-untyped-call", "Disallow calling functions without type annotations from annotated functions", - 'General') # type: Final -REDUNDANT_CAST = ErrorCode( - 'redundant-cast', "Check that cast changes type of expression", 'General') # type: Final -COMPARISON_OVERLAP = ErrorCode( - 'comparison-overlap', - "Check that types in comparisons and 'in' expressions overlap", 'General') # type: Final -NO_ANY_UNIMPORTED = ErrorCode( - 'no-any-unimported', 'Reject "Any" types from unfollowed imports', 'General') # type: Final -NO_ANY_RETURN = ErrorCode( - 'no-any-return', 'Reject returning value with "Any" type if return type is not "Any"', - 'General') # type: Final -UNREACHABLE = ErrorCode( - 'unreachable', "Warn about unreachable statements or expressions", 'General') # type: Final -REDUNDANT_EXPR = ErrorCode( - 'redundant-expr', - "Warn about redundant expressions", - 'General', - default_enabled=False) # type: Final -NAME_MATCH = ErrorCode( - 'name-match', "Check that type definition has consistent naming", 'General') # type: Final + "General", +) +REDUNDANT_CAST: Final = ErrorCode( + "redundant-cast", "Check that cast changes type of expression", "General" +) +COMPARISON_OVERLAP: Final = ErrorCode( + "comparison-overlap", "Check that types in comparisons and 'in' expressions overlap", "General" +) +NO_ANY_UNIMPORTED: Final = ErrorCode( + "no-any-unimported", 'Reject "Any" types from unfollowed imports', "General" +) +NO_ANY_RETURN: Final = ErrorCode( + "no-any-return", + 'Reject returning value with "Any" type if return type is not "Any"', + "General", +) +UNREACHABLE: Final = ErrorCode( + "unreachable", "Warn about unreachable statements or expressions", "General" +) +REDUNDANT_EXPR: Final = ErrorCode( + "redundant-expr", "Warn about redundant expressions", "General", default_enabled=False +) +TRUTHY_BOOL: Final[ErrorCode] = ErrorCode( + "truthy-bool", + "Warn about expressions that could always evaluate to true in boolean contexts", + "General", + default_enabled=False, +) +NAME_MATCH: Final = ErrorCode( + "name-match", "Check that type definition has consistent naming", "General" +) # Syntax errors are often blocking. -SYNTAX = ErrorCode( - 'syntax', "Report syntax errors", 'General') # type: Final +SYNTAX: Final = ErrorCode("syntax", "Report syntax errors", "General") # This is a catch-all for remaining uncategorized errors. -MISC = ErrorCode( - 'misc', "Miscellaneous other checks", 'General') # type: Final +MISC: Final = ErrorCode("misc", "Miscellaneous other checks", "General") diff --git a/mypy/errors.py b/mypy/errors.py index b3f99916b244..c711456468ed 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -1,7 +1,7 @@ import os.path import sys import traceback -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from collections import defaultdict from typing import Tuple, List, TypeVar, Set, Dict, Optional, TextIO, Callable @@ -10,12 +10,13 @@ from mypy.scope import Scope from mypy.options import Options from mypy.version import __version__ as mypy_version -from mypy.errorcodes import ErrorCode +from mypy.errorcodes import ErrorCode, IMPORT +from mypy.message_registry import ErrorMessage from mypy import errorcodes as codes from mypy.util import DEFAULT_SOURCE_OFFSET, is_typeshed_file -T = TypeVar('T') -allowed_duplicates = ['@overload', 'Got:', 'Expected:'] # type: Final +T = TypeVar("T") +allowed_duplicates: Final = ["@overload", "Got:", "Expected:"] class ErrorInfo: @@ -23,19 +24,19 @@ class ErrorInfo: # Description of a sequence of imports that refer to the source file # related to this error. Each item is a (path, line number) tuple. - import_ctx = None # type: List[Tuple[str, int]] + import_ctx: List[Tuple[str, int]] # The path to source file that was the source of this error. file = '' # The fully-qualified id of the source module for this error. - module = None # type: Optional[str] + module: Optional[str] = None # The name of the type in which this error is located at. - type = '' # type: Optional[str] # Unqualified, may be None + type: Optional[str] = "" # Unqualified, may be None # The name of the function or member in which this error is located at. - function_or_member = '' # type: Optional[str] # Unqualified, may be None + function_or_member: Optional[str] = "" # Unqualified, may be None # The line number related to this error within file. line = 0 # -1 if unknown @@ -50,7 +51,7 @@ class ErrorInfo: message = '' # The error code. - code = None # type: Optional[ErrorCode] + code: Optional[ErrorCode] = None # If True, we should halt build after the file that generated this error. blocker = False @@ -58,12 +59,19 @@ class ErrorInfo: # Only report this particular messages once per program. only_once = False + # Do not remove duplicate copies of this message (ignored if only_once is True). + allow_dups = False + # Actual origin of the error message as tuple (path, line number, end line number) # If end line number is unknown, use line number. - origin = None # type: Tuple[str, int, int] + origin: Tuple[str, int, int] # Fine-grained incremental target where this was reported - target = None # type: Optional[str] + target: Optional[str] = None + + # If True, don't show this message in output, but still record the error (needed + # by mypy daemon) + hidden = False def __init__(self, import_ctx: List[Tuple[str, int]], @@ -78,6 +86,7 @@ def __init__(self, code: Optional[ErrorCode], blocker: bool, only_once: bool, + allow_dups: bool, origin: Optional[Tuple[str, int, int]] = None, target: Optional[str] = None) -> None: self.import_ctx = import_ctx @@ -92,17 +101,19 @@ def __init__(self, self.code = code self.blocker = blocker self.only_once = only_once + self.allow_dups = allow_dups self.origin = origin or (file, line, line) self.target = target # Type used internally to represent errors: -# (path, line, column, severity, message, code) +# (path, line, column, severity, message, allow_dups, code) ErrorTuple = Tuple[Optional[str], int, int, str, str, + bool, Optional[ErrorCode]] @@ -116,47 +127,51 @@ class Errors: # Map from files to generated error messages. Is an OrderedDict so # that it can be used to order messages based on the order the # files were processed. - error_info_map = None # type: Dict[str, List[ErrorInfo]] + error_info_map: Dict[str, List[ErrorInfo]] # Files that we have reported the errors for - flushed_files = None # type: Set[str] + flushed_files: Set[str] # Current error context: nested import context/stack, as a list of (path, line) pairs. - import_ctx = None # type: List[Tuple[str, int]] + import_ctx: List[Tuple[str, int]] # Path name prefix that is removed from all paths, if set. - ignore_prefix = None # type: Optional[str] + ignore_prefix: Optional[str] = None # Path to current file. - file = '' # type: str + file: str = "" # Ignore some errors on these lines of each file # (path -> line -> error-codes) - ignored_lines = None # type: Dict[str, Dict[int, List[str]]] + ignored_lines: Dict[str, Dict[int, List[str]]] # Lines on which an error was actually ignored. - used_ignored_lines = None # type: Dict[str, Set[int]] + used_ignored_lines: Dict[str, Dict[int, List[str]]] # Files where all errors should be ignored. - ignored_files = None # type: Set[str] + ignored_files: Set[str] # Collection of reported only_once messages. - only_once_messages = None # type: Set[str] + only_once_messages: Set[str] # Set to True to show "In function "foo":" messages. - show_error_context = False # type: bool + show_error_context: bool = False # Set to True to show column numbers in error messages. - show_column_numbers = False # type: bool + show_column_numbers: bool = False # Set to True to show absolute file paths in error messages. - show_absolute_path = False # type: bool + show_absolute_path: bool = False # State for keeping track of the current fine-grained incremental mode target. # (See mypy.server.update for more about targets.) # Current module id. - target_module = None # type: Optional[str] - scope = None # type: Optional[Scope] + target_module: Optional[str] = None + scope: Optional[Scope] = None + + # Have we seen an import-related error so far? If yes, we filter out other messages + # in some cases to avoid reporting huge numbers of errors. + seen_import_error = False def __init__(self, show_error_context: bool = False, @@ -166,7 +181,8 @@ def __init__(self, read_source: Optional[Callable[[str], Optional[List[str]]]] = None, show_absolute_path: bool = False, enabled_error_codes: Optional[Set[ErrorCode]] = None, - disabled_error_codes: Optional[Set[ErrorCode]] = None) -> None: + disabled_error_codes: Optional[Set[ErrorCode]] = None, + many_errors_threshold: int = -1) -> None: self.show_error_context = show_error_context self.show_column_numbers = show_column_numbers self.show_error_codes = show_error_codes @@ -176,6 +192,7 @@ def __init__(self, self.read_source = read_source self.enabled_error_codes = enabled_error_codes or set() self.disabled_error_codes = disabled_error_codes or set() + self.many_errors_threshold = many_errors_threshold self.initialize() def initialize(self) -> None: @@ -184,11 +201,12 @@ def initialize(self) -> None: self.import_ctx = [] self.function_or_member = [None] self.ignored_lines = OrderedDict() - self.used_ignored_lines = defaultdict(set) + self.used_ignored_lines = defaultdict(lambda: defaultdict(list)) self.ignored_files = set() self.only_once_messages = set() self.scope = None self.target_module = None + self.seen_import_error = False def reset(self) -> None: self.initialize() @@ -201,12 +219,14 @@ def copy(self) -> 'Errors': self.read_source, self.show_absolute_path, self.enabled_error_codes, - self.disabled_error_codes) + self.disabled_error_codes, + self.many_errors_threshold) new.file = self.file new.import_ctx = self.import_ctx[:] new.function_or_member = self.function_or_member[:] new.target_module = self.target_module new.scope = self.scope + new.seen_import_error = self.seen_import_error return new def total_errors(self) -> int: @@ -277,6 +297,7 @@ def report(self, severity: str = 'error', file: Optional[str] = None, only_once: bool = False, + allow_dups: bool = False, origin_line: Optional[int] = None, offset: int = 0, end_line: Optional[int] = None) -> None: @@ -291,6 +312,7 @@ def report(self, severity: 'error' or 'note' file: if non-None, override current file as context only_once: if True, only report this exact message once per build + allow_dups: if True, allow duplicate copies of this message (ignored if only_once) origin_line: if non-None, override current context as origin end_line: if non-None, override current context as end """ @@ -320,7 +342,7 @@ def report(self, info = ErrorInfo(self.import_context(), file, self.current_module(), type, function, line, column, severity, message, code, - blocker, only_once, + blocker, only_once, allow_dups, origin=(self.file, origin_line, end_line), target=self.current_target()) self.add_error_info(info) @@ -330,6 +352,8 @@ def _add_error_info(self, file: str, info: ErrorInfo) -> None: if file not in self.error_info_map: self.error_info_map[file] = [] self.error_info_map[file].append(info) + if info.code is IMPORT: + self.seen_import_error = True def add_error_info(self, info: ErrorInfo) -> None: file, line, end_line = info.origin @@ -346,7 +370,8 @@ def add_error_info(self, info: ErrorInfo) -> None: for scope_line in range(line, end_line + 1): if self.is_ignored_error(scope_line, info, self.ignored_lines[file]): # Annotation requests us to ignore all errors on this line. - self.used_ignored_lines[file].add(scope_line) + self.used_ignored_lines[file][scope_line].append( + (info.code or codes.MISC).code) return if file in self.ignored_files: return @@ -354,8 +379,53 @@ def add_error_info(self, info: ErrorInfo) -> None: if info.message in self.only_once_messages: return self.only_once_messages.add(info.message) + if self.seen_import_error and info.code is not IMPORT and self.has_many_errors(): + # Missing stubs can easily cause thousands of errors about + # Any types, especially when upgrading to mypy 0.900, + # which no longer bundles third-party library stubs. Avoid + # showing too many errors to make it easier to see + # import-related errors. + info.hidden = True + self.report_hidden_errors(info) self._add_error_info(file, info) + def has_many_errors(self) -> bool: + if self.many_errors_threshold < 0: + return False + if len(self.error_info_map) >= self.many_errors_threshold: + return True + if sum(len(errors) + for errors in self.error_info_map.values()) >= self.many_errors_threshold: + return True + return False + + def report_hidden_errors(self, info: ErrorInfo) -> None: + message = ( + '(Skipping most remaining errors due to unresolved imports or missing stubs; ' + + 'fix these first)' + ) + if message in self.only_once_messages: + return + self.only_once_messages.add(message) + new_info = ErrorInfo( + import_ctx=info.import_ctx, + file=info.file, + module=info.module, + typ=None, + function_or_member=None, + line=info.line, + column=info.line, + severity='note', + message=message, + code=None, + blocker=False, + only_once=True, + allow_dups=False, + origin=info.origin, + target=info.target, + ) + self._add_error_info(info.origin[0], new_info) + def is_ignored_error(self, line: int, info: ErrorInfo, ignores: Dict[int, List[str]]) -> bool: if info.blocker: # Blocking errors can never be ignored @@ -393,11 +463,26 @@ def clear_errors_in_targets(self, path: str, targets: Set[str]) -> None: def generate_unused_ignore_errors(self, file: str) -> None: ignored_lines = self.ignored_lines[file] if not is_typeshed_file(file) and file not in self.ignored_files: - for line in set(ignored_lines) - self.used_ignored_lines[file]: + ignored_lines = self.ignored_lines[file] + used_ignored_lines = self.used_ignored_lines[file] + for line, ignored_codes in ignored_lines.items(): + used_ignored_codes = used_ignored_lines[line] + unused_ignored_codes = set(ignored_codes) - set(used_ignored_codes) + # `ignore` is used + if len(ignored_codes) == 0 and len(used_ignored_codes) > 0: + continue + # All codes appearing in `ignore[...]` are used + if len(ignored_codes) > 0 and len(unused_ignored_codes) == 0: + continue + # Display detail only when `ignore[...]` specifies more than one error code + unused_codes_message = "" + if len(ignored_codes) > 1 and len(unused_ignored_codes) > 0: + unused_codes_message = f"[{', '.join(sorted(unused_ignored_codes))}]" + message = f'Unused "type: ignore{unused_codes_message}" comment' # Don't use report since add_error_info will ignore the error! info = ErrorInfo(self.import_context(), file, self.current_module(), None, - None, line, -1, 'error', 'unused "type: ignore" comment', - None, False, False) + None, line, -1, 'error', message, + None, False, False, False) self._add_error_info(file, info) def num_messages(self) -> int: @@ -452,10 +537,11 @@ def format_messages(self, error_info: List[ErrorInfo], is True also append a relevant trimmed source code line (only for severity 'error'). """ - a = [] # type: List[str] + a: List[str] = [] + error_info = [info for info in error_info if not info.hidden] errors = self.render_messages(self.sort_messages(error_info)) errors = self.remove_duplicates(errors) - for file, line, column, severity, message, code in errors: + for file, line, column, severity, message, allow_dups, code in errors: s = '' if file is not None: if self.show_column_numbers and line >= 0 and column >= 0: @@ -530,15 +616,15 @@ def render_messages(self, errors: List[ErrorInfo]) -> List[ErrorTuple]: """Translate the messages into a sequence of tuples. - Each tuple is of form (path, line, col, severity, message, code). + Each tuple is of form (path, line, col, severity, message, allow_dups, code). The rendered sequence includes information about error contexts. The path item may be None. If the line item is negative, the line number is not defined for the tuple. """ - result = [] # type: List[ErrorTuple] - prev_import_context = [] # type: List[Tuple[str, int]] - prev_function_or_member = None # type: Optional[str] - prev_type = None # type: Optional[str] + result: List[ErrorTuple] = [] + prev_import_context: List[Tuple[str, int]] = [] + prev_function_or_member: Optional[str] = None + prev_type: Optional[str] = None for e in errors: # Report module import context, if different from previous message. @@ -559,7 +645,8 @@ def render_messages(self, # Remove prefix to ignore from path (if present) to # simplify path. path = remove_path_prefix(path, self.ignore_prefix) - result.append((None, -1, -1, 'note', fmt.format(path, line), None)) + result.append((None, -1, -1, 'note', + fmt.format(path, line), e.allow_dups, None)) i -= 1 file = self.simplify_path(e.file) @@ -571,27 +658,32 @@ def render_messages(self, e.type != prev_type): if e.function_or_member is None: if e.type is None: - result.append((file, -1, -1, 'note', 'At top level:', None)) + result.append((file, -1, -1, 'note', 'At top level:', e.allow_dups, None)) else: result.append((file, -1, -1, 'note', 'In class "{}":'.format( - e.type), None)) + e.type), e.allow_dups, None)) else: if e.type is None: result.append((file, -1, -1, 'note', 'In function "{}":'.format( - e.function_or_member), None)) + e.function_or_member), e.allow_dups, None)) else: result.append((file, -1, -1, 'note', 'In member "{}" of class "{}":'.format( - e.function_or_member, e.type), None)) + e.function_or_member, e.type), e.allow_dups, None)) elif e.type != prev_type: if e.type is None: - result.append((file, -1, -1, 'note', 'At top level:', None)) + result.append((file, -1, -1, 'note', 'At top level:', e.allow_dups, None)) else: result.append((file, -1, -1, 'note', - 'In class "{}":'.format(e.type), None)) + 'In class "{}":'.format(e.type), e.allow_dups, None)) - result.append((file, e.line, e.column, e.severity, e.message, e.code)) + if isinstance(e.message, ErrorMessage): + result.append( + (file, e.line, e.column, e.severity, e.message.value, e.allow_dups, e.code)) + else: + result.append( + (file, e.line, e.column, e.severity, e.message, e.allow_dups, e.code)) prev_import_context = e.import_ctx prev_function_or_member = e.function_or_member @@ -606,7 +698,7 @@ def sort_messages(self, errors: List[ErrorInfo]) -> List[ErrorInfo]: context by line number, but otherwise retain the general ordering of the messages. """ - result = [] # type: List[ErrorInfo] + result: List[ErrorInfo] = [] i = 0 while i < len(errors): i0 = i @@ -624,30 +716,32 @@ def sort_messages(self, errors: List[ErrorInfo]) -> List[ErrorInfo]: def remove_duplicates(self, errors: List[ErrorTuple]) -> List[ErrorTuple]: """Remove duplicates from a sorted error list.""" - res = [] # type: List[ErrorTuple] + res: List[ErrorTuple] = [] i = 0 while i < len(errors): dup = False # Use slightly special formatting for member conflicts reporting. conflicts_notes = False j = i - 1 - while j >= 0 and errors[j][0] == errors[i][0]: - if errors[j][4].strip() == 'Got:': - conflicts_notes = True - j -= 1 - j = i - 1 - while (j >= 0 and errors[j][0] == errors[i][0] and - errors[j][1] == errors[i][1]): - if (errors[j][3] == errors[i][3] and - # Allow duplicate notes in overload conflicts reporting. - not ((errors[i][3] == 'note' and - errors[i][4].strip() in allowed_duplicates) - or (errors[i][4].strip().startswith('def ') and - conflicts_notes)) and - errors[j][4] == errors[i][4]): # ignore column - dup = True - break - j -= 1 + # Find duplicates, unless duplicates are allowed. + if not errors[i][5]: + while j >= 0 and errors[j][0] == errors[i][0]: + if errors[j][4].strip() == 'Got:': + conflicts_notes = True + j -= 1 + j = i - 1 + while (j >= 0 and errors[j][0] == errors[i][0] and + errors[j][1] == errors[i][1]): + if (errors[j][3] == errors[i][3] and + # Allow duplicate notes in overload conflicts reporting. + not ((errors[i][3] == 'note' and + errors[i][4].strip() in allowed_duplicates) + or (errors[i][4].strip().startswith('def ') and + conflicts_notes)) and + errors[j][4] == errors[i][4]): # ignore column + dup = True + break + j -= 1 if not dup: res.append(errors[i]) i += 1 @@ -667,10 +761,10 @@ class CompileError(Exception): """ - messages = None # type: List[str] + messages: List[str] use_stdout = False # Can be set in case there was a module with a blocking error - module_with_blocker = None # type: Optional[str] + module_with_blocker: Optional[str] = None def __init__(self, messages: List[str], diff --git a/mypy/expandtype.py b/mypy/expandtype.py index c9a1a2430afb..ca1bac71cc52 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -1,11 +1,12 @@ from typing import Dict, Iterable, List, TypeVar, Mapping, cast from mypy.types import ( - Type, Instance, CallableType, TypeGuardType, TypeVisitor, UnboundType, AnyType, - NoneType, TypeVarType, Overloaded, TupleType, TypedDictType, UnionType, + Type, Instance, CallableType, TypeVisitor, UnboundType, AnyType, + NoneType, Overloaded, TupleType, TypedDictType, UnionType, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, - FunctionLike, TypeVarDef, LiteralType, get_proper_type, ProperType, - TypeAliasType) + FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType, + TypeAliasType, ParamSpecType, TypeVarLikeType +) def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type: @@ -23,7 +24,7 @@ def expand_type_by_instance(typ: Type, instance: Instance) -> Type: if not instance.args: return typ else: - variables = {} # type: Dict[TypeVarId, Type] + variables: Dict[TypeVarId, Type] = {} for binder, arg in zip(instance.type.defn.type_vars, instance.args): variables[binder.id] = arg return expand_type(typ, variables) @@ -37,27 +38,30 @@ def freshen_function_type_vars(callee: F) -> F: if isinstance(callee, CallableType): if not callee.is_generic(): return cast(F, callee) - tvdefs = [] - tvmap = {} # type: Dict[TypeVarId, Type] + tvs = [] + tvmap: Dict[TypeVarId, Type] = {} for v in callee.variables: - # TODO(shantanu): fix for ParamSpecDef - assert isinstance(v, TypeVarDef) - tvdef = TypeVarDef.new_unification_variable(v) - tvdefs.append(tvdef) - tvmap[v.id] = TypeVarType(tvdef) - fresh = cast(CallableType, expand_type(callee, tvmap)).copy_modified(variables=tvdefs) + # TODO(PEP612): fix for ParamSpecType + if isinstance(v, TypeVarType): + tv: TypeVarLikeType = TypeVarType.new_unification_variable(v) + else: + assert isinstance(v, ParamSpecType) + tv = ParamSpecType.new_unification_variable(v) + tvs.append(tv) + tvmap[v.id] = tv + fresh = cast(CallableType, expand_type(callee, tvmap)).copy_modified(variables=tvs) return cast(F, fresh) else: assert isinstance(callee, Overloaded) fresh_overload = Overloaded([freshen_function_type_vars(item) - for item in callee.items()]) + for item in callee.items]) return cast(F, fresh_overload) class ExpandTypeVisitor(TypeVisitor[Type]): """Visitor that substitutes type variables with values.""" - variables = None # type: Mapping[TypeVarId, Type] # TypeVar id -> TypeVar value + variables: Mapping[TypeVarId, Type] # TypeVar id -> TypeVar value def __init__(self, variables: Mapping[TypeVarId, Type]) -> None: self.variables = variables @@ -95,15 +99,45 @@ def visit_type_var(self, t: TypeVarType) -> Type: else: return repl + def visit_param_spec(self, t: ParamSpecType) -> Type: + repl = get_proper_type(self.variables.get(t.id, t)) + if isinstance(repl, Instance): + inst = repl + # Return copy of instance with type erasure flag on. + return Instance(inst.type, inst.args, line=inst.line, + column=inst.column, erased=True) + elif isinstance(repl, ParamSpecType): + return repl.with_flavor(t.flavor) + else: + return repl + def visit_callable_type(self, t: CallableType) -> Type: + param_spec = t.param_spec() + if param_spec is not None: + repl = get_proper_type(self.variables.get(param_spec.id)) + # If a ParamSpec in a callable type is substituted with a + # callable type, we can't use normal substitution logic, + # since ParamSpec is actually split into two components + # *P.args and **P.kwargs in the original type. Instead, we + # must expand both of them with all the argument types, + # kinds and names in the replacement. The return type in + # the replacement is ignored. + if isinstance(repl, CallableType): + # Substitute *args: P.args, **kwargs: P.kwargs + t = t.expand_param_spec(repl) + # TODO: Substitute remaining arg types + return t.copy_modified(ret_type=t.ret_type.accept(self), + type_guard=(t.type_guard.accept(self) + if t.type_guard is not None else None)) + return t.copy_modified(arg_types=self.expand_types(t.arg_types), ret_type=t.ret_type.accept(self), type_guard=(t.type_guard.accept(self) if t.type_guard is not None else None)) def visit_overloaded(self, t: Overloaded) -> Type: - items = [] # type: List[CallableType] - for item in t.items(): + items: List[CallableType] = [] + for item in t.items: new_item = item.accept(self) assert isinstance(new_item, ProperType) assert isinstance(new_item, CallableType) @@ -126,9 +160,6 @@ def visit_union_type(self, t: UnionType) -> Type: from mypy.typeops import make_simplified_union # asdf return make_simplified_union(self.expand_types(t.items), t.line, t.column) - def visit_type_guard_type(self, t: TypeGuardType) -> ProperType: - return TypeGuardType(t.type_guard.accept(self)) - def visit_partial_type(self, t: PartialType) -> Type: return t @@ -145,7 +176,7 @@ def visit_type_alias_type(self, t: TypeAliasType) -> Type: return t.copy_modified(args=self.expand_types(t.args)) def expand_types(self, types: Iterable[Type]) -> List[Type]: - a = [] # type: List[Type] + a: List[Type] = [] for t in types: a.append(t.accept(self)) return a diff --git a/mypy/exprtotype.py b/mypy/exprtotype.py index 578080477e0c..8f6f6c11f346 100644 --- a/mypy/exprtotype.py +++ b/mypy/exprtotype.py @@ -4,14 +4,15 @@ from mypy.nodes import ( Expression, NameExpr, MemberExpr, IndexExpr, RefExpr, TupleExpr, IntExpr, FloatExpr, UnaryExpr, - ComplexExpr, ListExpr, StrExpr, BytesExpr, UnicodeExpr, EllipsisExpr, CallExpr, + ComplexExpr, ListExpr, StrExpr, BytesExpr, UnicodeExpr, EllipsisExpr, CallExpr, OpExpr, get_member_expr_fullname ) from mypy.fastparse import parse_type_string from mypy.types import ( Type, UnboundType, TypeList, EllipsisType, AnyType, CallableArgument, TypeOfAny, - RawExpressionType, ProperType + RawExpressionType, ProperType, UnionType ) +from mypy.options import Options class TypeTranslationError(Exception): @@ -29,15 +30,21 @@ def _extract_argument_name(expr: Expression) -> Optional[str]: raise TypeTranslationError() -def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = None) -> ProperType: +def expr_to_unanalyzed_type(expr: Expression, + options: Optional[Options] = None, + allow_new_syntax: bool = False, + _parent: Optional[Expression] = None) -> ProperType: """Translate an expression to the corresponding type. The result is not semantically analyzed. It can be UnboundType or TypeList. Raise TypeTranslationError if the expression cannot represent a type. + + If allow_new_syntax is True, allow all type syntax independent of the target + Python version (used in stubs). """ # The `parent` parameter is used in recursive calls to provide context for # understanding whether an CallableArgument is ok. - name = None # type: Optional[str] + name: Optional[str] = None if isinstance(expr, NameExpr): name = expr.name if name == 'True': @@ -53,7 +60,7 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No else: raise TypeTranslationError() elif isinstance(expr, IndexExpr): - base = expr_to_unanalyzed_type(expr.base, expr) + base = expr_to_unanalyzed_type(expr.base, options, allow_new_syntax, expr) if isinstance(base, UnboundType): if base.args: raise TypeTranslationError() @@ -69,14 +76,20 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No # of the Annotation definition and only returning the type information, # losing all the annotations. - return expr_to_unanalyzed_type(args[0], expr) + return expr_to_unanalyzed_type(args[0], options, allow_new_syntax, expr) else: - base.args = tuple(expr_to_unanalyzed_type(arg, expr) for arg in args) + base.args = tuple(expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr) + for arg in args) if not base.args: base.empty_tuple_index = True return base else: raise TypeTranslationError() + elif (isinstance(expr, OpExpr) + and expr.op == '|' + and ((options and options.python_version >= (3, 10)) or allow_new_syntax)): + return UnionType([expr_to_unanalyzed_type(expr.left, options, allow_new_syntax), + expr_to_unanalyzed_type(expr.right, options, allow_new_syntax)]) elif isinstance(expr, CallExpr) and isinstance(_parent, ListExpr): c = expr.callee names = [] @@ -96,7 +109,7 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No # Go through the constructor args to get its name and type. name = None default_type = AnyType(TypeOfAny.unannotated) - typ = default_type # type: Type + typ: Type = default_type for i, arg in enumerate(expr.args): if expr.arg_names[i] is not None: if expr.arg_names[i] == "name": @@ -109,19 +122,20 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No if typ is not default_type: # Two types raise TypeTranslationError() - typ = expr_to_unanalyzed_type(arg, expr) + typ = expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr) continue else: raise TypeTranslationError() elif i == 0: - typ = expr_to_unanalyzed_type(arg, expr) + typ = expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr) elif i == 1: name = _extract_argument_name(arg) else: raise TypeTranslationError() return CallableArgument(typ, name, arg_const, expr.line, expr.column) elif isinstance(expr, ListExpr): - return TypeList([expr_to_unanalyzed_type(t, expr) for t in expr.items], + return TypeList([expr_to_unanalyzed_type(t, options, allow_new_syntax, expr) + for t in expr.items], line=expr.line, column=expr.column) elif isinstance(expr, StrExpr): return parse_type_string(expr.value, 'builtins.str', expr.line, expr.column, @@ -133,7 +147,7 @@ def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = No return parse_type_string(expr.value, 'builtins.unicode', expr.line, expr.column, assume_str_is_unicode=True) elif isinstance(expr, UnaryExpr): - typ = expr_to_unanalyzed_type(expr.expr) + typ = expr_to_unanalyzed_type(expr.expr, options, allow_new_syntax) if isinstance(typ, RawExpressionType): if isinstance(typ.literal_value, int) and expr.op == '-': typ.literal_value *= -1 diff --git a/mypy/fastparse.py b/mypy/fastparse.py index b250095c74a8..34fe2c0da32d 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1,10 +1,12 @@ +from mypy.util import unnamed_function +import copy import re import sys import warnings import typing # for typing.Type, which conflicts with types.Type from typing import ( - Tuple, Union, TypeVar, Callable, Sequence, Optional, Any, Dict, cast, List, overload + Tuple, Union, TypeVar, Callable, Sequence, Optional, Any, Dict, cast, List ) from typing_extensions import Final, Literal, overload @@ -25,7 +27,7 @@ StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, AwaitExpr, TempNode, Expression, Statement, - ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR2, + ArgKind, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR2, check_arg_names, FakeInfo, ) @@ -42,7 +44,7 @@ try: # pull this into a final variable to make mypyc be quiet about the # the default argument warning - PY_MINOR_VERSION = sys.version_info[1] # type: Final + PY_MINOR_VERSION: Final = sys.version_info[1] # Check if we can use the stdlib ast module instead of typed_ast. if sys.version_info >= (3, 8): @@ -122,14 +124,14 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, # There is no way to create reasonable fallbacks at this stage, # they must be patched later. -MISSING_FALLBACK = FakeInfo("fallback can't be filled out until semanal") # type: Final -_dummy_fallback = Instance(MISSING_FALLBACK, [], -1) # type: Final +MISSING_FALLBACK: Final = FakeInfo("fallback can't be filled out until semanal") +_dummy_fallback: Final = Instance(MISSING_FALLBACK, [], -1) -TYPE_COMMENT_SYNTAX_ERROR = 'syntax error in type comment' # type: Final +TYPE_COMMENT_SYNTAX_ERROR: Final = "syntax error in type comment" -INVALID_TYPE_IGNORE = 'Invalid "type: ignore" comment' # type: Final +INVALID_TYPE_IGNORE: Final = 'Invalid "type: ignore" comment' -TYPE_IGNORE_PATTERN = re.compile(r'[^#]*#\s*type:\s*ignore\s*(.*)') +TYPE_IGNORE_PATTERN: Final = re.compile(r'[^#]*#\s*type:\s*ignore\s*(.*)') def parse(source: Union[str, bytes], @@ -228,8 +230,8 @@ def parse_type_comment(type_comment: str, extra_ignore = TYPE_IGNORE_PATTERN.match(type_comment) if extra_ignore: # Typeshed has a non-optional return type for group! - tag = cast(Any, extra_ignore).group(1) # type: Optional[str] - ignored = parse_type_ignore_tag(tag) # type: Optional[List[str]] + tag: Optional[str] = cast(Any, extra_ignore).group(1) + ignored: Optional[List[str]] = parse_type_ignore_tag(tag) if ignored is None: if errors is not None: errors.report(line, column, INVALID_TYPE_IGNORE, code=codes.SYNTAX) @@ -294,17 +296,17 @@ def __init__(self, is_stub: bool, errors: Errors) -> None: # 'C' for class, 'F' for function - self.class_and_function_stack = [] # type: List[Literal['C', 'F']] - self.imports = [] # type: List[ImportBase] + self.class_and_function_stack: List[Literal["C", "F"]] = [] + self.imports: List[ImportBase] = [] self.options = options self.is_stub = is_stub self.errors = errors - self.type_ignores = {} # type: Dict[int, List[str]] + self.type_ignores: Dict[int, List[str]] = {} # Cache of visit_X methods keyed by type of visited object - self.visitor_cache = {} # type: Dict[type, Callable[[Optional[AST]], Any]] + self.visitor_cache: Dict[type, Callable[[Optional[AST]], Any]] = {} def note(self, msg: str, line: int, column: int) -> None: self.errors.report(line, column, msg, severity='note', code=codes.SYNTAX) @@ -335,7 +337,7 @@ def set_line(self, node: N, n: Union[ast3.expr, ast3.stmt, ast3.ExceptHandler]) return node def translate_opt_expr_list(self, l: Sequence[Optional[AST]]) -> List[Optional[Expression]]: - res = [] # type: List[Optional[Expression]] + res: List[Optional[Expression]] = [] for e in l: exp = self.visit(e) res.append(exp) @@ -357,12 +359,13 @@ def translate_stmt_list(self, # ignores the whole module: if (ismodule and stmts and self.type_ignores and min(self.type_ignores) < self.get_lineno(stmts[0])): - self.errors.used_ignored_lines[self.errors.file].add(min(self.type_ignores)) + self.errors.used_ignored_lines[self.errors.file][min(self.type_ignores)].append( + codes.MISC.code) block = Block(self.fix_function_overloads(self.translate_stmt_list(stmts))) mark_block_unreachable(block) return [block] - res = [] # type: List[Statement] + res: List[Statement] = [] for stmt in stmts: node = self.visit(stmt) res.append(node) @@ -384,7 +387,7 @@ def translate_type_comment(self, self.type_ignores[lineno] = extra_ignore return typ - op_map = { + op_map: Final[Dict[typing.Type[AST], str]] = { ast3.Add: '+', ast3.Sub: '-', ast3.Mult: '*', @@ -398,7 +401,7 @@ def translate_type_comment(self, ast3.BitXor: '^', ast3.BitAnd: '&', ast3.FloorDiv: '//' - } # type: Final[Dict[typing.Type[AST], str]] + } def from_operator(self, op: ast3.operator) -> str: op_name = ASTConverter.op_map.get(type(op)) @@ -407,7 +410,7 @@ def from_operator(self, op: ast3.operator) -> str: else: return op_name - comp_op_map = { + comp_op_map: Final[Dict[typing.Type[AST], str]] = { ast3.Gt: '>', ast3.Lt: '<', ast3.Eq: '==', @@ -418,7 +421,7 @@ def from_operator(self, op: ast3.operator) -> str: ast3.IsNot: 'is not', ast3.In: 'in', ast3.NotIn: 'not in' - } # type: Final[Dict[typing.Type[AST], str]] + } def from_comp_operator(self, op: ast3.cmpop) -> str: op_name = ASTConverter.comp_op_map.get(type(op)) @@ -441,9 +444,9 @@ def as_required_block(self, stmts: List[ast3.stmt], lineno: int) -> Block: return b def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: - ret = [] # type: List[Statement] - current_overload = [] # type: List[OverloadPart] - current_overload_name = None # type: Optional[str] + ret: List[Statement] = [] + current_overload: List[OverloadPart] = [] + current_overload_name: Optional[str] = None for stmt in stmts: if (current_overload_name is not None and isinstance(stmt, (Decorator, FuncDef)) @@ -455,7 +458,12 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: elif len(current_overload) > 1: ret.append(OverloadedFuncDef(current_overload)) - if isinstance(stmt, Decorator): + # If we have multiple decorated functions named "_" next to each, we want to treat + # them as a series of regular FuncDefs instead of one OverloadedFuncDef because + # most of mypy/mypyc assumes that all the functions in an OverloadedFuncDef are + # related, but multiple underscore functions next to each other aren't necessarily + # related + if isinstance(stmt, Decorator) and not unnamed_function(stmt.name): current_overload = [stmt] current_overload_name = stmt.name else: @@ -522,15 +530,14 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], lineno = n.lineno args = self.transform_args(n.args, lineno, no_type_check=no_type_check) + if special_function_elide_names(n.name): + for arg in args: + arg.pos_only = True - posonlyargs = [arg.arg for arg in getattr(n.args, "posonlyargs", [])] arg_kinds = [arg.kind for arg in args] - arg_names = [arg.variable.name for arg in args] # type: List[Optional[str]] - arg_names = [None if argument_elide_name(name) or name in posonlyargs else name - for name in arg_names] - if special_function_elide_names(n.name): - arg_names = [None] * len(arg_names) - arg_types = [] # type: List[Optional[Type]] + arg_names = [None if arg.pos_only else arg.variable.name for arg in args] + + arg_types: List[Optional[Type]] = [] if no_type_check: arg_types = [None] * len(args) return_type = None @@ -602,10 +609,11 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], AnyType(TypeOfAny.unannotated), _dummy_fallback) - func_def = FuncDef(n.name, - args, - self.as_required_block(n.body, lineno), - func_type) + func_def = FuncDef( + n.name, + args, + self.as_required_block(n.body, lineno), + func_type) if isinstance(func_def.type, CallableType): # semanal.py does some in-place modifications we want to avoid func_def.unanalyzed_type = func_def.type.copy_modified() @@ -620,7 +628,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], # Before 3.8, [typed_]ast the line number points to the first decorator. # In 3.8, it points to the 'def' line, where we want it. lineno += len(n.decorator_list) - end_lineno = None # type: Optional[int] + end_lineno: Optional[int] = None else: # Set end_lineno to the old pre-3.8 lineno, in order to keep # existing "# type: ignore" comments working: @@ -637,7 +645,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], deco = Decorator(func_def, self.translate_expr_list(n.decorator_list), var) first = n.decorator_list[0] deco.set_line(first.lineno, first.col_offset) - retval = deco # type: Union[FuncDef, Decorator] + retval: Union[FuncDef, Decorator] = deco else: # FuncDef overrides set_line -- can't use self.set_line func_def.set_line(lineno, n.col_offset) @@ -659,18 +667,21 @@ def transform_args(self, no_type_check: bool = False, ) -> List[Argument]: new_args = [] - names = [] # type: List[ast3.arg] - args_args = getattr(args, "posonlyargs", []) + args.args + names: List[ast3.arg] = [] + posonlyargs = getattr(args, "posonlyargs", cast(List[ast3.arg], [])) + args_args = posonlyargs + args.args args_defaults = args.defaults num_no_defaults = len(args_args) - len(args_defaults) # positional arguments without defaults - for a in args_args[:num_no_defaults]: - new_args.append(self.make_argument(a, None, ARG_POS, no_type_check)) + for i, a in enumerate(args_args[:num_no_defaults]): + pos_only = i < len(posonlyargs) + new_args.append(self.make_argument(a, None, ARG_POS, no_type_check, pos_only)) names.append(a) # positional arguments with defaults - for a, d in zip(args_args[num_no_defaults:], args_defaults): - new_args.append(self.make_argument(a, d, ARG_OPT, no_type_check)) + for i, (a, d) in enumerate(zip(args_args[num_no_defaults:], args_defaults)): + pos_only = num_no_defaults + i < len(posonlyargs) + new_args.append(self.make_argument(a, d, ARG_OPT, no_type_check, pos_only)) names.append(a) # *arg @@ -696,8 +707,8 @@ def transform_args(self, return new_args - def make_argument(self, arg: ast3.arg, default: Optional[ast3.expr], kind: int, - no_type_check: bool) -> Argument: + def make_argument(self, arg: ast3.arg, default: Optional[ast3.expr], kind: ArgKind, + no_type_check: bool, pos_only: bool = False) -> Argument: if no_type_check: arg_type = None else: @@ -710,7 +721,10 @@ def make_argument(self, arg: ast3.arg, default: Optional[ast3.expr], kind: int, arg_type = TypeConverter(self.errors, line=arg.lineno).visit(annotation) else: arg_type = self.translate_type_comment(arg, type_comment) - return Argument(Var(arg.arg), arg_type, self.visit(default), kind) + if argument_elide_name(arg.arg): + pos_only = True + + return Argument(Var(arg.arg), arg_type, self.visit(default), kind, pos_only) def fail_arg(self, msg: str, arg: ast3.arg) -> None: self.fail(msg, arg.lineno, arg.col_offset) @@ -771,7 +785,7 @@ def visit_Assign(self, n: ast3.Assign) -> AssignmentStmt: def visit_AnnAssign(self, n: ast3.AnnAssign) -> AssignmentStmt: line = n.lineno if n.value is None: # always allow 'x: int' - rvalue = TempNode(AnyType(TypeOfAny.special_form), no_rhs=True) # type: Expression + rvalue: Expression = TempNode(AnyType(TypeOfAny.special_form), no_rhs=True) rvalue.line = line rvalue.column = n.col_offset else: @@ -872,7 +886,7 @@ def visit_Assert(self, n: ast3.Assert) -> AssertStmt: # Import(alias* names) def visit_Import(self, n: ast3.Import) -> Import: - names = [] # type: List[Tuple[str, Optional[str]]] + names: List[Tuple[str, Optional[str]]] = [] for alias in n.names: name = self.translate_module_id(alias.name) asname = alias.asname @@ -891,7 +905,7 @@ def visit_ImportFrom(self, n: ast3.ImportFrom) -> ImportBase: assert n.level is not None if len(n.names) == 1 and n.names[0].name == '*': mod = n.module if n.module is not None else '' - i = ImportAll(mod, n.level) # type: ImportBase + i: ImportBase = ImportAll(mod, n.level) else: i = ImportFrom(self.translate_module_id(n.module) if n.module is not None else '', n.level, @@ -1095,7 +1109,7 @@ def visit_Call(self, n: Call) -> CallExpr: # Constant(object value) -- a constant, in Python 3.8. def visit_Constant(self, n: Constant) -> Any: val = n.value - e = None # type: Any + e: Any = None if val is None: e = NameExpr('None') elif isinstance(val, str): @@ -1122,9 +1136,9 @@ def visit_Num(self, n: ast3.Num) -> Union[IntExpr, FloatExpr, ComplexExpr]: # a parent of int and float, and this causes isinstance below # to think that the complex branch is always picked. Avoid # this by throwing away the type. - val = n.n # type: object + val: object = n.n if isinstance(val, int): - e = IntExpr(val) # type: Union[IntExpr, FloatExpr, ComplexExpr] + e: Union[IntExpr, FloatExpr, ComplexExpr] = IntExpr(val) elif isinstance(val, float): e = FloatExpr(val) elif isinstance(val, complex): @@ -1206,7 +1220,7 @@ def visit_Attribute(self, n: Attribute) -> Union[MemberExpr, SuperExpr]: if (isinstance(obj, CallExpr) and isinstance(obj.callee, NameExpr) and obj.callee.name == 'super'): - e = SuperExpr(member_expr.name, obj) # type: Union[MemberExpr, SuperExpr] + e: Union[MemberExpr, SuperExpr] = SuperExpr(member_expr.name, obj) else: e = member_expr return self.set_line(e, n) @@ -1241,10 +1255,10 @@ def visit_Name(self, n: Name) -> NameExpr: # List(expr* elts, expr_context ctx) def visit_List(self, n: ast3.List) -> Union[ListExpr, TupleExpr]: - expr_list = [self.visit(e) for e in n.elts] # type: List[Expression] + expr_list: List[Expression] = [self.visit(e) for e in n.elts] if isinstance(n.ctx, ast3.Store): # [x, y] = z and (x, y) = z means exactly the same thing - e = TupleExpr(expr_list) # type: Union[ListExpr, TupleExpr] + e: Union[ListExpr, TupleExpr] = TupleExpr(expr_list) else: e = ListExpr(expr_list) return self.set_line(e, n) @@ -1272,6 +1286,12 @@ def visit_Index(self, n: Index) -> Node: # cast for mypyc's benefit on Python 3.9 return self.visit(cast(Any, n).value) + def visit_Match(self, n: Any) -> Node: + self.fail("Match statement is not supported", + line=n.lineno, column=n.col_offset, blocker=True) + # Just return some valid node + return PassStmt() + class TypeConverter: def __init__(self, @@ -1284,7 +1304,7 @@ def __init__(self, self.errors = errors self.line = line self.override_column = override_column - self.node_stack = [] # type: List[AST] + self.node_stack: List[AST] = [] self.assume_str_is_unicode = assume_str_is_unicode self.is_evaluated = is_evaluated @@ -1357,7 +1377,7 @@ def translate_expr_list(self, l: Sequence[ast3.expr]) -> List[Type]: def visit_raw_str(self, s: str) -> Type: # An escape hatch that allows the AST walker in fastparse2 to - # directly hook into the Python 3.5 type converter in some cases + # directly hook into the Python 3 type converter in some cases # without needing to create an intermediary `Str` object. _, typ = parse_type_comment(s.strip(), self.line, @@ -1379,9 +1399,9 @@ def visit_Call(self, e: Call) -> Type: if not constructor: self.fail("Expected arg constructor name", e.lineno, e.col_offset) - name = None # type: Optional[str] + name: Optional[str] = None default_type = AnyType(TypeOfAny.special_form) - typ = default_type # type: Type + typ: Type = default_type for i, arg in enumerate(e.args): if i == 0: converted = self.visit(arg) @@ -1490,7 +1510,7 @@ def numeric_type(self, value: object, n: AST) -> Type: # to think that the complex branch is always picked. Avoid # this by throwing away the type. if isinstance(value, int): - numeric_value = value # type: Optional[int] + numeric_value: Optional[int] = value type_name = 'builtins.int' else: # Other kinds of numbers (floats, complex) are not valid parameters for @@ -1525,7 +1545,7 @@ def visit_Str(self, n: Str) -> Type: # this method doesn't actually ever run.) We can't just do # an attribute access with a `# type: ignore` because it would be # unused on < 3.8. - kind = getattr(n, 'kind') # type: str # noqa + kind: str = getattr(n, "kind") # noqa if 'u' in kind or self.assume_str_is_unicode: return parse_type_string(n.s, 'builtins.unicode', self.line, n.col_offset, @@ -1539,22 +1559,38 @@ def visit_Bytes(self, n: Bytes) -> Type: contents = bytes_to_human_readable_repr(n.s) return RawExpressionType(contents, 'builtins.bytes', self.line, column=n.col_offset) + def visit_Index(self, n: ast3.Index) -> Type: + # cast for mypyc's benefit on Python 3.9 + return self.visit(cast(Any, n).value) + + def visit_Slice(self, n: ast3.Slice) -> Type: + return self.invalid_type( + n, note="did you mean to use ',' instead of ':' ?" + ) + # Subscript(expr value, slice slice, expr_context ctx) # Python 3.8 and before # Subscript(expr value, expr slice, expr_context ctx) # Python 3.9 and later def visit_Subscript(self, n: ast3.Subscript) -> Type: if sys.version_info >= (3, 9): # Really 3.9a5 or later - sliceval = n.slice # type: Any - if (isinstance(sliceval, ast3.Slice) or - (isinstance(sliceval, ast3.Tuple) and - any(isinstance(x, ast3.Slice) for x in sliceval.elts))): - self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) - return AnyType(TypeOfAny.from_error) + sliceval: Any = n.slice + # Python 3.8 or earlier use a different AST structure for subscripts + elif isinstance(n.slice, ast3.Index): + sliceval: Any = n.slice.value + elif isinstance(n.slice, ast3.Slice): + sliceval = copy.deepcopy(n.slice) # so we don't mutate passed AST + if getattr(sliceval, "col_offset", None) is None: + # Fix column information so that we get Python 3.9+ message order + sliceval.col_offset = sliceval.lower.col_offset else: - # Python 3.8 or earlier use a different AST structure for subscripts - if not isinstance(n.slice, Index): - self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1)) - return AnyType(TypeOfAny.from_error) - sliceval = n.slice.value + assert isinstance(n.slice, ast3.ExtSlice) + dims = copy.deepcopy(n.slice.dims) + for s in dims: + if getattr(s, "col_offset", None) is None: + if isinstance(s, ast3.Index): + s.col_offset = s.value.col_offset # type: ignore + elif isinstance(s, ast3.Slice): + s.col_offset = s.lower.col_offset # type: ignore + sliceval = ast3.Tuple(dims, n.ctx) empty_tuple_index = False if isinstance(sliceval, ast3.Tuple): diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 3473253a8aaa..2d288bf158e5 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -14,6 +14,7 @@ different class hierarchies, which made it difficult to write a shared visitor between the two in a typesafe way. """ +from mypy.util import unnamed_function import sys import warnings @@ -36,7 +37,7 @@ UnaryExpr, LambdaExpr, ComparisonExpr, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, Statement, BackquoteExpr, PrintStmt, ExecStmt, - ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, OverloadPart, check_arg_names, + ArgKind, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, OverloadPart, check_arg_names, FakeInfo, ) from mypy.types import ( @@ -82,11 +83,11 @@ # There is no way to create reasonable fallbacks at this stage, # they must be patched later. -MISSING_FALLBACK = FakeInfo("fallback can't be filled out until semanal") # type: Final -_dummy_fallback = Instance(MISSING_FALLBACK, [], -1) # type: Final +MISSING_FALLBACK: Final = FakeInfo("fallback can't be filled out until semanal") +_dummy_fallback: Final = Instance(MISSING_FALLBACK, [], -1) -TYPE_COMMENT_SYNTAX_ERROR = 'syntax error in type comment' # type: Final -TYPE_COMMENT_AST_ERROR = 'invalid type comment' # type: Final +TYPE_COMMENT_SYNTAX_ERROR: Final = "syntax error in type comment" +TYPE_COMMENT_AST_ERROR: Final = "invalid type comment" def parse(source: Union[str, bytes], @@ -144,8 +145,8 @@ def __init__(self, options: Options, errors: Errors) -> None: # 'C' for class, 'F' for function - self.class_and_function_stack = [] # type: List[Literal['C', 'F']] - self.imports = [] # type: List[ImportBase] + self.class_and_function_stack: List[Literal["C", "F"]] = [] + self.imports: List[ImportBase] = [] self.options = options self.errors = errors @@ -170,9 +171,9 @@ def __init__(self, self.unicode_literals = False # Cache of visit_X methods keyed by type of visited object - self.visitor_cache = {} # type: Dict[type, Callable[[Optional[AST]], Any]] + self.visitor_cache: Dict[type, Callable[[Optional[AST]], Any]] = {} - self.type_ignores = {} # type: Dict[int, List[str]] + self.type_ignores: Dict[int, List[str]] = {} def fail(self, msg: str, line: int, column: int, blocker: bool = True) -> None: if blocker or not self.options.ignore_errors: @@ -195,7 +196,7 @@ def set_line(self, node: N, n: Union[ast27.expr, ast27.stmt, ast27.ExceptHandler return node def translate_expr_list(self, l: Sequence[AST]) -> List[Expression]: - res = [] # type: List[Expression] + res: List[Expression] = [] for e in l: exp = self.visit(e) assert isinstance(exp, Expression) @@ -214,12 +215,13 @@ def translate_stmt_list(self, # ignores the whole module: if (module and stmts and self.type_ignores and min(self.type_ignores) < self.get_lineno(stmts[0])): - self.errors.used_ignored_lines[self.errors.file].add(min(self.type_ignores)) + self.errors.used_ignored_lines[self.errors.file][min(self.type_ignores)].append( + codes.MISC.code) block = Block(self.fix_function_overloads(self.translate_stmt_list(stmts))) mark_block_unreachable(block) return [block] - res = [] # type: List[Statement] + res: List[Statement] = [] for stmt in stmts: node = self.visit(stmt) assert isinstance(node, Statement) @@ -241,7 +243,7 @@ def translate_type_comment(self, n: ast27.stmt, self.type_ignores[lineno] = extra_ignore return typ - op_map = { + op_map: Final[Dict[typing.Type[AST], str]] = { ast27.Add: '+', ast27.Sub: '-', ast27.Mult: '*', @@ -254,7 +256,7 @@ def translate_type_comment(self, n: ast27.stmt, ast27.BitXor: '^', ast27.BitAnd: '&', ast27.FloorDiv: '//' - } # type: Final[Dict[typing.Type[AST], str]] + } def from_operator(self, op: ast27.operator) -> str: op_name = ASTConverter.op_map.get(type(op)) @@ -265,7 +267,7 @@ def from_operator(self, op: ast27.operator) -> str: else: return op_name - comp_op_map = { + comp_op_map: Final[Dict[typing.Type[AST], str]] = { ast27.Gt: '>', ast27.Lt: '<', ast27.Eq: '==', @@ -276,7 +278,7 @@ def from_operator(self, op: ast27.operator) -> str: ast27.IsNot: 'is not', ast27.In: 'in', ast27.NotIn: 'not in' - } # type: Final[Dict[typing.Type[AST], str]] + } def from_comp_operator(self, op: ast27.cmpop) -> str: op_name = ASTConverter.comp_op_map.get(type(op)) @@ -299,9 +301,9 @@ def as_required_block(self, stmts: List[ast27.stmt], lineno: int) -> Block: return b def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: - ret = [] # type: List[Statement] - current_overload = [] # type: List[OverloadPart] - current_overload_name = None # type: Optional[str] + ret: List[Statement] = [] + current_overload: List[OverloadPart] = [] + current_overload_name: Optional[str] = None for stmt in stmts: if (current_overload_name is not None and isinstance(stmt, (Decorator, FuncDef)) @@ -313,7 +315,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: elif len(current_overload) > 1: ret.append(OverloadedFuncDef(current_overload)) - if isinstance(stmt, Decorator): + if isinstance(stmt, Decorator) and not unnamed_function(stmt.name): current_overload = [stmt] current_overload_name = stmt.name else: @@ -369,14 +371,14 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement: converter = TypeConverter(self.errors, line=lineno, override_column=n.col_offset, assume_str_is_unicode=self.unicode_literals) args, decompose_stmts = self.transform_args(n.args, lineno) + if special_function_elide_names(n.name): + for arg in args: + arg.pos_only = True arg_kinds = [arg.kind for arg in args] - arg_names = [arg.variable.name for arg in args] # type: List[Optional[str]] - arg_names = [None if argument_elide_name(name) else name for name in arg_names] - if special_function_elide_names(n.name): - arg_names = [None] * len(arg_names) + arg_names = [None if arg.pos_only else arg.variable.name for arg in args] - arg_types = [] # type: List[Optional[Type]] + arg_types: List[Optional[Type]] = [] type_comment = n.type_comment if (n.decorator_list and any(is_no_type_check_decorator(d) for d in n.decorator_list)): arg_types = [None] * len(args) @@ -460,7 +462,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement: func_def.body.set_line(func_def.get_line()) dec = Decorator(func_def, self.translate_expr_list(n.decorator_list), var) dec.set_line(lineno, n.col_offset) - retval = dec # type: Statement + retval: Statement = dec else: # Overrides set_line -- can't use self.set_line func_def.set_line(lineno, n.col_offset) @@ -480,19 +482,19 @@ def transform_args(self, n: ast27.arguments, line: int, ) -> Tuple[List[Argument], List[Statement]]: - type_comments = n.type_comments # type: Sequence[Optional[str]] + type_comments: Sequence[Optional[str]] = n.type_comments converter = TypeConverter(self.errors, line=line, assume_str_is_unicode=self.unicode_literals) - decompose_stmts = [] # type: List[Statement] + decompose_stmts: List[Statement] = [] n_args = n.args args = [(self.convert_arg(i, arg, line, decompose_stmts), self.get_type(i, type_comments, converter)) for i, arg in enumerate(n_args)] defaults = self.translate_expr_list(n.defaults) - names = [name for arg in n_args for name in self.extract_names(arg)] # type: List[str] + names: List[str] = [name for arg in n_args for name in self.extract_names(arg)] - new_args = [] # type: List[Argument] + new_args: List[Argument] = [] num_no_defaults = len(args) - len(defaults) # positional arguments without defaults for a, annotation in args[:num_no_defaults]: @@ -518,6 +520,10 @@ def transform_args(self, new_args.append(Argument(Var(n.kwarg), typ, None, ARG_STAR2)) names.append(n.kwarg) + for arg in new_args: + if argument_elide_name(arg.variable.name): + arg.pos_only = True + # We don't have any context object to give, but we have closed around the line num def fail_arg(msg: str, arg: None) -> None: self.fail(msg, line, 0) @@ -558,7 +564,7 @@ def get_type(self, typ = converter.visit_raw_str(comment) extra_ignore = TYPE_IGNORE_PATTERN.match(comment) if extra_ignore: - tag = cast(Any, extra_ignore).group(1) # type: Optional[str] + tag: Optional[str] = cast(Any, extra_ignore).group(1) ignored = parse_type_ignore_tag(tag) if ignored is None: self.fail(INVALID_TYPE_IGNORE, converter.line, -1) @@ -691,7 +697,7 @@ def try_handler(self, orelse: List[ast27.stmt], finalbody: List[ast27.stmt], lineno: int) -> TryStmt: - vs = [] # type: List[Optional[NameExpr]] + vs: List[Optional[NameExpr]] = [] for item in handlers: if item.name is None: vs.append(None) @@ -732,7 +738,7 @@ def visit_Assert(self, n: ast27.Assert) -> AssertStmt: # Import(alias* names) def visit_Import(self, n: ast27.Import) -> Import: - names = [] # type: List[Tuple[str, Optional[str]]] + names: List[Tuple[str, Optional[str]]] = [] for alias in n.names: name = self.translate_module_id(alias.name) asname = alias.asname @@ -751,7 +757,7 @@ def visit_ImportFrom(self, n: ast27.ImportFrom) -> ImportBase: assert n.level is not None if len(n.names) == 1 and n.names[0].name == '*': mod = n.module if n.module is not None else '' - i = ImportAll(mod, n.level) # type: ImportBase + i: ImportBase = ImportAll(mod, n.level) else: module_id = self.translate_module_id(n.module) if n.module is not None else '' i = ImportFrom(module_id, n.level, [(a.name, a.asname) for a in n.names]) @@ -922,9 +928,9 @@ def visit_Compare(self, n: ast27.Compare) -> ComparisonExpr: # Call(expr func, expr* args, keyword* keywords) # keyword = (identifier? arg, expr value) def visit_Call(self, n: Call) -> CallExpr: - arg_types = [] # type: List[ast27.expr] - arg_kinds = [] # type: List[int] - signature = [] # type: List[Optional[str]] + arg_types: List[ast27.expr] = [] + arg_kinds: List[ArgKind] = [] + signature: List[Optional[str]] = [] args = n.args arg_types.extend(args) @@ -958,14 +964,14 @@ def visit_Num(self, n: ast27.Num) -> Expression: # a parent of int and float, and this causes isinstance below # to think that the complex branch is always picked. Avoid # this by throwing away the type. - value = n.n # type: object + value: object = n.n is_inverse = False if str(n.n).startswith('-'): # Hackish because of complex. value = -n.n is_inverse = True if isinstance(value, int): - expr = IntExpr(value) # type: Expression + expr: Expression = IntExpr(value) elif isinstance(value, float): expr = FloatExpr(value) elif isinstance(value, complex): @@ -990,7 +996,7 @@ def visit_Str(self, n: ast27.Str) -> Expression: # to be unicode. if isinstance(n.s, bytes): contents = bytes_to_human_readable_repr(n.s) - e = StrExpr(contents, from_python_3=False) # type: Union[StrExpr, UnicodeExpr] + e: Union[StrExpr, UnicodeExpr] = StrExpr(contents, from_python_3=False) return self.set_line(e, n) else: e = UnicodeExpr(n.s) @@ -1011,7 +1017,7 @@ def visit_Attribute(self, n: Attribute) -> Expression: if (isinstance(obj, CallExpr) and isinstance(obj.callee, NameExpr) and obj.callee.name == 'super'): - e = SuperExpr(member_expr.name, obj) # type: Expression + e: Expression = SuperExpr(member_expr.name, obj) else: e = member_expr return self.set_line(e, n) @@ -1033,10 +1039,10 @@ def visit_Name(self, n: Name) -> NameExpr: # List(expr* elts, expr_context ctx) def visit_List(self, n: ast27.List) -> Union[ListExpr, TupleExpr]: - expr_list = [self.visit(e) for e in n.elts] # type: List[Expression] + expr_list: List[Expression] = [self.visit(e) for e in n.elts] if isinstance(n.ctx, ast27.Store): # [x, y] = z and (x, y) = z means exactly the same thing - e = TupleExpr(expr_list) # type: Union[ListExpr, TupleExpr] + e: Union[ListExpr, TupleExpr] = TupleExpr(expr_list) else: e = ListExpr(expr_list) return self.set_line(e, n) diff --git a/mypy/find_sources.py b/mypy/find_sources.py index 4f50d8ff52b2..a44648f261ed 100644 --- a/mypy/find_sources.py +++ b/mypy/find_sources.py @@ -10,7 +10,7 @@ from mypy.fscache import FileSystemCache from mypy.options import Options -PY_EXTENSIONS = tuple(PYTHON_EXTENSIONS) # type: Final +PY_EXTENSIONS: Final = tuple(PYTHON_EXTENSIONS) class InvalidSourceList(Exception): @@ -101,7 +101,7 @@ def is_explicit_package_base(self, path: str) -> bool: def find_sources_in_dir(self, path: str) -> List[BuildSource]: sources = [] - seen = set() # type: Set[str] + seen: Set[str] = set() names = sorted(self.fscache.listdir(path), key=keyfunc) for name in names: # Skip certain names altogether diff --git a/mypy/fixup.py b/mypy/fixup.py index f995ad36f0f6..da54c40e733f 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -4,14 +4,13 @@ from typing_extensions import Final from mypy.nodes import ( - MypyFile, SymbolNode, SymbolTable, SymbolTableNode, - TypeInfo, FuncDef, OverloadedFuncDef, Decorator, Var, - TypeVarExpr, ClassDef, Block, TypeAlias, + MypyFile, SymbolTable, TypeInfo, FuncDef, OverloadedFuncDef, + Decorator, Var, TypeVarExpr, ClassDef, Block, TypeAlias, ) from mypy.types import ( - CallableType, Instance, Overloaded, TupleType, TypeGuardType, TypedDictType, + CallableType, Instance, Overloaded, TupleType, TypedDictType, TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType, - TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, TypeVarDef + TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, ParamSpecType ) from mypy.visitor import NodeVisitor from mypy.lookup import lookup_fully_qualified @@ -28,7 +27,7 @@ def fixup_module(tree: MypyFile, modules: Dict[str, MypyFile], # TODO: Fix up .info when deserializing, i.e. much earlier. class NodeFixer(NodeVisitor[None]): - current_info = None # type: Optional[TypeInfo] + current_info: Optional[TypeInfo] = None def __init__(self, modules: Dict[str, MypyFile], allow_missing: bool) -> None: self.modules = modules @@ -58,7 +57,8 @@ def visit_type_info(self, info: TypeInfo) -> None: if info.metaclass_type: info.metaclass_type.accept(self.type_fixer) if info._mro_refs: - info.mro = [lookup_qualified_typeinfo(self.modules, name, self.allow_missing) + info.mro = [lookup_fully_qualified_typeinfo(self.modules, name, + allow_missing=self.allow_missing) for name in info._mro_refs] info._mro_refs = None finally: @@ -74,8 +74,8 @@ def visit_symbol_table(self, symtab: SymbolTable, table_fullname: str) -> None: if cross_ref in self.modules: value.node = self.modules[cross_ref] else: - stnode = lookup_qualified_stnode(self.modules, cross_ref, - self.allow_missing) + stnode = lookup_fully_qualified(cross_ref, self.modules, + raise_on_missing=not self.allow_missing) if stnode is not None: assert stnode.node is not None, (table_fullname + "." + key, cross_ref) value.node = stnode.node @@ -121,9 +121,10 @@ def visit_decorator(self, d: Decorator) -> None: def visit_class_def(self, c: ClassDef) -> None: for v in c.type_vars: - for value in v.values: - value.accept(self.type_fixer) - v.upper_bound.accept(self.type_fixer) + if isinstance(v, TypeVarType): + for value in v.values: + value.accept(self.type_fixer) + v.upper_bound.accept(self.type_fixer) def visit_type_var_expr(self, tv: TypeVarExpr) -> None: for value in tv.values: @@ -151,7 +152,8 @@ def visit_instance(self, inst: Instance) -> None: if type_ref is None: return # We've already been here. inst.type_ref = None - inst.type = lookup_qualified_typeinfo(self.modules, type_ref, self.allow_missing) + inst.type = lookup_fully_qualified_typeinfo(self.modules, type_ref, + allow_missing=self.allow_missing) # TODO: Is this needed or redundant? # Also fix up the bases, just in case. for base in inst.type.bases: @@ -167,7 +169,8 @@ def visit_type_alias_type(self, t: TypeAliasType) -> None: if type_ref is None: return # We've already been here. t.type_ref = None - t.alias = lookup_qualified_alias(self.modules, type_ref, self.allow_missing) + t.alias = lookup_fully_qualified_alias(self.modules, type_ref, + allow_missing=self.allow_missing) for a in t.args: a.accept(self) @@ -184,7 +187,7 @@ def visit_callable_type(self, ct: CallableType) -> None: if ct.ret_type is not None: ct.ret_type.accept(self) for v in ct.variables: - if isinstance(v, TypeVarDef): + if isinstance(v, TypeVarType): if v.values: for val in v.values: val.accept(self) @@ -196,7 +199,7 @@ def visit_callable_type(self, ct: CallableType) -> None: ct.type_guard.accept(self) def visit_overloaded(self, t: Overloaded) -> None: - for ct in t.items(): + for ct in t.items: ct.accept(self) def visit_erased_type(self, o: Any) -> None: @@ -228,8 +231,8 @@ def visit_typeddict_type(self, tdt: TypedDictType) -> None: it.accept(self) if tdt.fallback is not None: if tdt.fallback.type_ref is not None: - if lookup_qualified(self.modules, tdt.fallback.type_ref, - self.allow_missing) is None: + if lookup_fully_qualified(tdt.fallback.type_ref, self.modules, + raise_on_missing=not self.allow_missing) is None: # We reject fake TypeInfos for TypedDict fallbacks because # the latter are used in type checking and must be valid. tdt.fallback.type_ref = 'typing._TypedDict' @@ -245,6 +248,9 @@ def visit_type_var(self, tvt: TypeVarType) -> None: if tvt.upper_bound is not None: tvt.upper_bound.accept(self) + def visit_param_spec(self, p: ParamSpecType) -> None: + p.upper_bound.accept(self) + def visit_unbound_type(self, o: UnboundType) -> None: for a in o.args: a.accept(self) @@ -254,9 +260,6 @@ def visit_union_type(self, ut: UnionType) -> None: for it in ut.items: it.accept(self) - def visit_type_guard_type(self, t: TypeGuardType) -> None: - t.type_guard.accept(self) - def visit_void(self, o: Any) -> None: pass # Nothing to descend into. @@ -264,9 +267,10 @@ def visit_type_type(self, t: TypeType) -> None: t.item.accept(self) -def lookup_qualified_typeinfo(modules: Dict[str, MypyFile], name: str, - allow_missing: bool) -> TypeInfo: - node = lookup_qualified(modules, name, allow_missing) +def lookup_fully_qualified_typeinfo(modules: Dict[str, MypyFile], name: str, *, + allow_missing: bool) -> TypeInfo: + stnode = lookup_fully_qualified(name, modules, raise_on_missing=not allow_missing) + node = stnode.node if stnode else None if isinstance(node, TypeInfo): return node else: @@ -278,9 +282,10 @@ def lookup_qualified_typeinfo(modules: Dict[str, MypyFile], name: str, return missing_info(modules) -def lookup_qualified_alias(modules: Dict[str, MypyFile], name: str, - allow_missing: bool) -> TypeAlias: - node = lookup_qualified(modules, name, allow_missing) +def lookup_fully_qualified_alias(modules: Dict[str, MypyFile], name: str, *, + allow_missing: bool) -> TypeAlias: + stnode = lookup_fully_qualified(name, modules, raise_on_missing=not allow_missing) + node = stnode.node if stnode else None if isinstance(node, TypeAlias): return node else: @@ -292,21 +297,7 @@ def lookup_qualified_alias(modules: Dict[str, MypyFile], name: str, return missing_alias() -def lookup_qualified(modules: Dict[str, MypyFile], name: str, - allow_missing: bool) -> Optional[SymbolNode]: - stnode = lookup_qualified_stnode(modules, name, allow_missing) - if stnode is None: - return None - else: - return stnode.node - - -def lookup_qualified_stnode(modules: Dict[str, MypyFile], name: str, - allow_missing: bool) -> Optional[SymbolTableNode]: - return lookup_fully_qualified(name, modules, raise_on_missing=not allow_missing) - - -_SUGGESTION = "" # type: Final +_SUGGESTION: Final = "" def missing_info(modules: Dict[str, MypyFile]) -> TypeInfo: @@ -315,8 +306,7 @@ def missing_info(modules: Dict[str, MypyFile]) -> TypeInfo: dummy_def.fullname = suggestion info = TypeInfo(SymbolTable(), dummy_def, "") - obj_type = lookup_qualified(modules, 'builtins.object', False) - assert isinstance(obj_type, TypeInfo) + obj_type = lookup_fully_qualified_typeinfo(modules, 'builtins.object', allow_missing=False) info.bases = [Instance(obj_type, [])] info.mro = [info, obj_type] return info diff --git a/mypy/fscache.py b/mypy/fscache.py index aa688868cc71..ea71577b5f86 100644 --- a/mypy/fscache.py +++ b/mypy/fscache.py @@ -30,7 +30,6 @@ import os import stat -import sys from typing import Dict, List, Set from mypy.util import hash_digest from mypy_extensions import mypyc_attr @@ -41,7 +40,7 @@ class FileSystemCache: def __init__(self) -> None: # The package root is not flushed with the caches. # It is set by set_package_root() below. - self.package_root = [] # type: List[str] + self.package_root: List[str] = [] self.flush() def set_package_root(self, package_root: List[str]) -> None: @@ -49,16 +48,16 @@ def set_package_root(self, package_root: List[str]) -> None: def flush(self) -> None: """Start another transaction and empty all caches.""" - self.stat_cache = {} # type: Dict[str, os.stat_result] - self.stat_error_cache = {} # type: Dict[str, OSError] - self.listdir_cache = {} # type: Dict[str, List[str]] - self.listdir_error_cache = {} # type: Dict[str, OSError] - self.isfile_case_cache = {} # type: Dict[str, bool] - self.exists_case_cache = {} # type: Dict[str, bool] - self.read_cache = {} # type: Dict[str, bytes] - self.read_error_cache = {} # type: Dict[str, Exception] - self.hash_cache = {} # type: Dict[str, str] - self.fake_package_cache = set() # type: Set[str] + self.stat_cache: Dict[str, os.stat_result] = {} + self.stat_error_cache: Dict[str, OSError] = {} + self.listdir_cache: Dict[str, List[str]] = {} + self.listdir_error_cache: Dict[str, OSError] = {} + self.isfile_case_cache: Dict[str, bool] = {} + self.exists_case_cache: Dict[str, bool] = {} + self.read_cache: Dict[str, bytes] = {} + self.read_error_cache: Dict[str, Exception] = {} + self.hash_cache: Dict[str, str] = {} + self.fake_package_cache: Set[str] = set() def stat(self, path: str) -> os.stat_result: if path in self.stat_cache: @@ -107,6 +106,9 @@ def init_under_package_root(self, path: str) -> bool: dirname, basename = os.path.split(path) if basename != '__init__.py': return False + if not os.path.basename(dirname).isidentifier(): + # Can't put an __init__.py in a place that's not an identifier + return False try: st = self.stat(dirname) except OSError: @@ -144,7 +146,7 @@ def _fake_init(self, path: str) -> os.stat_result: # Get stat result as a sequence so we can modify it. # (Alas, typeshed's os.stat_result is not a sequence yet.) tpl = tuple(st) # type: ignore[arg-type, var-annotated] - seq = list(tpl) # type: List[float] + seq: List[float] = list(tpl) seq[stat.ST_MODE] = stat.S_IFREG | 0o444 seq[stat.ST_INO] = 1 seq[stat.ST_NLINK] = 1 @@ -199,9 +201,6 @@ def isfile_case(self, path: str, prefix: str) -> bool: The caller must ensure that prefix is a valid file system prefix of path. """ - if sys.platform == "linux": - # Assume that the file system on Linux is case sensitive - return self.isfile(path) if not self.isfile(path): # Fast path return False @@ -220,12 +219,14 @@ def isfile_case(self, path: str, prefix: str) -> bool: res = False if res: # Also recursively check the other path components in case sensitive way. - res = self._exists_case(head, prefix) + res = self.exists_case(head, prefix) self.isfile_case_cache[path] = res return res - def _exists_case(self, path: str, prefix: str) -> bool: - """Helper to check path components in case sensitive fashion, up to prefix.""" + def exists_case(self, path: str, prefix: str) -> bool: + """Return whether path exists - checking path components in case sensitive + fashion, up to prefix. + """ if path in self.exists_case_cache: return self.exists_case_cache[path] head, tail = os.path.split(path) @@ -242,7 +243,7 @@ def _exists_case(self, path: str, prefix: str) -> bool: res = False if res: # Also recursively check other path components. - res = self._exists_case(head, prefix) + res = self.exists_case(head, prefix) self.exists_case_cache[path] = res return res diff --git a/mypy/fswatcher.py b/mypy/fswatcher.py index 7ab78b2c4ed3..80af313e8227 100644 --- a/mypy/fswatcher.py +++ b/mypy/fswatcher.py @@ -29,8 +29,8 @@ class FileSystemWatcher: def __init__(self, fs: FileSystemCache) -> None: self.fs = fs - self._paths = set() # type: Set[str] - self._file_data = {} # type: Dict[str, Optional[FileData]] + self._paths: Set[str] = set() + self._file_data: Dict[str, Optional[FileData]] = {} def dump_file_data(self) -> Dict[str, Tuple[float, int, str]]: return {k: v for k, v in self._file_data.items() if v is not None} diff --git a/mypy/gclogger.py b/mypy/gclogger.py index 650ef2f04930..1f36225461de 100644 --- a/mypy/gclogger.py +++ b/mypy/gclogger.py @@ -8,7 +8,7 @@ class GcLogger: """Context manager to log GC stats and overall time.""" def __enter__(self) -> 'GcLogger': - self.gc_start_time = None # type: Optional[float] + self.gc_start_time: Optional[float] = None self.gc_time = 0.0 self.gc_calls = 0 self.gc_collected = 0 diff --git a/mypy/indirection.py b/mypy/indirection.py index aff942ce9393..238f46c8830f 100644 --- a/mypy/indirection.py +++ b/mypy/indirection.py @@ -19,8 +19,8 @@ class TypeIndirectionVisitor(TypeVisitor[Set[str]]): """Returns all module references within a particular type.""" def __init__(self) -> None: - self.cache = {} # type: Dict[types.Type, Set[str]] - self.seen_aliases = set() # type: Set[types.TypeAliasType] + self.cache: Dict[types.Type, Set[str]] = {} + self.seen_aliases: Set[types.TypeAliasType] = set() def find_modules(self, typs: Iterable[types.Type]) -> Set[str]: self.seen_aliases.clear() @@ -28,7 +28,7 @@ def find_modules(self, typs: Iterable[types.Type]) -> Set[str]: def _visit(self, typ_or_typs: Union[types.Type, Iterable[types.Type]]) -> Set[str]: typs = [typ_or_typs] if isinstance(typ_or_typs, types.Type) else typ_or_typs - output = set() # type: Set[str] + output: Set[str] = set() for typ in typs: if isinstance(typ, types.TypeAliasType): # Avoid infinite recursion for recursive type aliases. @@ -64,6 +64,9 @@ def visit_deleted_type(self, t: types.DeletedType) -> Set[str]: def visit_type_var(self, t: types.TypeVarType) -> Set[str]: return self._visit(t.values) | self._visit(t.upper_bound) + def visit_param_spec(self, t: types.ParamSpecType) -> Set[str]: + return set() + def visit_instance(self, t: types.Instance) -> Set[str]: out = self._visit(t.args) if t.type: @@ -83,7 +86,7 @@ def visit_callable_type(self, t: types.CallableType) -> Set[str]: return out def visit_overloaded(self, t: types.Overloaded) -> Set[str]: - return self._visit(t.items()) | self._visit(t.fallback) + return self._visit(t.items) | self._visit(t.fallback) def visit_tuple_type(self, t: types.TupleType) -> Set[str]: return self._visit(t.items) | self._visit(t.partial_fallback) @@ -97,9 +100,6 @@ def visit_literal_type(self, t: types.LiteralType) -> Set[str]: def visit_union_type(self, t: types.UnionType) -> Set[str]: return self._visit(t.items) - def visit_type_guard_type(self, t: types.TypeGuardType) -> Set[str]: - return self._visit(t.type_guard) - def visit_partial_type(self, t: types.PartialType) -> Set[str]: return set() diff --git a/mypy/infer.py b/mypy/infer.py index c2f7fbd35e72..ca521e211493 100644 --- a/mypy/infer.py +++ b/mypy/infer.py @@ -1,18 +1,34 @@ """Utilities for type argument inference.""" -from typing import List, Optional, Sequence +from typing import List, Optional, Sequence, NamedTuple from mypy.constraints import ( infer_constraints, infer_constraints_for_callable, SUBTYPE_OF, SUPERTYPE_OF ) -from mypy.types import Type, TypeVarId, CallableType +from mypy.types import Type, TypeVarId, CallableType, Instance +from mypy.nodes import ArgKind from mypy.solve import solve_constraints +class ArgumentInferContext(NamedTuple): + """Type argument inference context. + + We need this because we pass around ``Mapping`` and ``Iterable`` types. + These types are only known by ``TypeChecker`` itself. + It is required for ``*`` and ``**`` argument inference. + + https://github.com/python/mypy/issues/11144 + """ + + mapping_type: Instance + iterable_type: Instance + + def infer_function_type_arguments(callee_type: CallableType, arg_types: Sequence[Optional[Type]], - arg_kinds: List[int], + arg_kinds: List[ArgKind], formal_to_actual: List[List[int]], + context: ArgumentInferContext, strict: bool = True) -> List[Optional[Type]]: """Infer the type arguments of a generic function. @@ -29,7 +45,7 @@ def infer_function_type_arguments(callee_type: CallableType, """ # Infer constraints. constraints = infer_constraints_for_callable( - callee_type, arg_types, arg_kinds, formal_to_actual) + callee_type, arg_types, arg_kinds, formal_to_actual, context) # Solve constraints. type_vars = callee_type.type_var_ids() diff --git a/mypy/ipc.py b/mypy/ipc.py index 83d3ca787329..8a6a310d7ff8 100644 --- a/mypy/ipc.py +++ b/mypy/ipc.py @@ -23,8 +23,8 @@ _IPCHandle = int kernel32 = ctypes.windll.kernel32 - DisconnectNamedPipe = kernel32.DisconnectNamedPipe # type: Callable[[_IPCHandle], int] - FlushFileBuffers = kernel32.FlushFileBuffers # type: Callable[[_IPCHandle], int] + DisconnectNamedPipe: Callable[[_IPCHandle], int] = kernel32.DisconnectNamedPipe + FlushFileBuffers: Callable[[_IPCHandle], int] = kernel32.FlushFileBuffers else: import socket _IPCHandle = socket.socket @@ -42,7 +42,7 @@ class IPCBase: and writing. """ - connection = None # type: _IPCHandle + connection: _IPCHandle def __init__(self, name: str, timeout: Optional[float]) -> None: self.name = name @@ -175,7 +175,7 @@ def __exit__(self, class IPCServer(IPCBase): - BUFFER_SIZE = 2**16 # type: Final + BUFFER_SIZE: Final = 2 ** 16 def __init__(self, name: str, timeout: Optional[float] = None) -> None: if sys.platform == 'win32': diff --git a/mypy/join.py b/mypy/join.py index 53a1fce973dc..e0d926f3fcf4 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -1,24 +1,113 @@ """Calculation of the least upper bound types (joins).""" -from mypy.ordered_dict import OrderedDict -from typing import List, Optional +from mypy.backports import OrderedDict +from typing import List, Optional, Tuple from mypy.types import ( Type, AnyType, NoneType, TypeVisitor, Instance, UnboundType, TypeVarType, CallableType, TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded, LiteralType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, get_proper_type, - ProperType, get_proper_types, TypeAliasType, PlaceholderType, TypeGuardType + ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType ) from mypy.maptype import map_instance_to_supertype from mypy.subtypes import ( is_subtype, is_equivalent, is_subtype_ignoring_tvars, is_proper_subtype, is_protocol_implementation, find_member ) -from mypy.nodes import ARG_NAMED, ARG_NAMED_OPT +from mypy.nodes import INVARIANT, COVARIANT, CONTRAVARIANT import mypy.typeops from mypy import state +class InstanceJoiner: + def __init__(self) -> None: + self.seen_instances: List[Tuple[Instance, Instance]] = [] + + def join_instances(self, t: Instance, s: Instance) -> ProperType: + if (t, s) in self.seen_instances or (s, t) in self.seen_instances: + return object_from_instance(t) + + self.seen_instances.append((t, s)) + + # Calculate the join of two instance types + if t.type == s.type: + # Simplest case: join two types with the same base type (but + # potentially different arguments). + + # Combine type arguments. + args: List[Type] = [] + # N.B: We use zip instead of indexing because the lengths might have + # mismatches during daemon reprocessing. + for ta, sa, type_var in zip(t.args, s.args, t.type.defn.type_vars): + ta_proper = get_proper_type(ta) + sa_proper = get_proper_type(sa) + new_type: Optional[Type] = None + if isinstance(ta_proper, AnyType): + new_type = AnyType(TypeOfAny.from_another_any, ta_proper) + elif isinstance(sa_proper, AnyType): + new_type = AnyType(TypeOfAny.from_another_any, sa_proper) + elif isinstance(type_var, TypeVarType): + if type_var.variance == COVARIANT: + new_type = join_types(ta, sa, self) + if len(type_var.values) != 0 and new_type not in type_var.values: + self.seen_instances.pop() + return object_from_instance(t) + if not is_subtype(new_type, type_var.upper_bound): + self.seen_instances.pop() + return object_from_instance(t) + # TODO: contravariant case should use meet but pass seen instances as + # an argument to keep track of recursive checks. + elif type_var.variance in (INVARIANT, CONTRAVARIANT): + if not is_equivalent(ta, sa): + self.seen_instances.pop() + return object_from_instance(t) + # If the types are different but equivalent, then an Any is involved + # so using a join in the contravariant case is also OK. + new_type = join_types(ta, sa, self) + else: + # ParamSpec type variables behave the same, independent of variance + if not is_equivalent(ta, sa): + return get_proper_type(type_var.upper_bound) + new_type = join_types(ta, sa, self) + assert new_type is not None + args.append(new_type) + result: ProperType = Instance(t.type, args) + elif t.type.bases and is_subtype_ignoring_tvars(t, s): + result = self.join_instances_via_supertype(t, s) + else: + # Now t is not a subtype of s, and t != s. Now s could be a subtype + # of t; alternatively, we need to find a common supertype. This works + # in of the both cases. + result = self.join_instances_via_supertype(s, t) + + self.seen_instances.pop() + return result + + def join_instances_via_supertype(self, t: Instance, s: Instance) -> ProperType: + # Give preference to joins via duck typing relationship, so that + # join(int, float) == float, for example. + if t.type._promote and is_subtype(t.type._promote, s): + return join_types(t.type._promote, s, self) + elif s.type._promote and is_subtype(s.type._promote, t): + return join_types(t, s.type._promote, self) + # Compute the "best" supertype of t when joined with s. + # The definition of "best" may evolve; for now it is the one with + # the longest MRO. Ties are broken by using the earlier base. + best: Optional[ProperType] = None + for base in t.type.bases: + mapped = map_instance_to_supertype(t, base.type) + res = self.join_instances(mapped, s) + if best is None or is_better(res, best): + best = res + assert best is not None + promote = get_proper_type(t.type._promote) + if isinstance(promote, Instance): + res = self.join_instances(promote, s) + if is_better(res, best): + best = res + return best + + def join_simple(declaration: Optional[Type], s: Type, t: Type) -> ProperType: """Return a simple least upper bound given the declared type.""" # TODO: check infinite recursion for aliases here. @@ -69,7 +158,7 @@ def trivial_join(s: Type, t: Type) -> ProperType: return object_or_any_from_type(get_proper_type(t)) -def join_types(s: Type, t: Type) -> ProperType: +def join_types(s: Type, t: Type, instance_joiner: Optional[InstanceJoiner] = None) -> ProperType: """Return the least upper bound of s and t. For example, the join of 'int' and 'object' is 'object'. @@ -110,7 +199,7 @@ def join_types(s: Type, t: Type) -> ProperType: return AnyType(TypeOfAny.from_error) # Use a visitor to handle non-trivial cases. - return t.accept(TypeJoinVisitor(s)) + return t.accept(TypeJoinVisitor(s, instance_joiner)) class TypeJoinVisitor(TypeVisitor[ProperType]): @@ -120,8 +209,9 @@ class TypeJoinVisitor(TypeVisitor[ProperType]): s: The other (left) type operand. """ - def __init__(self, s: ProperType) -> None: + def __init__(self, s: ProperType, instance_joiner: Optional[InstanceJoiner] = None) -> None: self.s = s + self.instance_joiner = instance_joiner def visit_unbound_type(self, t: UnboundType) -> ProperType: return AnyType(TypeOfAny.special_form) @@ -161,10 +251,17 @@ def visit_type_var(self, t: TypeVarType) -> ProperType: else: return self.default(self.s) + def visit_param_spec(self, t: ParamSpecType) -> ProperType: + if self.s == t: + return t + return self.default(self.s) + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): - nominal = join_instances(t, self.s) - structural = None # type: Optional[Instance] + if self.instance_joiner is None: + self.instance_joiner = InstanceJoiner() + nominal = self.instance_joiner.join_instances(t, self.s) + structural: Optional[Instance] = None if t.type.is_protocol and is_protocol_implementation(self.s, t): structural = t elif self.s.type.is_protocol and is_protocol_implementation(t, self.s): @@ -245,12 +342,12 @@ def visit_overloaded(self, t: Overloaded) -> ProperType: # Ov([Any, int] -> Any, [Any, int] -> Any) # # TODO: Consider more cases of callable subtyping. - result = [] # type: List[CallableType] + result: List[CallableType] = [] s = self.s if isinstance(s, FunctionLike): # The interesting case where both types are function types. - for t_item in t.items(): - for s_item in s.items(): + for t_item in t.items: + for s_item in s.items: if is_similar_callables(t_item, s_item): if is_equivalent(t_item, s_item): result.append(combine_similar_callables(t_item, s_item)) @@ -282,11 +379,13 @@ def visit_tuple_type(self, t: TupleType) -> ProperType: # * Joining with any Sequence also returns a Sequence: # Tuple[int, bool] + List[bool] becomes Sequence[int] if isinstance(self.s, TupleType) and self.s.length() == t.length(): - fallback = join_instances(mypy.typeops.tuple_fallback(self.s), - mypy.typeops.tuple_fallback(t)) + if self.instance_joiner is None: + self.instance_joiner = InstanceJoiner() + fallback = self.instance_joiner.join_instances(mypy.typeops.tuple_fallback(self.s), + mypy.typeops.tuple_fallback(t)) assert isinstance(fallback, Instance) if self.s.length() == t.length(): - items = [] # type: List[Type] + items: List[Type] = [] for i in range(t.length()): items.append(self.join(t.items[i], self.s.items[i])) return TupleType(items, fallback) @@ -340,9 +439,6 @@ def visit_type_type(self, t: TypeType) -> ProperType: def visit_type_alias_type(self, t: TypeAliasType) -> ProperType: assert False, "This should be never called, got {}".format(t) - def visit_type_guard_type(self, t: TypeGuardType) -> ProperType: - assert False, "This should be never called, got {}".format(t) - def join(self, s: Type, t: Type) -> ProperType: return join_types(s, t) @@ -360,60 +456,12 @@ def default(self, typ: Type) -> ProperType: return self.default(typ.fallback) elif isinstance(typ, TypeVarType): return self.default(typ.upper_bound) + elif isinstance(typ, ParamSpecType): + return self.default(typ.upper_bound) else: return AnyType(TypeOfAny.special_form) -def join_instances(t: Instance, s: Instance) -> ProperType: - """Calculate the join of two instance types.""" - if t.type == s.type: - # Simplest case: join two types with the same base type (but - # potentially different arguments). - if is_subtype(t, s) or is_subtype(s, t): - # Compatible; combine type arguments. - args = [] # type: List[Type] - # N.B: We use zip instead of indexing because the lengths might have - # mismatches during daemon reprocessing. - for ta, sa in zip(t.args, s.args): - args.append(join_types(ta, sa)) - return Instance(t.type, args) - else: - # Incompatible; return trivial result object. - return object_from_instance(t) - elif t.type.bases and is_subtype_ignoring_tvars(t, s): - return join_instances_via_supertype(t, s) - else: - # Now t is not a subtype of s, and t != s. Now s could be a subtype - # of t; alternatively, we need to find a common supertype. This works - # in of the both cases. - return join_instances_via_supertype(s, t) - - -def join_instances_via_supertype(t: Instance, s: Instance) -> ProperType: - # Give preference to joins via duck typing relationship, so that - # join(int, float) == float, for example. - if t.type._promote and is_subtype(t.type._promote, s): - return join_types(t.type._promote, s) - elif s.type._promote and is_subtype(s.type._promote, t): - return join_types(t, s.type._promote) - # Compute the "best" supertype of t when joined with s. - # The definition of "best" may evolve; for now it is the one with - # the longest MRO. Ties are broken by using the earlier base. - best = None # type: Optional[ProperType] - for base in t.type.bases: - mapped = map_instance_to_supertype(t, base.type) - res = join_instances(mapped, s) - if best is None or is_better(res, best): - best = res - assert best is not None - promote = get_proper_type(t.type._promote) - if isinstance(promote, Instance): - res = join_instances(promote, s) - if is_better(res, best): - best = res - return best - - def is_better(t: Type, s: Type) -> bool: # Given two possible results from join_instances_via_supertype(), # indicate whether t is the better one. @@ -439,7 +487,8 @@ def is_similar_callables(t: CallableType, s: CallableType) -> bool: def join_similar_callables(t: CallableType, s: CallableType) -> CallableType: from mypy.meet import meet_types - arg_types = [] # type: List[Type] + + arg_types: List[Type] = [] for i in range(len(t.arg_types)): arg_types.append(meet_types(t.arg_types[i], s.arg_types[i])) # TODO in combine_similar_callables also applies here (names and kinds) @@ -457,7 +506,7 @@ def join_similar_callables(t: CallableType, s: CallableType) -> CallableType: def combine_similar_callables(t: CallableType, s: CallableType) -> CallableType: - arg_types = [] # type: List[Type] + arg_types: List[Type] = [] for i in range(len(t.arg_types)): arg_types.append(join_types(t.arg_types[i], s.arg_types[i])) # TODO kinds and argument names @@ -493,11 +542,10 @@ def combine_arg_names(t: CallableType, s: CallableType) -> List[Optional[str]]: """ num_args = len(t.arg_types) new_names = [] - named = (ARG_NAMED, ARG_NAMED_OPT) for i in range(num_args): t_name = t.arg_names[i] s_name = s.arg_names[i] - if t_name == s_name or t.arg_kinds[i] in named or s.arg_kinds[i] in named: + if t_name == s_name or t.arg_kinds[i].is_named() or s.arg_kinds[i].is_named(): new_names.append(t_name) else: new_names.append(None) diff --git a/mypy/literals.py b/mypy/literals.py index 95872cbd9fca..00cf5916bec2 100644 --- a/mypy/literals.py +++ b/mypy/literals.py @@ -61,6 +61,9 @@ def literal(e: Expression) -> int: elif isinstance(e, (MemberExpr, UnaryExpr, StarExpr)): return literal(e.expr) + elif isinstance(e, AssignmentExpr): + return literal(e.target) + elif isinstance(e, IndexExpr): if literal(e.index) == LITERAL_YES: return literal(e.base) @@ -125,7 +128,7 @@ def visit_op_expr(self, e: OpExpr) -> Key: return ('Binary', e.op, literal_hash(e.left), literal_hash(e.right)) def visit_comparison_expr(self, e: ComparisonExpr) -> Key: - rest = tuple(e.operators) # type: Any + rest: Any = tuple(e.operators) rest += tuple(literal_hash(o) for o in e.operands) return ('Comparison',) + rest @@ -134,7 +137,7 @@ def visit_unary_expr(self, e: UnaryExpr) -> Key: def seq_expr(self, e: Union[ListExpr, TupleExpr, SetExpr], name: str) -> Optional[Key]: if all(literal(x) == LITERAL_YES for x in e.items): - rest = tuple(literal_hash(x) for x in e.items) # type: Any + rest: Any = tuple(literal_hash(x) for x in e.items) return (name,) + rest return None @@ -143,9 +146,10 @@ def visit_list_expr(self, e: ListExpr) -> Optional[Key]: def visit_dict_expr(self, e: DictExpr) -> Optional[Key]: if all(a and literal(a) == literal(b) == LITERAL_YES for a, b in e.items): - rest = tuple((literal_hash(a) if a else None, literal_hash(b)) - for a, b in e.items) # type: Any - return ('Dict',) + rest + rest: Any = tuple( + (literal_hash(a) if a else None, literal_hash(b)) for a, b in e.items + ) + return ("Dict",) + rest return None def visit_tuple_expr(self, e: TupleExpr) -> Optional[Key]: @@ -159,8 +163,8 @@ def visit_index_expr(self, e: IndexExpr) -> Optional[Key]: return ('Index', literal_hash(e.base), literal_hash(e.index)) return None - def visit_assignment_expr(self, e: AssignmentExpr) -> None: - return None + def visit_assignment_expr(self, e: AssignmentExpr) -> Optional[Key]: + return literal_hash(e.target) def visit_call_expr(self, e: CallExpr) -> None: return None @@ -241,4 +245,4 @@ def visit_temp_node(self, e: TempNode) -> None: return None -_hasher = _Hasher() # type: Final +_hasher: Final = _Hasher() diff --git a/mypy/lookup.py b/mypy/lookup.py index 41464d83dc5e..fcb2f1607393 100644 --- a/mypy/lookup.py +++ b/mypy/lookup.py @@ -9,7 +9,7 @@ # TODO: gradually move existing lookup functions to this module. -def lookup_fully_qualified(name: str, modules: Dict[str, MypyFile], +def lookup_fully_qualified(name: str, modules: Dict[str, MypyFile], *, raise_on_missing: bool = False) -> Optional[SymbolTableNode]: """Find a symbol using it fully qualified name. diff --git a/mypy/main.py b/mypy/main.py index f3625553f681..d765781838cf 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -28,8 +28,8 @@ from mypy.version import __version__ -orig_stat = os.stat # type: Final -MEM_PROFILE = False # type: Final # If True, dump memory profile +orig_stat: Final = os.stat +MEM_PROFILE: Final = False # If True, dump memory profile def stat_proxy(path: str) -> os.stat_result: @@ -48,13 +48,16 @@ def main(script_path: Optional[str], stdout: TextIO, stderr: TextIO, args: Optional[List[str]] = None, + clean_exit: bool = False, ) -> None: """Main entry point to the type checker. Args: script_path: Path to the 'mypy' script (used for finding data files). args: Custom command-line arguments. If not given, sys.argv[1:] will - be used. + be used. + clean_exit: Don't hard kill the process on exit. This allows catching + SystemExit. """ util.check_python_version('mypy') t0 = time.time() @@ -66,48 +69,41 @@ def main(script_path: Optional[str], fscache = FileSystemCache() sources, options = process_options(args, stdout=stdout, stderr=stderr, fscache=fscache) + if clean_exit: + options.fast_exit = False - messages = [] formatter = util.FancyFormatter(stdout, stderr, options.show_error_codes) if options.install_types and (stdout is not sys.stdout or stderr is not sys.stderr): # Since --install-types performs user input, we want regular stdout and stderr. - fail("--install-types not supported in this mode of running mypy", stderr, options) + fail("error: --install-types not supported in this mode of running mypy", stderr, options) + + if options.non_interactive and not options.install_types: + fail("error: --non-interactive is only supported with --install-types", stderr, options) + + if options.install_types and not options.incremental: + fail("error: --install-types not supported with incremental mode disabled", + stderr, options) + + if options.install_types and options.python_executable is None: + fail("error: --install-types not supported without python executable or site packages", + stderr, options) if options.install_types and not sources: - install_types(options.cache_dir, formatter) + install_types(formatter, options, non_interactive=options.non_interactive) return - def flush_errors(new_messages: List[str], serious: bool) -> None: - if options.pretty: - new_messages = formatter.fit_in_terminal(new_messages) - messages.extend(new_messages) - f = stderr if serious else stdout - for msg in new_messages: - if options.color_output: - msg = formatter.colorize(msg) - f.write(msg + '\n') - f.flush() + res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr) - serious = False - blockers = False - res = None - try: - # Keep a dummy reference (res) for memory profiling below, as otherwise - # the result could be freed. - res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr) - except CompileError as e: - blockers = True - if not e.use_stdout: - serious = True - if options.warn_unused_configs and options.unused_configs and not options.incremental: - print("Warning: unused section(s) in %s: %s" % - (options.config_file, - get_config_module_names(options.config_file, - [glob for glob in options.per_module_options.keys() - if glob in options.unused_configs])), - file=stderr) - maybe_write_junit_xml(time.time() - t0, serious, messages, options) + if options.non_interactive: + missing_pkgs = read_types_packages_to_install(options.cache_dir, after_run=True) + if missing_pkgs: + # Install missing type packages and rerun build. + install_types(formatter, options, after_run=True, non_interactive=True) + fscache.flush() + print() + res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr) + show_messages(messages, stderr, formatter, options) if MEM_PROFILE: from mypy.memprofile import print_memory_profile @@ -129,9 +125,12 @@ def flush_errors(new_messages: List[str], serious: bool) -> None: stdout.write(formatter.format_success(len(sources), options.color_output) + '\n') stdout.flush() - if options.install_types: - install_types(options.cache_dir, formatter, after_run=True) - return + if options.install_types and not options.non_interactive: + result = install_types(formatter, options, after_run=True, non_interactive=False) + if result: + print() + print("note: Run mypy again for up-to-date results with installed types") + code = 2 if options.fast_exit: # Exit without freeing objects -- it's faster. @@ -145,6 +144,62 @@ def flush_errors(new_messages: List[str], serious: bool) -> None: list([res]) +def run_build(sources: List[BuildSource], + options: Options, + fscache: FileSystemCache, + t0: float, + stdout: TextIO, + stderr: TextIO) -> Tuple[Optional[build.BuildResult], List[str], bool]: + formatter = util.FancyFormatter(stdout, stderr, options.show_error_codes) + + messages = [] + + def flush_errors(new_messages: List[str], serious: bool) -> None: + if options.pretty: + new_messages = formatter.fit_in_terminal(new_messages) + messages.extend(new_messages) + if options.non_interactive: + # Collect messages and possibly show them later. + return + f = stderr if serious else stdout + show_messages(new_messages, f, formatter, options) + + serious = False + blockers = False + res = None + try: + # Keep a dummy reference (res) for memory profiling afterwards, as otherwise + # the result could be freed. + res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr) + except CompileError as e: + blockers = True + if not e.use_stdout: + serious = True + if (options.warn_unused_configs + and options.unused_configs + and not options.incremental + and not options.non_interactive): + print("Warning: unused section(s) in %s: %s" % + (options.config_file, + get_config_module_names(options.config_file, + [glob for glob in options.per_module_options.keys() + if glob in options.unused_configs])), + file=stderr) + maybe_write_junit_xml(time.time() - t0, serious, messages, options) + return res, messages, blockers + + +def show_messages(messages: List[str], + f: TextIO, + formatter: util.FancyFormatter, + options: Options) -> None: + for msg in messages: + if options.color_output: + msg = formatter.colorize(msg) + f.write(msg + '\n') + f.flush() + + # Make the help output a little less jarring. class AugmentedHelpFormatter(argparse.RawDescriptionHelpFormatter): def __init__(self, prog: str) -> None: @@ -161,11 +216,11 @@ def _fill_text(self, text: str, width: int, indent: str) -> str: # Define pairs of flag prefixes with inverse meaning. -flag_prefix_pairs = [ +flag_prefix_pairs: Final = [ ('allow', 'disallow'), ('show', 'hide'), -] # type: Final -flag_prefix_map = {} # type: Final[Dict[str, str]] +] +flag_prefix_map: Final[Dict[str, str]] = {} for a, b in flag_prefix_pairs: flag_prefix_map[a] = b flag_prefix_map[b] = a @@ -190,8 +245,8 @@ class PythonExecutableInferenceError(Exception): def python_executable_prefix(v: str) -> List[str]: if sys.platform == 'win32': # on Windows, all Python executables are named `python`. To handle this, there - # is the `py` launcher, which can be passed a version e.g. `py -3.5`, and it will - # execute an installed Python 3.5 interpreter. See also: + # is the `py` launcher, which can be passed a version e.g. `py -3.8`, and it will + # execute an installed Python 3.8 interpreter. See also: # https://docs.python.org/3/using/windows.html#python-launcher-for-windows return ['py', '-{}'.format(v)] else: @@ -235,11 +290,11 @@ def infer_python_executable(options: Options, options.python_executable = python_executable -HEADER = """%(prog)s [-h] [-v] [-V] [more options; see below] - [-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]""" # type: Final +HEADER: Final = """%(prog)s [-h] [-v] [-V] [more options; see below] + [-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]""" -DESCRIPTION = """ +DESCRIPTION: Final = """ Mypy is a program that will type check your Python code. Pass in any files or folders you want to type check. Mypy will @@ -260,11 +315,11 @@ def infer_python_executable(options: Options, command line flags. For more details, see: - https://mypy.readthedocs.io/en/stable/config_file.html -""" # type: Final +""" -FOOTER = """Environment variables: +FOOTER: Final = """Environment variables: Define MYPYPATH for additional module search path entries. - Define MYPY_CACHE_DIR to override configuration cache_dir path.""" # type: Final + Define MYPY_CACHE_DIR to override configuration cache_dir path.""" class CapturableArgumentParser(argparse.ArgumentParser): @@ -387,8 +442,8 @@ def process_options(args: List[str], stdout=stdout, stderr=stderr) - strict_flag_names = [] # type: List[str] - strict_flag_assignments = [] # type: List[Tuple[str, bool]] + strict_flag_names: List[str] = [] + strict_flag_assignments: List[Tuple[str, bool]] = [] def add_invertible_flag(flag: str, *, @@ -663,6 +718,8 @@ def add_invertible_flag(flag: str, add_invertible_flag('--show-absolute-path', default=False, help="Show absolute paths to files", group=error_group) + error_group.add_argument('--soft-error-limit', default=defaults.MANY_ERRORS_THRESHOLD, + type=int, dest="many_errors_threshold", help=argparse.SUPPRESS) incremental_group = parser.add_argument_group( title='Incremental mode', @@ -720,7 +777,7 @@ def add_invertible_flag(flag: str, dest='shadow_file', action='append', help="When encountering SOURCE_FILE, read and type check " "the contents of SHADOW_FILE instead.") - add_invertible_flag('--fast-exit', default=False, help=argparse.SUPPRESS, + add_invertible_flag('--fast-exit', default=True, help=argparse.SUPPRESS, group=internals_group) report_group = parser.add_argument_group( @@ -749,6 +806,10 @@ def add_invertible_flag(flag: str, add_invertible_flag('--install-types', default=False, strict_flag=False, help="Install detected missing library stub packages using pip", group=other_group) + add_invertible_flag('--non-interactive', default=False, strict_flag=False, + help=("Install stubs without asking for confirmation and hide " + + "errors, with --install-types"), + group=other_group, inverse="--interactive") if server_options: # TODO: This flag is superfluous; remove after a short transition (2018-03-16) @@ -799,8 +860,6 @@ def add_invertible_flag(flag: str, # Must be followed by another flag or by '--' (and then only file args may follow). parser.add_argument('--cache-map', nargs='+', dest='special-opts:cache_map', help=argparse.SUPPRESS) - # PEP 612 support is a work in progress, hide it from users - parser.add_argument('--wip-pep-612', action="store_true", help=argparse.SUPPRESS) # options specifying code to check code_group = parser.add_argument_group( @@ -813,11 +872,13 @@ def add_invertible_flag(flag: str, group=code_group) code_group.add_argument( "--exclude", + action="append", metavar="PATTERN", - default="", + default=[], help=( "Regular expression to match file names, directory names or paths which mypy should " - "ignore while recursively discovering files to check, e.g. --exclude '/setup\\.py$'" + "ignore while recursively discovering files to check, e.g. --exclude '/setup\\.py$'. " + "May be specified more than once, eg. --exclude a --exclude b" ) ) code_group.add_argument( @@ -956,6 +1017,11 @@ def set_strict_flags() -> None: process_cache_map(parser, special_opts, options) + # An explicitly specified cache_fine_grained implies local_partial_types + # (because otherwise the cache is not compatible with dmypy) + if options.cache_fine_grained: + options.local_partial_types = True + # Let logical_deps imply cache_fine_grained (otherwise the former is useless). if options.logical_deps: options.cache_fine_grained = True @@ -1068,29 +1134,48 @@ def fail(msg: str, stderr: TextIO, options: Options) -> None: sys.exit(2) -def install_types(cache_dir: str, - formatter: util.FancyFormatter, - after_run: bool = False) -> None: - """Install stub packages using pip if some missing stubs were detected.""" +def read_types_packages_to_install(cache_dir: str, after_run: bool) -> List[str]: if not os.path.isdir(cache_dir): - sys.stderr.write( - "Error: no mypy cache directory (you must enable incremental mode)\n") + if not after_run: + sys.stderr.write( + "error: Can't determine which types to install with no files to check " + + "(and no cache from previous mypy run)\n" + ) + else: + sys.stderr.write( + "error: --install-types failed (no mypy cache directory)\n" + ) sys.exit(2) fnam = build.missing_stubs_file(cache_dir) if not os.path.isfile(fnam): - # If there are no missing stubs, generate no output. - return + # No missing stubs. + return [] with open(fnam) as f: - packages = [line.strip() for line in f.readlines()] - if after_run: + return [line.strip() for line in f.readlines()] + + +def install_types(formatter: util.FancyFormatter, + options: Options, + *, + after_run: bool = False, + non_interactive: bool = False) -> bool: + """Install stub packages using pip if some missing stubs were detected.""" + packages = read_types_packages_to_install(options.cache_dir, after_run) + if not packages: + # If there are no missing stubs, generate no output. + return False + if after_run and not non_interactive: print() print('Installing missing stub packages:') - cmd = [sys.executable, '-m', 'pip', 'install'] + packages + assert options.python_executable, 'Python executable required to install types' + cmd = [options.python_executable, '-m', 'pip', 'install'] + packages print(formatter.style(' '.join(cmd), 'none', bold=True)) print() - x = input('Install? [yN] ') - if not x.strip() or not x.lower().startswith('y'): - print(formatter.style('mypy: Skipping installation', 'red', bold=True)) - sys.exit(2) - print() + if not non_interactive: + x = input('Install? [yN] ') + if not x.strip() or not x.lower().startswith('y'): + print(formatter.style('mypy: Skipping installation', 'red', bold=True)) + sys.exit(2) + print() subprocess.run(cmd) + return True diff --git a/mypy/maptype.py b/mypy/maptype.py index 5e58754655ef..1216c6015378 100644 --- a/mypy/maptype.py +++ b/mypy/maptype.py @@ -28,11 +28,11 @@ def map_instance_to_supertypes(instance: Instance, supertype: TypeInfo) -> List[Instance]: # FIX: Currently we should only have one supertype per interface, so no # need to return an array - result = [] # type: List[Instance] + result: List[Instance] = [] for path in class_derivation_paths(instance.type, supertype): types = [instance] for sup in path: - a = [] # type: List[Instance] + a: List[Instance] = [] for t in types: a.extend(map_instance_to_direct_supertypes(t, sup)) types = a @@ -56,7 +56,7 @@ def class_derivation_paths(typ: TypeInfo, """ # FIX: Currently we might only ever have a single path, so this could be # simplified - result = [] # type: List[List[TypeInfo]] + result: List[List[TypeInfo]] = [] for base in typ.bases: btype = base.type @@ -74,7 +74,7 @@ def map_instance_to_direct_supertypes(instance: Instance, supertype: TypeInfo) -> List[Instance]: # FIX: There should only be one supertypes, always. typ = instance.type - result = [] # type: List[Instance] + result: List[Instance] = [] for b in typ.bases: if b.type == supertype: diff --git a/mypy/meet.py b/mypy/meet.py index 558de6ec92c9..644b57afbcbe 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -1,20 +1,19 @@ -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import List, Optional, Tuple, Callable -from mypy.join import ( - is_similar_callables, combine_similar_callables, join_type_list, unpack_callback_protocol -) from mypy.types import ( Type, AnyType, TypeVisitor, UnboundType, NoneType, TypeVarType, Instance, CallableType, TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType, - ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardType + ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardedType, + ParamSpecType ) from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype from mypy.erasetype import erase_type from mypy.maptype import map_instance_to_supertype from mypy.typeops import tuple_fallback, make_simplified_union, is_recursive_pair from mypy import state +from mypy import join # TODO Describe this module. @@ -53,6 +52,10 @@ def meet_types(s: Type, t: Type) -> ProperType: def narrow_declared_type(declared: Type, narrowed: Type) -> Type: """Return the declared type narrowed down to another type.""" # TODO: check infinite recursion for aliases here. + if isinstance(narrowed, TypeGuardedType): # type: ignore[misc] + # A type guard forces the new type even if it doesn't overlap the old. + return narrowed.type_guard + declared = get_proper_type(declared) narrowed = get_proper_type(narrowed) @@ -72,6 +75,8 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type: for x in narrowed.relevant_items()]) elif isinstance(narrowed, AnyType): return narrowed + elif isinstance(narrowed, TypeVarType) and is_subtype(narrowed.upper_bound, declared): + return narrowed elif isinstance(declared, TypeType) and isinstance(narrowed, TypeType): return TypeType.make_normalized(narrow_declared_type(declared.item, narrowed.item)) elif (isinstance(declared, TypeType) @@ -127,7 +132,7 @@ def get_possible_variants(typ: Type) -> List[Type]: elif isinstance(typ, Overloaded): # Note: doing 'return typ.items()' makes mypy # infer a too-specific return type of List[CallableType] - return list(typ.items()) + return list(typ.items) else: return [typ] @@ -142,6 +147,13 @@ def is_overlapping_types(left: Type, If 'prohibit_none_typevar_overlap' is True, we disallow None from overlapping with TypeVars (in both strict-optional and non-strict-optional mode). """ + if ( + isinstance(left, TypeGuardedType) # type: ignore[misc] + or isinstance(right, TypeGuardedType) # type: ignore[misc] + ): + # A type guard forces the new type even if it doesn't overlap the old. + return True + left, right = get_proper_types((left, right)) def _is_overlapping_types(left: Type, right: Type) -> bool: @@ -446,7 +458,7 @@ def visit_any(self, t: AnyType) -> ProperType: def visit_union_type(self, t: UnionType) -> ProperType: if isinstance(self.s, UnionType): - meets = [] # type: List[Type] + meets: List[Type] = [] for x in t.items: for y in self.s.items: meets.append(meet_types(x, y)) @@ -488,6 +500,12 @@ def visit_type_var(self, t: TypeVarType) -> ProperType: else: return self.default(self.s) + def visit_param_spec(self, t: ParamSpecType) -> ProperType: + if self.s == t: + return self.s + else: + return self.default(self.s) + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): si = self.s @@ -495,7 +513,7 @@ def visit_instance(self, t: Instance) -> ProperType: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. - args = [] # type: List[Type] + args: List[Type] = [] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for ta, sia in zip(t.args, si.args): @@ -518,7 +536,7 @@ def visit_instance(self, t: Instance) -> ProperType: else: return NoneType() elif isinstance(self.s, FunctionLike) and t.type.is_protocol: - call = unpack_callback_protocol(t) + call = join.unpack_callback_protocol(t) if call: return meet_types(call, self.s) elif isinstance(self.s, FunctionLike) and self.s.is_type_obj() and t.type.is_metaclass(): @@ -536,9 +554,9 @@ def visit_instance(self, t: Instance) -> ProperType: return self.default(self.s) def visit_callable_type(self, t: CallableType) -> ProperType: - if isinstance(self.s, CallableType) and is_similar_callables(t, self.s): + if isinstance(self.s, CallableType) and join.is_similar_callables(t, self.s): if is_equivalent(t, self.s): - return combine_similar_callables(t, self.s) + return join.combine_similar_callables(t, self.s) result = meet_similar_callables(t, self.s) # We set the from_type_type flag to suppress error when a collection of # concrete class objects gets inferred as their common abstract superclass. @@ -556,7 +574,7 @@ def visit_callable_type(self, t: CallableType) -> ProperType: return TypeType.make_normalized(res) return self.default(self.s) elif isinstance(self.s, Instance) and self.s.type.is_protocol: - call = unpack_callback_protocol(self.s) + call = join.unpack_callback_protocol(self.s) if call: return meet_types(t, call) return self.default(self.s) @@ -566,8 +584,8 @@ def visit_overloaded(self, t: Overloaded) -> ProperType: # as TypeJoinVisitor.visit_overloaded(). s = self.s if isinstance(s, FunctionLike): - if s.items() == t.items(): - return Overloaded(t.items()) + if s.items == t.items: + return Overloaded(t.items) elif is_subtype(s, t): return s elif is_subtype(t, s): @@ -575,14 +593,14 @@ def visit_overloaded(self, t: Overloaded) -> ProperType: else: return meet_types(t.fallback, s.fallback) elif isinstance(self.s, Instance) and self.s.type.is_protocol: - call = unpack_callback_protocol(self.s) + call = join.unpack_callback_protocol(self.s) if call: return meet_types(t, call) return meet_types(t.fallback, s) def visit_tuple_type(self, t: TupleType) -> ProperType: if isinstance(self.s, TupleType) and self.s.length() == t.length(): - items = [] # type: List[Type] + items: List[Type] = [] for i in range(t.length()): items.append(self.meet(t.items[i], self.s.items[i])) # TODO: What if the fallbacks are different? @@ -602,7 +620,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> ProperType: if (not is_equivalent(l, r) or (name in t.required_keys) != (name in self.s.required_keys)): return self.default(self.s) - item_list = [] # type: List[Tuple[str, Type]] + item_list: List[Tuple[str, Type]] = [] for (item_name, s_item_type, t_item_type) in self.s.zipall(t): if s_item_type is not None: item_list.append((item_name, s_item_type)) @@ -611,7 +629,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> ProperType: assert t_item_type is not None item_list.append((item_name, t_item_type)) items = OrderedDict(item_list) - mapping_value_type = join_type_list(list(items.values())) + mapping_value_type = join.join_type_list(list(items.values())) fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type) required_keys = t.required_keys | self.s.required_keys return TypedDictType(items, required_keys, fallback) @@ -648,9 +666,6 @@ def visit_type_type(self, t: TypeType) -> ProperType: def visit_type_alias_type(self, t: TypeAliasType) -> ProperType: assert False, "This should be never called, got {}".format(t) - def visit_type_guard_type(self, t: TypeGuardType) -> ProperType: - assert False, "This should be never called, got {}".format(t) - def meet(self, s: Type, t: Type) -> ProperType: return meet_types(s, t) @@ -666,7 +681,8 @@ def default(self, typ: Type) -> ProperType: def meet_similar_callables(t: CallableType, s: CallableType) -> CallableType: from mypy.join import join_types - arg_types = [] # type: List[Type] + + arg_types: List[Type] = [] for i in range(len(t.arg_types)): arg_types.append(join_types(t.arg_types[i], s.arg_types[i])) # TODO in combine_similar_callables also applies here (names and kinds) diff --git a/mypy/memprofile.py b/mypy/memprofile.py index 9ed2c4afee06..5052d0418994 100644 --- a/mypy/memprofile.py +++ b/mypy/memprofile.py @@ -51,8 +51,8 @@ def collect_memory_stats() -> Tuple[Dict[str, int], if isinstance(x, tuple): inferred[id(x)] = '%s (tuple)' % n - freqs = {} # type: Dict[str, int] - memuse = {} # type: Dict[str, int] + freqs: Dict[str, int] = {} + memuse: Dict[str, int] = {} for obj in objs: if id(obj) in inferred: name = inferred[id(obj)] diff --git a/mypy/message_registry.py b/mypy/message_registry.py index b434acf94308..77dff1154833 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -6,139 +6,226 @@ add a method to MessageBuilder and call this instead. """ +from typing import NamedTuple, Optional from typing_extensions import Final +from mypy import errorcodes as codes + + +class ErrorMessage(NamedTuple): + value: str + code: Optional[codes.ErrorCode] = None + + def format(self, *args: object, **kwargs: object) -> "ErrorMessage": + return ErrorMessage(self.value.format(*args, **kwargs), code=self.code) + + # Invalid types -INVALID_TYPE_RAW_ENUM_VALUE = "Invalid type: try using Literal[{}.{}] instead?" # type: Final +INVALID_TYPE_RAW_ENUM_VALUE: Final = "Invalid type: try using Literal[{}.{}] instead?" # Type checker error message constants -NO_RETURN_VALUE_EXPECTED = 'No return value expected' # type: Final -MISSING_RETURN_STATEMENT = 'Missing return statement' # type: Final -INVALID_IMPLICIT_RETURN = 'Implicit return in function which does not return' # type: Final -INCOMPATIBLE_RETURN_VALUE_TYPE = 'Incompatible return value type' # type: Final -RETURN_VALUE_EXPECTED = 'Return value expected' # type: Final -NO_RETURN_EXPECTED = 'Return statement in function which does not return' # type: Final -INVALID_EXCEPTION = 'Exception must be derived from BaseException' # type: Final -INVALID_EXCEPTION_TYPE = 'Exception type must be derived from BaseException' # type: Final -RETURN_IN_ASYNC_GENERATOR = '"return" with value in async generator is not allowed' # type: Final -INVALID_RETURN_TYPE_FOR_GENERATOR = \ - 'The return type of a generator function should be "Generator"' \ - ' or one of its supertypes' # type: Final -INVALID_RETURN_TYPE_FOR_ASYNC_GENERATOR = \ - 'The return type of an async generator function should be "AsyncGenerator" or one of its ' \ - 'supertypes' # type: Final -INVALID_GENERATOR_RETURN_ITEM_TYPE = \ - 'The return type of a generator function must be None in' \ - ' its third type parameter in Python 2' # type: Final -YIELD_VALUE_EXPECTED = 'Yield value expected' # type: Final -INCOMPATIBLE_TYPES = 'Incompatible types' # type: Final -INCOMPATIBLE_TYPES_IN_ASSIGNMENT = 'Incompatible types in assignment' # type: Final -INCOMPATIBLE_REDEFINITION = 'Incompatible redefinition' # type: Final -INCOMPATIBLE_TYPES_IN_AWAIT = 'Incompatible types in "await"' # type: Final -INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AENTER = \ - 'Incompatible types in "async with" for "__aenter__"' # type: Final -INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AEXIT = \ - 'Incompatible types in "async with" for "__aexit__"' # type: Final -INCOMPATIBLE_TYPES_IN_ASYNC_FOR = 'Incompatible types in "async for"' # type: Final - -INCOMPATIBLE_TYPES_IN_YIELD = 'Incompatible types in "yield"' # type: Final -INCOMPATIBLE_TYPES_IN_YIELD_FROM = 'Incompatible types in "yield from"' # type: Final -INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION = \ - 'Incompatible types in string interpolation' # type: Final -MUST_HAVE_NONE_RETURN_TYPE = 'The return type of "{}" must be None' # type: Final -INVALID_TUPLE_INDEX_TYPE = 'Invalid tuple index type' # type: Final -TUPLE_INDEX_OUT_OF_RANGE = 'Tuple index out of range' # type: Final -INVALID_SLICE_INDEX = 'Slice index must be an integer or None' # type: Final -CANNOT_INFER_LAMBDA_TYPE = 'Cannot infer type of lambda' # type: Final -CANNOT_ACCESS_INIT = 'Cannot access "__init__" directly' # type: Final -NON_INSTANCE_NEW_TYPE = '"__new__" must return a class instance (got {})' # type: Final -INVALID_NEW_TYPE = 'Incompatible return type for "__new__"' # type: Final -BAD_CONSTRUCTOR_TYPE = 'Unsupported decorated constructor type' # type: Final -CANNOT_ASSIGN_TO_METHOD = 'Cannot assign to a method' # type: Final -CANNOT_ASSIGN_TO_TYPE = 'Cannot assign to a type' # type: Final -INCONSISTENT_ABSTRACT_OVERLOAD = \ - 'Overloaded method has both abstract and non-abstract variants' # type: Final -MULTIPLE_OVERLOADS_REQUIRED = 'Single overload definition, multiple required' # type: Final -READ_ONLY_PROPERTY_OVERRIDES_READ_WRITE = \ - 'Read-only property cannot override read-write property' # type: Final -FORMAT_REQUIRES_MAPPING = 'Format requires a mapping' # type: Final -RETURN_TYPE_CANNOT_BE_CONTRAVARIANT = \ - "Cannot use a contravariant type variable as return type" # type: Final -FUNCTION_PARAMETER_CANNOT_BE_COVARIANT = \ - "Cannot use a covariant type variable as a parameter" # type: Final -INCOMPATIBLE_IMPORT_OF = "Incompatible import of" # type: Final -FUNCTION_TYPE_EXPECTED = "Function is missing a type annotation" # type: Final -ONLY_CLASS_APPLICATION = "Type application is only supported for generic classes" # type: Final -RETURN_TYPE_EXPECTED = "Function is missing a return type annotation" # type: Final -ARGUMENT_TYPE_EXPECTED = \ - "Function is missing a type annotation for one or more arguments" # type: Final -KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE = \ - 'Keyword argument only valid with "str" key type in call to "dict"' # type: Final -ALL_MUST_BE_SEQ_STR = 'Type of __all__ must be {}, not {}' # type: Final -INVALID_TYPEDDICT_ARGS = \ - 'Expected keyword arguments, {...}, or dict(...) in TypedDict constructor' # type: Final -TYPEDDICT_KEY_MUST_BE_STRING_LITERAL = \ - 'Expected TypedDict key to be string literal' # type: Final -MALFORMED_ASSERT = 'Assertion is always true, perhaps remove parentheses?' # type: Final -DUPLICATE_TYPE_SIGNATURES = 'Function has duplicate type signatures' # type: Final -DESCRIPTOR_SET_NOT_CALLABLE = "{}.__set__ is not callable" # type: Final -DESCRIPTOR_GET_NOT_CALLABLE = "{}.__get__ is not callable" # type: Final -MODULE_LEVEL_GETATTRIBUTE = '__getattribute__ is not valid at the module level' # type: Final +NO_RETURN_VALUE_EXPECTED: Final = ErrorMessage("No return value expected", codes.RETURN_VALUE) +MISSING_RETURN_STATEMENT: Final = ErrorMessage("Missing return statement", codes.RETURN) +INVALID_IMPLICIT_RETURN: Final = ErrorMessage("Implicit return in function which does not return") +INCOMPATIBLE_RETURN_VALUE_TYPE: Final = ErrorMessage( + "Incompatible return value type", codes.RETURN_VALUE +) +RETURN_VALUE_EXPECTED: Final = ErrorMessage("Return value expected", codes.RETURN_VALUE) +NO_RETURN_EXPECTED: Final = ErrorMessage("Return statement in function which does not return") +INVALID_EXCEPTION: Final = ErrorMessage("Exception must be derived from BaseException") +INVALID_EXCEPTION_TYPE: Final = ErrorMessage("Exception type must be derived from BaseException") +RETURN_IN_ASYNC_GENERATOR: Final = ErrorMessage( + '"return" with value in async generator is not allowed' +) +INVALID_RETURN_TYPE_FOR_GENERATOR: Final = ErrorMessage( + 'The return type of a generator function should be "Generator"' " or one of its supertypes" +) +INVALID_RETURN_TYPE_FOR_ASYNC_GENERATOR: Final = ErrorMessage( + 'The return type of an async generator function should be "AsyncGenerator" or one of its ' + "supertypes" +) +INVALID_GENERATOR_RETURN_ITEM_TYPE: Final = ErrorMessage( + "The return type of a generator function must be None in" + " its third type parameter in Python 2" +) +YIELD_VALUE_EXPECTED: Final = ErrorMessage("Yield value expected") +INCOMPATIBLE_TYPES: Final = "Incompatible types" +INCOMPATIBLE_TYPES_IN_ASSIGNMENT: Final = "Incompatible types in assignment" +INCOMPATIBLE_TYPES_IN_AWAIT: Final = ErrorMessage('Incompatible types in "await"') +INCOMPATIBLE_REDEFINITION: Final = ErrorMessage("Incompatible redefinition") +INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AENTER: Final = ( + 'Incompatible types in "async with" for "__aenter__"' +) +INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AEXIT: Final = ( + 'Incompatible types in "async with" for "__aexit__"' +) +INCOMPATIBLE_TYPES_IN_ASYNC_FOR: Final = 'Incompatible types in "async for"' + +INCOMPATIBLE_TYPES_IN_YIELD: Final = ErrorMessage('Incompatible types in "yield"') +INCOMPATIBLE_TYPES_IN_YIELD_FROM: Final = ErrorMessage('Incompatible types in "yield from"') +INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION: Final = "Incompatible types in string interpolation" +MUST_HAVE_NONE_RETURN_TYPE: Final = ErrorMessage('The return type of "{}" must be None') +INVALID_TUPLE_INDEX_TYPE: Final = ErrorMessage("Invalid tuple index type") +TUPLE_INDEX_OUT_OF_RANGE: Final = ErrorMessage("Tuple index out of range") +INVALID_SLICE_INDEX: Final = ErrorMessage("Slice index must be an integer or None") +CANNOT_INFER_LAMBDA_TYPE: Final = ErrorMessage("Cannot infer type of lambda") +CANNOT_ACCESS_INIT: Final = 'Cannot access "__init__" directly' +NON_INSTANCE_NEW_TYPE: Final = ErrorMessage('"__new__" must return a class instance (got {})') +INVALID_NEW_TYPE: Final = ErrorMessage('Incompatible return type for "__new__"') +BAD_CONSTRUCTOR_TYPE: Final = ErrorMessage("Unsupported decorated constructor type") +CANNOT_ASSIGN_TO_METHOD: Final = "Cannot assign to a method" +CANNOT_ASSIGN_TO_TYPE: Final = "Cannot assign to a type" +INCONSISTENT_ABSTRACT_OVERLOAD: Final = ErrorMessage( + "Overloaded method has both abstract and non-abstract variants" +) +MULTIPLE_OVERLOADS_REQUIRED: Final = ErrorMessage("Single overload definition, multiple required") +READ_ONLY_PROPERTY_OVERRIDES_READ_WRITE: Final = ErrorMessage( + "Read-only property cannot override read-write property" +) +FORMAT_REQUIRES_MAPPING: Final = "Format requires a mapping" +RETURN_TYPE_CANNOT_BE_CONTRAVARIANT: Final = ErrorMessage( + "Cannot use a contravariant type variable as return type" +) +FUNCTION_PARAMETER_CANNOT_BE_COVARIANT: Final = ErrorMessage( + "Cannot use a covariant type variable as a parameter" +) +INCOMPATIBLE_IMPORT_OF: Final = "Incompatible import of" +FUNCTION_TYPE_EXPECTED: Final = ErrorMessage( + "Function is missing a type annotation", codes.NO_UNTYPED_DEF +) +ONLY_CLASS_APPLICATION: Final = ErrorMessage( + "Type application is only supported for generic classes" +) +RETURN_TYPE_EXPECTED: Final = ErrorMessage( + "Function is missing a return type annotation", codes.NO_UNTYPED_DEF +) +ARGUMENT_TYPE_EXPECTED: Final = ErrorMessage( + "Function is missing a type annotation for one or more arguments", codes.NO_UNTYPED_DEF +) +KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE: Final = ErrorMessage( + 'Keyword argument only valid with "str" key type in call to "dict"' +) +ALL_MUST_BE_SEQ_STR: Final = ErrorMessage("Type of __all__ must be {}, not {}") +INVALID_TYPEDDICT_ARGS: Final = ErrorMessage( + "Expected keyword arguments, {...}, or dict(...) in TypedDict constructor" +) +TYPEDDICT_KEY_MUST_BE_STRING_LITERAL: Final = ErrorMessage( + "Expected TypedDict key to be string literal" +) +MALFORMED_ASSERT: Final = ErrorMessage("Assertion is always true, perhaps remove parentheses?") +DUPLICATE_TYPE_SIGNATURES: Final = "Function has duplicate type signatures" +DESCRIPTOR_SET_NOT_CALLABLE: Final = ErrorMessage("{}.__set__ is not callable") +DESCRIPTOR_GET_NOT_CALLABLE: Final = "{}.__get__ is not callable" +MODULE_LEVEL_GETATTRIBUTE: Final = ErrorMessage( + "__getattribute__ is not valid at the module level" +) +NAME_NOT_IN_SLOTS: Final = ErrorMessage( + 'Trying to assign name "{}" that is not in "__slots__" of type "{}"' +) +TYPE_ALWAYS_TRUE: Final = ErrorMessage( + "{} which does not implement __bool__ or __len__ " + "so it could always be true in boolean context", + code=codes.TRUTHY_BOOL, +) +TYPE_ALWAYS_TRUE_UNIONTYPE: Final = ErrorMessage( + "{} of which no members implement __bool__ or __len__ " + "so it could always be true in boolean context", + code=codes.TRUTHY_BOOL, +) +FUNCTION_ALWAYS_TRUE: Final = ErrorMessage( + 'Function {} could always be true in boolean context', + code=codes.TRUTHY_BOOL, +) +NOT_CALLABLE: Final = '{} not callable' +PYTHON2_PRINT_FILE_TYPE: Final = ( + 'Argument "file" to "print" has incompatible type "{}"; expected "{}"' +) # Generic -GENERIC_INSTANCE_VAR_CLASS_ACCESS = \ - 'Access to generic instance variables via class is ambiguous' # type: Final -GENERIC_CLASS_VAR_ACCESS = \ - 'Access to generic class variables is ambiguous' # type: Final -BARE_GENERIC = 'Missing type parameters for generic type {}' # type: Final -IMPLICIT_GENERIC_ANY_BUILTIN = \ - 'Implicit generic "Any". Use "{}" and specify generic parameters' # type: Final +GENERIC_INSTANCE_VAR_CLASS_ACCESS: Final = ( + "Access to generic instance variables via class is ambiguous" +) +GENERIC_CLASS_VAR_ACCESS: Final = "Access to generic class variables is ambiguous" +BARE_GENERIC: Final = "Missing type parameters for generic type {}" +IMPLICIT_GENERIC_ANY_BUILTIN: Final = ( + 'Implicit generic "Any". Use "{}" and specify generic parameters' +) # TypeVar -INCOMPATIBLE_TYPEVAR_VALUE = 'Value of type variable "{}" of {} cannot be {}' # type: Final -CANNOT_USE_TYPEVAR_AS_EXPRESSION = \ - 'Type variable "{}.{}" cannot be used as an expression' # type: Final +INCOMPATIBLE_TYPEVAR_VALUE: Final = 'Value of type variable "{}" of {} cannot be {}' +CANNOT_USE_TYPEVAR_AS_EXPRESSION: Final = 'Type variable "{}.{}" cannot be used as an expression' +INVALID_TYPEVAR_AS_TYPEARG: Final = 'Type variable "{}" not valid as type argument value for "{}"' +INVALID_TYPEVAR_ARG_BOUND: Final = 'Type argument {} of "{}" must be a subtype of {}' +INVALID_TYPEVAR_ARG_VALUE: Final = 'Invalid type argument value for "{}"' +TYPEVAR_VARIANCE_DEF: Final = 'TypeVar "{}" may only be a literal bool' +TYPEVAR_BOUND_MUST_BE_TYPE: Final = 'TypeVar "bound" must be a type' +TYPEVAR_UNEXPECTED_ARGUMENT: Final = 'Unexpected argument to "TypeVar()"' # Super -TOO_MANY_ARGS_FOR_SUPER = 'Too many arguments for "super"' # type: Final -TOO_FEW_ARGS_FOR_SUPER = 'Too few arguments for "super"' # type: Final -SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED = '"super" with a single argument not supported' # type: Final -UNSUPPORTED_ARG_1_FOR_SUPER = 'Unsupported argument 1 for "super"' # type: Final -UNSUPPORTED_ARG_2_FOR_SUPER = 'Unsupported argument 2 for "super"' # type: Final -SUPER_VARARGS_NOT_SUPPORTED = 'Varargs not supported with "super"' # type: Final -SUPER_POSITIONAL_ARGS_REQUIRED = '"super" only accepts positional arguments' # type: Final -SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1 = \ - 'Argument 2 for "super" not an instance of argument 1' # type: Final -TARGET_CLASS_HAS_NO_BASE_CLASS = 'Target class has no base class' # type: Final -SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED = \ - 'super() outside of a method is not supported' # type: Final -SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED = \ - 'super() requires one or more positional arguments in enclosing function' # type: Final +TOO_MANY_ARGS_FOR_SUPER: Final = ErrorMessage('Too many arguments for "super"') +TOO_FEW_ARGS_FOR_SUPER: Final = ErrorMessage('Too few arguments for "super"', codes.CALL_ARG) +SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED: Final = ErrorMessage( + '"super" with a single argument not supported' +) +UNSUPPORTED_ARG_1_FOR_SUPER: Final = ErrorMessage('Unsupported argument 1 for "super"') +UNSUPPORTED_ARG_2_FOR_SUPER: Final = ErrorMessage('Unsupported argument 2 for "super"') +SUPER_VARARGS_NOT_SUPPORTED: Final = ErrorMessage('Varargs not supported with "super"') +SUPER_POSITIONAL_ARGS_REQUIRED: Final = ErrorMessage('"super" only accepts positional arguments') +SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1: Final = ErrorMessage( + 'Argument 2 for "super" not an instance of argument 1' +) +TARGET_CLASS_HAS_NO_BASE_CLASS: Final = ErrorMessage("Target class has no base class") +SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED: Final = ErrorMessage( + "super() outside of a method is not supported" +) +SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED: Final = ErrorMessage( + "super() requires one or more positional arguments in enclosing function" +) # Self-type -MISSING_OR_INVALID_SELF_TYPE = \ - "Self argument missing for a non-static method (or an invalid type for self)" # type: Final -ERASED_SELF_TYPE_NOT_SUPERTYPE = \ - 'The erased type of self "{}" is not a supertype of its class "{}"' # type: Final -INVALID_SELF_TYPE_OR_EXTRA_ARG = \ - "Invalid type for self, or extra argument type in function annotation" # type: Final +MISSING_OR_INVALID_SELF_TYPE: Final = ErrorMessage( + "Self argument missing for a non-static method (or an invalid type for self)" +) +ERASED_SELF_TYPE_NOT_SUPERTYPE: Final = ErrorMessage( + 'The erased type of self "{}" is not a supertype of its class "{}"' +) +INVALID_SELF_TYPE_OR_EXTRA_ARG: Final = ErrorMessage( + "Invalid type for self, or extra argument type in function annotation" +) # Final -CANNOT_INHERIT_FROM_FINAL = 'Cannot inherit from final class "{}"' # type: Final -DEPENDENT_FINAL_IN_CLASS_BODY = \ - "Final name declared in class body cannot depend on type variables" # type: Final -CANNOT_ACCESS_FINAL_INSTANCE_ATTR = \ - 'Cannot access final instance attribute "{}" on class object' # type: Final +CANNOT_INHERIT_FROM_FINAL: Final = ErrorMessage('Cannot inherit from final class "{}"') +DEPENDENT_FINAL_IN_CLASS_BODY: Final = ErrorMessage( + "Final name declared in class body cannot depend on type variables" +) +CANNOT_ACCESS_FINAL_INSTANCE_ATTR: Final = ( + 'Cannot access final instance attribute "{}" on class object' +) +CANNOT_MAKE_DELETABLE_FINAL: Final = ErrorMessage("Deletable attribute cannot be final") # ClassVar -CANNOT_OVERRIDE_INSTANCE_VAR = \ - 'Cannot override instance variable (previously declared on base class "{}") with class ' \ - 'variable' # type: Final -CANNOT_OVERRIDE_CLASS_VAR = \ - 'Cannot override class variable (previously declared on base class "{}") with instance ' \ - 'variable' # type: Final +CANNOT_OVERRIDE_INSTANCE_VAR: Final = ErrorMessage( + 'Cannot override instance variable (previously declared on base class "{}") with class ' + "variable" +) +CANNOT_OVERRIDE_CLASS_VAR: Final = ErrorMessage( + 'Cannot override class variable (previously declared on base class "{}") with instance ' + "variable" +) +CLASS_VAR_WITH_TYPEVARS: Final = 'ClassVar cannot contain type variables' +CLASS_VAR_OUTSIDE_OF_CLASS: Final = ( + 'ClassVar can only be used for assignments in class body' +) # Protocol -RUNTIME_PROTOCOL_EXPECTED = \ - 'Only @runtime_checkable protocols can be used with instance and class checks' # type: Final -CANNOT_INSTANTIATE_PROTOCOL = 'Cannot instantiate protocol class "{}"' # type: Final +RUNTIME_PROTOCOL_EXPECTED: Final = ErrorMessage( + "Only @runtime_checkable protocols can be used with instance and class checks" +) +CANNOT_INSTANTIATE_PROTOCOL: Final = ErrorMessage('Cannot instantiate protocol class "{}"') +TOO_MANY_UNION_COMBINATIONS: Final = ErrorMessage( + "Not all union combinations were tried because there are too many unions" +) + +CONTIGUOUS_ITERABLE_EXPECTED: Final = ErrorMessage("Contiguous iterable with same type expected") +ITERABLE_TYPE_EXPECTED: Final = ErrorMessage("Invalid type '{}' for *expr (iterable expected)") +TYPE_GUARD_POS_ARG_REQUIRED: Final = ErrorMessage("Type guard requires positional argument") diff --git a/mypy/messages.py b/mypy/messages.py index 0d10b9bef5d6..da284cc88ba4 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -8,31 +8,32 @@ Historically we tried to avoid all message string literals in the type checker but we are moving away from this convention. """ +from contextlib import contextmanager -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict import re import difflib from textwrap import dedent -from typing import cast, List, Dict, Any, Sequence, Iterable, Tuple, Set, Optional, Union +from typing import cast, List, Dict, Any, Sequence, Iterable, Iterator, Tuple, Set, Optional, Union from typing_extensions import Final from mypy.erasetype import erase_type from mypy.errors import Errors from mypy.types import ( Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType, LiteralType, - UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, TypeVarDef, + UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, UninhabitedType, TypeOfAny, UnboundType, PartialType, get_proper_type, ProperType, - get_proper_types + ParamSpecType, get_proper_types ) from mypy.typetraverser import TypeTraverserVisitor from mypy.nodes import ( - TypeInfo, Context, MypyFile, op_methods, op_methods_to_symbols, - FuncDef, reverse_builtin_aliases, - ARG_POS, ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, + TypeInfo, Context, MypyFile, FuncDef, reverse_builtin_aliases, + ArgKind, ARG_POS, ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, ReturnStmt, NameExpr, Var, CONTRAVARIANT, COVARIANT, SymbolNode, - CallExpr, IndexExpr, StrExpr, SymbolTable, TempNode + CallExpr, IndexExpr, StrExpr, SymbolTable, TempNode, SYMBOL_FUNCBASE_TYPES ) +from mypy.operators import op_methods, op_methods_to_symbols from mypy.subtypes import ( is_subtype, find_member, get_member_flags, IS_SETTABLE, IS_CLASSVAR, IS_CLASS_OR_STATIC, @@ -42,7 +43,7 @@ from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes -TYPES_FOR_UNIMPORTED_HINTS = { +TYPES_FOR_UNIMPORTED_HINTS: Final = { 'typing.Any', 'typing.Callable', 'typing.Dict', @@ -55,23 +56,23 @@ 'typing.TypeVar', 'typing.Union', 'typing.cast', -} # type: Final +} -ARG_CONSTRUCTOR_NAMES = { +ARG_CONSTRUCTOR_NAMES: Final = { ARG_POS: "Arg", ARG_OPT: "DefaultArg", ARG_NAMED: "NamedArg", ARG_NAMED_OPT: "DefaultNamedArg", ARG_STAR: "VarArg", ARG_STAR2: "KwArg", -} # type: Final +} # Map from the full name of a missing definition to the test fixture (under # test-data/unit/fixtures/) that provides the definition. This is used for # generating better error messages when running mypy tests only. -SUGGESTED_TEST_FIXTURES = { +SUGGESTED_TEST_FIXTURES: Final = { 'builtins.list': 'list.pyi', 'builtins.dict': 'dict.pyi', 'builtins.set': 'set.pyi', @@ -82,7 +83,7 @@ 'builtins.isinstance': 'isinstancelist.pyi', 'builtins.property': 'property.pyi', 'builtins.classmethod': 'classmethod.pyi', -} # type: Final +} class MessageBuilder: @@ -98,9 +99,9 @@ class MessageBuilder: # Report errors using this instance. It knows about the current file and # import context. - errors = None # type: Errors + errors: Errors - modules = None # type: Dict[str, MypyFile] + modules: Dict[str, MypyFile] # Number of times errors have been disabled. disable_count = 0 @@ -136,11 +137,13 @@ def add_errors(self, messages: 'MessageBuilder') -> None: for info in errs: self.errors.add_error_info(info) - def disable_errors(self) -> None: + @contextmanager + def disable_errors(self) -> Iterator[None]: self.disable_count += 1 - - def enable_errors(self) -> None: - self.disable_count -= 1 + try: + yield + finally: + self.disable_count -= 1 def is_errors(self) -> bool: return self.errors.is_errors() @@ -161,7 +164,8 @@ def report(self, code: Optional[ErrorCode] = None, file: Optional[str] = None, origin: Optional[Context] = None, - offset: int = 0) -> None: + offset: int = 0, + allow_dups: bool = False) -> None: """Report an error or note (unless disabled).""" if origin is not None: end_line = origin.end_line @@ -174,8 +178,7 @@ def report(self, context.get_column() if context else -1, msg, severity=severity, file=file, offset=offset, origin_line=origin.get_line() if origin else None, - end_line=end_line, - code=code) + end_line=end_line, code=code, allow_dups=allow_dups) def fail(self, msg: str, @@ -183,9 +186,11 @@ def fail(self, *, code: Optional[ErrorCode] = None, file: Optional[str] = None, - origin: Optional[Context] = None) -> None: + origin: Optional[Context] = None, + allow_dups: bool = False) -> None: """Report an error message (unless disabled).""" - self.report(msg, context, 'error', code=code, file=file, origin=origin) + self.report(msg, context, 'error', code=code, file=file, + origin=origin, allow_dups=allow_dups) def note(self, msg: str, @@ -193,19 +198,21 @@ def note(self, file: Optional[str] = None, origin: Optional[Context] = None, offset: int = 0, + allow_dups: bool = False, *, code: Optional[ErrorCode] = None) -> None: """Report a note (unless disabled).""" self.report(msg, context, 'note', file=file, origin=origin, - offset=offset, code=code) + offset=offset, allow_dups=allow_dups, code=code) def note_multiline(self, messages: str, context: Context, file: Optional[str] = None, origin: Optional[Context] = None, offset: int = 0, + allow_dups: bool = False, code: Optional[ErrorCode] = None) -> None: """Report as many notes as lines in the message (unless disabled).""" for msg in messages.splitlines(): self.report(msg, context, 'note', file=file, origin=origin, - offset=offset, code=code) + offset=offset, allow_dups=allow_dups, code=code) # # Specific operations @@ -282,8 +289,8 @@ def has_no_attr(self, # Explain that the problem is that the type of the function is not known. self.fail('Cannot call function of unknown type', context, code=codes.OPERATOR) else: - self.fail('{} not callable'.format(format_type(original_type)), context, - code=codes.OPERATOR) + self.fail(message_registry.NOT_CALLABLE.format( + format_type(original_type)), context, code=codes.OPERATOR) else: # The non-special case: a missing ordinary attribute. extra = '' @@ -338,6 +345,16 @@ def has_no_attr(self, self.fail('Item {} of {} has no attribute "{}"{}'.format( typ_format, orig_type_format, member, extra), context, code=codes.UNION_ATTR) + elif isinstance(original_type, TypeVarType): + bound = get_proper_type(original_type.upper_bound) + if isinstance(bound, UnionType): + typ_fmt, bound_fmt = format_type_distinctly(typ, bound) + original_type_fmt = format_type(original_type) + self.fail( + 'Item {} of the upper bound {} of type variable {} has no ' + 'attribute "{}"{}'.format( + typ_fmt, bound_fmt, original_type_fmt, member, extra), + context, code=codes.UNION_ATTR) return AnyType(TypeOfAny.from_error) def unsupported_operand_types(self, @@ -380,7 +397,7 @@ def unsupported_left_operand(self, op: str, typ: Type, self.fail(msg, context, code=codes.OPERATOR) def not_callable(self, typ: Type, context: Context) -> Type: - self.fail('{} not callable'.format(format_type(typ)), context) + self.fail(message_registry.NOT_CALLABLE.format(format_type(typ)), context) return AnyType(TypeOfAny.from_error) def untyped_function_call(self, callee: CallableType, context: Context) -> Type: @@ -394,7 +411,7 @@ def incompatible_argument(self, m: int, callee: CallableType, arg_type: Type, - arg_kind: int, + arg_kind: ArgKind, object_type: Optional[Type], context: Context, outer_context: Context) -> Optional[ErrorCode]: @@ -460,7 +477,7 @@ def incompatible_argument(self, msg = '' code = codes.MISC - notes = [] # type: List[str] + notes: List[str] = [] if callee_name == '': name = callee_name[1:-1] n -= 1 @@ -632,6 +649,7 @@ def missing_named_argument(self, callee: CallableType, context: Context, name: s def too_many_arguments(self, callee: CallableType, context: Context) -> None: msg = 'Too many arguments' + for_function(callee) self.fail(msg, context, code=codes.CALL_ARG) + self.maybe_note_about_special_args(callee, context) def too_many_arguments_from_typed_dict(self, callee: CallableType, @@ -651,6 +669,18 @@ def too_many_positional_arguments(self, callee: CallableType, context: Context) -> None: msg = 'Too many positional arguments' + for_function(callee) self.fail(msg, context) + self.maybe_note_about_special_args(callee, context) + + def maybe_note_about_special_args(self, callee: CallableType, context: Context) -> None: + # https://github.com/python/mypy/issues/11309 + first_arg = callee.def_extras.get('first_arg') + if first_arg and first_arg not in {'self', 'cls', 'mcs'}: + self.note( + 'Looks like the first special argument in a method ' + 'is not named "self", "cls", or "mcs", ' + 'maybe it is missing?', + context, + ) def unexpected_keyword_argument(self, callee: CallableType, name: str, arg_type: Type, context: Context) -> None: @@ -688,7 +718,7 @@ def duplicate_argument_value(self, callee: CallableType, index: int, def does_not_return_value(self, callee_type: Optional[Type], context: Context) -> None: """Report an error about use of an unusable type.""" - name = None # type: Optional[str] + name: Optional[str] = None callee_type = get_proper_type(callee_type) if isinstance(callee_type, FunctionLike): name = callable_name(callee_type) @@ -698,6 +728,9 @@ def does_not_return_value(self, callee_type: Optional[Type], context: Context) - else: self.fail('Function does not return a value', context, code=codes.FUNC_RETURNS_VALUE) + def underscore_function_call(self, context: Context) -> None: + self.fail('Calling function named "_" is not allowed', context) + def deleted_as_rvalue(self, typ: DeletedType, context: Context) -> None: """Report an error about using an deleted type as an rvalue.""" if typ.source is None: @@ -719,7 +752,6 @@ def deleted_as_lvalue(self, typ: DeletedType, context: Context) -> None: self.fail('Assignment to variable{} outside except: block'.format(s), context) def no_variant_matches_arguments(self, - plausible_targets: List[CallableType], overload: Overloaded, arg_types: List[Type], context: Context, @@ -743,8 +775,11 @@ def no_variant_matches_arguments(self, self.fail('No overload variant{} matches argument types {}' .format(name_str, arg_types_str), context, code=code) - self.pretty_overload_matches(plausible_targets, overload, context, offset=2, max_items=2, - code=code) + self.note( + 'Possible overload variant{}:'.format(plural_s(len(overload.items))), + context, code=code) + for item in overload.items: + self.note(pretty_callable(item), context, offset=4, code=code) def wrong_number_values_to_unpack(self, provided: int, expected: int, context: Context) -> None: @@ -763,7 +798,7 @@ def unpacking_strings_disallowed(self, context: Context) -> None: self.fail("Unpacking a string is disallowed", context) def type_not_iterable(self, type: Type, context: Context) -> None: - self.fail('"{}" object is not iterable'.format(type), context) + self.fail('{} object is not iterable'.format(format_type(type)), context) def incompatible_operator_assignment(self, op: str, context: Context) -> None: @@ -781,11 +816,54 @@ def overload_signature_incompatible_with_supertype( self.note(note_template.format(supertype), context, code=codes.OVERRIDE) def signature_incompatible_with_supertype( - self, name: str, name_in_super: str, supertype: str, - context: Context) -> None: + self, name: str, name_in_super: str, supertype: str, context: Context, + original: Optional[FunctionLike] = None, + override: Optional[FunctionLike] = None) -> None: + code = codes.OVERRIDE target = self.override_target(name, name_in_super, supertype) self.fail('Signature of "{}" incompatible with {}'.format( - name, target), context, code=codes.OVERRIDE) + name, target), context, code=code) + + INCLUDE_DECORATOR = True # Include @classmethod and @staticmethod decorators, if any + ALLOW_DUPS = True # Allow duplicate notes, needed when signatures are duplicates + ALIGN_OFFSET = 1 # One space, to account for the difference between error and note + OFFSET = 4 # Four spaces, so that notes will look like this: + # error: Signature of "f" incompatible with supertype "A" + # note: Superclass: + # note: def f(self) -> str + # note: Subclass: + # note: def f(self, x: str) -> None + if original is not None and isinstance(original, (CallableType, Overloaded)) \ + and override is not None and isinstance(override, (CallableType, Overloaded)): + self.note('Superclass:', context, offset=ALIGN_OFFSET + OFFSET, code=code) + self.pretty_callable_or_overload(original, context, offset=ALIGN_OFFSET + 2 * OFFSET, + add_class_or_static_decorator=INCLUDE_DECORATOR, + allow_dups=ALLOW_DUPS, code=code) + + self.note('Subclass:', context, offset=ALIGN_OFFSET + OFFSET, code=code) + self.pretty_callable_or_overload(override, context, offset=ALIGN_OFFSET + 2 * OFFSET, + add_class_or_static_decorator=INCLUDE_DECORATOR, + allow_dups=ALLOW_DUPS, code=code) + + def pretty_callable_or_overload(self, + tp: Union[CallableType, Overloaded], + context: Context, + *, + offset: int = 0, + add_class_or_static_decorator: bool = False, + allow_dups: bool = False, + code: Optional[ErrorCode] = None) -> None: + if isinstance(tp, CallableType): + if add_class_or_static_decorator: + decorator = pretty_class_or_static_decorator(tp) + if decorator is not None: + self.note(decorator, context, offset=offset, allow_dups=allow_dups, code=code) + self.note(pretty_callable(tp), context, + offset=offset, allow_dups=allow_dups, code=code) + elif isinstance(tp, Overloaded): + self.pretty_overload(tp, context, offset, + add_class_or_static_decorator=add_class_or_static_decorator, + allow_dups=allow_dups, code=code) def argument_incompatible_with_supertype( self, arg_num: int, name: str, type_name: Optional[str], @@ -904,6 +982,12 @@ def string_interpolation_with_star_and_key(self, context: Context) -> None: self.fail('String interpolation contains both stars and mapping keys', context, code=codes.STRING_FORMATTING) + def requires_int_or_single_byte(self, context: Context, + format_call: bool = False) -> None: + self.fail('"{}c" requires an integer in range(256) or a single byte' + .format(':' if format_call else '%'), + context, code=codes.STRING_FORMATTING) + def requires_int_or_char(self, context: Context, format_call: bool = False) -> None: self.fail('"{}c" requires int or char'.format(':' if format_call else '%'), @@ -1067,11 +1151,12 @@ def yield_from_invalid_operand_type(self, expr: Type, context: Context) -> Type: return AnyType(TypeOfAny.from_error) def invalid_signature(self, func_type: Type, context: Context) -> None: - self.fail('Invalid signature "{}"'.format(func_type), context) + self.fail('Invalid signature {}'.format(format_type(func_type)), context) def invalid_signature_for_special_method( self, func_type: Type, context: Context, method_name: str) -> None: - self.fail('Invalid signature "{}" for "{}"'.format(func_type, method_name), context) + self.fail('Invalid signature {} for "{}"'.format(format_type(func_type), method_name), + context) def reveal_type(self, typ: Type, context: Context) -> None: self.note('Revealed type is "{}"'.format(typ), context) @@ -1181,7 +1266,7 @@ def typeddict_key_not_found( matches = best_matches(item_name, typ.items.keys()) if matches: self.note("Did you mean {}?".format( - pretty_seq(matches[:3], "or")), context) + pretty_seq(matches[:3], "or")), context, code=codes.TYPEDDICT_ITEM) def typeddict_context_ambiguous( self, @@ -1347,9 +1432,11 @@ def report_protocol_problems(self, # note: method, attr MAX_ITEMS = 2 # Maximum number of conflicts, missing members, and overloads shown # List of special situations where we don't want to report additional problems - exclusions = {TypedDictType: ['typing.Mapping'], - TupleType: ['typing.Iterable', 'typing.Sequence'], - Instance: []} # type: Dict[type, List[str]] + exclusions: Dict[type, List[str]] = { + TypedDictType: ["typing.Mapping"], + TupleType: ["typing.Iterable", "typing.Sequence"], + Instance: [], + } if supertype.type.fullname in exclusions[type(subtype)]: return if any(isinstance(tp, UninhabitedType) for tp in get_proper_types(supertype.args)): @@ -1404,13 +1491,13 @@ def report_protocol_problems(self, self.note(pretty_callable(exp), context, offset=2 * OFFSET, code=code) else: assert isinstance(exp, Overloaded) - self.pretty_overload(exp, context, OFFSET, MAX_ITEMS, code=code) + self.pretty_overload(exp, context, 2 * OFFSET, code=code) self.note('Got:', context, offset=OFFSET, code=code) if isinstance(got, CallableType): self.note(pretty_callable(got), context, offset=2 * OFFSET, code=code) else: assert isinstance(got, Overloaded) - self.pretty_overload(got, context, OFFSET, MAX_ITEMS, code=code) + self.pretty_overload(got, context, 2 * OFFSET, code=code) self.print_more(conflict_types, context, OFFSET, MAX_ITEMS, code=code) # Report flag conflicts (i.e. settable vs read-only etc.) @@ -1442,52 +1529,20 @@ def pretty_overload(self, tp: Overloaded, context: Context, offset: int, - max_items: int, *, + add_class_or_static_decorator: bool = False, + allow_dups: bool = False, code: Optional[ErrorCode] = None) -> None: - for item in tp.items()[:max_items]: - self.note('@overload', context, offset=2 * offset, code=code) - self.note(pretty_callable(item), context, offset=2 * offset, code=code) - left = len(tp.items()) - max_items - if left > 0: - msg = '<{} more overload{} not shown>'.format(left, plural_s(left)) - self.note(msg, context, offset=2 * offset, code=code) - - def pretty_overload_matches(self, - targets: List[CallableType], - func: Overloaded, - context: Context, - offset: int, - max_items: int, - code: ErrorCode) -> None: - if not targets: - targets = func.items() - - shown = min(max_items, len(targets)) - max_matching = len(targets) - max_available = len(func.items()) - - # If there are 3 matches but max_items == 2, we might as well show - # all three items instead of having the 3rd item be an error message. - if shown + 1 == max_matching: - shown = max_matching - - self.note('Possible overload variant{}:'.format(plural_s(shown)), context, code=code) - for item in targets[:shown]: - self.note(pretty_callable(item), context, offset=2 * offset, code=code) - - assert shown <= max_matching <= max_available - if shown < max_matching <= max_available: - left = max_matching - shown - msg = '<{} more similar overload{} not shown, out of {} total overloads>'.format( - left, plural_s(left), max_available) - self.note(msg, context, offset=2 * offset, code=code) - elif shown == max_matching < max_available: - left = max_available - shown - msg = '<{} more non-matching overload{} not shown>'.format(left, plural_s(left)) - self.note(msg, context, offset=2 * offset, code=code) - else: - assert shown == max_matching == max_available + for item in tp.items: + self.note('@overload', context, offset=offset, allow_dups=allow_dups, code=code) + + if add_class_or_static_decorator: + decorator = pretty_class_or_static_decorator(item) + if decorator is not None: + self.note(decorator, context, offset=offset, allow_dups=allow_dups, code=code) + + self.note(pretty_callable(item), context, + offset=offset, allow_dups=allow_dups, code=code) def print_more(self, conflicts: Sequence[Any], @@ -1559,8 +1614,8 @@ def generate_incompatible_tuple_error(self, for i, (lhs_t, rhs_t) in enumerate(zip(lhs_types, rhs_types)): if not is_subtype(lhs_t, rhs_t): if error_cnt < 3: - notes.append('Expression tuple item {} has type "{}"; "{}" expected; ' - .format(str(i), format_type_bare(rhs_t), format_type_bare(lhs_t))) + notes.append('Expression tuple item {} has type {}; {} expected; ' + .format(str(i), format_type(rhs_t), format_type(lhs_t))) error_cnt += 1 error_msg = msg + ' ({} tuple items are incompatible'.format(str(error_cnt)) @@ -1630,7 +1685,7 @@ def format(typ: Type) -> str: return '{}[{}]'.format(alias, ', '.join(items)) else: # There are type arguments. Convert the arguments to strings. - a = [] # type: List[str] + a: List[str] = [] for arg in itype.args: a.append(format(arg)) s = ', '.join(a) @@ -1638,6 +1693,8 @@ def format(typ: Type) -> str: elif isinstance(typ, TypeVarType): # This is similar to non-generic instance types. return typ.name + elif isinstance(typ, ParamSpecType): + return typ.name_with_suffix() elif isinstance(typ, TupleType): # Prefer the name of the fallback class (if not tuple), as it's more informative. if typ.partial_fallback.type.fullname != 'builtins.tuple': @@ -1697,21 +1754,27 @@ def format(typ: Type) -> str: if func.is_type_obj(): # The type of a type object type can be derived from the # return type (this always works). - return format(TypeType.make_normalized(erase_type(func.items()[0].ret_type))) + return format(TypeType.make_normalized(erase_type(func.items[0].ret_type))) elif isinstance(func, CallableType): - return_type = format(func.ret_type) + if func.type_guard is not None: + return_type = f'TypeGuard[{format(func.type_guard)}]' + else: + return_type = format(func.ret_type) if func.is_ellipsis_args: return 'Callable[..., {}]'.format(return_type) + param_spec = func.param_spec() + if param_spec is not None: + return f'Callable[{param_spec.name}, {return_type}]' arg_strings = [] for arg_name, arg_type, arg_kind in zip( func.arg_names, func.arg_types, func.arg_kinds): if (arg_kind == ARG_POS and arg_name is None - or verbosity == 0 and arg_kind in (ARG_POS, ARG_OPT)): + or verbosity == 0 and arg_kind.is_positional()): arg_strings.append(format(arg_type)) else: constructor = ARG_CONSTRUCTOR_NAMES[arg_kind] - if arg_kind in (ARG_STAR, ARG_STAR2) or arg_name is None: + if arg_kind.is_star() or arg_name is None: arg_strings.append("{}({})".format( constructor, format(arg_type))) @@ -1749,7 +1812,7 @@ def collect_all_instances(t: Type) -> List[Instance]: class CollectAllInstancesQuery(TypeTraverserVisitor): def __init__(self) -> None: - self.instances = [] # type: List[Instance] + self.instances: List[Instance] = [] def visit_instance(self, t: Instance) -> None: self.instances.append(t) @@ -1762,7 +1825,7 @@ def find_type_overlaps(*types: Type) -> Set[str]: This is used to ensure that distinct types with the same short name are printed with their fullname. """ - d = {} # type: Dict[str, Set[str]] + d: Dict[str, Set[str]] = {} for type in types: for inst in collect_all_instances(type): d.setdefault(inst.type.name, set()).add(inst.type.fullname) @@ -1770,7 +1833,7 @@ def find_type_overlaps(*types: Type) -> Set[str]: if 'typing.{}'.format(shortname) in TYPES_FOR_UNIMPORTED_HINTS: d[shortname].add('typing.{}'.format(shortname)) - overlaps = set() # type: Set[str] + overlaps: Set[str] = set() for fullnames in d.values(): if len(fullnames) > 1: overlaps.update(fullnames) @@ -1834,6 +1897,16 @@ def format_type_distinctly(*types: Type, bare: bool = False) -> Tuple[str, ...]: return tuple(quote_type_string(s) for s in strs) +def pretty_class_or_static_decorator(tp: CallableType) -> Optional[str]: + """Return @classmethod or @staticmethod, if any, for the given callable type.""" + if tp.definition is not None and isinstance(tp.definition, SYMBOL_FUNCBASE_TYPES): + if tp.definition.is_class: + return '@classmethod' + if tp.definition.is_static: + return '@staticmethod' + return None + + def pretty_callable(tp: CallableType) -> str: """Return a nice easily-readable representation of a callable type. For example: @@ -1844,7 +1917,7 @@ def [T <: int] f(self, x: int, y: T) -> None for i in range(len(tp.arg_types)): if s: s += ', ' - if tp.arg_kinds[i] in (ARG_NAMED, ARG_NAMED_OPT) and not asterisk: + if tp.arg_kinds[i].is_named() and not asterisk: s += '*, ' asterisk = True if tp.arg_kinds[i] == ARG_STAR: @@ -1856,14 +1929,14 @@ def [T <: int] f(self, x: int, y: T) -> None if name: s += name + ': ' s += format_type_bare(tp.arg_types[i]) - if tp.arg_kinds[i] in (ARG_OPT, ARG_NAMED_OPT): + if tp.arg_kinds[i].is_optional(): s += ' = ...' # If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list if isinstance(tp.definition, FuncDef) and tp.definition.name is not None: - definition_args = tp.definition.arg_names + definition_args = [arg.variable.name for arg in tp.definition.arguments] if definition_args and tp.arg_names != definition_args \ - and len(definition_args) > 0: + and len(definition_args) > 0 and definition_args[0]: if s: s = ', ' + s s = definition_args[0] + s @@ -1878,11 +1951,16 @@ def [T <: int] f(self, x: int, y: T) -> None else: s = '({})'.format(s) - s += ' -> ' + format_type_bare(tp.ret_type) + s += ' -> ' + if tp.type_guard is not None: + s += 'TypeGuard[{}]'.format(format_type_bare(tp.type_guard)) + else: + s += format_type_bare(tp.ret_type) + if tp.variables: tvars = [] for tvar in tp.variables: - if isinstance(tvar, TypeVarDef): + if isinstance(tvar, TypeVarType): upper_bound = get_proper_type(tvar.upper_bound) if (isinstance(upper_bound, Instance) and upper_bound.type.fullname != 'builtins.object'): @@ -1894,7 +1972,7 @@ def [T <: int] f(self, x: int, y: T) -> None else: tvars.append(tvar.name) else: - # For other TypeVarLikeDefs, just use the repr + # For other TypeVarLikeTypes, just use the repr tvars.append(repr(tvar)) s = '[{}] {}'.format(', '.join(tvars), s) return 'def {}'.format(s) @@ -1914,7 +1992,7 @@ def get_missing_protocol_members(left: Instance, right: Instance) -> List[str]: (i.e. completely missing) in 'left'. """ assert right.type.is_protocol - missing = [] # type: List[str] + missing: List[str] = [] for member in right.type.protocol_members: if not find_member(member, left, left): missing.append(member) @@ -1926,7 +2004,7 @@ def get_conflict_protocol_types(left: Instance, right: Instance) -> List[Tuple[s Return them as a list of ('member', 'got', 'expected'). """ assert right.type.is_protocol - conflicts = [] # type: List[Tuple[str, Type, Type]] + conflicts: List[Tuple[str, Type, Type]] = [] for member in right.type.protocol_members: if member in ('__init__', '__new__'): continue @@ -1949,7 +2027,7 @@ def get_bad_protocol_flags(left: Instance, right: Instance 'left' and 'right'. """ assert right.type.is_protocol - all_flags = [] # type: List[Tuple[str, Set[int], Set[int]]] + all_flags: List[Tuple[str, Set[int], Set[int]]] = [] for member in right.type.protocol_members: if find_member(member, left, left): item = (member, @@ -2046,15 +2124,10 @@ def find_defining_module(modules: Dict[str, MypyFile], typ: CallableType) -> Opt return None -def temp_message_builder() -> MessageBuilder: - """Return a message builder usable for throwaway errors (which may not format properly).""" - return MessageBuilder(Errors(), {}) - - # For hard-coding suggested missing member alternatives. -COMMON_MISTAKES = { +COMMON_MISTAKES: Final[Dict[str, Sequence[str]]] = { 'add': ('append', 'extend'), -} # type: Final[Dict[str, Sequence[str]]] +} def best_matches(current: str, options: Iterable[str]) -> List[str]: diff --git a/mypy/metastore.py b/mypy/metastore.py index a75d6b2ffdba..3d4cdeff3400 100644 --- a/mypy/metastore.py +++ b/mypy/metastore.py @@ -146,8 +146,7 @@ def list_all(self) -> Iterable[str]: CREATE INDEX IF NOT EXISTS path_idx on files(path); ''' # No migrations yet -MIGRATIONS = [ -] # type: List[str] +MIGRATIONS: List[str] = [] def connect_db(db_file: str) -> 'sqlite3.Connection': diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 41e60cedb5cd..8dcaee6f99d6 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -10,15 +10,15 @@ import re import subprocess import sys -from enum import Enum +from enum import Enum, unique from typing import Dict, Iterator, List, NamedTuple, Optional, Set, Tuple, Union -from typing_extensions import Final +from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.fscache import FileSystemCache from mypy.options import Options -from mypy.stubinfo import legacy_bundled_packages -from mypy import sitepkgs +from mypy.stubinfo import is_legacy_bundled_package +from mypy import pyinfo # Paths to be searched in find_module(). SearchPaths = NamedTuple( @@ -33,14 +33,18 @@ OnePackageDir = Tuple[str, bool] PackageDirs = List[OnePackageDir] -PYTHON_EXTENSIONS = ['.pyi', '.py'] # type: Final +# Minimum and maximum Python versions for modules in stdlib as (major, minor) +StdlibVersions: _TypeAlias = Dict[str, Tuple[Tuple[int, int], Optional[Tuple[int, int]]]] -PYTHON2_STUB_DIR = '@python2' # type: Final +PYTHON_EXTENSIONS: Final = [".pyi", ".py"] + +PYTHON2_STUB_DIR: Final = "@python2" # TODO: Consider adding more reasons here? # E.g. if we deduce a module would likely be found if the user were # to set the --namespace-packages flag. +@unique class ModuleNotFoundReason(Enum): # The module was not found: we found neither stubs nor a plausible code # implementation (with or without a py.typed file). @@ -69,7 +73,10 @@ def error_message_templates(self, daemon: bool) -> Tuple[str, List[str]]: notes = ["You may be running mypy in a subpackage, " "mypy should be run on the package root"] elif self is ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS: - msg = 'Skipping analyzing "{module}": found module but no type hints or library stubs' + msg = ( + 'Skipping analyzing "{module}": module is installed, but missing library stubs ' + 'or py.typed marker' + ) notes = [doc_link] elif self is ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED: msg = ( @@ -122,21 +129,24 @@ class FindModuleCache: def __init__(self, search_paths: SearchPaths, fscache: Optional[FileSystemCache], - options: Optional[Options]) -> None: + options: Optional[Options], + stdlib_py_versions: Optional[StdlibVersions] = None) -> None: self.search_paths = search_paths self.fscache = fscache or FileSystemCache() # Cache for get_toplevel_possibilities: # search_paths -> (toplevel_id -> list(package_dirs)) - self.initial_components = {} # type: Dict[Tuple[str, ...], Dict[str, List[str]]] + self.initial_components: Dict[Tuple[str, ...], Dict[str, List[str]]] = {} # Cache find_module: id -> result - self.results = {} # type: Dict[str, ModuleSearchResult] - self.ns_ancestors = {} # type: Dict[str, str] + self.results: Dict[str, ModuleSearchResult] = {} + self.ns_ancestors: Dict[str, str] = {} self.options = options custom_typeshed_dir = None if options: custom_typeshed_dir = options.custom_typeshed_dir - self.stdlib_py_versions = load_stdlib_py_versions(custom_typeshed_dir) - self.python2 = options and options.python_version[0] == 2 + self.stdlib_py_versions = ( + stdlib_py_versions or load_stdlib_py_versions(custom_typeshed_dir) + ) + self.python_major_ver = 3 if options is None else options.python_version[0] def clear(self) -> None: self.results.clear() @@ -174,7 +184,7 @@ def get_toplevel_possibilities(self, lib_path: Tuple[str, ...], id: str) -> List return self.initial_components[lib_path].get(id, []) # Enumerate all the files in the directories on lib_path and produce the map - components = {} # type: Dict[str, List[str]] + components: Dict[str, List[str]] = {} for dir in lib_path: try: contents = self.fscache.listdir(dir) @@ -187,7 +197,7 @@ def get_toplevel_possibilities(self, lib_path: Tuple[str, ...], id: str) -> List name = os.path.splitext(name)[0] components.setdefault(name, []).append(dir) - if self.python2: + if self.python_major_ver == 2: components = {id: filter_redundant_py2_dirs(dirs) for id, dirs in components.items()} @@ -203,7 +213,9 @@ def find_module(self, id: str, *, fast_path: bool = False) -> ModuleSearchResult if id not in self.results: top_level = id.partition('.')[0] use_typeshed = True - if top_level in self.stdlib_py_versions: + if id in self.stdlib_py_versions: + use_typeshed = self._typeshed_has_version(id) + elif top_level in self.stdlib_py_versions: use_typeshed = self._typeshed_has_version(top_level) self.results[id] = self._find_module(id, use_typeshed) if (not fast_path @@ -230,9 +242,14 @@ def _find_module_non_stub_helper(self, components: List[str], elif not plausible_match and (self.fscache.isdir(dir_path) or self.fscache.isfile(dir_path + ".py")): plausible_match = True - if components[0] in legacy_bundled_packages: + if is_legacy_bundled_package(components[0], self.python_major_ver): + if (len(components) == 1 + or (self.find_module(components[0]) is + ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED)): + return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED + if is_legacy_bundled_package('.'.join(components[:2]), self.python_major_ver): return ModuleNotFoundReason.APPROVED_STUBS_NOT_INSTALLED - elif plausible_match: + if plausible_match: return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS else: return ModuleNotFoundReason.NOT_FOUND @@ -250,7 +267,12 @@ def _can_find_module_in_parent_dir(self, id: str) -> bool: of the current working directory. """ working_dir = os.getcwd() - parent_search = FindModuleCache(SearchPaths((), (), (), ()), self.fscache, self.options) + parent_search = FindModuleCache( + SearchPaths((), (), (), ()), + self.fscache, + self.options, + stdlib_py_versions=self.stdlib_py_versions + ) while any(file.endswith(("__init__.py", "__init__.pyi")) for file in os.listdir(working_dir)): working_dir = os.path.dirname(working_dir) @@ -271,15 +293,15 @@ def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult: # We have two sets of folders so that we collect *all* stubs folders and # put them in the front of the search path - third_party_inline_dirs = [] # type: PackageDirs - third_party_stubs_dirs = [] # type: PackageDirs + third_party_inline_dirs: PackageDirs = [] + third_party_stubs_dirs: PackageDirs = [] found_possible_third_party_missing_type_hints = False need_installed_stubs = False # Third-party stub/typed packages for pkg_dir in self.search_paths.package_path: stub_name = components[0] + '-stubs' stub_dir = os.path.join(pkg_dir, stub_name) - if self.python2: + if self.python_major_ver == 2: alt_stub_name = components[0] + '-python2-stubs' alt_stub_dir = os.path.join(pkg_dir, alt_stub_name) if fscache.isdir(alt_stub_dir): @@ -347,7 +369,7 @@ def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult: for extension in PYTHON_EXTENSIONS: path = base_path + sepinit + extension suffix = '-stubs' - if self.python2: + if self.python_major_ver == 2: if os.path.isdir(base_path + '-python2-stubs'): suffix = '-python2-stubs' path_stubs = base_path + suffix + sepinit + extension @@ -365,7 +387,7 @@ def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult: # In namespace mode, register a potential namespace package if self.options and self.options.namespace_packages: - if fscache.isdir(base_path) and not has_init: + if fscache.exists_case(base_path, dir_prefix) and not has_init: near_misses.append((base_path, dir_prefix)) # No package, look for module. @@ -428,10 +450,10 @@ def _is_compatible_stub_package(self, stub_dir: str) -> bool: metadata_fnam = os.path.join(stub_dir, 'METADATA.toml') if os.path.isfile(metadata_fnam): # Delay import for a possible minor performance win. - import toml - with open(metadata_fnam, 'r') as f: - metadata = toml.load(f) - if self.python2: + import tomli + with open(metadata_fnam, encoding="utf-8") as f: + metadata = tomli.loads(f.read()) + if self.python_major_ver == 2: return bool(metadata.get('python2', False)) else: return bool(metadata.get('python3', True)) @@ -456,7 +478,7 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]: # calls find_module, which will handle the preference between packages, pyi and py. # Another difference is it doesn't handle nested search paths / package roots. - seen = set() # type: Set[str] + seen: Set[str] = set() names = sorted(self.fscache.listdir(package_path)) for name in names: # Skip certain names altogether @@ -489,16 +511,21 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]: return sources -def matches_exclude(subpath: str, exclude: str, fscache: FileSystemCache, verbose: bool) -> bool: - if not exclude: +def matches_exclude(subpath: str, + excludes: List[str], + fscache: FileSystemCache, + verbose: bool) -> bool: + if not excludes: return False subpath_str = os.path.relpath(subpath).replace(os.sep, "/") if fscache.isdir(subpath): subpath_str += "/" - if re.search(exclude, subpath_str): - if verbose: - print("TRACE: Excluding {}".format(subpath_str), file=sys.stderr) - return True + for exclude in excludes: + if re.search(exclude, subpath_str): + if verbose: + print("TRACE: Excluding {} (matches pattern {})".format(subpath_str, exclude), + file=sys.stderr) + return True return False @@ -540,7 +567,7 @@ def default_lib_path(data_dir: str, pyversion: Tuple[int, int], custom_typeshed_dir: Optional[str]) -> List[str]: """Return default standard library search paths.""" - path = [] # type: List[str] + path: List[str] = [] if custom_typeshed_dir: typeshed_dir = os.path.join(custom_typeshed_dir, "stdlib") @@ -577,6 +604,27 @@ def default_lib_path(data_dir: str, return path +@functools.lru_cache(maxsize=None) +def get_prefixes(python_executable: Optional[str]) -> Tuple[str, str]: + """Get the sys.base_prefix and sys.prefix for the given python. + + This runs a subprocess call to get the prefix paths of the given Python executable. + To avoid repeatedly calling a subprocess (which can be slow!) we + lru_cache the results. + """ + if python_executable is None: + return '', '' + elif python_executable == sys.executable: + # Use running Python's package dirs + return pyinfo.getprefixes() + else: + # Use subprocess to get the package directory of given Python + # executable + return ast.literal_eval( + subprocess.check_output([python_executable, pyinfo.__file__, 'getprefixes'], + stderr=subprocess.PIPE).decode()) + + @functools.lru_cache(maxsize=None) def get_site_packages_dirs(python_executable: Optional[str]) -> Tuple[List[str], List[str]]: """Find package directories for given python. @@ -590,19 +638,19 @@ def get_site_packages_dirs(python_executable: Optional[str]) -> Tuple[List[str], return [], [] elif python_executable == sys.executable: # Use running Python's package dirs - site_packages = sitepkgs.getsitepackages() + site_packages = pyinfo.getsitepackages() else: # Use subprocess to get the package directory of given Python # executable site_packages = ast.literal_eval( - subprocess.check_output([python_executable, sitepkgs.__file__], + subprocess.check_output([python_executable, pyinfo.__file__, 'getsitepackages'], stderr=subprocess.PIPE).decode()) return expand_site_packages(site_packages) def expand_site_packages(site_packages: List[str]) -> Tuple[List[str], List[str]]: """Expands .pth imports in site-packages directories""" - egg_dirs = [] # type: List[str] + egg_dirs: List[str] = [] for dir in site_packages: if not os.path.isdir(dir): continue @@ -692,7 +740,7 @@ def compute_search_paths(sources: List[BuildSource], lib_path.appendleft(os.path.join(root_dir, 'test-data', 'unit', 'lib-stub')) # alt_lib_path is used by some tests to bypass the normal lib_path mechanics. # If we don't have one, grab directories of source files. - python_path = [] # type: List[str] + python_path: List[str] = [] if not alt_lib_path: for source in sources: # Include directory of the program file in the module search path. @@ -731,6 +779,8 @@ def compute_search_paths(sources: List[BuildSource], mypypath = add_py2_mypypath_entries(mypypath) egg_dirs, site_packages = get_site_packages_dirs(options.python_executable) + base_prefix, prefix = get_prefixes(options.python_executable) + is_venv = base_prefix != prefix for site_dir in site_packages: assert site_dir not in lib_path if (site_dir in mypypath or @@ -740,7 +790,7 @@ def compute_search_paths(sources: List[BuildSource], print("See https://mypy.readthedocs.io/en/stable/running_mypy.html" "#how-mypy-handles-imports for more info", file=sys.stderr) sys.exit(1) - elif site_dir in python_path: + elif site_dir in python_path and (is_venv and not site_dir.startswith(prefix)): print("{} is in the PYTHONPATH. Please change directory" " so it is not.".format(site_dir), file=sys.stderr) @@ -752,8 +802,7 @@ def compute_search_paths(sources: List[BuildSource], typeshed_path=tuple(lib_path)) -def load_stdlib_py_versions(custom_typeshed_dir: Optional[str] - ) -> Dict[str, Tuple[Tuple[int, int], Optional[Tuple[int, int]]]]: +def load_stdlib_py_versions(custom_typeshed_dir: Optional[str]) -> StdlibVersions: """Return dict with minimum and maximum Python versions of stdlib modules. The contents look like diff --git a/mypy/moduleinspect.py b/mypy/moduleinspect.py index 94491de4d804..ebcbb25ea5e5 100644 --- a/mypy/moduleinspect.py +++ b/mypy/moduleinspect.py @@ -45,9 +45,9 @@ def get_package_properties(package_id: str) -> ModuleProperties: package = importlib.import_module(package_id) except BaseException as e: raise InspectError(str(e)) from e - name = getattr(package, '__name__', package_id) - file = getattr(package, '__file__', None) - path = getattr(package, '__path__', None) # type: Optional[List[str]] + name = getattr(package, "__name__", package_id) + file = getattr(package, "__file__", None) + path: Optional[List[str]] = getattr(package, "__path__", None) if not isinstance(path, list): path = None pkg_all = getattr(package, '__all__', None) @@ -118,8 +118,8 @@ def __init__(self) -> None: self._start() def _start(self) -> None: - self.tasks = Queue() # type: Queue[str] - self.results = Queue() # type: Queue[Union[ModuleProperties, str]] + self.tasks: Queue[str] = Queue() + self.results: Queue[Union[ModuleProperties, str]] = Queue() self.proc = Process(target=worker, args=(self.tasks, self.results, sys.path)) self.proc.start() self.counter = 0 # Number of successful roundtrips diff --git a/mypy/mro.py b/mypy/mro.py index 59c53996e628..2aeb96e4e756 100644 --- a/mypy/mro.py +++ b/mypy/mro.py @@ -44,7 +44,7 @@ def linearize_hierarchy(info: TypeInfo, def merge(seqs: List[List[TypeInfo]]) -> List[TypeInfo]: seqs = [s[:] for s in seqs] - result = [] # type: List[TypeInfo] + result: List[TypeInfo] = [] while True: seqs = [s for s in seqs if s] if not seqs: diff --git a/mypy/nodes.py b/mypy/nodes.py index a50c76ca06cd..78a018f94a78 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1,13 +1,14 @@ """Abstract syntax tree node classes (i.e. parse tree).""" import os +from enum import Enum, unique from abc import abstractmethod -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from collections import defaultdict from typing import ( Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional, Callable, Sequence, Iterator ) -from typing_extensions import DefaultDict, Final, TYPE_CHECKING +from typing_extensions import DefaultDict, Final, TYPE_CHECKING, TypeAlias as _TypeAlias from mypy_extensions import trait import mypy.strconv @@ -24,7 +25,7 @@ class Context: def __init__(self, line: int = -1, column: int = -1) -> None: self.line = line self.column = column - self.end_line = None # type: Optional[int] + self.end_line: Optional[int] = None def set_line(self, target: Union['Context', int], @@ -63,49 +64,52 @@ def get_column(self) -> int: T = TypeVar('T') -JsonDict = Dict[str, Any] +JsonDict: _TypeAlias = Dict[str, Any] # Symbol table node kinds # # TODO rename to use more descriptive names -LDEF = 0 # type: Final -GDEF = 1 # type: Final -MDEF = 2 # type: Final +LDEF: Final = 0 +GDEF: Final = 1 +MDEF: Final = 2 # Placeholder for a name imported via 'from ... import'. Second phase of # semantic will replace this the actual imported reference. This is # needed so that we can detect whether a name has been imported during # XXX what? -UNBOUND_IMPORTED = 3 # type: Final +UNBOUND_IMPORTED: Final = 3 # RevealExpr node kinds -REVEAL_TYPE = 0 # type: Final -REVEAL_LOCALS = 1 # type: Final +REVEAL_TYPE: Final = 0 +REVEAL_LOCALS: Final = 1 -LITERAL_YES = 2 # type: Final -LITERAL_TYPE = 1 # type: Final -LITERAL_NO = 0 # type: Final +LITERAL_YES: Final = 2 +LITERAL_TYPE: Final = 1 +LITERAL_NO: Final = 0 -node_kinds = { +node_kinds: Final = { LDEF: 'Ldef', GDEF: 'Gdef', MDEF: 'Mdef', UNBOUND_IMPORTED: 'UnboundImported', -} # type: Final -inverse_node_kinds = {_kind: _name for _name, _kind in node_kinds.items()} # type: Final +} +inverse_node_kinds: Final = {_kind: _name for _name, _kind in node_kinds.items()} -implicit_module_attrs = {'__name__': '__builtins__.str', - '__doc__': None, # depends on Python version, see semanal.py - '__file__': '__builtins__.str', - '__package__': '__builtins__.str'} # type: Final +implicit_module_attrs: Final = { + '__name__': '__builtins__.str', + '__doc__': None, # depends on Python version, see semanal.py + '__path__': None, # depends on if the module is a package + '__file__': '__builtins__.str', + '__package__': '__builtins__.str' +} # These aliases exist because built-in class objects are not subscriptable. # For example `list[int]` fails at runtime. Instead List[int] should be used. -type_aliases = { +type_aliases: Final = { 'typing.List': 'builtins.list', 'typing.Dict': 'builtins.dict', 'typing.Set': 'builtins.set', @@ -115,11 +119,11 @@ def get_column(self) -> int: 'typing.DefaultDict': 'collections.defaultdict', 'typing.Deque': 'collections.deque', 'typing.OrderedDict': 'collections.OrderedDict', -} # type: Final +} # This keeps track of the oldest supported Python version where the corresponding # alias source is available. -type_aliases_source_versions = { +type_aliases_source_versions: Final = { 'typing.List': (2, 7), 'typing.Dict': (2, 7), 'typing.Set': (2, 7), @@ -129,17 +133,22 @@ def get_column(self) -> int: 'typing.DefaultDict': (2, 7), 'typing.Deque': (2, 7), 'typing.OrderedDict': (3, 7), -} # type: Final +} -reverse_builtin_aliases = { +# This keeps track of aliases in `typing_extensions`, which we treat specially. +typing_extensions_aliases: Final = { + # See: https://github.com/python/mypy/issues/11528 + 'typing_extensions.OrderedDict': 'collections.OrderedDict', +} + +reverse_builtin_aliases: Final = { 'builtins.list': 'typing.List', 'builtins.dict': 'typing.Dict', 'builtins.set': 'typing.Set', 'builtins.frozenset': 'typing.FrozenSet', -} # type: Final +} -_nongen_builtins = {'builtins.tuple': 'typing.Tuple', - 'builtins.enumerate': ''} # type: Final +_nongen_builtins: Final = {"builtins.tuple": "typing.Tuple", "builtins.enumerate": ""} _nongen_builtins.update((name, alias) for alias, name in type_aliases.items()) # Drop OrderedDict from this for backward compatibility del _nongen_builtins['collections.OrderedDict'] @@ -150,9 +159,11 @@ def get_nongen_builtins(python_version: Tuple[int, int]) -> Dict[str, str]: return _nongen_builtins if python_version < (3, 9) else {} -RUNTIME_PROTOCOL_DECOS = ('typing.runtime_checkable', - 'typing_extensions.runtime', - 'typing_extensions.runtime_checkable') # type: Final +RUNTIME_PROTOCOL_DECOS: Final = ( + "typing.runtime_checkable", + "typing_extensions.runtime", + "typing_extensions.runtime_checkable", +) class Node(Context): @@ -196,13 +207,14 @@ class FakeExpression(Expression): We need a dummy expression in one place, and can't instantiate Expression because it is a trait and mypyc barfs. """ - pass + + __slots__ = () # TODO: # Lvalue = Union['NameExpr', 'MemberExpr', 'IndexExpr', 'SuperExpr', 'StarExpr' # 'TupleExpr']; see #1783. -Lvalue = Expression +Lvalue: _TypeAlias = Expression @trait @@ -235,39 +247,43 @@ def deserialize(cls, data: JsonDict) -> 'SymbolNode': # Items: fullname, related symbol table node, surrounding type (if any) -Definition = Tuple[str, 'SymbolTableNode', Optional['TypeInfo']] +Definition: _TypeAlias = Tuple[str, 'SymbolTableNode', Optional['TypeInfo']] class MypyFile(SymbolNode): """The abstract syntax tree of a single source file.""" + __slots__ = ('_fullname', 'path', 'defs', 'alias_deps', + 'is_bom', 'names', 'imports', 'ignored_lines', 'is_stub', + 'is_cache_skeleton', 'is_partial_stub_package', 'plugin_deps') + # Fully qualified module name - _fullname = None # type: Bogus[str] + _fullname: Bogus[str] # Path to the file (empty string if not known) - path = '' + path: str # Top-level definitions and statements - defs = None # type: List[Statement] + defs: List[Statement] # Type alias dependencies as mapping from target to set of alias full names - alias_deps = None # type: DefaultDict[str, Set[str]] + alias_deps: DefaultDict[str, Set[str]] # Is there a UTF-8 BOM at the start? - is_bom = False - names = None # type: SymbolTable + is_bom: bool + names: "SymbolTable" # All import nodes within the file (also ones within functions etc.) - imports = None # type: List[ImportBase] + imports: List["ImportBase"] # Lines on which to ignore certain errors when checking. # If the value is empty, ignore all errors; otherwise, the list contains all # error codes to ignore. - ignored_lines = None # type: Dict[int, List[str]] + ignored_lines: Dict[int, List[str]] # Is this file represented by a stub file (.pyi)? - is_stub = False + is_stub: bool # Is this loaded from the cache and thus missing the actual body of the file? - is_cache_skeleton = False + is_cache_skeleton: bool # Does this represent an __init__.pyi stub with a module __getattr__ # (i.e. a partial stub package), for such packages we suppress any missing # module errors in addition to missing attribute errors. - is_partial_stub_package = False + is_partial_stub_package: bool # Plugin-created dependencies - plugin_deps = None # type: Dict[str, Set[str]] + plugin_deps: Dict[str, Set[str]] def __init__(self, defs: List[Statement], @@ -286,6 +302,11 @@ def __init__(self, else: self.ignored_lines = {} + self.path = '' + self.is_stub = False + self.is_cache_skeleton = False + self.is_partial_stub_package = False + def local_definitions(self) -> Iterator[Definition]: """Return all definitions within the module (including nested). @@ -332,9 +353,11 @@ def deserialize(cls, data: JsonDict) -> 'MypyFile': class ImportBase(Statement): """Base class for all import statements.""" - is_unreachable = False # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc. - is_top_level = False # Ditto if outside any class or def - is_mypy_only = False # Ditto if inside `if TYPE_CHECKING` or `if MYPY` + __slots__ = ('is_unreachable', 'is_top_level', 'is_mypy_only', 'assignments') + + is_unreachable: bool # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc. + is_top_level: bool # Ditto if outside any class or def + is_mypy_only: bool # Ditto if inside `if TYPE_CHECKING` or `if MYPY` # If an import replaces existing definitions, we construct dummy assignment # statements that assign the imported names to the names in the current scope, @@ -342,17 +365,22 @@ class ImportBase(Statement): # # x = 1 # from m import x <-- add assignment representing "x = m.x" - assignments = None # type: List[AssignmentStmt] + assignments: List["AssignmentStmt"] def __init__(self) -> None: super().__init__() self.assignments = [] + self.is_unreachable = False + self.is_top_level = False + self.is_mypy_only = False class Import(ImportBase): """import m [as n]""" - ids = None # type: List[Tuple[str, Optional[str]]] # (module id, as id) + __slots__ = ('ids',) + + ids: List[Tuple[str, Optional[str]]] # (module id, as id) def __init__(self, ids: List[Tuple[str, Optional[str]]]) -> None: super().__init__() @@ -365,9 +393,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class ImportFrom(ImportBase): """from m import x [as y], ...""" - id = None # type: str - relative = None # type: int - names = None # type: List[Tuple[str, Optional[str]]] # Tuples (name, as name) + __slots__ = ('id', 'names', 'relative') + + id: str + relative: int + names: List[Tuple[str, Optional[str]]] # Tuples (name, as name) def __init__(self, id: str, relative: int, names: List[Tuple[str, Optional[str]]]) -> None: super().__init__() @@ -381,10 +411,13 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class ImportAll(ImportBase): """from m import *""" - id = None # type: str - relative = None # type: int + + __slots__ = ('id', 'relative', 'imported_names') + + id: str + relative: int # NOTE: Only filled and used by old semantic analyzer. - imported_names = None # type: List[str] + imported_names: List[str] def __init__(self, id: str, relative: int) -> None: super().__init__() @@ -408,6 +441,8 @@ class ImportedName(SymbolNode): can't be visited. """ + __slots__ = ('target_fullname',) + def __init__(self, target_fullname: str) -> None: super().__init__() self.target_fullname = target_fullname @@ -431,9 +466,7 @@ def __str__(self) -> str: return 'ImportedName(%s)' % self.target_fullname -FUNCBASE_FLAGS = [ - 'is_property', 'is_class', 'is_static', 'is_final' -] # type: Final +FUNCBASE_FLAGS: Final = ["is_property", "is_class", "is_static", "is_final"] class FuncBase(Node): @@ -464,9 +497,9 @@ def __init__(self) -> None: super().__init__() # Type signature. This is usually CallableType or Overloaded, but it can be # something else for decorated functions. - self.type = None # type: Optional[mypy.types.ProperType] + self.type: Optional[mypy.types.ProperType] = None # Original, not semantically analyzed type (used for reprocessing) - self.unanalyzed_type = None # type: Optional[mypy.types.ProperType] + self.unanalyzed_type: Optional[mypy.types.ProperType] = None # If method, reference to TypeInfo # TODO: Type should be Optional[TypeInfo] self.info = FUNC_NO_INFO @@ -487,7 +520,7 @@ def fullname(self) -> Bogus[str]: return self._fullname -OverloadPart = Union['FuncDef', 'Decorator'] +OverloadPart: _TypeAlias = Union['FuncDef', 'Decorator'] class OverloadedFuncDef(FuncBase, SymbolNode, Statement): @@ -500,9 +533,11 @@ class OverloadedFuncDef(FuncBase, SymbolNode, Statement): Overloaded variants must be consecutive in the source file. """ - items = None # type: List[OverloadPart] - unanalyzed_items = None # type: List[OverloadPart] - impl = None # type: Optional[OverloadPart] + __slots__ = ('items', 'unanalyzed_items', 'impl') + + items: List[OverloadPart] + unanalyzed_items: List[OverloadPart] + impl: Optional[OverloadPart] def __init__(self, items: List['OverloadPart']) -> None: super().__init__() @@ -558,18 +593,20 @@ def deserialize(cls, data: JsonDict) -> 'OverloadedFuncDef': class Argument(Node): """A single argument in a FuncItem.""" - __slots__ = ('variable', 'type_annotation', 'initializer', 'kind') + __slots__ = ('variable', 'type_annotation', 'initializer', 'kind', 'pos_only') def __init__(self, variable: 'Var', type_annotation: 'Optional[mypy.types.Type]', initializer: Optional[Expression], - kind: int) -> None: + kind: 'ArgKind', + pos_only: bool = False) -> None: super().__init__() self.variable = variable self.type_annotation = type_annotation self.initializer = initializer self.kind = kind # must be an ARG_* constant + self.pos_only = pos_only def set_line(self, target: Union[Context, int], @@ -583,10 +620,10 @@ def set_line(self, self.variable.set_line(self.line, self.column, self.end_line) -FUNCITEM_FLAGS = FUNCBASE_FLAGS + [ +FUNCITEM_FLAGS: Final = FUNCBASE_FLAGS + [ 'is_overload', 'is_generator', 'is_coroutine', 'is_async_generator', 'is_awaitable_coroutine', -] # type: Final +] class FuncItem(FuncBase): @@ -608,24 +645,27 @@ class FuncItem(FuncBase): 'expanded', # Variants of function with type variables with values expanded ) + __deletable__ = ('arguments', 'max_pos', 'min_args') + def __init__(self, arguments: List[Argument], body: 'Block', typ: 'Optional[mypy.types.FunctionLike]' = None) -> None: super().__init__() self.arguments = arguments - self.arg_names = [arg.variable.name for arg in self.arguments] - self.arg_kinds = [arg.kind for arg in self.arguments] # type: List[int] - self.max_pos = self.arg_kinds.count(ARG_POS) + self.arg_kinds.count(ARG_OPT) - self.body = body + self.arg_names = [None if arg.pos_only else arg.variable.name for arg in arguments] + self.arg_kinds: List[ArgKind] = [arg.kind for arg in self.arguments] + self.max_pos: int = ( + self.arg_kinds.count(ARG_POS) + self.arg_kinds.count(ARG_OPT)) + self.body: 'Block' = body self.type = typ self.unanalyzed_type = typ - self.is_overload = False - self.is_generator = False - self.is_coroutine = False - self.is_async_generator = False - self.is_awaitable_coroutine = False - self.expanded = [] # type: List[FuncItem] + self.is_overload: bool = False + self.is_generator: bool = False + self.is_coroutine: bool = False + self.is_async_generator: bool = False + self.is_awaitable_coroutine: bool = False + self.expanded: List[FuncItem] = [] self.min_args = 0 for i in range(len(self.arguments)): @@ -647,9 +687,9 @@ def is_dynamic(self) -> bool: return self.type is None -FUNCDEF_FLAGS = FUNCITEM_FLAGS + [ +FUNCDEF_FLAGS: Final = FUNCITEM_FLAGS + [ 'is_decorated', 'is_conditional', 'is_abstract', -] # type: Final +] class FuncDef(FuncItem, SymbolNode, Statement): @@ -677,7 +717,7 @@ def __init__(self, self.is_abstract = False self.is_final = False # Original conditional definition - self.original_def = None # type: Union[None, FuncDef, Var, Decorator] + self.original_def: Union[None, FuncDef, Var, Decorator] = None @property def name(self) -> str: @@ -697,7 +737,7 @@ def serialize(self) -> JsonDict: 'name': self._name, 'fullname': self._fullname, 'arg_names': self.arg_names, - 'arg_kinds': self.arg_kinds, + 'arg_kinds': [int(x.value) for x in self.arg_kinds], 'type': None if self.type is None else self.type.serialize(), 'flags': get_flags(self, FUNCDEF_FLAGS), # TODO: Do we need expanded, original_def? @@ -717,7 +757,7 @@ def deserialize(cls, data: JsonDict) -> 'FuncDef': set_flags(ret, data['flags']) # NOTE: ret.info is set in the fixup phase. ret.arg_names = data['arg_names'] - ret.arg_kinds = data['arg_kinds'] + ret.arg_kinds = [ArgKind(x) for x in data['arg_kinds']] # Leave these uninitialized so that future uses will trigger an error del ret.arguments del ret.max_pos @@ -736,13 +776,15 @@ class Decorator(SymbolNode, Statement): A single Decorator object can include any number of function decorators. """ - func = None # type: FuncDef # Decorated function - decorators = None # type: List[Expression] # Decorators (may be empty) + __slots__ = ('func', 'decorators', 'original_decorators', 'var', 'is_overload') + + func: FuncDef # Decorated function + decorators: List[Expression] # Decorators (may be empty) # Some decorators are removed by semanal, keep the original here. - original_decorators = None # type: List[Expression] + original_decorators: List[Expression] # TODO: This is mostly used for the type; consider replacing with a 'type' attribute - var = None # type: Var # Represents the decorated function obj - is_overload = False + var: "Var" # Represents the decorated function obj + is_overload: bool def __init__(self, func: FuncDef, decorators: List[Expression], var: 'Var') -> None: @@ -793,12 +835,13 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': return dec -VAR_FLAGS = [ +VAR_FLAGS: Final = [ 'is_self', 'is_initialized_in_class', 'is_staticmethod', 'is_classmethod', 'is_property', 'is_settable_property', 'is_suppressed_import', 'is_classvar', 'is_abstract_var', 'is_final', 'final_unset_in_class', 'final_set_in_init', 'explicit_self_type', 'is_ready', 'from_module_getattr', -] # type: Final + 'has_explicit_value', +] class Var(SymbolNode): @@ -828,6 +871,7 @@ class Var(SymbolNode): 'is_suppressed_import', 'explicit_self_type', 'from_module_getattr', + 'has_explicit_value', ) def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: @@ -837,7 +881,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: self._fullname = cast('Bogus[str]', None) # Name with module prefix # TODO: Should be Optional[TypeInfo] self.info = VAR_NO_INFO - self.type = type # type: Optional[mypy.types.Type] # Declared or inferred type, or None + self.type: Optional[mypy.types.Type] = type # Declared or inferred type, or None # Is this the first argument to an ordinary method (usually "self")? self.is_self = False self.is_ready = True # If inferred, is the inferred type available? @@ -858,7 +902,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: # If constant value is a simple literal, # store the literal value (unboxed) for the benefit of # tools like mypyc. - self.final_value = None # type: Optional[Union[int, float, bool, str]] + self.final_value: Optional[Union[int, float, bool, str]] = None # Where the value was set (only for class attributes) self.final_unset_in_class = False self.final_set_in_init = False @@ -872,6 +916,9 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: self.explicit_self_type = False # If True, this is an implicit Var created due to module-level __getattr__. self.from_module_getattr = False + # Var can be created with an explicit value `a = 1` or without one `a: int`, + # we need a way to tell which one is which. + self.has_explicit_value = False @property def name(self) -> str: @@ -887,12 +934,13 @@ def accept(self, visitor: NodeVisitor[T]) -> T: def serialize(self) -> JsonDict: # TODO: Leave default values out? # NOTE: Sometimes self.is_ready is False here, but we don't care. - data = {'.class': 'Var', - 'name': self._name, - 'fullname': self._fullname, - 'type': None if self.type is None else self.type.serialize(), - 'flags': get_flags(self, VAR_FLAGS), - } # type: JsonDict + data: JsonDict = { + ".class": "Var", + "name": self._name, + "fullname": self._fullname, + "type": None if self.type is None else self.type.serialize(), + "flags": get_flags(self, VAR_FLAGS), + } if self.final_value is not None: data['final_value'] = self.final_value return data @@ -913,30 +961,35 @@ def deserialize(cls, data: JsonDict) -> 'Var': class ClassDef(Statement): """Class definition""" - name = None # type: str # Name of the class without module prefix - fullname = None # type: Bogus[str] # Fully qualified name of the class - defs = None # type: Block - type_vars = None # type: List[mypy.types.TypeVarDef] + __slots__ = ('name', 'fullname', 'defs', 'type_vars', 'base_type_exprs', + 'removed_base_type_exprs', 'info', 'metaclass', 'decorators', + 'keywords', 'analyzed', 'has_incompatible_baseclass') + + name: str # Name of the class without module prefix + fullname: Bogus[str] # Fully qualified name of the class + defs: "Block" + type_vars: List["mypy.types.TypeVarLikeType"] # Base class expressions (not semantically analyzed -- can be arbitrary expressions) - base_type_exprs = None # type: List[Expression] + base_type_exprs: List[Expression] # Special base classes like Generic[...] get moved here during semantic analysis - removed_base_type_exprs = None # type: List[Expression] - info = None # type: TypeInfo # Related TypeInfo - metaclass = None # type: Optional[Expression] - decorators = None # type: List[Expression] - keywords = None # type: OrderedDict[str, Expression] - analyzed = None # type: Optional[Expression] - has_incompatible_baseclass = False + removed_base_type_exprs: List[Expression] + info: "TypeInfo" # Related TypeInfo + metaclass: Optional[Expression] + decorators: List[Expression] + keywords: "OrderedDict[str, Expression]" + analyzed: Optional[Expression] + has_incompatible_baseclass: bool def __init__(self, name: str, defs: 'Block', - type_vars: Optional[List['mypy.types.TypeVarDef']] = None, + type_vars: Optional[List['mypy.types.TypeVarLikeType']] = None, base_type_exprs: Optional[List[Expression]] = None, metaclass: Optional[Expression] = None, keywords: Optional[List[Tuple[str, Expression]]] = None) -> None: super().__init__() self.name = name + self.fullname = None # type: ignore self.defs = defs self.type_vars = type_vars or [] self.base_type_exprs = base_type_exprs or [] @@ -945,6 +998,8 @@ def __init__(self, self.metaclass = metaclass self.decorators = [] self.keywords = OrderedDict(keywords or []) + self.analyzed = None + self.has_incompatible_baseclass = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_class_def(self) @@ -966,7 +1021,7 @@ def deserialize(self, data: JsonDict) -> 'ClassDef': assert data['.class'] == 'ClassDef' res = ClassDef(data['name'], Block([]), - [mypy.types.TypeVarDef.deserialize(v) for v in data['type_vars']], + [mypy.types.TypeVarType.deserialize(v) for v in data['type_vars']], ) res.fullname = data['fullname'] return res @@ -975,7 +1030,9 @@ def deserialize(self, data: JsonDict) -> 'ClassDef': class GlobalDecl(Statement): """Declaration global x, y, ...""" - names = None # type: List[str] + __slots__ = ('names',) + + names: List[str] def __init__(self, names: List[str]) -> None: super().__init__() @@ -988,7 +1045,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class NonlocalDecl(Statement): """Declaration nonlocal x, y, ...""" - names = None # type: List[str] + __slots__ = ('names',) + + names: List[str] def __init__(self, names: List[str]) -> None: super().__init__() @@ -1020,7 +1079,10 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class ExpressionStmt(Statement): """An expression as a statement, such as print(s).""" - expr = None # type: Expression + + __slots__ = ('expr',) + + expr: Expression def __init__(self, expr: Expression) -> None: super().__init__() @@ -1041,24 +1103,27 @@ class AssignmentStmt(Statement): An lvalue can be NameExpr, TupleExpr, ListExpr, MemberExpr, or IndexExpr. """ - lvalues = None # type: List[Lvalue] + __slots__ = ('lvalues', 'rvalue', 'type', 'unanalyzed_type', 'new_syntax', + 'is_alias_def', 'is_final_def') + + lvalues: List[Lvalue] # This is a TempNode if and only if no rvalue (x: t). - rvalue = None # type: Expression + rvalue: Expression # Declared type in a comment, may be None. - type = None # type: Optional[mypy.types.Type] + type: Optional["mypy.types.Type"] # Original, not semantically analyzed type in annotation (used for reprocessing) - unanalyzed_type = None # type: Optional[mypy.types.Type] + unanalyzed_type: Optional["mypy.types.Type"] # This indicates usage of PEP 526 type annotation syntax in assignment. - new_syntax = False # type: bool + new_syntax: bool # Does this assignment define a type alias? - is_alias_def = False + is_alias_def: bool # Is this a final definition? # Final attributes can't be re-assigned once set, and can't be overridden # in a subclass. This flag is not set if an attempted declaration was found to # be invalid during semantic analysis. It is still set to `True` if # a final declaration overrides another final declaration (this is checked # during type checking when MROs are known). - is_final_def = False + is_final_def: bool def __init__(self, lvalues: List[Lvalue], rvalue: Expression, type: 'Optional[mypy.types.Type]' = None, new_syntax: bool = False) -> None: @@ -1068,6 +1133,8 @@ def __init__(self, lvalues: List[Lvalue], rvalue: Expression, self.type = type self.unanalyzed_type = type self.new_syntax = new_syntax + self.is_alias_def = False + self.is_final_def = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_assignment_stmt(self) @@ -1076,9 +1143,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class OperatorAssignmentStmt(Statement): """Operator assignment statement such as x += 1""" - op = '' - lvalue = None # type: Lvalue - rvalue = None # type: Expression + __slots__ = ('op', 'lvalue', 'rvalue') + + op: str # TODO: Enum? + lvalue: Lvalue + rvalue: Expression def __init__(self, op: str, lvalue: Lvalue, rvalue: Expression) -> None: super().__init__() @@ -1091,9 +1160,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class WhileStmt(Statement): - expr = None # type: Expression - body = None # type: Block - else_body = None # type: Optional[Block] + __slots__ = ('expr', 'body', 'else_body') + + expr: Expression + body: Block + else_body: Optional[Block] def __init__(self, expr: Expression, body: Block, else_body: Optional[Block]) -> None: super().__init__() @@ -1106,21 +1177,25 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class ForStmt(Statement): + __slots__ = ('index', 'index_type', 'unanalyzed_index_type', + 'inferred_item_type', 'inferred_iterator_type', + 'expr', 'body', 'else_body', 'is_async') + # Index variables - index = None # type: Lvalue + index: Lvalue # Type given by type comments for index, can be None - index_type = None # type: Optional[mypy.types.Type] + index_type: Optional["mypy.types.Type"] # Original, not semantically analyzed type in annotation (used for reprocessing) - unanalyzed_index_type = None # type: Optional[mypy.types.Type] + unanalyzed_index_type: Optional["mypy.types.Type"] # Inferred iterable item type - inferred_item_type = None # type: Optional[mypy.types.Type] + inferred_item_type: Optional["mypy.types.Type"] # Inferred iterator type - inferred_iterator_type = None # type: Optional[mypy.types.Type] + inferred_iterator_type: Optional["mypy.types.Type"] # Expression to iterate - expr = None # type: Expression - body = None # type: Block - else_body = None # type: Optional[Block] - is_async = False # True if `async for ...` (PEP 492, Python 3.5) + expr: Expression + body: Block + else_body: Optional[Block] + is_async: bool # True if `async for ...` (PEP 492, Python 3.5) def __init__(self, index: Lvalue, @@ -1132,16 +1207,21 @@ def __init__(self, self.index = index self.index_type = index_type self.unanalyzed_index_type = index_type + self.inferred_item_type = None + self.inferred_iterator_type = None self.expr = expr self.body = body self.else_body = else_body + self.is_async = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_for_stmt(self) class ReturnStmt(Statement): - expr = None # type: Optional[Expression] + __slots__ = ('expr',) + + expr: Optional[Expression] def __init__(self, expr: Optional[Expression]) -> None: super().__init__() @@ -1152,8 +1232,10 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class AssertStmt(Statement): - expr = None # type: Expression - msg = None # type: Optional[Expression] + __slots__ = ('expr', 'msg') + + expr: Expression + msg: Optional[Expression] def __init__(self, expr: Expression, msg: Optional[Expression] = None) -> None: super().__init__() @@ -1165,7 +1247,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class DelStmt(Statement): - expr = None # type: Lvalue + __slots__ = ('expr',) + + expr: Lvalue def __init__(self, expr: Lvalue) -> None: super().__init__() @@ -1176,24 +1260,32 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class BreakStmt(Statement): + __slots__ = () + def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_break_stmt(self) class ContinueStmt(Statement): + __slots__ = () + def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_continue_stmt(self) class PassStmt(Statement): + __slots__ = () + def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_pass_stmt(self) class IfStmt(Statement): - expr = None # type: List[Expression] - body = None # type: List[Block] - else_body = None # type: Optional[Block] + __slots__ = ('expr', 'body', 'else_body') + + expr: List[Expression] + body: List[Block] + else_body: Optional[Block] def __init__(self, expr: List[Expression], body: List[Block], else_body: Optional[Block]) -> None: @@ -1207,9 +1299,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class RaiseStmt(Statement): + __slots__ = ('expr', 'from_expr') + # Plain 'raise' is a valid statement. - expr = None # type: Optional[Expression] - from_expr = None # type: Optional[Expression] + expr: Optional[Expression] + from_expr: Optional[Expression] def __init__(self, expr: Optional[Expression], from_expr: Optional[Expression]) -> None: super().__init__() @@ -1221,13 +1315,15 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class TryStmt(Statement): - body = None # type: Block # Try body + __slots__ = ('body', 'types', 'vars', 'handlers', 'else_body', 'finally_body') + + body: Block # Try body # Plain 'except:' also possible - types = None # type: List[Optional[Expression]] # Except type expressions - vars = None # type: List[Optional[NameExpr]] # Except variable names - handlers = None # type: List[Block] # Except bodies - else_body = None # type: Optional[Block] - finally_body = None # type: Optional[Block] + types: List[Optional[Expression]] # Except type expressions + vars: List[Optional["NameExpr"]] # Except variable names + handlers: List[Block] # Except bodies + else_body: Optional[Block] + finally_body: Optional[Block] def __init__(self, body: Block, vars: List['Optional[NameExpr]'], types: List[Optional[Expression]], @@ -1246,14 +1342,17 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class WithStmt(Statement): - expr = None # type: List[Expression] - target = None # type: List[Optional[Lvalue]] + __slots__ = ('expr', 'target', 'unanalyzed_type', + 'analyzed_types', 'body', 'is_async') + + expr: List[Expression] + target: List[Optional[Lvalue]] # Type given by type comments for target, can be None - unanalyzed_type = None # type: Optional[mypy.types.Type] + unanalyzed_type: Optional["mypy.types.Type"] # Semantically analyzed types from type comment (TypeList type expanded) - analyzed_types = None # type: List[mypy.types.Type] - body = None # type: Block - is_async = False # True if `async with ...` (PEP 492, Python 3.5) + analyzed_types: List["mypy.types.Type"] + body: Block + is_async: bool # True if `async with ...` (PEP 492, Python 3.5) def __init__(self, expr: List[Expression], target: List[Optional[Lvalue]], body: Block, target_type: 'Optional[mypy.types.Type]' = None) -> None: @@ -1263,6 +1362,7 @@ def __init__(self, expr: List[Expression], target: List[Optional[Lvalue]], self.unanalyzed_type = target_type self.analyzed_types = [] self.body = body + self.is_async = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_with_stmt(self) @@ -1271,10 +1371,12 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class PrintStmt(Statement): """Python 2 print statement""" - args = None # type: List[Expression] - newline = False + __slots__ = ('args', 'newline', 'target') + + args: List[Expression] + newline: bool # The file-like target object (given using >>). - target = None # type: Optional[Expression] + target: Optional[Expression] def __init__(self, args: List[Expression], @@ -1292,9 +1394,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class ExecStmt(Statement): """Python 2 exec statement""" - expr = None # type: Expression - globals = None # type: Optional[Expression] - locals = None # type: Optional[Expression] + __slots__ = ('expr', 'globals', 'locals') + + expr: Expression + globals: Optional[Expression] + locals: Optional[Expression] def __init__(self, expr: Expression, globals: Optional[Expression], @@ -1314,7 +1418,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class IntExpr(Expression): """Integer literal""" - value = 0 + __slots__ = ('value',) + + value: int # 0 by default def __init__(self, value: int) -> None: super().__init__() @@ -1338,7 +1444,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class StrExpr(Expression): """String literal""" - value = '' + __slots__ = ('value', 'from_python_3') + + value: str # '' by default # Keeps track of whether this string originated from Python 2 source code vs # Python 3 source code. We need to keep track of this information so we can @@ -1352,7 +1460,7 @@ class StrExpr(Expression): # is meant to be `Literal[u'foo']` or `Literal[b'foo']`. # # This field keeps track of that information. - from_python_3 = True + from_python_3: bool def __init__(self, value: str, from_python_3: bool = False) -> None: super().__init__() @@ -1366,6 +1474,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class BytesExpr(Expression): """Bytes literal""" + __slots__ = ('value',) + # Note: we deliberately do NOT use bytes here because it ends up # unnecessarily complicating a lot of the result logic. For example, # we'd have to worry about converting the bytes into a format we can @@ -1375,7 +1485,7 @@ class BytesExpr(Expression): # # It's more convenient to just store the human-readable representation # from the very start. - value = '' + value: str def __init__(self, value: str) -> None: super().__init__() @@ -1388,7 +1498,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class UnicodeExpr(Expression): """Unicode literal (Python 2.x)""" - value = '' + __slots__ = ('value',) + + value: str def __init__(self, value: str) -> None: super().__init__() @@ -1401,7 +1513,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class FloatExpr(Expression): """Float literal""" - value = 0.0 + __slots__ = ('value',) + + value: float # 0.0 by default def __init__(self, value: float) -> None: super().__init__() @@ -1414,6 +1528,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class ComplexExpr(Expression): """Complex literal""" + __slots__ = ('value',) + + value: complex + def __init__(self, value: complex) -> None: super().__init__() self.value = value @@ -1425,6 +1543,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class EllipsisExpr(Expression): """Ellipsis (...)""" + __slots__ = () + def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_ellipsis(self) @@ -1432,7 +1552,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class StarExpr(Expression): """Star expression""" - expr = None # type: Expression + __slots__ = ('expr', 'valid') + + expr: Expression + valid: bool def __init__(self, expr: Expression) -> None: super().__init__() @@ -1454,11 +1577,11 @@ class RefExpr(Expression): def __init__(self) -> None: super().__init__() # LDEF/GDEF/MDEF/... (None if not available) - self.kind = None # type: Optional[int] + self.kind: Optional[int] = None # Var, FuncDef or TypeInfo that describes this - self.node = None # type: Optional[SymbolNode] + self.node: Optional[SymbolNode] = None # Fully qualified name (or name if not global) - self.fullname = None # type: Optional[str] + self.fullname: Optional[str] = None # Does this define a new name? self.is_new_def = False # Does this define a new name with inferred type? @@ -1469,7 +1592,7 @@ def __init__(self) -> None: # Is this expression appears as an rvalue of a valid type alias definition? self.is_alias_rvalue = False # Cache type guard from callable_type.type_guard - self.type_guard = None # type: Optional[mypy.types.Type] + self.type_guard: Optional["mypy.types.Type"] = None class NameExpr(RefExpr): @@ -1504,26 +1627,58 @@ def __init__(self, expr: Expression, name: str) -> None: self.name = name # The variable node related to a definition through 'self.x = '. # The nodes of other kinds of member expressions are resolved during type checking. - self.def_var = None # type: Optional[Var] + self.def_var: Optional[Var] = None def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_member_expr(self) # Kinds of arguments +@unique +class ArgKind(Enum): + # Positional argument + ARG_POS = 0 + # Positional, optional argument (functions only, not calls) + ARG_OPT = 1 + # *arg argument + ARG_STAR = 2 + # Keyword argument x=y in call, or keyword-only function arg + ARG_NAMED = 3 + # **arg argument + ARG_STAR2 = 4 + # In an argument list, keyword-only and also optional + ARG_NAMED_OPT = 5 + + def is_positional(self, star: bool = False) -> bool: + return ( + self == ARG_POS + or self == ARG_OPT + or (star and self == ARG_STAR) + ) + + def is_named(self, star: bool = False) -> bool: + return ( + self == ARG_NAMED + or self == ARG_NAMED_OPT + or (star and self == ARG_STAR2) + ) + + def is_required(self) -> bool: + return self == ARG_POS or self == ARG_NAMED -# Positional argument -ARG_POS = 0 # type: Final -# Positional, optional argument (functions only, not calls) -ARG_OPT = 1 # type: Final -# *arg argument -ARG_STAR = 2 # type: Final -# Keyword argument x=y in call, or keyword-only function arg -ARG_NAMED = 3 # type: Final -# **arg argument -ARG_STAR2 = 4 # type: Final -# In an argument list, keyword-only and also optional -ARG_NAMED_OPT = 5 # type: Final + def is_optional(self) -> bool: + return self == ARG_OPT or self == ARG_NAMED_OPT + + def is_star(self) -> bool: + return self == ARG_STAR or self == ARG_STAR2 + + +ARG_POS: Final = ArgKind.ARG_POS +ARG_OPT: Final = ArgKind.ARG_OPT +ARG_STAR: Final = ArgKind.ARG_STAR +ARG_NAMED: Final = ArgKind.ARG_NAMED +ARG_STAR2: Final = ArgKind.ARG_STAR2 +ARG_NAMED_OPT: Final = ArgKind.ARG_NAMED_OPT class CallExpr(Expression): @@ -1538,7 +1693,7 @@ class CallExpr(Expression): def __init__(self, callee: Expression, args: List[Expression], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: List[Optional[str]], analyzed: Optional[Expression] = None) -> None: super().__init__() @@ -1549,7 +1704,7 @@ def __init__(self, self.args = args self.arg_kinds = arg_kinds # ARG_ constants # Each name can be None if not a keyword argument. - self.arg_names = arg_names # type: List[Optional[str]] + self.arg_names: List[Optional[str]] = arg_names # If not None, the node that represents the meaning of the CallExpr. For # cast(...) this is a CastExpr. self.analyzed = analyzed @@ -1559,7 +1714,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class YieldFromExpr(Expression): - expr = None # type: Expression + __slots__ = ('expr',) + + expr: Expression def __init__(self, expr: Expression) -> None: super().__init__() @@ -1570,7 +1727,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class YieldExpr(Expression): - expr = None # type: Optional[Expression] + __slots__ = ('expr',) + + expr: Optional[Expression] def __init__(self, expr: Optional[Expression]) -> None: super().__init__() @@ -1586,18 +1745,21 @@ class IndexExpr(Expression): Also wraps type application such as List[int] as a special form. """ - base = None # type: Expression - index = None # type: Expression + __slots__ = ('base', 'index', 'method_type', 'analyzed') + + base: Expression + index: Expression # Inferred __getitem__ method type - method_type = None # type: Optional[mypy.types.Type] + method_type: Optional["mypy.types.Type"] # If not None, this is actually semantically a type application # Class[type, ...] or a type alias initializer. - analyzed = None # type: Union[TypeApplication, TypeAliasExpr, None] + analyzed: Union["TypeApplication", "TypeAliasExpr", None] def __init__(self, base: Expression, index: Expression) -> None: super().__init__() self.base = base self.index = index + self.method_type = None self.analyzed = None def accept(self, visitor: ExpressionVisitor[T]) -> T: @@ -1607,15 +1769,18 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class UnaryExpr(Expression): """Unary operation""" - op = '' - expr = None # type: Expression + __slots__ = ('op', 'expr', 'method_type') + + op: str # TODO: Enum? + expr: Expression # Inferred operator method type - method_type = None # type: Optional[mypy.types.Type] + method_type: Optional["mypy.types.Type"] def __init__(self, op: str, expr: Expression) -> None: super().__init__() self.op = op self.expr = expr + self.method_type = None def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_unary_expr(self) @@ -1623,6 +1788,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class AssignmentExpr(Expression): """Assignment expressions in Python 3.8+, like "a := 2".""" + + __slots__ = ('target', 'value') + def __init__(self, target: Expression, value: Expression) -> None: super().__init__() self.target = target @@ -1632,119 +1800,31 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_assignment_expr(self) -# Map from binary operator id to related method name (in Python 3). -op_methods = { - '+': '__add__', - '-': '__sub__', - '*': '__mul__', - '/': '__truediv__', - '%': '__mod__', - 'divmod': '__divmod__', - '//': '__floordiv__', - '**': '__pow__', - '@': '__matmul__', - '&': '__and__', - '|': '__or__', - '^': '__xor__', - '<<': '__lshift__', - '>>': '__rshift__', - '==': '__eq__', - '!=': '__ne__', - '<': '__lt__', - '>=': '__ge__', - '>': '__gt__', - '<=': '__le__', - 'in': '__contains__', -} # type: Final - -op_methods_to_symbols = {v: k for (k, v) in op_methods.items()} # type: Final -op_methods_to_symbols['__div__'] = '/' - -comparison_fallback_method = '__cmp__' # type: Final -ops_falling_back_to_cmp = {'__ne__', '__eq__', - '__lt__', '__le__', - '__gt__', '__ge__'} # type: Final - - -ops_with_inplace_method = { - '+', '-', '*', '/', '%', '//', '**', '@', '&', '|', '^', '<<', '>>'} # type: Final - -inplace_operator_methods = set( - '__i' + op_methods[op][2:] for op in ops_with_inplace_method) # type: Final - -reverse_op_methods = { - '__add__': '__radd__', - '__sub__': '__rsub__', - '__mul__': '__rmul__', - '__truediv__': '__rtruediv__', - '__mod__': '__rmod__', - '__divmod__': '__rdivmod__', - '__floordiv__': '__rfloordiv__', - '__pow__': '__rpow__', - '__matmul__': '__rmatmul__', - '__and__': '__rand__', - '__or__': '__ror__', - '__xor__': '__rxor__', - '__lshift__': '__rlshift__', - '__rshift__': '__rrshift__', - '__eq__': '__eq__', - '__ne__': '__ne__', - '__lt__': '__gt__', - '__ge__': '__le__', - '__gt__': '__lt__', - '__le__': '__ge__', -} # type: Final - -# Suppose we have some class A. When we do A() + A(), Python will only check -# the output of A().__add__(A()) and skip calling the __radd__ method entirely. -# This shortcut is used only for the following methods: -op_methods_that_shortcut = { - '__add__', - '__sub__', - '__mul__', - '__div__', - '__truediv__', - '__mod__', - '__divmod__', - '__floordiv__', - '__pow__', - '__matmul__', - '__and__', - '__or__', - '__xor__', - '__lshift__', - '__rshift__', -} # type: Final - -normal_from_reverse_op = dict((m, n) for n, m in reverse_op_methods.items()) # type: Final -reverse_op_method_set = set(reverse_op_methods.values()) # type: Final - -unary_op_methods = { - '-': '__neg__', - '+': '__pos__', - '~': '__invert__', -} # type: Final - - class OpExpr(Expression): """Binary operation (other than . or [] or comparison operators, which have specific nodes).""" - op = '' - left = None # type: Expression - right = None # type: Expression + __slots__ = ('op', 'left', 'right', + 'method_type', 'right_always', 'right_unreachable') + + op: str # TODO: Enum? + left: Expression + right: Expression # Inferred type for the operator method type (when relevant). - method_type = None # type: Optional[mypy.types.Type] - # Is the right side going to be evaluated every time? - right_always = False - # Is the right side unreachable? - right_unreachable = False + method_type: Optional["mypy.types.Type"] + # Per static analysis only: Is the right side going to be evaluated every time? + right_always: bool + # Per static analysis only: Is the right side unreachable? + right_unreachable: bool def __init__(self, op: str, left: Expression, right: Expression) -> None: super().__init__() self.op = op self.left = left self.right = right + self.method_type = None + self.right_always = False + self.right_unreachable = False def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_op_expr(self) @@ -1753,10 +1833,12 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class ComparisonExpr(Expression): """Comparison expression (e.g. a < b > c < d).""" - operators = None # type: List[str] - operands = None # type: List[Expression] + __slots__ = ('operators', 'operands', 'method_types') + + operators: List[str] + operands: List[Expression] # Inferred type for the operator methods (when relevant; None for 'is'). - method_types = None # type: List[Optional[mypy.types.Type]] + method_types: List[Optional["mypy.types.Type"]] def __init__(self, operators: List[str], operands: List[Expression]) -> None: super().__init__() @@ -1781,9 +1863,11 @@ class SliceExpr(Expression): This is only valid as index in index expressions. """ - begin_index = None # type: Optional[Expression] - end_index = None # type: Optional[Expression] - stride = None # type: Optional[Expression] + __slots__ = ('begin_index', 'end_index', 'stride') + + begin_index: Optional[Expression] + end_index: Optional[Expression] + stride: Optional[Expression] def __init__(self, begin_index: Optional[Expression], end_index: Optional[Expression], @@ -1800,8 +1884,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class CastExpr(Expression): """Cast expression cast(type, expr).""" - expr = None # type: Expression - type = None # type: mypy.types.Type + __slots__ = ('expr', 'type') + + expr: Expression + type: "mypy.types.Type" def __init__(self, expr: Expression, typ: 'mypy.types.Type') -> None: super().__init__() @@ -1815,9 +1901,11 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class RevealExpr(Expression): """Reveal type expression reveal_type(expr) or reveal_locals() expression.""" - expr = None # type: Optional[Expression] - kind = 0 # type: int - local_nodes = None # type: Optional[List[Var]] + __slots__ = ('expr', 'kind', 'local_nodes') + + expr: Optional[Expression] + kind: int + local_nodes: Optional[List[Var]] def __init__( self, kind: int, @@ -1835,14 +1923,17 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class SuperExpr(Expression): """Expression super().name""" - name = '' - info = None # type: Optional[TypeInfo] # Type that contains this super expression - call = None # type: CallExpr # The expression super(...) + __slots__ = ('name', 'info', 'call') + + name: str + info: Optional["TypeInfo"] # Type that contains this super expression + call: CallExpr # The expression super(...) def __init__(self, name: str, call: CallExpr) -> None: super().__init__() self.name = name self.call = call + self.info = None def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_super_expr(self) @@ -1872,7 +1963,9 @@ def is_dynamic(self) -> bool: class ListExpr(Expression): """List literal expression [...].""" - items = None # type: List[Expression] + __slots__ = ('items',) + + items: List[Expression] def __init__(self, items: List[Expression]) -> None: super().__init__() @@ -1885,7 +1978,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class DictExpr(Expression): """Dictionary literal expression {key: value, ...}.""" - items = None # type: List[Tuple[Optional[Expression], Expression]] + __slots__ = ('items',) + + items: List[Tuple[Optional[Expression], Expression]] def __init__(self, items: List[Tuple[Optional[Expression], Expression]]) -> None: super().__init__() @@ -1900,7 +1995,9 @@ class TupleExpr(Expression): Also lvalue sequences (..., ...) and [..., ...]""" - items = None # type: List[Expression] + __slots__ = ('items',) + + items: List[Expression] def __init__(self, items: List[Expression]) -> None: super().__init__() @@ -1913,7 +2010,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class SetExpr(Expression): """Set literal expression {value, ...}.""" - items = None # type: List[Expression] + __slots__ = ('items',) + + items: List[Expression] def __init__(self, items: List[Expression]) -> None: super().__init__() @@ -1926,11 +2025,13 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class GeneratorExpr(Expression): """Generator expression ... for ... in ... [ for ... in ... ] [ if ... ].""" - left_expr = None # type: Expression - sequences = None # type: List[Expression] - condlists = None # type: List[List[Expression]] - is_async = None # type: List[bool] - indices = None # type: List[Lvalue] + __slots__ = ('left_expr', 'sequences', 'condlists', 'is_async', 'indices') + + left_expr: Expression + sequences: List[Expression] + condlists: List[List[Expression]] + is_async: List[bool] + indices: List[Lvalue] def __init__(self, left_expr: Expression, indices: List[Lvalue], sequences: List[Expression], condlists: List[List[Expression]], @@ -1949,7 +2050,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class ListComprehension(Expression): """List comprehension (e.g. [x + 1 for x in a])""" - generator = None # type: GeneratorExpr + __slots__ = ('generator',) + + generator: GeneratorExpr def __init__(self, generator: GeneratorExpr) -> None: super().__init__() @@ -1962,7 +2065,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class SetComprehension(Expression): """Set comprehension (e.g. {x + 1 for x in a})""" - generator = None # type: GeneratorExpr + __slots__ = ('generator',) + + generator: GeneratorExpr def __init__(self, generator: GeneratorExpr) -> None: super().__init__() @@ -1975,12 +2080,14 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class DictionaryComprehension(Expression): """Dictionary comprehension (e.g. {k: v for k, v in a}""" - key = None # type: Expression - value = None # type: Expression - sequences = None # type: List[Expression] - condlists = None # type: List[List[Expression]] - is_async = None # type: List[bool] - indices = None # type: List[Lvalue] + __slots__ = ('key', 'value', 'sequences', 'condlists', 'is_async', 'indices') + + key: Expression + value: Expression + sequences: List[Expression] + condlists: List[List[Expression]] + is_async: List[bool] + indices: List[Lvalue] def __init__(self, key: Expression, value: Expression, indices: List[Lvalue], sequences: List[Expression], condlists: List[List[Expression]], @@ -2000,9 +2107,11 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class ConditionalExpr(Expression): """Conditional expression (e.g. x if y else z)""" - cond = None # type: Expression - if_expr = None # type: Expression - else_expr = None # type: Expression + __slots__ = ('cond', 'if_expr', 'else_expr') + + cond: Expression + if_expr: Expression + else_expr: Expression def __init__(self, cond: Expression, if_expr: Expression, else_expr: Expression) -> None: super().__init__() @@ -2017,7 +2126,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class BackquoteExpr(Expression): """Python 2 expression `...`.""" - expr = None # type: Expression + __slots__ = ('expr',) + + expr: Expression def __init__(self, expr: Expression) -> None: super().__init__() @@ -2030,8 +2141,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class TypeApplication(Expression): """Type application expr[type, ...]""" - expr = None # type: Expression - types = None # type: List[mypy.types.Type] + __slots__ = ('expr', 'types') + + expr: Expression + types: List["mypy.types.Type"] def __init__(self, expr: Expression, types: List['mypy.types.Type']) -> None: super().__init__() @@ -2051,23 +2164,26 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: # # If T is contravariant in Foo[T], Foo[object] is a subtype of # Foo[int], but not vice versa. -INVARIANT = 0 # type: Final -COVARIANT = 1 # type: Final -CONTRAVARIANT = 2 # type: Final +INVARIANT: Final = 0 +COVARIANT: Final = 1 +CONTRAVARIANT: Final = 2 class TypeVarLikeExpr(SymbolNode, Expression): """Base class for TypeVarExpr and ParamSpecExpr.""" - _name = '' - _fullname = '' + + __slots__ = ('_name', '_fullname', 'upper_bound', 'variance') + + _name: str + _fullname: str # Upper bound: only subtypes of upper_bound are valid as values. By default # this is 'object', meaning no restriction. - upper_bound = None # type: mypy.types.Type + upper_bound: "mypy.types.Type" # Variance of the type variable. Invariant is the default. # TypeVar(..., covariant=True) defines a covariant type variable. # TypeVar(..., contravariant=True) defines a contravariant type # variable. - variance = INVARIANT + variance: int def __init__( self, name: str, fullname: str, upper_bound: 'mypy.types.Type', variance: int = INVARIANT @@ -2098,9 +2214,12 @@ class TypeVarExpr(TypeVarLikeExpr): 1. a generic class that uses the type variable as a type argument or 2. a generic function that refers to the type variable in its signature. """ + + __slots__ = ('values',) + # Value restriction: only types in the list are valid as values. If the # list is empty, there is no restriction. - values = None # type: List[mypy.types.Type] + values: List["mypy.types.Type"] def __init__(self, name: str, fullname: str, values: List['mypy.types.Type'], @@ -2132,6 +2251,8 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarExpr': class ParamSpecExpr(TypeVarLikeExpr): + __slots__ = () + def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_paramspec_expr(self) @@ -2158,16 +2279,19 @@ def deserialize(cls, data: JsonDict) -> 'ParamSpecExpr': class TypeAliasExpr(Expression): """Type alias expression (rvalue).""" + __slots__ = ('type', 'tvars', 'no_args', 'node') + # The target type. - type = None # type: mypy.types.Type + type: "mypy.types.Type" # Names of unbound type variables used to define the alias - tvars = None # type: List[str] + tvars: List[str] # Whether this alias was defined in bare form. Used to distinguish # between # A = List # and # A = List[Any] - no_args = False # type: bool + no_args: bool + node: 'TypeAlias' def __init__(self, node: 'TypeAlias') -> None: super().__init__() @@ -2183,10 +2307,12 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class NamedTupleExpr(Expression): """Named tuple expression namedtuple(...) or NamedTuple(...).""" + __slots__ = ('info', 'is_typed') + # The class representation of this named tuple (its tuple_type attribute contains # the tuple item types) - info = None # type: TypeInfo - is_typed = False # whether this class was created with typing.NamedTuple + info: "TypeInfo" + is_typed: bool # whether this class was created with typing.NamedTuple def __init__(self, info: 'TypeInfo', is_typed: bool = False) -> None: super().__init__() @@ -2200,8 +2326,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class TypedDictExpr(Expression): """Typed dict expression TypedDict(...).""" + __slots__ = ('info',) + # The class representation of this typed dict - info = None # type: TypeInfo + info: "TypeInfo" def __init__(self, info: 'TypeInfo') -> None: super().__init__() @@ -2214,11 +2342,13 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class EnumCallExpr(Expression): """Named tuple expression Enum('name', 'val1 val2 ...').""" + __slots__ = ('info', 'items', 'values') + # The class representation of this enumerated type - info = None # type: TypeInfo + info: "TypeInfo" # The item names (for debugging) - items = None # type: List[str] - values = None # type: List[Optional[Expression]] + items: List[str] + values: List[Optional[Expression]] def __init__(self, info: 'TypeInfo', items: List[str], values: List[Optional[Expression]]) -> None: @@ -2234,7 +2364,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class PromoteExpr(Expression): """Ducktype class decorator expression _promote(...).""" - type = None # type: mypy.types.Type + __slots__ = ('type',) + + type: "mypy.types.Type" def __init__(self, type: 'mypy.types.Type') -> None: super().__init__() @@ -2246,19 +2378,21 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class NewTypeExpr(Expression): """NewType expression NewType(...).""" - name = None # type: str + + __slots__ = ('name', 'old_type', 'info') + + name: str # The base type (the second argument to NewType) - old_type = None # type: Optional[mypy.types.Type] + old_type: Optional["mypy.types.Type"] # The synthesized class representing the new type (inherits old_type) - info = None # type: Optional[TypeInfo] + info: Optional["TypeInfo"] def __init__(self, name: str, old_type: 'Optional[mypy.types.Type]', line: int, column: int) -> None: - super().__init__() + super().__init__(line=line, column=column) self.name = name self.old_type = old_type - self.line = line - self.column = column + self.info = None def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_newtype_expr(self) @@ -2267,7 +2401,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class AwaitExpr(Expression): """Await expression (await ...).""" - expr = None # type: Expression + __slots__ = ('expr',) + + expr: Expression def __init__(self, expr: Expression) -> None: super().__init__() @@ -2288,10 +2424,12 @@ class TempNode(Expression): some fixed type. """ - type = None # type: mypy.types.Type + __slots__ = ('type', 'no_rhs') + + type: "mypy.types.Type" # Is this TempNode used to indicate absence of a right hand side in an annotated assignment? # (e.g. for 'x: int' the rvalue is TempNode(AnyType(TypeOfAny.special_form), no_rhs=True)) - no_rhs = False # type: bool + no_rhs: bool def __init__(self, typ: 'mypy.types.Type', @@ -2326,28 +2464,44 @@ class is generic then it will be a type constructor of higher kind. the appropriate number of arguments. """ - _fullname = None # type: Bogus[str] # Fully qualified name + __slots__ = ( + '_fullname', 'module_name', 'defn', 'mro', '_mro_refs', 'bad_mro', 'is_final', + 'declared_metaclass', 'metaclass_type', 'names', 'is_abstract', + 'is_protocol', 'runtime_protocol', 'abstract_attributes', + 'deletable_attributes', 'slots', 'assuming', 'assuming_proper', + 'inferring', 'is_enum', 'fallback_to_any', 'type_vars', 'bases', + '_promote', 'tuple_type', 'is_named_tuple', 'typeddict_type', + 'is_newtype', 'is_intersection', 'metadata', + ) + + _fullname: Bogus[str] # Fully qualified name # Fully qualified name for the module this type was defined in. This # information is also in the fullname, but is harder to extract in the # case of nested class definitions. - module_name = None # type: str - defn = None # type: ClassDef # Corresponding ClassDef + module_name: str + defn: ClassDef # Corresponding ClassDef # Method Resolution Order: the order of looking up attributes. The first # value always to refers to this class. - mro = None # type: List[TypeInfo] + mro: List["TypeInfo"] # Used to stash the names of the mro classes temporarily between # deserialization and fixup. See deserialize() for why. - _mro_refs = None # type: Optional[List[str]] - bad_mro = False # Could not construct full MRO - - declared_metaclass = None # type: Optional[mypy.types.Instance] - metaclass_type = None # type: Optional[mypy.types.Instance] - - names = None # type: SymbolTable # Names defined directly in this type - is_abstract = False # Does the class have any abstract attributes? - is_protocol = False # Is this a protocol class? - runtime_protocol = False # Does this protocol support isinstance checks? - abstract_attributes = None # type: List[str] + _mro_refs: Optional[List[str]] + bad_mro: bool # Could not construct full MRO + is_final: bool + + declared_metaclass: Optional["mypy.types.Instance"] + metaclass_type: Optional["mypy.types.Instance"] + + names: "SymbolTable" # Names defined directly in this type + is_abstract: bool # Does the class have any abstract attributes? + is_protocol: bool # Is this a protocol class? + runtime_protocol: bool # Does this protocol support isinstance checks? + abstract_attributes: List[str] + deletable_attributes: List[str] # Used by mypyc only + # Does this type have concrete `__slots__` defined? + # If class does not have `__slots__` defined then it is `None`, + # if it has empty `__slots__` then it is an empty set. + slots: Optional[Set[str]] # The attributes 'assuming' and 'assuming_proper' represent structural subtype matrices. # @@ -2369,8 +2523,8 @@ class is generic then it will be a type constructor of higher kind. # If concurrent/parallel type checking will be added in future, # then there should be one matrix per thread/process to avoid false negatives # during the type checking phase. - assuming = None # type: List[Tuple[mypy.types.Instance, mypy.types.Instance]] - assuming_proper = None # type: List[Tuple[mypy.types.Instance, mypy.types.Instance]] + assuming: List[Tuple["mypy.types.Instance", "mypy.types.Instance"]] + assuming_proper: List[Tuple["mypy.types.Instance", "mypy.types.Instance"]] # Ditto for temporary 'inferring' stack of recursive constraint inference. # It contains Instance's of protocol types that appeared as an argument to # constraints.infer_constraints(). We need 'inferring' to avoid infinite recursion for @@ -2380,82 +2534,98 @@ class is generic then it will be a type constructor of higher kind. # since this would require to pass them in many dozens of calls. In particular, # there is a dependency infer_constraint -> is_subtype -> is_callable_subtype -> # -> infer_constraints. - inferring = None # type: List[mypy.types.Instance] + inferring: List["mypy.types.Instance"] # 'inferring' and 'assuming' can't be made sets, since we need to use # is_same_type to correctly treat unions. # Classes inheriting from Enum shadow their true members with a __getattr__, so we # have to treat them as a special case. - is_enum = False + is_enum: bool # If true, any unknown attributes should have type 'Any' instead # of generating a type error. This would be true if there is a # base class with type 'Any', but other use cases may be # possible. This is similar to having __getattr__ that returns Any # (and __setattr__), but without the __getattr__ method. - fallback_to_any = False + fallback_to_any: bool # Information related to type annotations. # Generic type variable names (full names) - type_vars = None # type: List[str] + type_vars: List[str] # Direct base classes. - bases = None # type: List[mypy.types.Instance] + bases: List["mypy.types.Instance"] # Another type which this type will be treated as a subtype of, # even though it's not a subclass in Python. The non-standard # `@_promote` decorator introduces this, and there are also # several builtin examples, in particular `int` -> `float`. - _promote = None # type: Optional[mypy.types.Type] + _promote: Optional["mypy.types.Type"] # Representation of a Tuple[...] base class, if the class has any # (e.g., for named tuples). If this is not None, the actual Type # object used for this class is not an Instance but a TupleType; # the corresponding Instance is set as the fallback type of the # tuple type. - tuple_type = None # type: Optional[mypy.types.TupleType] + tuple_type: Optional["mypy.types.TupleType"] # Is this a named tuple type? - is_named_tuple = False + is_named_tuple: bool # If this class is defined by the TypedDict type constructor, # then this is not None. - typeddict_type = None # type: Optional[mypy.types.TypedDictType] + typeddict_type: Optional["mypy.types.TypedDictType"] # Is this a newtype type? - is_newtype = False + is_newtype: bool # Is this a synthesized intersection type? - is_intersection = False + is_intersection: bool # This is a dictionary that will be serialized and un-serialized as is. # It is useful for plugins to add their data to save in the cache. - metadata = None # type: Dict[str, JsonDict] + metadata: Dict[str, JsonDict] - FLAGS = [ + FLAGS: Final = [ 'is_abstract', 'is_enum', 'fallback_to_any', 'is_named_tuple', 'is_newtype', 'is_protocol', 'runtime_protocol', 'is_final', 'is_intersection', - ] # type: Final + ] def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> None: """Initialize a TypeInfo.""" super().__init__() + self._fullname = defn.fullname self.names = names self.defn = defn self.module_name = module_name self.type_vars = [] self.bases = [] self.mro = [] - self._fullname = defn.fullname + self._mro_refs = None + self.bad_mro = False + self.declared_metaclass = None + self.metaclass_type = None self.is_abstract = False self.abstract_attributes = [] + self.deletable_attributes = [] + self.slots = None self.assuming = [] self.assuming_proper = [] self.inferring = [] + self.is_protocol = False + self.runtime_protocol = False self.add_type_vars() - self.metadata = {} self.is_final = False + self.is_enum = False + self.fallback_to_any = False + self._promote = None + self.tuple_type = None + self.is_named_tuple = False + self.typeddict_type = None + self.is_newtype = False + self.is_intersection = False + self.metadata = {} def add_type_vars(self) -> None: if self.defn.type_vars: @@ -2492,7 +2662,7 @@ def get_containing_type_info(self, name: str) -> 'Optional[TypeInfo]': def protocol_members(self) -> List[str]: # Protocol members are names of all attributes/methods defined in a protocol # and in all its supertypes (except for 'object'). - members = set() # type: Set[str] + members: Set[str] = set() assert self.mro, "This property can be only accessed after MRO is (re-)calculated" for base in self.mro[:-1]: # we skip "object" since everyone implements it if base.is_protocol: @@ -2519,12 +2689,14 @@ def __bool__(self) -> bool: def has_readable_member(self, name: str) -> bool: return self.get(name) is not None - def get_method(self, name: str) -> Optional[FuncBase]: + def get_method(self, name: str) -> Union[FuncBase, Decorator, None]: for cls in self.mro: if name in cls.names: node = cls.names[name].node if isinstance(node, FuncBase): return node + elif isinstance(node, Decorator): # Two `if`s make `mypyc` happy + return node else: return None return None @@ -2578,7 +2750,7 @@ def dump(self, """Return a string dump of the contents of the TypeInfo.""" if not str_conv: str_conv = mypy.strconv.StrConv() - base = '' # type: str + base: str = "" def type_str(typ: 'mypy.types.Type') -> str: if type_str_conv: @@ -2675,6 +2847,9 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo': class FakeInfo(TypeInfo): + + __slots__ = ('msg',) + # types.py defines a single instance of this class, called types.NOT_READY. # This instance is used as a temporary placeholder in the process of de-serialization # of 'Instance' types. The de-serialization happens in two steps: In the first step, @@ -2705,9 +2880,9 @@ def __getattribute__(self, attr: str) -> None: raise AssertionError(object.__getattribute__(self, 'msg')) -VAR_NO_INFO = FakeInfo('Var is lacking info') # type: Final[TypeInfo] -CLASSDEF_NO_INFO = FakeInfo('ClassDef is lacking info') # type: Final[TypeInfo] -FUNC_NO_INFO = FakeInfo('FuncBase for non-methods lack info') # type: Final[TypeInfo] +VAR_NO_INFO: Final[TypeInfo] = FakeInfo("Var is lacking info") +CLASSDEF_NO_INFO: Final[TypeInfo] = FakeInfo("ClassDef is lacking info") +FUNC_NO_INFO: Final[TypeInfo] = FakeInfo("FuncBase for non-methods lack info") class TypeAlias(SymbolNode): @@ -2817,7 +2992,7 @@ def __init__(self, target: 'mypy.types.Type', fullname: str, line: int, column: self.normalized = normalized # This attribute is manipulated by TypeAliasType. If non-None, # it is the cached value. - self._is_recursive = None # type: Optional[bool] + self._is_recursive: Optional[bool] = None self.eager = eager super().__init__(line, column) @@ -2830,15 +3005,16 @@ def fullname(self) -> str: return self._fullname def serialize(self) -> JsonDict: - data = {'.class': 'TypeAlias', - 'fullname': self._fullname, - 'target': self.target.serialize(), - 'alias_tvars': self.alias_tvars, - 'no_args': self.no_args, - 'normalized': self.normalized, - 'line': self.line, - 'column': self.column - } # type: JsonDict + data: JsonDict = { + ".class": "TypeAlias", + "fullname": self._fullname, + "target": self.target.serialize(), + "alias_tvars": self.alias_tvars, + "no_args": self.no_args, + "normalized": self.normalized, + "line": self.line, + "column": self.column, + } return data def accept(self, visitor: NodeVisitor[T]) -> T: @@ -2907,6 +3083,8 @@ class C(Sequence[C]): ... something that can support general recursive types. """ + __slots__ = ('_fullname', 'node', 'line', 'becomes_typeinfo') + def __init__(self, fullname: str, node: Node, line: int, *, becomes_typeinfo: bool = False) -> None: self._fullname = fullname @@ -3013,7 +3191,7 @@ def __init__(self, self.module_public = module_public self.implicit = implicit self.module_hidden = module_hidden - self.cross_ref = None # type: Optional[str] + self.cross_ref: Optional[str] = None self.plugin_generated = plugin_generated self.no_serialize = no_serialize @@ -3059,9 +3237,10 @@ def serialize(self, prefix: str, name: str) -> JsonDict: prefix: full name of the containing module or class; or None name: name of this object relative to the containing object """ - data = {'.class': 'SymbolTableNode', - 'kind': node_kinds[self.kind], - } # type: JsonDict + data: JsonDict = { + ".class": "SymbolTableNode", + "kind": node_kinds[self.kind], + } if self.module_hidden: data['module_hidden'] = True if not self.module_public: @@ -3117,8 +3296,10 @@ class SymbolTable(Dict[str, SymbolTableNode]): This is used for module, class and function namespaces. """ + __slots__ = () + def __str__(self) -> str: - a = [] # type: List[str] + a: List[str] = [] for key, value in self.items(): # Filter out the implicit import of builtins. if isinstance(value, SymbolTableNode): @@ -3138,7 +3319,7 @@ def copy(self) -> 'SymbolTable': for key, node in self.items()]) def serialize(self, fullname: str) -> JsonDict: - data = {'.class': 'SymbolTable'} # type: JsonDict + data: JsonDict = {".class": "SymbolTable"} for key, value in self.items(): # Skip __builtins__: it's a reference to the builtins # module that gets added to every module by @@ -3174,7 +3355,7 @@ def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]: Return a string of form foo.bar, foo.bar.baz, or similar, or None if the argument cannot be represented in this form. """ - initial = None # type: Optional[str] + initial: Optional[str] = None if isinstance(expr.expr, NameExpr): initial = expr.expr.name elif isinstance(expr.expr, MemberExpr): @@ -3184,15 +3365,16 @@ def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]: return '{}.{}'.format(initial, expr.name) -deserialize_map = { +deserialize_map: Final = { key: obj.deserialize for key, obj in globals().items() if type(obj) is not FakeInfo and isinstance(obj, type) and issubclass(obj, SymbolNode) and obj is not SymbolNode -} # type: Final +} -def check_arg_kinds(arg_kinds: List[int], nodes: List[T], fail: Callable[[str, T], None]) -> None: +def check_arg_kinds( + arg_kinds: List[ArgKind], nodes: List[T], fail: Callable[[str, T], None]) -> None: is_var_arg = False is_kw_arg = False seen_named = False @@ -3228,7 +3410,7 @@ def check_arg_kinds(arg_kinds: List[int], nodes: List[T], fail: Callable[[str, T def check_arg_names(names: Sequence[Optional[str]], nodes: List[T], fail: Callable[[str, T], None], description: str = 'function definition') -> None: - seen_names = set() # type: Set[Optional[str]] + seen_names: Set[Optional[str]] = set() for name, node in zip(names, nodes): if name is not None and name in seen_names: fail('Duplicate argument "{}" in {}'.format(name, description), node) diff --git a/mypy/operators.py b/mypy/operators.py new file mode 100644 index 000000000000..aa26cb2ec6e9 --- /dev/null +++ b/mypy/operators.py @@ -0,0 +1,109 @@ +"""Information about Python operators""" + +from typing_extensions import Final + + +# Map from binary operator id to related method name (in Python 3). +op_methods: Final = { + '+': '__add__', + '-': '__sub__', + '*': '__mul__', + '/': '__truediv__', + '%': '__mod__', + 'divmod': '__divmod__', + '//': '__floordiv__', + '**': '__pow__', + '@': '__matmul__', + '&': '__and__', + '|': '__or__', + '^': '__xor__', + '<<': '__lshift__', + '>>': '__rshift__', + '==': '__eq__', + '!=': '__ne__', + '<': '__lt__', + '>=': '__ge__', + '>': '__gt__', + '<=': '__le__', + 'in': '__contains__', +} + +op_methods_to_symbols: Final = {v: k for (k, v) in op_methods.items()} +op_methods_to_symbols['__div__'] = '/' + +comparison_fallback_method: Final = "__cmp__" +ops_falling_back_to_cmp: Final = {"__ne__", "__eq__", "__lt__", "__le__", "__gt__", "__ge__"} + + +ops_with_inplace_method: Final = { + "+", + "-", + "*", + "/", + "%", + "//", + "**", + "@", + "&", + "|", + "^", + "<<", + ">>", +} + +inplace_operator_methods: Final = set("__i" + op_methods[op][2:] for op in ops_with_inplace_method) + +reverse_op_methods: Final = { + '__add__': '__radd__', + '__sub__': '__rsub__', + '__mul__': '__rmul__', + '__truediv__': '__rtruediv__', + '__mod__': '__rmod__', + '__divmod__': '__rdivmod__', + '__floordiv__': '__rfloordiv__', + '__pow__': '__rpow__', + '__matmul__': '__rmatmul__', + '__and__': '__rand__', + '__or__': '__ror__', + '__xor__': '__rxor__', + '__lshift__': '__rlshift__', + '__rshift__': '__rrshift__', + '__eq__': '__eq__', + '__ne__': '__ne__', + '__lt__': '__gt__', + '__ge__': '__le__', + '__gt__': '__lt__', + '__le__': '__ge__', +} + +reverse_op_method_names: Final = set(reverse_op_methods.values()) + +# Suppose we have some class A. When we do A() + A(), Python will only check +# the output of A().__add__(A()) and skip calling the __radd__ method entirely. +# This shortcut is used only for the following methods: +op_methods_that_shortcut: Final = { + '__add__', + '__sub__', + '__mul__', + '__div__', + '__truediv__', + '__mod__', + '__divmod__', + '__floordiv__', + '__pow__', + '__matmul__', + '__and__', + '__or__', + '__xor__', + '__lshift__', + '__rshift__', +} + +normal_from_reverse_op: Final = dict((m, n) for n, m in reverse_op_methods.items()) +reverse_op_method_set: Final = set(reverse_op_methods.values()) + +unary_op_methods: Final = { + '-': '__neg__', + '+': '__pos__', + '~': '__invert__', +} diff --git a/mypy/options.py b/mypy/options.py index 9e41ad7d310d..58278b1580e8 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -1,4 +1,4 @@ -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict import re import pprint import sys @@ -14,12 +14,12 @@ class BuildType: - STANDARD = 0 # type: Final - MODULE = 1 # type: Final - PROGRAM_TEXT = 2 # type: Final + STANDARD: Final = 0 + MODULE: Final = 1 + PROGRAM_TEXT: Final = 2 -PER_MODULE_OPTIONS = { +PER_MODULE_OPTIONS: Final = { # Please keep this list sorted "allow_redefinition", "allow_untyped_globals", @@ -53,11 +53,11 @@ class BuildType: "warn_return_any", "warn_unreachable", "warn_unused_ignores", -} # type: Final +} -OPTIONS_AFFECTING_CACHE = ((PER_MODULE_OPTIONS | - {"platform", "bazel", "plugins"}) - - {"debug_cache"}) # type: Final +OPTIONS_AFFECTING_CACHE: Final = (PER_MODULE_OPTIONS | {"platform", "bazel", "plugins"}) - { + "debug_cache" +} class Options: @@ -65,23 +65,25 @@ class Options: def __init__(self) -> None: # Cache for clone_for_module() - self._per_module_cache = None # type: Optional[Dict[str, Options]] + self._per_module_cache: Optional[Dict[str, Options]] = None # -- build options -- self.build_type = BuildType.STANDARD - self.python_version = sys.version_info[:2] # type: Tuple[int, int] + self.python_version: Tuple[int, int] = sys.version_info[:2] # The executable used to search for PEP 561 packages. If this is None, # then mypy does not search for PEP 561 packages. - self.python_executable = sys.executable # type: Optional[str] + self.python_executable: Optional[str] = sys.executable self.platform = sys.platform - self.custom_typing_module = None # type: Optional[str] - self.custom_typeshed_dir = None # type: Optional[str] - self.mypy_path = [] # type: List[str] - self.report_dirs = {} # type: Dict[str, str] + self.custom_typing_module: Optional[str] = None + self.custom_typeshed_dir: Optional[str] = None + self.mypy_path: List[str] = [] + self.report_dirs: Dict[str, str] = {} # Show errors in PEP 561 packages/site-packages modules self.no_silence_site_packages = False self.no_site_packages = False self.ignore_missing_imports = False + # Is ignore_missing_imports set in a per-module section + self.ignore_missing_imports_per_module = False self.follow_imports = 'normal' # normal|silent|skip|error # Whether to respect the follow_imports setting even for stub files. # Intended to be used for disabling specific stubs. @@ -98,7 +100,7 @@ def __init__(self) -> None: # top-level __init__.py to your packages. self.explicit_package_bases = False # File names, directory names or subpaths to avoid checking - self.exclude = "" # type: str + self.exclude: List[str] = [] # disallow_any options self.disallow_any_generics = False @@ -159,7 +161,7 @@ def __init__(self) -> None: # Files in which to allow strict-Optional related errors # TODO: Kill this in favor of show_none_errors - self.strict_optional_whitelist = None # type: Optional[List[str]] + self.strict_optional_whitelist: Optional[List[str]] = None # Alternate way to show/hide strict-None-checking related errors self.show_none_errors = True @@ -186,36 +188,36 @@ def __init__(self) -> None: self.warn_unreachable = False # Variable names considered True - self.always_true = [] # type: List[str] + self.always_true: List[str] = [] # Variable names considered False - self.always_false = [] # type: List[str] + self.always_false: List[str] = [] # Error codes to disable - self.disable_error_code = [] # type: List[str] - self.disabled_error_codes = set() # type: Set[ErrorCode] + self.disable_error_code: List[str] = [] + self.disabled_error_codes: Set[ErrorCode] = set() # Error codes to enable - self.enable_error_code = [] # type: List[str] - self.enabled_error_codes = set() # type: Set[ErrorCode] + self.enable_error_code: List[str] = [] + self.enabled_error_codes: Set[ErrorCode] = set() # Use script name instead of __main__ self.scripts_are_modules = False # Config file name - self.config_file = None # type: Optional[str] + self.config_file: Optional[str] = None # A filename containing a JSON mapping from filenames to # mtime/size/hash arrays, used to avoid having to recalculate # source hashes as often. - self.quickstart_file = None # type: Optional[str] + self.quickstart_file: Optional[str] = None # A comma-separated list of files/directories for mypy to type check; # supports globbing - self.files = None # type: Optional[List[str]] + self.files: Optional[List[str]] = None # Write junit.xml to given file - self.junit_xml = None # type: Optional[str] + self.junit_xml: Optional[str] = None # Caching and incremental checking options self.incremental = True @@ -240,16 +242,13 @@ def __init__(self) -> None: # mypy. (Like mypyc.) self.preserve_asts = False - # PEP 612 support is a work in progress, hide it from users - self.wip_pep_612 = False - # Paths of user plugins - self.plugins = [] # type: List[str] + self.plugins: List[str] = [] # Per-module options (raw) - self.per_module_options = OrderedDict() # type: OrderedDict[str, Dict[str, object]] - self._glob_options = [] # type: List[Tuple[str, Pattern[str]]] - self.unused_configs = set() # type: Set[str] + self.per_module_options: OrderedDict[str, Dict[str, object]] = OrderedDict() + self._glob_options: List[Tuple[str, Pattern[str]]] = [] + self.unused_configs: Set[str] = set() # -- development options -- self.verbosity = 0 # More verbose messages (for troubleshooting) @@ -268,8 +267,8 @@ def __init__(self) -> None: self.use_builtins_fixtures = False # -- experimental options -- - self.shadow_file = None # type: Optional[List[List[str]]] - self.show_column_numbers = False # type: bool + self.shadow_file: Optional[List[List[str]]] = None + self.show_column_numbers: bool = False self.show_error_codes = False # Use soft word wrap and show trimmed source snippets with error location markers. self.pretty = False @@ -284,17 +283,24 @@ def __init__(self) -> None: self.export_types = False # List of package roots -- directories under these are packages even # if they don't have __init__.py. - self.package_root = [] # type: List[str] - self.cache_map = {} # type: Dict[str, Tuple[str, str]] + self.package_root: List[str] = [] + self.cache_map: Dict[str, Tuple[str, str]] = {} # Don't properly free objects on exit, just kill the current process. - self.fast_exit = False + self.fast_exit = True # Used to transform source code before parsing if not None # TODO: Make the type precise (AnyStr -> AnyStr) - self.transform_source = None # type: Optional[Callable[[Any], Any]] + self.transform_source: Optional[Callable[[Any], Any]] = None # Print full path to each file in the report. - self.show_absolute_path = False # type: bool + self.show_absolute_path: bool = False # Install missing stub packages if True self.install_types = False + # Install missing stub packages in non-interactive mode (don't prompt for + # confirmation, and don't show any errors) + self.non_interactive = False + # When we encounter errors that may cause many additional errors, + # skip most errors after this many messages have been reported. + # -1 means unlimited. + self.many_errors_threshold = defaults.MANY_ERRORS_THRESHOLD # To avoid breaking plugin compatibility, keep providing new_semantic_analyzer @property @@ -321,6 +327,10 @@ def apply_changes(self, changes: Dict[str, object]) -> 'Options': replace_object_state(new_options, self, copy_dict=True) for key, value in changes.items(): setattr(new_options, key, value) + if changes.get("ignore_missing_imports"): + # This is the only option for which a per-module and a global + # option sometimes beheave differently. + new_options.ignore_missing_imports_per_module = True return new_options def build_per_module_cache(self) -> None: diff --git a/mypy/ordered_dict.py b/mypy/ordered_dict.py deleted file mode 100644 index f1e78ac242f7..000000000000 --- a/mypy/ordered_dict.py +++ /dev/null @@ -1,9 +0,0 @@ -# OrderedDict is kind of slow, so for most of our uses in Python 3.6 -# and later we'd rather just use dict - -import sys - -if sys.version_info < (3, 6): - from collections import OrderedDict as OrderedDict -else: - OrderedDict = dict diff --git a/mypy/plugin.py b/mypy/plugin.py index b83ca0633ba8..3772d7039b05 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -120,18 +120,21 @@ class C: pass """ from abc import abstractmethod -from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict +from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict, Union from mypy_extensions import trait, mypyc_attr from mypy.nodes import ( - Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr + Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr, ArgKind ) from mypy.tvar_scope import TypeVarLikeScope -from mypy.types import Type, Instance, CallableType, TypeList, UnboundType, ProperType +from mypy.types import ( + Type, Instance, CallableType, TypeList, UnboundType, ProperType, FunctionLike +) from mypy.messages import MessageBuilder from mypy.options import Options from mypy.lookup import lookup_fully_qualified from mypy.errorcodes import ErrorCode +from mypy.message_registry import ErrorMessage @trait @@ -146,7 +149,7 @@ class TypeAnalyzerPluginInterface: # This might be different from Plugin.options (that contains default/global options) # if there are per-file options in the config. This applies to all other interfaces # in this file. - options = None # type: Options + options: Options @abstractmethod def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None: @@ -165,7 +168,7 @@ def analyze_type(self, typ: Type) -> Type: @abstractmethod def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], - List[int], + List[ArgKind], List[Optional[str]]]]: """Find types, kinds, and names of arguments from extended callable syntax.""" raise NotImplementedError @@ -189,7 +192,7 @@ class CommonPluginApi: # Global mypy options. # Per-file options can be only accessed on various # XxxPluginInterface classes. - options = None # type: Options + options: Options @abstractmethod def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]: @@ -209,9 +212,9 @@ class CheckerPluginInterface: docstrings in checker.py for more details. """ - msg = None # type: MessageBuilder - options = None # type: Options - path = None # type: str + msg: MessageBuilder + options: Options + path: str # Type context for type inference @property @@ -221,7 +224,8 @@ def type_context(self) -> List[Optional[Type]]: raise NotImplementedError @abstractmethod - def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None: + def fail(self, msg: Union[str, ErrorMessage], ctx: Context, *, + code: Optional[ErrorCode] = None) -> None: """Emit an error message at given location.""" raise NotImplementedError @@ -241,17 +245,29 @@ class SemanticAnalyzerPluginInterface: # TODO: clean-up lookup functions. """ - modules = None # type: Dict[str, MypyFile] + modules: Dict[str, MypyFile] # Options for current file. - options = None # type: Options - cur_mod_id = None # type: str - msg = None # type: MessageBuilder + options: Options + cur_mod_id: str + msg: MessageBuilder @abstractmethod - def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> Instance: + def named_type(self, fullname: str, + args: Optional[List[Type]] = None) -> Instance: """Construct an instance of a builtin type with given type arguments.""" raise NotImplementedError + @abstractmethod + def named_type_or_none(self, fullname: str, + args: Optional[List[Type]] = None) -> Optional[Instance]: + """Construct an instance of a type with given type arguments. + + Return None if a type could not be constructed for the qualified + type name. This is possible when the qualified name includes a + module name and the module has not been imported. + """ + raise NotImplementedError + @abstractmethod def parse_bool(self, expr: Expression) -> Optional[bool]: """Parse True/False literals.""" @@ -283,11 +299,6 @@ def class_type(self, self_type: Type) -> Type: """Generate type of first argument of class methods from type of self.""" raise NotImplementedError - @abstractmethod - def builtin_type(self, fully_qualified_name: str) -> Instance: - """Deprecated: use named_type instead.""" - raise NotImplementedError - @abstractmethod def lookup_fully_qualified(self, name: str) -> SymbolTableNode: """Lookup a symbol by its fully qualified name. @@ -355,6 +366,11 @@ def final_iteration(self) -> bool: """Is this the final iteration of semantic analysis?""" raise NotImplementedError + @property + @abstractmethod + def is_stub_file(self) -> bool: + raise NotImplementedError + # A context for querying for configuration data about a module for # cache invalidation purposes. @@ -382,8 +398,8 @@ def final_iteration(self) -> bool: # callback at least sometimes can infer a more precise type. FunctionContext = NamedTuple( 'FunctionContext', [ - ('arg_types', List[List[Type]]), # List of actual caller types for each formal argument - ('arg_kinds', List[List[int]]), # Ditto for argument kinds, see nodes.ARG_* constants + ('arg_types', List[List[Type]]), # List of actual caller types for each formal argument + ('arg_kinds', List[List[ArgKind]]), # Ditto for argument kinds, see nodes.ARG_* constants # Names of formal parameters from the callee definition, # these will be sufficient in most cases. ('callee_arg_names', List[Optional[str]]), @@ -420,7 +436,7 @@ def final_iteration(self) -> bool: ('type', ProperType), # Base object type for method call ('arg_types', List[List[Type]]), # List of actual caller types for each formal argument # see FunctionContext for details about names and kinds - ('arg_kinds', List[List[int]]), + ('arg_kinds', List[List[ArgKind]]), ('callee_arg_names', List[Optional[str]]), ('arg_names', List[List[Optional[str]]]), ('default_return_type', Type), # Return type inferred by mypy @@ -475,7 +491,7 @@ def __init__(self, options: Options) -> None: # This can't be set in __init__ because it is executed too soon in build.py. # Therefore, build.py *must* set it later before graph processing starts # by calling set_modules(). - self._modules = None # type: Optional[Dict[str, MypyFile]] + self._modules: Optional[Dict[str, MypyFile]] = None def set_modules(self, modules: Dict[str, MypyFile]) -> None: self._modules = modules @@ -544,7 +560,7 @@ def func(x: Other[int]) -> None: return None def get_function_signature_hook(self, fullname: str - ) -> Optional[Callable[[FunctionSigContext], CallableType]]: + ) -> Optional[Callable[[FunctionSigContext], FunctionLike]]: """Adjust the signature of a function. This method is called before type checking a function call. Plugin @@ -577,7 +593,7 @@ def get_function_hook(self, fullname: str return None def get_method_signature_hook(self, fullname: str - ) -> Optional[Callable[[MethodSigContext], CallableType]]: + ) -> Optional[Callable[[MethodSigContext], FunctionLike]]: """Adjust the signature of a method. This method is called before type checking a method call. Plugin @@ -748,7 +764,7 @@ def get_type_analyze_hook(self, fullname: str return self._find_hook(lambda plugin: plugin.get_type_analyze_hook(fullname)) def get_function_signature_hook(self, fullname: str - ) -> Optional[Callable[[FunctionSigContext], CallableType]]: + ) -> Optional[Callable[[FunctionSigContext], FunctionLike]]: return self._find_hook(lambda plugin: plugin.get_function_signature_hook(fullname)) def get_function_hook(self, fullname: str @@ -756,7 +772,7 @@ def get_function_hook(self, fullname: str return self._find_hook(lambda plugin: plugin.get_function_hook(fullname)) def get_method_signature_hook(self, fullname: str - ) -> Optional[Callable[[MethodSigContext], CallableType]]: + ) -> Optional[Callable[[MethodSigContext], FunctionLike]]: return self._find_hook(lambda plugin: plugin.get_method_signature_hook(fullname)) def get_method_hook(self, fullname: str diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 0c4b4b0c701f..051dae18b96c 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -1,13 +1,13 @@ """Plugin for supporting the attrs library (http://www.attrs.org)""" -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import Optional, Dict, List, cast, Tuple, Iterable from typing_extensions import Final import mypy.plugin # To avoid circular imports. from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError -from mypy.fixup import lookup_qualified_stnode +from mypy.lookup import lookup_fully_qualified from mypy.nodes import ( Context, Argument, Var, ARG_OPT, ARG_POS, TypeInfo, AssignmentStmt, TupleExpr, ListExpr, NameExpr, CallExpr, RefExpr, FuncDef, @@ -21,8 +21,8 @@ deserialize_and_fixup_type ) from mypy.types import ( - Type, AnyType, TypeOfAny, CallableType, NoneType, TypeVarDef, TypeVarType, - Overloaded, UnionType, FunctionLike, get_proper_type + TupleType, Type, AnyType, TypeOfAny, CallableType, NoneType, TypeVarType, + Overloaded, UnionType, FunctionLike, get_proper_type, ) from mypy.typeops import make_simplified_union, map_type_from_supertype from mypy.typevars import fill_typevars @@ -32,29 +32,24 @@ KW_ONLY_PYTHON_2_UNSUPPORTED = "kw_only is not supported in Python 2" # The names of the different functions that create classes or arguments. -attr_class_makers = { +attr_class_makers: Final = { 'attr.s', 'attr.attrs', 'attr.attributes', -} # type: Final -attr_dataclass_makers = { +} +attr_dataclass_makers: Final = { 'attr.dataclass', -} # type: Final -attr_frozen_makers = { - 'attr.frozen' -} # type: Final -attr_define_makers = { - 'attr.define', - 'attr.mutable' -} # type: Final -attr_attrib_makers = { +} +attr_frozen_makers: Final = {"attr.frozen"} +attr_define_makers: Final = {"attr.define", "attr.mutable"} +attr_attrib_makers: Final = { 'attr.ib', 'attr.attrib', 'attr.attr', 'attr.field', -} # type: Final +} -SELF_TVAR_NAME = '_AT' # type: Final +SELF_TVAR_NAME: Final = "_AT" class Converter: @@ -92,16 +87,17 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: if self.converter.name: # When a converter is set the init_type is overridden by the first argument # of the converter method. - converter = lookup_qualified_stnode(ctx.api.modules, self.converter.name, True) + converter = lookup_fully_qualified(self.converter.name, ctx.api.modules, + raise_on_missing=False) if not converter: # The converter may be a local variable. Check there too. converter = ctx.api.lookup_qualified(self.converter.name, self.info, True) # Get the type of the converter. - converter_type = None # type: Optional[Type] + converter_type: Optional[Type] = None if converter and isinstance(converter.node, TypeInfo): from mypy.checkmember import type_object_type # To avoid import cycle. - converter_type = type_object_type(converter.node, ctx.api.builtin_type) + converter_type = type_object_type(converter.node, ctx.api.named_type) elif converter and isinstance(converter.node, OverloadedFuncDef): converter_type = converter.node.type elif converter and converter.type: @@ -112,8 +108,8 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: if isinstance(converter_type, CallableType) and converter_type.arg_types: init_type = ctx.api.anal_type(converter_type.arg_types[0]) elif isinstance(converter_type, Overloaded): - types = [] # type: List[Type] - for item in converter_type.items(): + types: List[Type] = [] + for item in converter_type.items: # Walk the overloads looking for methods that can accept one argument. num_arg_types = len(item.arg_types) if not num_arg_types: @@ -276,6 +272,7 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', init = _get_decorator_bool_argument(ctx, 'init', True) frozen = _get_frozen(ctx, frozen_default) order = _determine_eq_order(ctx) + slots = _get_decorator_bool_argument(ctx, 'slots', False) auto_attribs = _get_decorator_optional_bool_argument(ctx, 'auto_attribs', auto_attribs_default) kw_only = _get_decorator_bool_argument(ctx, 'kw_only', False) @@ -305,6 +302,10 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', ctx.api.defer() return + _add_attrs_magic_attribute(ctx, raw_attr_types=[info[attr.name].type for attr in attributes]) + if slots: + _add_slots(ctx, attributes) + # Save the attributes so that subclasses can reuse them. ctx.cls.info.metadata['attrs'] = { 'attributes': [attr.serialize() for attr in attributes], @@ -340,7 +341,7 @@ def _analyze_class(ctx: 'mypy.plugin.ClassDefContext', auto_attribs=None means we'll detect which mode to use. kw_only=True means that all attributes created here will be keyword only args in __init__. """ - own_attrs = OrderedDict() # type: OrderedDict[str, Attribute] + own_attrs: OrderedDict[str, Attribute] = OrderedDict() if auto_attribs is None: auto_attribs = _detect_auto_attribs(ctx) @@ -557,7 +558,7 @@ def _attribute_from_attrib_maker(ctx: 'mypy.plugin.ClassDefContext', type_arg = _get_argument(rvalue, 'type') if type_arg and not init_type: try: - un_type = expr_to_unanalyzed_type(type_arg) + un_type = expr_to_unanalyzed_type(type_arg, ctx.api.options, ctx.api.is_stub_file) except TypeTranslationError: ctx.api.fail('Invalid argument to type', type_arg) else: @@ -627,8 +628,8 @@ def _parse_assignments( lvalue: Expression, stmt: AssignmentStmt) -> Tuple[List[NameExpr], List[Expression]]: """Convert a possibly complex assignment expression into lists of lvalues and rvalues.""" - lvalues = [] # type: List[NameExpr] - rvalues = [] # type: List[Expression] + lvalues: List[NameExpr] = [] + rvalues: List[Expression] = [] if isinstance(lvalue, (TupleExpr, ListExpr)): if all(isinstance(item, NameExpr) for item in lvalue.items): lvalues = cast(List[NameExpr], lvalue.items) @@ -642,22 +643,21 @@ def _parse_assignments( def _add_order(ctx: 'mypy.plugin.ClassDefContext', adder: 'MethodAdder') -> None: """Generate all the ordering methods for this class.""" - bool_type = ctx.api.named_type('__builtins__.bool') - object_type = ctx.api.named_type('__builtins__.object') + bool_type = ctx.api.named_type('builtins.bool') + object_type = ctx.api.named_type('builtins.object') # Make the types be: # AT = TypeVar('AT') # def __lt__(self: AT, other: AT) -> bool # This way comparisons with subclasses will work correctly. - tvd = TypeVarDef(SELF_TVAR_NAME, ctx.cls.info.fullname + '.' + SELF_TVAR_NAME, + tvd = TypeVarType(SELF_TVAR_NAME, ctx.cls.info.fullname + '.' + SELF_TVAR_NAME, -1, [], object_type) - tvd_type = TypeVarType(tvd) self_tvar_expr = TypeVarExpr(SELF_TVAR_NAME, ctx.cls.info.fullname + '.' + SELF_TVAR_NAME, [], object_type) ctx.cls.info.names[SELF_TVAR_NAME] = SymbolTableNode(MDEF, self_tvar_expr) - args = [Argument(Var('other', tvd_type), tvd_type, None, ARG_POS)] + args = [Argument(Var('other', tvd), tvd, None, ARG_POS)] for method in ['__lt__', '__le__', '__gt__', '__ge__']: - adder.add_method(method, args, bool_type, self_type=tvd_type, tvd=tvd) + adder.add_method(method, args, bool_type, self_type=tvd, tvd=tvd) def _make_frozen(ctx: 'mypy.plugin.ClassDefContext', attributes: List[Attribute]) -> None: @@ -709,6 +709,33 @@ def _add_init(ctx: 'mypy.plugin.ClassDefContext', attributes: List[Attribute], adder.add_method('__init__', args, NoneType()) +def _add_attrs_magic_attribute(ctx: 'mypy.plugin.ClassDefContext', + raw_attr_types: 'List[Optional[Type]]') -> None: + attr_name = '__attrs_attrs__' + any_type = AnyType(TypeOfAny.explicit) + attributes_types: 'List[Type]' = [ + ctx.api.named_type_or_none('attr.Attribute', [attr_type or any_type]) or any_type + for attr_type in raw_attr_types + ] + fallback_type = ctx.api.named_type('builtins.tuple', [ + ctx.api.named_type_or_none('attr.Attribute', [any_type]) or any_type, + ]) + var = Var(name=attr_name, type=TupleType(attributes_types, fallback=fallback_type)) + var.info = ctx.cls.info + var._fullname = ctx.cls.info.fullname + '.' + attr_name + ctx.cls.info.names[attr_name] = SymbolTableNode( + kind=MDEF, + node=var, + plugin_generated=True, + ) + + +def _add_slots(ctx: 'mypy.plugin.ClassDefContext', + attributes: List[Attribute]) -> None: + # Unlike `@dataclasses.dataclass`, `__slots__` is rewritten here. + ctx.cls.info.slots = {attr.name for attr in attributes} + + class MethodAdder: """Helper to add methods to a TypeInfo. @@ -724,7 +751,7 @@ def __init__(self, ctx: 'mypy.plugin.ClassDefContext') -> None: def add_method(self, method_name: str, args: List[Argument], ret_type: Type, self_type: Optional[Type] = None, - tvd: Optional[TypeVarDef] = None) -> None: + tvd: Optional[TypeVarType] = None) -> None: """Add a method: def (self, ) -> ): ... to info. self_type: The type to use for the self argument or None to use the inferred self type. diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py index 536022a1e09e..1beb53849327 100644 --- a/mypy/plugins/common.py +++ b/mypy/plugins/common.py @@ -4,10 +4,10 @@ ARG_POS, MDEF, Argument, Block, CallExpr, ClassDef, Expression, SYMBOL_FUNCBASE_TYPES, FuncDef, PassStmt, RefExpr, SymbolTableNode, Var, JsonDict, ) -from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface +from mypy.plugin import CheckerPluginInterface, ClassDefContext, SemanticAnalyzerPluginInterface from mypy.semanal import set_callable_name from mypy.types import ( - CallableType, Overloaded, Type, TypeVarDef, deserialize_type, get_proper_type, + CallableType, Overloaded, Type, TypeVarType, deserialize_type, get_proper_type, ) from mypy.typevars import fill_typevars from mypy.util import get_unique_redefinition_name @@ -62,7 +62,7 @@ def _get_argument(call: CallExpr, name: str) -> Optional[Expression]: callee_node_type = get_proper_type(callee_node.type) if isinstance(callee_node_type, Overloaded): # We take the last overload. - callee_type = callee_node_type.items()[-1] + callee_type = callee_node_type.items[-1] elif isinstance(callee_node_type, CallableType): callee_type = callee_node_type @@ -88,7 +88,7 @@ def add_method( args: List[Argument], return_type: Type, self_type: Optional[Type] = None, - tvar_def: Optional[TypeVarDef] = None, + tvar_def: Optional[TypeVarType] = None, ) -> None: """ Adds a new method to a class. @@ -103,16 +103,15 @@ def add_method( def add_method_to_class( - api: SemanticAnalyzerPluginInterface, + api: Union[SemanticAnalyzerPluginInterface, CheckerPluginInterface], cls: ClassDef, name: str, args: List[Argument], return_type: Type, self_type: Optional[Type] = None, - tvar_def: Optional[TypeVarDef] = None, + tvar_def: Optional[TypeVarType] = None, ) -> None: - """Adds a new method to a class definition. - """ + """Adds a new method to a class definition.""" info = cls.info # First remove any previously generated methods with the same name @@ -123,7 +122,10 @@ def add_method_to_class( cls.defs.body.remove(sym.node) self_type = self_type or fill_typevars(info) - function_type = api.named_type('__builtins__.function') + if isinstance(api, SemanticAnalyzerPluginInterface): + function_type = api.named_type('builtins.function') + else: + function_type = api.named_generic_type('builtins.function', []) args = [Argument(Var('self'), self_type, None, ARG_POS)] + args arg_types, arg_names, arg_kinds = [], [], [] diff --git a/mypy/plugins/ctypes.py b/mypy/plugins/ctypes.py index d2b69e423d4b..87ffcdfe3339 100644 --- a/mypy/plugins/ctypes.py +++ b/mypy/plugins/ctypes.py @@ -194,7 +194,7 @@ def array_value_callback(ctx: 'mypy.plugin.AttributeContext') -> Type: """Callback to provide an accurate type for ctypes.Array.value.""" et = _get_array_element_type(ctx.type) if et is not None: - types = [] # type: List[Type] + types: List[Type] = [] for tp in union_items(et): if isinstance(tp, AnyType): types.append(AnyType(TypeOfAny.from_another_any, source_any=tp)) @@ -215,7 +215,7 @@ def array_raw_callback(ctx: 'mypy.plugin.AttributeContext') -> Type: """Callback to provide an accurate type for ctypes.Array.raw.""" et = _get_array_element_type(ctx.type) if et is not None: - types = [] # type: List[Type] + types: List[Type] = [] for tp in union_items(et): if (isinstance(tp, AnyType) or isinstance(tp, Instance) and tp.type.fullname == 'ctypes.c_char'): diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 5d96ad90c4e7..6d78bc17e615 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -4,7 +4,7 @@ from typing_extensions import Final from mypy.nodes import ( - ARG_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, + ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, Context, Expression, JsonDict, NameExpr, RefExpr, SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode ) @@ -14,18 +14,23 @@ ) from mypy.typeops import map_type_from_supertype from mypy.types import ( - Type, Instance, NoneType, TypeVarDef, TypeVarType, CallableType, - get_proper_type + Type, Instance, NoneType, TypeVarType, CallableType, get_proper_type, + AnyType, TypeOfAny, ) from mypy.server.trigger import make_wildcard_trigger # The set of decorators that generate dataclasses. -dataclass_makers = { +dataclass_makers: Final = { 'dataclass', 'dataclasses.dataclass', -} # type: Final +} +# The set of functions that generate dataclass fields. +field_makers: Final = { + 'dataclasses.field', +} -SELF_TVAR_NAME = '_DT' # type: Final + +SELF_TVAR_NAME: Final = "_DT" class DataclassAttribute: @@ -39,6 +44,7 @@ def __init__( column: int, type: Optional[Type], info: TypeInfo, + kw_only: bool, ) -> None: self.name = name self.is_in_init = is_in_init @@ -48,13 +54,21 @@ def __init__( self.column = column self.type = type self.info = info + self.kw_only = kw_only def to_argument(self) -> Argument: + arg_kind = ARG_POS + if self.kw_only and self.has_default: + arg_kind = ARG_NAMED_OPT + elif self.kw_only and not self.has_default: + arg_kind = ARG_NAMED + elif not self.kw_only and self.has_default: + arg_kind = ARG_OPT return Argument( variable=self.to_var(), type_annotation=self.type, initializer=None, - kind=ARG_OPT if self.has_default else ARG_POS, + kind=arg_kind, ) def to_var(self) -> Var: @@ -70,6 +84,7 @@ def serialize(self) -> JsonDict: 'line': self.line, 'column': self.column, 'type': self.type.serialize(), + 'kw_only': self.kw_only, } @classmethod @@ -77,6 +92,8 @@ def deserialize( cls, info: TypeInfo, data: JsonDict, api: SemanticAnalyzerPluginInterface ) -> 'DataclassAttribute': data = data.copy() + if data.get('kw_only') is None: + data['kw_only'] = False typ = deserialize_and_fixup_type(data.pop('type'), api) return cls(type=typ, info=info, **data) @@ -113,7 +130,9 @@ def transform(self) -> None: 'eq': _get_decorator_bool_argument(self._ctx, 'eq', True), 'order': _get_decorator_bool_argument(self._ctx, 'order', False), 'frozen': _get_decorator_bool_argument(self._ctx, 'frozen', False), + 'slots': _get_decorator_bool_argument(self._ctx, 'slots', False), } + py_version = self._ctx.api.options.python_version # If there are no attributes, it may be that the semantic analyzer has not # processed them yet. In order to work around this, we can simply skip generating @@ -125,14 +144,15 @@ def transform(self) -> None: add_method( ctx, '__init__', - args=[attr.to_argument() for attr in attributes if attr.is_in_init], + args=[attr.to_argument() for attr in attributes if attr.is_in_init + and not self._is_kw_only_type(attr.type)], return_type=NoneType(), ) if (decorator_arguments['eq'] and info.get('__eq__') is None or decorator_arguments['order']): # Type variable for self types in generated methods. - obj_type = ctx.api.named_type('__builtins__.object') + obj_type = ctx.api.named_type('builtins.object') self_tvar_expr = TypeVarExpr(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, [], obj_type) info.names[SELF_TVAR_NAME] = SymbolTableNode(MDEF, self_tvar_expr) @@ -145,13 +165,12 @@ def transform(self) -> None: for method_name in ['__lt__', '__gt__', '__le__', '__ge__']: # Like for __eq__ and __ne__, we want "other" to match # the self type. - obj_type = ctx.api.named_type('__builtins__.object') - order_tvar_def = TypeVarDef(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, + obj_type = ctx.api.named_type('builtins.object') + order_tvar_def = TypeVarType(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, -1, [], obj_type) - order_other_type = TypeVarType(order_tvar_def) - order_return_type = ctx.api.named_type('__builtins__.bool') + order_return_type = ctx.api.named_type('builtins.bool') order_args = [ - Argument(Var('other', order_other_type), order_other_type, None, ARG_POS) + Argument(Var('other', order_tvar_def), order_tvar_def, None, ARG_POS) ] existing_method = info.get(method_name) @@ -167,7 +186,7 @@ def transform(self) -> None: method_name, args=order_args, return_type=order_return_type, - self_type=order_other_type, + self_type=order_tvar_def, tvar_def=order_tvar_def, ) @@ -176,13 +195,47 @@ def transform(self) -> None: else: self._propertize_callables(attributes) + if decorator_arguments['slots']: + self.add_slots(info, attributes, correct_version=py_version >= (3, 10)) + self.reset_init_only_vars(info, attributes) + self._add_dataclass_fields_magic_attribute() + info.metadata['dataclass'] = { 'attributes': [attr.serialize() for attr in attributes], 'frozen': decorator_arguments['frozen'], } + def add_slots(self, + info: TypeInfo, + attributes: List[DataclassAttribute], + *, + correct_version: bool) -> None: + if not correct_version: + # This means that version is lower than `3.10`, + # it is just a non-existent argument for `dataclass` function. + self._ctx.api.fail( + 'Keyword argument "slots" for "dataclass" ' + 'is only valid in Python 3.10 and higher', + self._ctx.reason, + ) + return + if info.slots is not None or info.names.get('__slots__'): + # This means we have a slots conflict. + # Class explicitly specifies `__slots__` field. + # And `@dataclass(slots=True)` is used. + # In runtime this raises a type error. + self._ctx.api.fail( + '"{}" both defines "__slots__" and is used with "slots=True"'.format( + self._ctx.cls.name, + ), + self._ctx.cls, + ) + return + + info.slots = {attr.name for attr in attributes} + def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribute]) -> None: """Remove init-only vars from the class and reset init var declarations.""" for attr in attributes: @@ -213,8 +266,9 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: # First, collect attributes belonging to the current class. ctx = self._ctx cls = self._ctx.cls - attrs = [] # type: List[DataclassAttribute] - known_attrs = set() # type: Set[str] + attrs: List[DataclassAttribute] = [] + known_attrs: Set[str] = set() + kw_only = _get_decorator_bool_argument(ctx, 'kw_only', False) for stmt in cls.defs.body: # Any assignment that doesn't use the new type declaration # syntax can be ignored out of hand. @@ -251,7 +305,10 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: is_init_var = True node.type = node_type.args[0] - has_field_call, field_args = _collect_field_args(stmt.rvalue) + if self._is_kw_only_type(node_type): + kw_only = True + + has_field_call, field_args = _collect_field_args(stmt.rvalue, ctx) is_in_init_param = field_args.get('init') if is_in_init_param is None: @@ -274,6 +331,13 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: # on self in the generated __init__(), not in the class body. sym.implicit = True + is_kw_only = kw_only + # Use the kw_only field arg if it is provided. Otherwise use the + # kw_only value from the decorator parameter. + field_kw_only_param = field_args.get('kw_only') + if field_kw_only_param is not None: + is_kw_only = bool(ctx.api.parse_bool(field_kw_only_param)) + known_attrs.add(lhs.name) attrs.append(DataclassAttribute( name=lhs.name, @@ -284,6 +348,7 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: column=stmt.column, type=sym.type, info=cls.info, + kw_only=is_kw_only, )) # Next, collect attributes belonging to any class in the MRO @@ -300,8 +365,8 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: # Each class depends on the set of attributes in its dataclass ancestors. ctx.api.add_plugin_dependency(make_wildcard_trigger(info.fullname)) - for data in info.metadata['dataclass']['attributes']: - name = data['name'] # type: str + for data in info.metadata["dataclass"]["attributes"]: + name: str = data["name"] if name not in known_attrs: attr = DataclassAttribute.deserialize(info, data, ctx.api) attr.expand_typevar_from_subtype(ctx.cls.info) @@ -318,15 +383,18 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: super_attrs.append(attr) break all_attrs = super_attrs + all_attrs + all_attrs.sort(key=lambda a: a.kw_only) # Ensure that arguments without a default don't follow # arguments that have a default. found_default = False + # Ensure that the KW_ONLY sentinel is only provided once + found_kw_sentinel = False for attr in all_attrs: - # If we find any attribute that is_in_init but that + # If we find any attribute that is_in_init, not kw_only, and that # doesn't have a default after one that does have one, # then that's an error. - if found_default and attr.is_in_init and not attr.has_default: + if found_default and attr.is_in_init and not attr.has_default and not attr.kw_only: # If the issue comes from merging different classes, report it # at the class definition point. context = (Context(line=attr.line, column=attr.column) if attr in attrs @@ -337,6 +405,14 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: ) found_default = found_default or (attr.has_default and attr.is_in_init) + if found_kw_sentinel and self._is_kw_only_type(attr.type): + context = (Context(line=attr.line, column=attr.column) if attr in attrs + else ctx.cls) + ctx.api.fail( + 'There may not be more than one field with the KW_ONLY type', + context, + ) + found_kw_sentinel = found_kw_sentinel or self._is_kw_only_type(attr.type) return all_attrs @@ -376,6 +452,32 @@ def _propertize_callables(self, attributes: List[DataclassAttribute]) -> None: var._fullname = info.fullname + '.' + var.name info.names[var.name] = SymbolTableNode(MDEF, var) + def _is_kw_only_type(self, node: Optional[Type]) -> bool: + """Checks if the type of the node is the KW_ONLY sentinel value.""" + if node is None: + return False + node_type = get_proper_type(node) + if not isinstance(node_type, Instance): + return False + return node_type.type.fullname == 'dataclasses.KW_ONLY' + + def _add_dataclass_fields_magic_attribute(self) -> None: + attr_name = '__dataclass_fields__' + any_type = AnyType(TypeOfAny.explicit) + field_type = self._ctx.api.named_type_or_none('dataclasses.Field', [any_type]) or any_type + attr_type = self._ctx.api.named_type('builtins.dict', [ + self._ctx.api.named_type('builtins.str'), + field_type, + ]) + var = Var(name=attr_name, type=attr_type) + var.info = self._ctx.cls.info + var._fullname = self._ctx.cls.info.fullname + '.' + attr_name + self._ctx.cls.info.names[attr_name] = SymbolTableNode( + kind=MDEF, + node=var, + plugin_generated=True, + ) + def dataclass_class_maker_callback(ctx: ClassDefContext) -> None: """Hooks into the class typechecking process to add support for dataclasses. @@ -384,7 +486,8 @@ def dataclass_class_maker_callback(ctx: ClassDefContext) -> None: transformer.transform() -def _collect_field_args(expr: Expression) -> Tuple[bool, Dict[str, Expression]]: +def _collect_field_args(expr: Expression, + ctx: ClassDefContext) -> Tuple[bool, Dict[str, Expression]]: """Returns a tuple where the first value represents whether or not the expression is a call to dataclass.field and the second is a dictionary of the keyword arguments that field() was called with. @@ -392,11 +495,21 @@ def _collect_field_args(expr: Expression) -> Tuple[bool, Dict[str, Expression]]: if ( isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and - expr.callee.fullname == 'dataclasses.field' + expr.callee.fullname in field_makers ): # field() only takes keyword arguments. args = {} - for name, arg in zip(expr.arg_names, expr.args): + for name, arg, kind in zip(expr.arg_names, expr.args, expr.arg_kinds): + if not kind.is_named(): + if kind.is_named(star=True): + # This means that `field` is used with `**` unpacking, + # the best we can do for now is not to fail. + # TODO: we can infer what's inside `**` and try to collect it. + message = 'Unpacking **kwargs in "field()" is not supported' + else: + message = '"field()" does not accept positional arguments' + ctx.api.fail(message, expr) + return True, {} assert name is not None args[name] = arg return True, args diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 552a52c5c860..67587090e0ba 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -9,12 +9,13 @@ ) from mypy.plugins.common import try_getting_str_literals from mypy.types import ( - Type, Instance, AnyType, TypeOfAny, CallableType, NoneType, TypedDictType, - TypeVarDef, TypeVarType, TPDICT_FB_NAMES, get_proper_type, LiteralType + FunctionLike, Type, Instance, AnyType, TypeOfAny, CallableType, NoneType, TypedDictType, + TypeVarType, TPDICT_FB_NAMES, get_proper_type, LiteralType, TupleType ) from mypy.subtypes import is_subtype from mypy.typeops import make_simplified_union from mypy.checkexpr import is_literal_type_like +from mypy.checker import detach_callable class DefaultPlugin(Plugin): @@ -22,19 +23,21 @@ class DefaultPlugin(Plugin): def get_function_hook(self, fullname: str ) -> Optional[Callable[[FunctionContext], Type]]: - from mypy.plugins import ctypes + from mypy.plugins import ctypes, singledispatch - if fullname == 'contextlib.contextmanager': + if fullname in ('contextlib.contextmanager', 'contextlib.asynccontextmanager'): return contextmanager_callback elif fullname == 'builtins.open' and self.python_version[0] == 3: return open_callback elif fullname == 'ctypes.Array': return ctypes.array_constructor_callback + elif fullname == 'functools.singledispatch': + return singledispatch.create_singledispatch_function_callback return None def get_method_signature_hook(self, fullname: str - ) -> Optional[Callable[[MethodSigContext], CallableType]]: - from mypy.plugins import ctypes + ) -> Optional[Callable[[MethodSigContext], FunctionLike]]: + from mypy.plugins import ctypes, singledispatch if fullname == 'typing.Mapping.get': return typed_dict_get_signature_callback @@ -44,15 +47,15 @@ def get_method_signature_hook(self, fullname: str return typed_dict_pop_signature_callback elif fullname in set(n + '.update' for n in TPDICT_FB_NAMES): return typed_dict_update_signature_callback - elif fullname in set(n + '.__delitem__' for n in TPDICT_FB_NAMES): - return typed_dict_delitem_signature_callback elif fullname == 'ctypes.Array.__setitem__': return ctypes.array_setitem_callback + elif fullname == singledispatch.SINGLEDISPATCH_CALLABLE_CALL_METHOD: + return singledispatch.call_singledispatch_function_callback return None def get_method_hook(self, fullname: str ) -> Optional[Callable[[MethodContext], Type]]: - from mypy.plugins import ctypes + from mypy.plugins import ctypes, singledispatch if fullname == 'typing.Mapping.get': return typed_dict_get_callback @@ -60,6 +63,8 @@ def get_method_hook(self, fullname: str return int_pow_callback elif fullname == 'builtins.int.__neg__': return int_neg_callback + elif fullname in ('builtins.tuple.__mul__', 'builtins.tuple.__rmul__'): + return tuple_mul_callback elif fullname in set(n + '.setdefault' for n in TPDICT_FB_NAMES): return typed_dict_setdefault_callback elif fullname in set(n + '.pop' for n in TPDICT_FB_NAMES): @@ -72,6 +77,10 @@ def get_method_hook(self, fullname: str return ctypes.array_iter_callback elif fullname == 'pathlib.Path.open': return path_open_callback + elif fullname == singledispatch.SINGLEDISPATCH_REGISTER_METHOD: + return singledispatch.singledispatch_register_callback + elif fullname == singledispatch.REGISTER_CALLABLE_CALL_METHOD: + return singledispatch.call_singledispatch_function_after_register_argument return None def get_attribute_hook(self, fullname: str @@ -183,12 +192,12 @@ def contextmanager_callback(ctx: FunctionContext) -> Type: and isinstance(default_return, CallableType)): # The stub signature doesn't preserve information about arguments so # add them back here. - return default_return.copy_modified( + return detach_callable(default_return.copy_modified( arg_types=arg_type.arg_types, arg_kinds=arg_type.arg_kinds, arg_names=arg_type.arg_names, variables=arg_type.variables, - is_ellipsis_args=arg_type.is_ellipsis_args) + is_ellipsis_args=arg_type.is_ellipsis_args)) return ctx.default_return_type @@ -219,8 +228,8 @@ def typed_dict_get_signature_callback(ctx: MethodSigContext) -> CallableType: # Tweak the signature to include the value type as context. It's # only needed for type inference since there's a union with a type # variable that accepts everything. - assert isinstance(signature.variables[0], TypeVarDef) - tv = TypeVarType(signature.variables[0]) + tv = signature.variables[0] + assert isinstance(tv, TypeVarType) return signature.copy_modified( arg_types=[signature.arg_types[0], make_simplified_union([value_type, tv])], @@ -237,7 +246,7 @@ def typed_dict_get_callback(ctx: MethodContext) -> Type: if keys is None: return ctx.default_return_type - output_types = [] # type: List[Type] + output_types: List[Type] = [] for key in keys: value_type = get_proper_type(ctx.type.items.get(key)) if value_type is None: @@ -284,8 +293,8 @@ def typed_dict_pop_signature_callback(ctx: MethodSigContext) -> CallableType: # Tweak the signature to include the value type as context. It's # only needed for type inference since there's a union with a type # variable that accepts everything. - assert isinstance(signature.variables[0], TypeVarDef) - tv = TypeVarType(signature.variables[0]) + tv = signature.variables[0] + assert isinstance(tv, TypeVarType) typ = make_simplified_union([value_type, tv]) return signature.copy_modified( arg_types=[str_type, typ], @@ -380,12 +389,6 @@ def typed_dict_setdefault_callback(ctx: MethodContext) -> Type: return ctx.default_return_type -def typed_dict_delitem_signature_callback(ctx: MethodSigContext) -> CallableType: - # Replace NoReturn as the argument type. - str_type = ctx.api.named_generic_type('builtins.str', []) - return ctx.default_signature.copy_modified(arg_types=[str_type]) - - def typed_dict_delitem_callback(ctx: MethodContext) -> Type: """Type check TypedDict.__delitem__.""" if (isinstance(ctx.type, TypedDictType) @@ -463,3 +466,24 @@ def int_neg_callback(ctx: MethodContext) -> Type: if isinstance(value, int): return LiteralType(value=-value, fallback=fallback) return ctx.default_return_type + + +def tuple_mul_callback(ctx: MethodContext) -> Type: + """Infer a more precise return type for tuple.__mul__ and tuple.__rmul__. + + This is used to return a specific sized tuple if multiplied by Literal int + """ + if not isinstance(ctx.type, TupleType): + return ctx.default_return_type + + arg_type = get_proper_type(ctx.arg_types[0][0]) + if isinstance(arg_type, Instance) and arg_type.last_known_value is not None: + value = arg_type.last_known_value.value + if isinstance(value, int): + return ctx.type.copy_modified(items=ctx.type.items * value) + elif isinstance(ctx.type, LiteralType): + value = arg_type.value + if isinstance(value, int): + return ctx.type.copy_modified(items=ctx.type.items * value) + + return ctx.default_return_type diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index ade32998ed14..ea9a02f5b41e 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -10,24 +10,22 @@ we actually bake some of it directly in to the semantic analysis layer (see semanal_enum.py). """ -from typing import Iterable, Optional, TypeVar +from typing import Iterable, Optional, Sequence, TypeVar, cast from typing_extensions import Final import mypy.plugin # To avoid circular imports. from mypy.types import Type, Instance, LiteralType, CallableType, ProperType, get_proper_type +from mypy.typeops import make_simplified_union from mypy.nodes import TypeInfo +from mypy.subtypes import is_equivalent +from mypy.semanal_enum import ENUM_BASES -# Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use -# enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. -ENUM_PREFIXES = {'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag'} # type: Final -ENUM_NAME_ACCESS = ( - {'{}.name'.format(prefix) for prefix in ENUM_PREFIXES} - | {'{}._name_'.format(prefix) for prefix in ENUM_PREFIXES} -) # type: Final -ENUM_VALUE_ACCESS = ( - {'{}.value'.format(prefix) for prefix in ENUM_PREFIXES} - | {'{}._value_'.format(prefix) for prefix in ENUM_PREFIXES} -) # type: Final +ENUM_NAME_ACCESS: Final = {"{}.name".format(prefix) for prefix in ENUM_BASES} | { + "{}._name_".format(prefix) for prefix in ENUM_BASES +} +ENUM_VALUE_ACCESS: Final = {"{}.value".format(prefix) for prefix in ENUM_BASES} | { + "{}._value_".format(prefix) for prefix in ENUM_BASES +} def enum_name_callback(ctx: 'mypy.plugin.AttributeContext') -> Type: @@ -167,19 +165,44 @@ class SomeEnum: get_proper_type(n.type) if n else None for n in stnodes if n is None or not n.implicit) - proper_types = ( + proper_types = list( _infer_value_type_with_auto_fallback(ctx, t) for t in node_types if t is None or not isinstance(t, CallableType)) underlying_type = _first(proper_types) if underlying_type is None: return ctx.default_attr_type + + # At first we try to predict future `value` type if all other items + # have the same type. For example, `int`. + # If this is the case, we simply return this type. + # See https://github.com/python/mypy/pull/9443 all_same_value_type = all( proper_type is not None and proper_type == underlying_type for proper_type in proper_types) if all_same_value_type: if underlying_type is not None: return underlying_type + + # But, after we started treating all `Enum` values as `Final`, + # we start to infer types in + # `item = 1` as `Literal[1]`, not just `int`. + # So, for example types in this `Enum` will all be different: + # + # class Ordering(IntEnum): + # one = 1 + # two = 2 + # three = 3 + # + # We will infer three `Literal` types here. + # They are not the same, but they are equivalent. + # So, we unify them to make sure `.value` prediction still works. + # Result will be `Literal[1] | Literal[2] | Literal[3]` for this case. + all_equivalent_types = all( + proper_type is not None and is_equivalent(proper_type, underlying_type) + for proper_type in proper_types) + if all_equivalent_types: + return make_simplified_union(cast(Sequence[Type], proper_types)) return ctx.default_attr_type assert isinstance(ctx.type, Instance) diff --git a/mypy/plugins/functools.py b/mypy/plugins/functools.py index 09bf9992476e..e52d478927e8 100644 --- a/mypy/plugins/functools.py +++ b/mypy/plugins/functools.py @@ -1,17 +1,18 @@ """Plugin for supporting the functools standard library module.""" from typing import Dict, NamedTuple, Optional +from typing_extensions import Final import mypy.plugin -from mypy.nodes import ARG_OPT, ARG_POS, ARG_STAR2, Argument, FuncItem, Var +from mypy.nodes import ARG_POS, ARG_STAR2, Argument, FuncItem, Var from mypy.plugins.common import add_method_to_class from mypy.types import AnyType, CallableType, get_proper_type, Type, TypeOfAny, UnboundType -functools_total_ordering_makers = { +functools_total_ordering_makers: Final = { 'functools.total_ordering', } -_ORDERING_METHODS = { +_ORDERING_METHODS: Final = { '__lt__', '__le__', '__gt__', @@ -44,9 +45,9 @@ def functools_total_ordering_maker_callback(ctx: mypy.plugin.ClassDefContext, return other_type = _find_other_type(root_method) - bool_type = ctx.api.named_type('__builtins__.bool') - ret_type = bool_type # type: Type - if root_method.type.ret_type != ctx.api.named_type('__builtins__.bool'): + bool_type = ctx.api.named_type('builtins.bool') + ret_type: Type = bool_type + if root_method.type.ret_type != ctx.api.named_type('builtins.bool'): proper_ret_type = get_proper_type(root_method.type.ret_type) if not (isinstance(proper_ret_type, UnboundType) and proper_ret_type.name.split('.')[-1] == 'bool'): @@ -65,7 +66,7 @@ def _find_other_type(method: _MethodInfo) -> Type: cur_pos_arg = 0 other_arg = None for arg_kind, arg_type in zip(method.type.arg_kinds, method.type.arg_types): - if arg_kind in (ARG_POS, ARG_OPT): + if arg_kind.is_positional(): if cur_pos_arg == first_arg_pos: other_arg = arg_type break @@ -84,7 +85,7 @@ def _find_other_type(method: _MethodInfo) -> Type: def _analyze_class(ctx: mypy.plugin.ClassDefContext) -> Dict[str, Optional[_MethodInfo]]: """Analyze the class body, its parents, and return the comparison methods found.""" # Traverse the MRO and collect ordering methods. - comparison_methods = {} # type: Dict[str, Optional[_MethodInfo]] + comparison_methods: Dict[str, Optional[_MethodInfo]] = {} # Skip object because total_ordering does not use methods from object for cls in ctx.cls.info.mro[:-1]: for name in _ORDERING_METHODS: diff --git a/mypy/plugins/singledispatch.py b/mypy/plugins/singledispatch.py new file mode 100644 index 000000000000..104faa38d1ce --- /dev/null +++ b/mypy/plugins/singledispatch.py @@ -0,0 +1,220 @@ +from mypy.messages import format_type +from mypy.plugins.common import add_method_to_class +from mypy.nodes import ( + ARG_POS, Argument, Block, ClassDef, SymbolTable, TypeInfo, Var, Context +) +from mypy.subtypes import is_subtype +from mypy.types import ( + AnyType, CallableType, Instance, NoneType, Overloaded, Type, TypeOfAny, get_proper_type, + FunctionLike +) +from mypy.plugin import CheckerPluginInterface, FunctionContext, MethodContext, MethodSigContext +from typing import List, NamedTuple, Optional, Sequence, TypeVar, Union +from typing_extensions import Final + +SingledispatchTypeVars = NamedTuple('SingledispatchTypeVars', [ + ('return_type', Type), + ('fallback', CallableType), +]) + +RegisterCallableInfo = NamedTuple('RegisterCallableInfo', [ + ('register_type', Type), + ('singledispatch_obj', Instance), +]) + +SINGLEDISPATCH_TYPE: Final = 'functools._SingleDispatchCallable' + +SINGLEDISPATCH_REGISTER_METHOD: Final = '{}.register'.format(SINGLEDISPATCH_TYPE) + +SINGLEDISPATCH_CALLABLE_CALL_METHOD: Final = '{}.__call__'.format(SINGLEDISPATCH_TYPE) + + +def get_singledispatch_info(typ: Instance) -> Optional[SingledispatchTypeVars]: + if len(typ.args) == 2: + return SingledispatchTypeVars(*typ.args) # type: ignore + return None + + +T = TypeVar('T') + + +def get_first_arg(args: List[List[T]]) -> Optional[T]: + """Get the element that corresponds to the first argument passed to the function""" + if args and args[0]: + return args[0][0] + return None + + +REGISTER_RETURN_CLASS: Final = '_SingleDispatchRegisterCallable' + +REGISTER_CALLABLE_CALL_METHOD: Final = 'functools.{}.__call__'.format( + REGISTER_RETURN_CLASS +) + + +def make_fake_register_class_instance(api: CheckerPluginInterface, type_args: Sequence[Type] + ) -> Instance: + defn = ClassDef(REGISTER_RETURN_CLASS, Block([])) + defn.fullname = 'functools.{}'.format(REGISTER_RETURN_CLASS) + info = TypeInfo(SymbolTable(), defn, "functools") + obj_type = api.named_generic_type('builtins.object', []).type + info.bases = [Instance(obj_type, [])] + info.mro = [info, obj_type] + defn.info = info + + func_arg = Argument(Var('name'), AnyType(TypeOfAny.implementation_artifact), None, ARG_POS) + add_method_to_class(api, defn, '__call__', [func_arg], NoneType()) + + return Instance(info, type_args) + + +PluginContext = Union[FunctionContext, MethodContext] + + +def fail(ctx: PluginContext, msg: str, context: Optional[Context]) -> None: + """Emit an error message. + + This tries to emit an error message at the location specified by `context`, falling back to the + location specified by `ctx.context`. This is helpful when the only context information about + where you want to put the error message may be None (like it is for `CallableType.definition`) + and falling back to the location of the calling function is fine.""" + # TODO: figure out if there is some more reliable way of getting context information, so this + # function isn't necessary + if context is not None: + err_context = context + else: + err_context = ctx.context + ctx.api.fail(msg, err_context) + + +def create_singledispatch_function_callback(ctx: FunctionContext) -> Type: + """Called for functools.singledispatch""" + func_type = get_proper_type(get_first_arg(ctx.arg_types)) + if isinstance(func_type, CallableType): + + if len(func_type.arg_kinds) < 1: + fail( + ctx, + 'Singledispatch function requires at least one argument', + func_type.definition, + ) + return ctx.default_return_type + + elif not func_type.arg_kinds[0].is_positional(star=True): + fail( + ctx, + 'First argument to singledispatch function must be a positional argument', + func_type.definition, + ) + return ctx.default_return_type + + # singledispatch returns an instance of functools._SingleDispatchCallable according to + # typeshed + singledispatch_obj = get_proper_type(ctx.default_return_type) + assert isinstance(singledispatch_obj, Instance) + singledispatch_obj.args += (func_type,) + + return ctx.default_return_type + + +def singledispatch_register_callback(ctx: MethodContext) -> Type: + """Called for functools._SingleDispatchCallable.register""" + assert isinstance(ctx.type, Instance) + # TODO: check that there's only one argument + first_arg_type = get_proper_type(get_first_arg(ctx.arg_types)) + if isinstance(first_arg_type, (CallableType, Overloaded)) and first_arg_type.is_type_obj(): + # HACK: We received a class as an argument to register. We need to be able + # to access the function that register is being applied to, and the typeshed definition + # of register has it return a generic Callable, so we create a new + # SingleDispatchRegisterCallable class, define a __call__ method, and then add a + # plugin hook for that. + + # is_subtype doesn't work when the right type is Overloaded, so we need the + # actual type + register_type = first_arg_type.items[0].ret_type + type_args = RegisterCallableInfo(register_type, ctx.type) + register_callable = make_fake_register_class_instance( + ctx.api, + type_args + ) + return register_callable + elif isinstance(first_arg_type, CallableType): + # TODO: do more checking for registered functions + register_function(ctx, ctx.type, first_arg_type) + # The typeshed stubs for register say that the function returned is Callable[..., T], even + # though the function returned is the same as the one passed in. We return the type of the + # function so that mypy can properly type check cases where the registered function is used + # directly (instead of through singledispatch) + return first_arg_type + + # fallback in case we don't recognize the arguments + return ctx.default_return_type + + +def register_function(ctx: PluginContext, singledispatch_obj: Instance, func: Type, + register_arg: Optional[Type] = None) -> None: + """Register a function""" + + func = get_proper_type(func) + if not isinstance(func, CallableType): + return + metadata = get_singledispatch_info(singledispatch_obj) + if metadata is None: + # if we never added the fallback to the type variables, we already reported an error, so + # just don't do anything here + return + dispatch_type = get_dispatch_type(func, register_arg) + if dispatch_type is None: + # TODO: report an error here that singledispatch requires at least one argument + # (might want to do the error reporting in get_dispatch_type) + return + fallback = metadata.fallback + + fallback_dispatch_type = fallback.arg_types[0] + if not is_subtype(dispatch_type, fallback_dispatch_type): + + fail(ctx, 'Dispatch type {} must be subtype of fallback function first argument {}'.format( + format_type(dispatch_type), format_type(fallback_dispatch_type) + ), func.definition) + return + return + + +def get_dispatch_type(func: CallableType, register_arg: Optional[Type]) -> Optional[Type]: + if register_arg is not None: + return register_arg + if func.arg_types: + return func.arg_types[0] + return None + + +def call_singledispatch_function_after_register_argument(ctx: MethodContext) -> Type: + """Called on the function after passing a type to register""" + register_callable = ctx.type + if isinstance(register_callable, Instance): + type_args = RegisterCallableInfo(*register_callable.args) # type: ignore + func = get_first_arg(ctx.arg_types) + if func is not None: + register_function(ctx, type_args.singledispatch_obj, func, type_args.register_type) + # see call to register_function in the callback for register + return func + return ctx.default_return_type + + +def rename_func(func: CallableType, new_name: CallableType) -> CallableType: + """Return a new CallableType that is `function` with the name of `new_name`""" + if new_name.name is not None: + signature_used = func.with_name(new_name.name) + else: + signature_used = func + return signature_used + + +def call_singledispatch_function_callback(ctx: MethodSigContext) -> FunctionLike: + """Called for functools._SingleDispatchCallable.__call__""" + if not isinstance(ctx.type, Instance): + return ctx.default_signature + metadata = get_singledispatch_info(ctx.type) + if metadata is None: + return ctx.default_signature + return metadata.fallback diff --git a/mypy/pyinfo.py b/mypy/pyinfo.py new file mode 100644 index 000000000000..3834c04e218e --- /dev/null +++ b/mypy/pyinfo.py @@ -0,0 +1,46 @@ +from __future__ import print_function +"""Utilities to find the site and prefix information of a Python executable, which may be Python 2. + +This file MUST remain compatible with Python 2. Since we cannot make any assumptions about the +Python being executed, this module should not use *any* dependencies outside of the standard +library found in Python 2. This file is run each mypy run, so it should be kept as fast as +possible. +""" +import site +import sys + +if __name__ == '__main__': + sys.path = sys.path[1:] # we don't want to pick up mypy.types + +MYPY = False +if MYPY: + from typing import List, Tuple + + +def getprefixes(): + # type: () -> Tuple[str, str] + return sys.base_prefix, sys.prefix + + +def getsitepackages(): + # type: () -> List[str] + res = [] + if hasattr(site, 'getsitepackages'): + res.extend(site.getsitepackages()) + + if hasattr(site, 'getusersitepackages') and site.ENABLE_USER_SITE: + res.insert(0, site.getusersitepackages()) + else: + from distutils.sysconfig import get_python_lib + res = [get_python_lib()] + return res + + +if __name__ == '__main__': + if sys.argv[-1] == 'getsitepackages': + print(repr(getsitepackages())) + elif sys.argv[-1] == 'getprefixes': + print(repr(getprefixes())) + else: + print("ERROR: incorrect argument to pyinfo.py.", file=sys.stderr) + sys.exit(1) diff --git a/mypy/reachability.py b/mypy/reachability.py index 0a29c9b3bba7..44a21b993cfc 100644 --- a/mypy/reachability.py +++ b/mypy/reachability.py @@ -13,27 +13,28 @@ from mypy.literals import literal # Inferred truth value of an expression. -ALWAYS_TRUE = 1 # type: Final -MYPY_TRUE = 2 # type: Final # True in mypy, False at runtime -ALWAYS_FALSE = 3 # type: Final -MYPY_FALSE = 4 # type: Final # False in mypy, True at runtime -TRUTH_VALUE_UNKNOWN = 5 # type: Final +ALWAYS_TRUE: Final = 1 +MYPY_TRUE: Final = 2 # True in mypy, False at runtime +ALWAYS_FALSE: Final = 3 +MYPY_FALSE: Final = 4 # False in mypy, True at runtime +TRUTH_VALUE_UNKNOWN: Final = 5 -inverted_truth_mapping = { +inverted_truth_mapping: Final = { ALWAYS_TRUE: ALWAYS_FALSE, ALWAYS_FALSE: ALWAYS_TRUE, TRUTH_VALUE_UNKNOWN: TRUTH_VALUE_UNKNOWN, MYPY_TRUE: MYPY_FALSE, MYPY_FALSE: MYPY_TRUE, -} # type: Final - -reverse_op = {"==": "==", - "!=": "!=", - "<": ">", - ">": "<", - "<=": ">=", - ">=": "<=", - } # type: Final +} + +reverse_op: Final = { + "==": "==", + "!=": "!=", + "<": ">", + ">": "<", + "<=": ">=", + ">=": "<=", +} def infer_reachability_of_if_statement(s: IfStmt, options: Options) -> None: diff --git a/mypy/renaming.py b/mypy/renaming.py index d2b4807e47e4..a43abb13c688 100644 --- a/mypy/renaming.py +++ b/mypy/renaming.py @@ -1,4 +1,5 @@ -from typing import Dict, List +from contextlib import contextmanager +from typing import Dict, Iterator, List from typing_extensions import Final from mypy.nodes import ( @@ -9,9 +10,9 @@ from mypy.traverser import TraverserVisitor # Scope kinds -FILE = 0 # type: Final -FUNCTION = 1 # type: Final -CLASS = 2 # type: Final +FILE: Final = 0 +FUNCTION: Final = 1 +CLASS: Final = 2 class VariableRenameVisitor(TraverserVisitor): @@ -53,20 +54,20 @@ def __init__(self) -> None: # Number of surrounding loop statements self.loop_depth = 0 # Map block id to loop depth. - self.block_loop_depth = {} # type: Dict[int, int] + self.block_loop_depth: Dict[int, int] = {} # Stack of block ids being processed. - self.blocks = [] # type: List[int] + self.blocks: List[int] = [] # List of scopes; each scope maps short (unqualified) name to block id. - self.var_blocks = [] # type: List[Dict[str, int]] + self.var_blocks: List[Dict[str, int]] = [] # References to variables that we may need to rename. List of # scopes; each scope is a mapping from name to list of collections # of names that refer to the same logical variable. - self.refs = [] # type: List[Dict[str, List[List[NameExpr]]]] + self.refs: List[Dict[str, List[List[NameExpr]]]] = [] # Number of reads of the most recent definition of a variable (per scope) - self.num_reads = [] # type: List[Dict[str, int]] + self.num_reads: List[Dict[str, int]] = [] # Kinds of nested scopes (FILE, FUNCTION or CLASS) - self.scope_kinds = [] # type: List[int] + self.scope_kinds: List[int] = [] def visit_mypy_file(self, file_node: MypyFile) -> None: """Rename variables within a file. @@ -74,61 +75,47 @@ def visit_mypy_file(self, file_node: MypyFile) -> None: This is the main entry point to this class. """ self.clear() - self.enter_scope(FILE) - self.enter_block() - - for d in file_node.defs: - d.accept(self) - - self.leave_block() - self.leave_scope() + with self.enter_scope(FILE), self.enter_block(): + for d in file_node.defs: + d.accept(self) def visit_func_def(self, fdef: FuncDef) -> None: # Conservatively do not allow variable defined before a function to # be redefined later, since function could refer to either definition. self.reject_redefinition_of_vars_in_scope() - self.enter_scope(FUNCTION) - self.enter_block() - - for arg in fdef.arguments: - name = arg.variable.name - # 'self' can't be redefined since it's special as it allows definition of - # attributes. 'cls' can't be used to define attributes so we can ignore it. - can_be_redefined = name != 'self' # TODO: Proper check - self.record_assignment(arg.variable.name, can_be_redefined) - self.handle_arg(name) + with self.enter_scope(FUNCTION), self.enter_block(): + for arg in fdef.arguments: + name = arg.variable.name + # 'self' can't be redefined since it's special as it allows definition of + # attributes. 'cls' can't be used to define attributes so we can ignore it. + can_be_redefined = name != 'self' # TODO: Proper check + self.record_assignment(arg.variable.name, can_be_redefined) + self.handle_arg(name) - for stmt in fdef.body.body: - stmt.accept(self) - - self.leave_block() - self.leave_scope() + for stmt in fdef.body.body: + stmt.accept(self) def visit_class_def(self, cdef: ClassDef) -> None: self.reject_redefinition_of_vars_in_scope() - self.enter_scope(CLASS) - super().visit_class_def(cdef) - self.leave_scope() + with self.enter_scope(CLASS): + super().visit_class_def(cdef) def visit_block(self, block: Block) -> None: - self.enter_block() - super().visit_block(block) - self.leave_block() + with self.enter_block(): + super().visit_block(block) def visit_while_stmt(self, stmt: WhileStmt) -> None: - self.enter_loop() - super().visit_while_stmt(stmt) - self.leave_loop() + with self.enter_loop(): + super().visit_while_stmt(stmt) def visit_for_stmt(self, stmt: ForStmt) -> None: stmt.expr.accept(self) self.analyze_lvalue(stmt.index, True) # Also analyze as non-lvalue so that every for loop index variable is assumed to be read. stmt.index.accept(self) - self.enter_loop() - stmt.body.accept(self) - self.leave_loop() + with self.enter_loop(): + stmt.body.accept(self) if stmt.else_body: stmt.else_body.accept(self) @@ -142,9 +129,8 @@ def visit_try_stmt(self, stmt: TryStmt) -> None: # Variables defined by a try statement get special treatment in the # type checker which allows them to be always redefined, so no need to # do renaming here. - self.enter_try() - super().visit_try_stmt(stmt) - self.leave_try() + with self.enter_try(): + super().visit_try_stmt(stmt) def visit_with_stmt(self, stmt: WithStmt) -> None: for expr in stmt.expr: @@ -275,40 +261,48 @@ def clear(self) -> None: self.blocks = [] self.var_blocks = [] - def enter_block(self) -> None: + @contextmanager + def enter_block(self) -> Iterator[None]: self.block_id += 1 self.blocks.append(self.block_id) self.block_loop_depth[self.block_id] = self.loop_depth + try: + yield + finally: + self.blocks.pop() - def leave_block(self) -> None: - self.blocks.pop() - - def enter_try(self) -> None: + @contextmanager + def enter_try(self) -> Iterator[None]: self.disallow_redef_depth += 1 + try: + yield + finally: + self.disallow_redef_depth -= 1 - def leave_try(self) -> None: - self.disallow_redef_depth -= 1 - - def enter_loop(self) -> None: + @contextmanager + def enter_loop(self) -> Iterator[None]: self.loop_depth += 1 - - def leave_loop(self) -> None: - self.loop_depth -= 1 + try: + yield + finally: + self.loop_depth -= 1 def current_block(self) -> int: return self.blocks[-1] - def enter_scope(self, kind: int) -> None: + @contextmanager + def enter_scope(self, kind: int) -> Iterator[None]: self.var_blocks.append({}) self.refs.append({}) self.num_reads.append({}) self.scope_kinds.append(kind) - - def leave_scope(self) -> None: - self.flush_refs() - self.var_blocks.pop() - self.num_reads.pop() - self.scope_kinds.pop() + try: + yield + finally: + self.flush_refs() + self.var_blocks.pop() + self.num_reads.pop() + self.scope_kinds.pop() def is_nested(self) -> int: return len(self.var_blocks) > 1 diff --git a/mypy/report.py b/mypy/report.py index 1ae9fd30c819..380a8c6b6441 100644 --- a/mypy/report.py +++ b/mypy/report.py @@ -14,7 +14,7 @@ import typing from typing import Any, Callable, Dict, List, Optional, Tuple, cast, Iterator -from typing_extensions import Final +from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.nodes import MypyFile, Expression, FuncDef from mypy import stats @@ -25,34 +25,36 @@ from mypy.defaults import REPORTER_NAMES try: - # mypyc doesn't properly handle import from of submodules that we - # don't have stubs for, hence the hacky double import - import lxml.etree # type: ignore # noqa: F401 - from lxml import etree + from lxml import etree # type: ignore LXML_INSTALLED = True except ImportError: LXML_INSTALLED = False -type_of_any_name_map = collections.OrderedDict([ - (TypeOfAny.unannotated, "Unannotated"), - (TypeOfAny.explicit, "Explicit"), - (TypeOfAny.from_unimported_type, "Unimported"), - (TypeOfAny.from_omitted_generics, "Omitted Generics"), - (TypeOfAny.from_error, "Error"), - (TypeOfAny.special_form, "Special Form"), - (TypeOfAny.implementation_artifact, "Implementation Artifact"), -]) # type: Final[collections.OrderedDict[int, str]] +type_of_any_name_map: Final["collections.OrderedDict[int, str]"] = collections.OrderedDict( + [ + (TypeOfAny.unannotated, "Unannotated"), + (TypeOfAny.explicit, "Explicit"), + (TypeOfAny.from_unimported_type, "Unimported"), + (TypeOfAny.from_omitted_generics, "Omitted Generics"), + (TypeOfAny.from_error, "Error"), + (TypeOfAny.special_form, "Special Form"), + (TypeOfAny.implementation_artifact, "Implementation Artifact"), + ] +) -ReporterClasses = Dict[str, Tuple[Callable[['Reports', str], 'AbstractReporter'], bool]] +ReporterClasses: _TypeAlias = Dict[ + str, + Tuple[Callable[['Reports', str], 'AbstractReporter'], bool], +] -reporter_classes = {} # type: Final[ReporterClasses] +reporter_classes: Final[ReporterClasses] = {} class Reports: def __init__(self, data_dir: str, report_dirs: Dict[str, str]) -> None: self.data_dir = data_dir - self.reporters = [] # type: List[AbstractReporter] - self.named_reporters = {} # type: Dict[str, AbstractReporter] + self.reporters: List[AbstractReporter] = [] + self.named_reporters: Dict[str, AbstractReporter] = {} for report_type, report_dir in sorted(report_dirs.items()): self.add_report(report_type, report_dir) @@ -145,7 +147,7 @@ def visit_func_def(self, defn: FuncDef) -> None: class LineCountReporter(AbstractReporter): def __init__(self, reports: Reports, output_dir: str) -> None: super().__init__(reports, output_dir) - self.counts = {} # type: Dict[str, Tuple[int, int, int, int]] + self.counts: Dict[str, Tuple[int, int, int, int]] = {} def on_file(self, tree: MypyFile, @@ -173,12 +175,12 @@ def on_file(self, annotated_funcs, total_funcs) def on_finish(self) -> None: - counts = sorted(((c, p) for p, c in self.counts.items()), - reverse=True) # type: List[Tuple[Tuple[int, int, int, int], str]] - total_counts = tuple(sum(c[i] for c, p in counts) - for i in range(4)) - with open(os.path.join(self.output_dir, 'linecount.txt'), 'w') as f: - f.write('{:7} {:7} {:6} {:6} total\n'.format(*total_counts)) + counts: List[Tuple[Tuple[int, int, int, int], str]] = sorted( + ((c, p) for p, c in self.counts.items()), reverse=True + ) + total_counts = tuple(sum(c[i] for c, p in counts) for i in range(4)) + with open(os.path.join(self.output_dir, "linecount.txt"), "w") as f: + f.write("{:7} {:7} {:6} {:6} total\n".format(*total_counts)) for c, p in counts: f.write('{:7} {:7} {:6} {:6} {}\n'.format( c[0], c[1], c[2], c[3], p)) @@ -192,8 +194,8 @@ class AnyExpressionsReporter(AbstractReporter): def __init__(self, reports: Reports, output_dir: str) -> None: super().__init__(reports, output_dir) - self.counts = {} # type: Dict[str, Tuple[int, int]] - self.any_types_counter = {} # type: Dict[str, typing.Counter[int]] + self.counts: Dict[str, Tuple[int, int]] = {} + self.any_types_counter: Dict[str, typing.Counter[int]] = {} def on_file(self, tree: MypyFile, @@ -256,7 +258,7 @@ def _report_any_exprs(self) -> None: total_coverage = (float(total_expr - total_any) / float(total_expr)) * 100 column_names = ["Name", "Anys", "Exprs", "Coverage"] - rows = [] # type: List[List[str]] + rows: List[List[str]] = [] for filename in sorted(self.counts): (num_any, num_total) = self.counts[filename] coverage = (float(num_total - num_any) / float(num_total)) * 100 @@ -267,14 +269,14 @@ def _report_any_exprs(self) -> None: self._write_out_report('any-exprs.txt', column_names, rows, total_row) def _report_types_of_anys(self) -> None: - total_counter = collections.Counter() # type: typing.Counter[int] + total_counter: typing.Counter[int] = collections.Counter() for counter in self.any_types_counter.values(): for any_type, value in counter.items(): total_counter[any_type] += value file_column_name = "Name" total_row_name = "Total" column_names = [file_column_name] + list(type_of_any_name_map.values()) - rows = [] # type: List[List[str]] + rows: List[List[str]] = [] for filename, counter in self.any_types_counter.items(): rows.append([filename] + [str(counter[typ]) for typ in type_of_any_name_map]) rows.sort(key=lambda x: x[0]) @@ -389,7 +391,7 @@ class LineCoverageReporter(AbstractReporter): def __init__(self, reports: Reports, output_dir: str) -> None: super().__init__(reports, output_dir) - self.lines_covered = {} # type: Dict[str, List[int]] + self.lines_covered: Dict[str, List[int]] = {} def on_file(self, tree: MypyFile, @@ -444,14 +446,13 @@ def __init__(self, reports: Reports, output_dir: str) -> None: self.css_html_path = os.path.join(reports.data_dir, 'xml', 'mypy-html.css') xsd_path = os.path.join(reports.data_dir, 'xml', 'mypy.xsd') self.schema = etree.XMLSchema(etree.parse(xsd_path)) - self.last_xml = None # type: Optional[Any] - self.files = [] # type: List[FileInfo] + self.last_xml: Optional[Any] = None + self.files: List[FileInfo] = [] # XML doesn't like control characters, but they are sometimes # legal in source code (e.g. comments, string literals). # Tabs (#x09) are allowed in XML content. - control_fixer = str.maketrans( - ''.join(chr(i) for i in range(32) if i != 9), '?' * 31) # type: Final + control_fixer: Final = str.maketrans("".join(chr(i) for i in range(32) if i != 9), "?" * 31) def on_file(self, tree: MypyFile, @@ -465,8 +466,8 @@ def on_file(self, except ValueError: return - if should_skip_path(path): - return + if should_skip_path(path) or os.path.isdir(path): + return # `path` can sometimes be a directory, see #11334 visitor = stats.StatisticsVisitor(inferred=True, filename=tree.fullname, @@ -501,7 +502,7 @@ def on_file(self, def _get_any_info_for_line(visitor: stats.StatisticsVisitor, lineno: int) -> str: if lineno in visitor.any_line_map: result = "Any Types on this line: " - counter = collections.Counter() # type: typing.Counter[int] + counter: typing.Counter[int] = collections.Counter() for typ in visitor.any_line_map[lineno]: counter[typ.type_of_any] += 1 for any_type, occurrences in counter.items(): @@ -548,8 +549,8 @@ class CoberturaPackage(object): def __init__(self, name: str) -> None: self.name = name - self.classes = {} # type: Dict[str, Any] - self.packages = {} # type: Dict[str, CoberturaPackage] + self.classes: Dict[str, Any] = {} + self.packages: Dict[str, CoberturaPackage] = {} self.total_lines = 0 self.covered_lines = 0 @@ -811,7 +812,7 @@ class LinePrecisionReporter(AbstractReporter): def __init__(self, reports: Reports, output_dir: str) -> None: super().__init__(reports, output_dir) - self.files = [] # type: List[FileInfo] + self.files: List[FileInfo] = [] def on_file(self, tree: MypyFile, diff --git a/mypy/sametypes.py b/mypy/sametypes.py index f599cc2f7b14..33cd7f0606cf 100644 --- a/mypy/sametypes.py +++ b/mypy/sametypes.py @@ -1,10 +1,11 @@ from typing import Sequence from mypy.types import ( - Type, TypeGuardType, UnboundType, AnyType, NoneType, TupleType, TypedDictType, + Type, UnboundType, AnyType, NoneType, TupleType, TypedDictType, UnionType, CallableType, TypeVarType, Instance, TypeVisitor, ErasedType, Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType, - ProperType, get_proper_type, TypeAliasType) + ProperType, get_proper_type, TypeAliasType, ParamSpecType +) from mypy.typeops import tuple_fallback, make_simplified_union @@ -96,6 +97,11 @@ def visit_type_var(self, left: TypeVarType) -> bool: return (isinstance(self.right, TypeVarType) and left.id == self.right.id) + def visit_param_spec(self, left: ParamSpecType) -> bool: + # Ignore upper bound since it's derived from flavor. + return (isinstance(self.right, ParamSpecType) and + left.id == self.right.id and left.flavor == self.right.flavor) + def visit_callable_type(self, left: CallableType) -> bool: # FIX generics if isinstance(self.right, CallableType): @@ -151,15 +157,9 @@ def visit_union_type(self, left: UnionType) -> bool: else: return False - def visit_type_guard_type(self, left: TypeGuardType) -> bool: - if isinstance(self.right, TypeGuardType): - return is_same_type(left.type_guard, self.right.type_guard) - else: - return False - def visit_overloaded(self, left: Overloaded) -> bool: if isinstance(self.right, Overloaded): - return is_same_types(left.items(), self.right.items()) + return is_same_types(left.items, self.right.items) else: return False diff --git a/mypy/scope.py b/mypy/scope.py index 22608ef3a0fe..fdc1c1a314fc 100644 --- a/mypy/scope.py +++ b/mypy/scope.py @@ -5,20 +5,22 @@ from contextlib import contextmanager from typing import List, Optional, Iterator, Tuple +from typing_extensions import TypeAlias as _TypeAlias +from mypy.backports import nullcontext from mypy.nodes import TypeInfo, FuncBase -SavedScope = Tuple[str, Optional[TypeInfo], Optional[FuncBase]] +SavedScope: _TypeAlias = Tuple[str, Optional[TypeInfo], Optional[FuncBase]] class Scope: """Track which target we are processing at any given time.""" def __init__(self) -> None: - self.module = None # type: Optional[str] - self.classes = [] # type: List[TypeInfo] - self.function = None # type: Optional[FuncBase] + self.module: Optional[str] = None + self.classes: List[TypeInfo] = [] + self.function: Optional[FuncBase] = None # Number of nested scopes ignored (that don't get their own separate targets) self.ignored = 0 @@ -51,18 +53,30 @@ def current_function_name(self) -> Optional[str]: """Return the current function's short name if it exists""" return self.function.name if self.function else None - def enter_file(self, prefix: str) -> None: + @contextmanager + def module_scope(self, prefix: str) -> Iterator[None]: self.module = prefix self.classes = [] self.function = None self.ignored = 0 + yield + assert self.module + self.module = None - def enter_function(self, fdef: FuncBase) -> None: + @contextmanager + def function_scope(self, fdef: FuncBase) -> Iterator[None]: if not self.function: self.function = fdef else: # Nested functions are part of the topmost function target. self.ignored += 1 + yield + if self.ignored: + # Leave a scope that's included in the enclosing target. + self.ignored -= 1 + else: + assert self.function + self.function = None def enter_class(self, info: TypeInfo) -> None: """Enter a class target scope.""" @@ -72,21 +86,21 @@ def enter_class(self, info: TypeInfo) -> None: # Classes within functions are part of the enclosing function target. self.ignored += 1 - def leave(self) -> None: - """Leave the innermost scope (can be any kind of scope).""" + def leave_class(self) -> None: + """Leave a class target scope.""" if self.ignored: # Leave a scope that's included in the enclosing target. self.ignored -= 1 - elif self.function: - # Function is always the innermost target. - self.function = None - elif self.classes: + else: + assert self.classes # Leave the innermost class. self.classes.pop() - else: - # Leave module. - assert self.module - self.module = None + + @contextmanager + def class_scope(self, info: TypeInfo) -> Iterator[None]: + self.enter_class(info) + yield + self.leave_class() def save(self) -> SavedScope: """Produce a saved scope that can be entered with saved_scope()""" @@ -94,31 +108,12 @@ def save(self) -> SavedScope: # We only save the innermost class, which is sufficient since # the rest are only needed for when classes are left. cls = self.classes[-1] if self.classes else None - return (self.module, cls, self.function) - - @contextmanager - def function_scope(self, fdef: FuncBase) -> Iterator[None]: - self.enter_function(fdef) - yield - self.leave() - - @contextmanager - def class_scope(self, info: TypeInfo) -> Iterator[None]: - self.enter_class(info) - yield - self.leave() + return self.module, cls, self.function @contextmanager def saved_scope(self, saved: SavedScope) -> Iterator[None]: module, info, function = saved - self.enter_file(module) - if info: - self.enter_class(info) - if function: - self.enter_function(function) - yield - if function: - self.leave() - if info: - self.leave() - self.leave() + with self.module_scope(module): + with self.class_scope(info) if info else nullcontext(): + with self.function_scope(function) if function else nullcontext(): + yield diff --git a/mypy/semanal.py b/mypy/semanal.py index 277beb480e97..f29965f6ff8f 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -53,7 +53,7 @@ from typing import ( List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable ) -from typing_extensions import Final +from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.nodes import ( MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, @@ -67,7 +67,7 @@ SymbolTableNode, ListComprehension, GeneratorExpr, LambdaExpr, MDEF, Decorator, SetExpr, TypeVarExpr, StrExpr, BytesExpr, PrintStmt, ConditionalExpr, PromoteExpr, - ComparisonExpr, StarExpr, ARG_POS, ARG_NAMED, type_aliases, + ComparisonExpr, StarExpr, ArgKind, ARG_POS, ARG_NAMED, type_aliases, YieldFromExpr, NamedTupleExpr, NonlocalDecl, SymbolNode, SetComprehension, DictionaryComprehension, TypeAlias, TypeAliasExpr, YieldExpr, ExecStmt, BackquoteExpr, ImportBase, AwaitExpr, @@ -75,8 +75,9 @@ PlaceholderNode, COVARIANT, CONTRAVARIANT, INVARIANT, get_nongen_builtins, get_member_expr_fullname, REVEAL_TYPE, REVEAL_LOCALS, is_final_node, TypedDictExpr, type_aliases_source_versions, + typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, - ParamSpecExpr + ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, FuncBase, implicit_module_attrs, ) from mypy.tvar_scope import TypeVarLikeScope from mypy.typevars import fill_typevars @@ -88,13 +89,13 @@ from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes from mypy.types import ( - FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, + FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, - get_proper_type, get_proper_types, TypeAliasType) -from mypy.typeops import function_type + get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType +) +from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery -from mypy.nodes import implicit_module_attrs from mypy.typeanal import ( TypeAnalyser, analyze_type_alias, no_subscript_builtin_alias, TypeVarLikeQuery, TypeVarLikeList, remove_dups, has_any_from_unimported_type, @@ -106,14 +107,16 @@ Plugin, ClassDefContext, SemanticAnalyzerPluginInterface, DynamicClassDefContext ) -from mypy.util import correct_relative_import, unmangle, module_prefix, is_typeshed_file +from mypy.util import ( + correct_relative_import, unmangle, module_prefix, is_typeshed_file, unnamed_function, +) from mypy.scope import Scope from mypy.semanal_shared import ( SemanticAnalyzerInterface, set_callable_name, calculate_tuple_fallback, PRIORITY_FALLBACKS ) from mypy.semanal_namedtuple import NamedTupleAnalyzer from mypy.semanal_typeddict import TypedDictAnalyzer -from mypy.semanal_enum import EnumCallAnalyzer +from mypy.semanal_enum import EnumCallAnalyzer, ENUM_BASES from mypy.semanal_newtype import NewTypeAnalyzer from mypy.reachability import ( infer_reachability_of_if_statement, infer_condition_value, ALWAYS_FALSE, ALWAYS_TRUE, @@ -124,7 +127,7 @@ T = TypeVar('T') -FUTURE_IMPORTS = { +FUTURE_IMPORTS: Final = { '__future__.nested_scopes': 'nested_scopes', '__future__.generators': 'generators', '__future__.division': 'division', @@ -135,16 +138,16 @@ '__future__.barry_as_FLUFL': 'barry_as_FLUFL', '__future__.generator_stop': 'generator_stop', '__future__.annotations': 'annotations', -} # type: Final +} # Special cased built-in classes that are needed for basic functionality and need to be # available very early on. -CORE_BUILTIN_CLASSES = ['object', 'bool', 'function'] # type: Final +CORE_BUILTIN_CLASSES: Final = ["object", "bool", "function"] # Used for tracking incomplete references -Tag = int +Tag: _TypeAlias = int class SemanticAnalyzer(NodeVisitor[None], @@ -156,31 +159,33 @@ class SemanticAnalyzer(NodeVisitor[None], AST. Note that type checking is performed as a separate pass. """ + __deletable__ = ['patches', 'options', 'cur_mod_node'] + # Module name space - modules = None # type: Dict[str, MypyFile] + modules: Dict[str, MypyFile] # Global name space for current module - globals = None # type: SymbolTable + globals: SymbolTable # Names declared using "global" (separate set for each scope) - global_decls = None # type: List[Set[str]] - # Names declated using "nonlocal" (separate set for each scope) - nonlocal_decls = None # type: List[Set[str]] + global_decls: List[Set[str]] + # Names declared using "nonlocal" (separate set for each scope) + nonlocal_decls: List[Set[str]] # Local names of function scopes; None for non-function scopes. - locals = None # type: List[Optional[SymbolTable]] + locals: List[Optional[SymbolTable]] # Whether each scope is a comprehension scope. - is_comprehension_stack = None # type: List[bool] + is_comprehension_stack: List[bool] # Nested block depths of scopes - block_depth = None # type: List[int] + block_depth: List[int] # TypeInfo of directly enclosing class (or None) - type = None # type: Optional[TypeInfo] + type: Optional[TypeInfo] = None # Stack of outer classes (the second tuple item contains tvars). - type_stack = None # type: List[Optional[TypeInfo]] + type_stack: List[Optional[TypeInfo]] # Type variables bound by the current scope, be it class or function - tvar_scope = None # type: TypeVarLikeScope + tvar_scope: TypeVarLikeScope # Per-module options - options = None # type: Options + options: Options # Stack of functions being analyzed - function_stack = None # type: List[FuncItem] + function_stack: List[FuncItem] # Set to True if semantic analysis defines a name, or replaces a # placeholder definition. If some iteration makes no progress, @@ -201,26 +206,26 @@ class SemanticAnalyzer(NodeVisitor[None], # # Note that a star import adds a special name '*' to the set, this blocks # adding _any_ names in the current file. - missing_names = None # type: List[Set[str]] + missing_names: List[Set[str]] # Callbacks that will be called after semantic analysis to tweak things. - patches = None # type: List[Tuple[int, Callable[[], None]]] + patches: List[Tuple[int, Callable[[], None]]] loop_depth = 0 # Depth of breakable loops cur_mod_id = '' # Current module id (or None) (phase 2) _is_stub_file = False # Are we analyzing a stub file? _is_typeshed_stub_file = False # Are we analyzing a typeshed stub file? - imports = None # type: Set[str] # Imported modules (during phase 2 analysis) + imports: Set[str] # Imported modules (during phase 2 analysis) # Note: some imports (and therefore dependencies) might # not be found in phase 1, for example due to * imports. - errors = None # type: Errors # Keeps track of generated errors - plugin = None # type: Plugin # Mypy plugin for special casing of library features - statement = None # type: Optional[Statement] # Statement/definition being analyzed - future_import_flags = None # type: Set[str] + errors: Errors # Keeps track of generated errors + plugin: Plugin # Mypy plugin for special casing of library features + statement: Optional[Statement] = None # Statement/definition being analyzed + future_import_flags: Set[str] # Mapping from 'async def' function definitions to their return type wrapped as a # 'Coroutine[Any, Any, T]'. Used to keep track of whether a function definition's # return type has already been wrapped, by checking if the function definition's # type is stored in this mapping and that it still matches. - wrapped_coro_return_types = {} # type: Dict[FuncDef, Type] + wrapped_coro_return_types: Dict[FuncDef, Type] = {} def __init__(self, modules: Dict[str, MypyFile], @@ -245,13 +250,14 @@ def __init__(self, # analyzed in several iterations until all names are resolved. We need to save # the local namespaces for the top level function and all nested functions between # these iterations. See also semanal_main.process_top_level_function(). - self.saved_locals = {} \ - # type: Dict[Union[FuncItem, GeneratorExpr, DictionaryComprehension], SymbolTable] + self.saved_locals: Dict[ + Union[FuncItem, GeneratorExpr, DictionaryComprehension], SymbolTable + ] = {} self.imports = set() self.type = None self.type_stack = [] # Are the namespaces of classes being processed complete? - self.incomplete_type_stack = [] # type: List[bool] + self.incomplete_type_stack: List[bool] = [] self.tvar_scope = TypeVarLikeScope() self.function_stack = [] self.block_depth = [0] @@ -265,9 +271,9 @@ def __init__(self, # missing name in these namespaces, we need to defer the current analysis target, # since it's possible that the name will be there once the namespace is complete. self.incomplete_namespaces = incomplete_namespaces - self.all_exports = [] # type: List[str] + self.all_exports: List[str] = [] # Map from module id to list of explicitly exported names (i.e. names in __all__). - self.export_map = {} # type: Dict[str, List[str]] + self.export_map: Dict[str, List[str]] = {} self.plugin = plugin # If True, process function definitions. If False, don't. This is used # for processing module top levels in fine-grained incremental mode. @@ -276,9 +282,9 @@ def __init__(self, # Trace line numbers for every file where deferral happened during analysis of # current SCC or top-level function. - self.deferral_debug_context = [] # type: List[Tuple[str, int]] + self.deferral_debug_context: List[Tuple[str, int]] = [] - self.future_import_flags = set() # type: Set[str] + self.future_import_flags: Set[str] = set() # mypyc doesn't properly handle implementing an abstractproperty # with a regular attribute so we make them properties @@ -306,9 +312,12 @@ def prepare_file(self, file_node: MypyFile) -> None: if file_node.fullname == 'builtins': self.prepare_builtins_namespace(file_node) if file_node.fullname == 'typing': - self.prepare_typing_namespace(file_node) + self.prepare_typing_namespace(file_node, type_aliases) + if file_node.fullname == 'typing_extensions': + self.prepare_typing_namespace(file_node, typing_extensions_aliases) - def prepare_typing_namespace(self, file_node: MypyFile) -> None: + def prepare_typing_namespace(self, file_node: MypyFile, + aliases: Dict[str, str]) -> None: """Remove dummy alias definitions such as List = TypeAlias(object) from typing. They will be replaced with real aliases when corresponding targets are ready. @@ -330,7 +339,7 @@ def helper(defs: List[Statement]) -> None: if (isinstance(stmt, AssignmentStmt) and len(stmt.lvalues) == 1 and isinstance(stmt.lvalues[0], NameExpr)): # Assignment to a simple name, remove it if it is a dummy alias. - if 'typing.' + stmt.lvalues[0].name in type_aliases: + if f'{file_node.fullname}.{stmt.lvalues[0].name}' in aliases: defs.remove(stmt) helper(file_node.defs) @@ -355,7 +364,7 @@ def prepare_builtins_namespace(self, file_node: MypyFile) -> None: assert isinstance(bool_info, TypeInfo) bool_type = Instance(bool_info, []) - special_var_types = [ + special_var_types: List[Tuple[str, Type]] = [ ('None', NoneType()), # reveal_type is a mypy-only function that gives an error with # the type of its arg. @@ -366,7 +375,7 @@ def prepare_builtins_namespace(self, file_node: MypyFile) -> None: ('True', bool_type), ('False', bool_type), ('__debug__', bool_type), - ] # type: List[Tuple[str, Type]] + ] for name, typ in special_var_types: v = Var(name, typ) @@ -407,6 +416,8 @@ def refresh_top_level(self, file_node: MypyFile) -> None: self.accept(d) if file_node.fullname == 'typing': self.add_builtin_aliases(file_node) + if file_node.fullname == 'typing_extensions': + self.add_typing_extension_aliases(file_node) self.adjust_public_exports() self.export_map[self.cur_mod_id] = self.all_exports self.all_exports = [] @@ -417,10 +428,21 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None: # unicode docstrings should be accepted in Python 2 if name == '__doc__': if self.options.python_version >= (3, 0): - typ = UnboundType('__builtins__.str') # type: Type + typ: Type = UnboundType("__builtins__.str") else: typ = UnionType([UnboundType('__builtins__.str'), UnboundType('__builtins__.unicode')]) + elif name == '__path__': + if not file_node.is_package_init_file(): + continue + # Need to construct the type ourselves, to avoid issues with __builtins__.list + # not being subscriptable or typing.List not getting bound + sym = self.lookup_qualified("__builtins__.list", Context()) + if not sym: + continue + node = sym.node + assert isinstance(node, TypeInfo) + typ = Instance(node, [self.str_type()]) else: assert t is not None, 'type should be specified for {}'.format(name) typ = UnboundType(t) @@ -457,30 +479,53 @@ def add_builtin_aliases(self, tree: MypyFile) -> None: name = alias.split('.')[-1] if name in tree.names and not isinstance(tree.names[name].node, PlaceholderNode): continue - tag = self.track_incomplete_refs() - n = self.lookup_fully_qualified_or_none(target_name) - if n: - if isinstance(n.node, PlaceholderNode): - self.mark_incomplete(name, tree) - else: - # Found built-in class target. Create alias. - target = self.named_type_or_none(target_name, []) - assert target is not None - # Transform List to List[Any], etc. - fix_instance_types(target, self.fail, self.note, self.options.python_version) - alias_node = TypeAlias(target, alias, - line=-1, column=-1, # there is no context - no_args=True, normalized=True) - self.add_symbol(name, alias_node, tree) - elif self.found_incomplete_ref(tag): - # Built-in class target may not ready yet -- defer. + self.create_alias(tree, target_name, alias, name) + + def add_typing_extension_aliases(self, tree: MypyFile) -> None: + """Typing extensions module does contain some type aliases. + + We need to analyze them as such, because in typeshed + they are just defined as `_Alias()` call. + Which is not supported natively. + """ + assert tree.fullname == 'typing_extensions' + + for alias, target_name in typing_extensions_aliases.items(): + name = alias.split('.')[-1] + if name in tree.names and isinstance(tree.names[name].node, TypeAlias): + continue # Do not reset TypeAliases on the second pass. + + # We need to remove any node that is there at the moment. It is invalid. + tree.names.pop(name, None) + + # Now, create a new alias. + self.create_alias(tree, target_name, alias, name) + + def create_alias(self, tree: MypyFile, target_name: str, alias: str, name: str) -> None: + tag = self.track_incomplete_refs() + n = self.lookup_fully_qualified_or_none(target_name) + if n: + if isinstance(n.node, PlaceholderNode): self.mark_incomplete(name, tree) else: - # Test fixtures may be missing some builtin classes, which is okay. - # Kill the placeholder if there is one. - if name in tree.names: - assert isinstance(tree.names[name].node, PlaceholderNode) - del tree.names[name] + # Found built-in class target. Create alias. + target = self.named_type_or_none(target_name, []) + assert target is not None + # Transform List to List[Any], etc. + fix_instance_types(target, self.fail, self.note, self.options.python_version) + alias_node = TypeAlias(target, alias, + line=-1, column=-1, # there is no context + no_args=True, normalized=True) + self.add_symbol(name, alias_node, tree) + elif self.found_incomplete_ref(tag): + # Built-in class target may not ready yet -- defer. + self.mark_incomplete(name, tree) + else: + # Test fixtures may be missing some builtin classes, which is okay. + # Kill the placeholder if there is one. + if name in tree.names: + assert isinstance(tree.names[name].node, PlaceholderNode) + del tree.names[name] def adjust_public_exports(self) -> None: """Adjust the module visibility of globals due to __all__.""" @@ -512,36 +557,35 @@ def file_context(self, self.errors.set_file(file_node.path, file_node.fullname, scope=scope) self.cur_mod_node = file_node self.cur_mod_id = file_node.fullname - scope.enter_file(self.cur_mod_id) - self._is_stub_file = file_node.path.lower().endswith('.pyi') - self._is_typeshed_stub_file = is_typeshed_file(file_node.path) - self.globals = file_node.names - self.tvar_scope = TypeVarLikeScope() - - self.named_tuple_analyzer = NamedTupleAnalyzer(options, self) - self.typed_dict_analyzer = TypedDictAnalyzer(options, self, self.msg) - self.enum_call_analyzer = EnumCallAnalyzer(options, self) - self.newtype_analyzer = NewTypeAnalyzer(options, self, self.msg) - - # Counter that keeps track of references to undefined things potentially caused by - # incomplete namespaces. - self.num_incomplete_refs = 0 - - if active_type: - self.incomplete_type_stack.append(False) - scope.enter_class(active_type) - self.enter_class(active_type.defn.info) - for tvar in active_type.defn.type_vars: - self.tvar_scope.bind_existing(tvar) - - yield - - if active_type: - scope.leave() - self.leave_class() - self.type = None - self.incomplete_type_stack.pop() - scope.leave() + with scope.module_scope(self.cur_mod_id): + self._is_stub_file = file_node.path.lower().endswith('.pyi') + self._is_typeshed_stub_file = is_typeshed_file(file_node.path) + self.globals = file_node.names + self.tvar_scope = TypeVarLikeScope() + + self.named_tuple_analyzer = NamedTupleAnalyzer(options, self) + self.typed_dict_analyzer = TypedDictAnalyzer(options, self, self.msg) + self.enum_call_analyzer = EnumCallAnalyzer(options, self) + self.newtype_analyzer = NewTypeAnalyzer(options, self, self.msg) + + # Counter that keeps track of references to undefined things potentially caused by + # incomplete namespaces. + self.num_incomplete_refs = 0 + + if active_type: + self.incomplete_type_stack.append(False) + scope.enter_class(active_type) + self.enter_class(active_type.defn.info) + for tvar in active_type.defn.type_vars: + self.tvar_scope.bind_existing(tvar) + + yield + + if active_type: + scope.leave_class() + self.leave_class() + self.type = None + self.incomplete_type_stack.pop() del self.options # @@ -646,7 +690,7 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None: elif isinstance(functype, CallableType): self_type = get_proper_type(functype.arg_types[0]) if isinstance(self_type, AnyType): - leading_type = fill_typevars(info) # type: Type + leading_type: Type = fill_typevars(info) if func.is_class or func.name == '__new__': leading_type = self.class_type(leading_type) func.type = replace_implicit_first_type(functype, leading_type) @@ -662,6 +706,12 @@ def f(): ... # Error: 'f' redefined """ if isinstance(new, Decorator): new = new.func + if ( + isinstance(previous, (FuncDef, Decorator)) + and unnamed_function(new.name) + and unnamed_function(previous.name) + ): + return True if isinstance(previous, (FuncDef, Var, Decorator)) and new.is_conditional: new.original_def = previous return True @@ -710,7 +760,7 @@ def analyze_overloaded_func_def(self, defn: OverloadedFuncDef) -> None: # This is a property. first_item.func.is_overload = True self.analyze_property_with_multi_part_definition(defn) - typ = function_type(first_item.func, self.builtin_type('builtins.function')) + typ = function_type(first_item.func, self.named_type('builtins.function')) assert isinstance(typ, CallableType) types = [typ] else: @@ -759,7 +809,7 @@ def analyze_overload_sigs_and_impl( """ types = [] non_overload_indexes = [] - impl = None # type: Optional[OverloadPart] + impl: Optional[OverloadPart] = None for i, item in enumerate(defn.items): if i != 0: # Assume that the first item was already visited @@ -767,7 +817,7 @@ def analyze_overload_sigs_and_impl( item.accept(self) # TODO: support decorated overloaded functions properly if isinstance(item, Decorator): - callable = function_type(item.func, self.builtin_type('builtins.function')) + callable = function_type(item.func, self.named_type('builtins.function')) assert isinstance(callable, CallableType) if not any(refers_to_fullname(dec, 'typing.overload') for dec in item.decorators): @@ -819,7 +869,7 @@ def handle_missing_overload_implementation(self, defn: OverloadedFuncDef) -> Non """Generate error about missing overload implementation (only if needed).""" if not self.is_stub_file: if self.type and self.type.is_protocol and not self.is_func_scope(): - # An overloded protocol method doesn't need an implementation. + # An overloaded protocol method doesn't need an implementation. for item in defn.items: if isinstance(item, Decorator): item.func.is_abstract = True @@ -931,23 +981,22 @@ def analyze_function_body(self, defn: FuncItem) -> None: a = self.type_analyzer() a.bind_function_type_variables(cast(CallableType, defn.type), defn) self.function_stack.append(defn) - self.enter(defn) - for arg in defn.arguments: - self.add_local(arg.variable, defn) + with self.enter(defn): + for arg in defn.arguments: + self.add_local(arg.variable, defn) - # The first argument of a non-static, non-class method is like 'self' - # (though the name could be different), having the enclosing class's - # instance type. - if is_method and not defn.is_static and not defn.is_class and defn.arguments: - defn.arguments[0].variable.is_self = True + # The first argument of a non-static, non-class method is like 'self' + # (though the name could be different), having the enclosing class's + # instance type. + if is_method and not defn.is_static and not defn.is_class and defn.arguments: + defn.arguments[0].variable.is_self = True - defn.body.accept(self) - self.leave() + defn.body.accept(self) self.function_stack.pop() def check_classvar_in_signature(self, typ: ProperType) -> None: if isinstance(typ, Overloaded): - for t in typ.items(): # type: ProperType + for t in typ.items: # type: ProperType self.check_classvar_in_signature(t) return if not isinstance(typ, CallableType): @@ -980,7 +1029,7 @@ def visit_decorator(self, dec: Decorator) -> None: dec.func._fullname = self.qualified_name(dec.name) for d in dec.decorators: d.accept(self) - removed = [] # type: List[int] + removed: List[int] = [] no_type_check = False for i, d in enumerate(dec.decorators): # A bunch of decorators are special cased here. @@ -1075,11 +1124,12 @@ def analyze_class(self, defn: ClassDef) -> None: self.update_metaclass(defn) bases = defn.base_type_exprs - bases, tvar_defs, is_protocol = self.clean_up_bases_and_infer_type_variables(defn, bases, - context=defn) + bases, tvar_defs, is_protocol = self.clean_up_bases_and_infer_type_variables( + defn, bases, context=defn) for tvd in tvar_defs: - if any(has_placeholder(t) for t in [tvd.upper_bound] + tvd.values): + if (isinstance(tvd, TypeVarType) + and any(has_placeholder(t) for t in [tvd.upper_bound] + tvd.values)): # Some type variable bounds or values are not ready, we need # to re-analyze this class. self.defer() @@ -1241,7 +1291,7 @@ def clean_up_bases_and_infer_type_variables( defn: ClassDef, base_type_exprs: List[Expression], context: Context) -> Tuple[List[Expression], - List[TypeVarDef], + List[TypeVarLikeType], bool]: """Remove extra base classes such as Generic and infer type vars. @@ -1256,14 +1306,14 @@ class Foo(Bar, Generic[T]): ... Returns (remaining base expressions, inferred type variables, is protocol). """ - removed = [] # type: List[int] - declared_tvars = [] # type: TypeVarLikeList + removed: List[int] = [] + declared_tvars: TypeVarLikeList = [] is_protocol = False for i, base_expr in enumerate(base_type_exprs): self.analyze_type_expr(base_expr) try: - base = expr_to_unanalyzed_type(base_expr) + base = self.expr_to_unanalyzed_type(base_expr) except TypeTranslationError: # This error will be caught later. continue @@ -1302,12 +1352,9 @@ class Foo(Bar, Generic[T]): ... # grained incremental mode. defn.removed_base_type_exprs.append(defn.base_type_exprs[i]) del base_type_exprs[i] - tvar_defs = [] # type: List[TypeVarDef] + tvar_defs: List[TypeVarLikeType] = [] for name, tvar_expr in declared_tvars: tvar_def = self.tvar_scope.bind_new(name, tvar_expr) - assert isinstance(tvar_def, TypeVarDef), ( - "mypy does not currently support ParamSpec use in generic classes" - ) tvar_defs.append(tvar_def) return base_type_exprs, tvar_defs, is_protocol @@ -1333,7 +1380,7 @@ def analyze_class_typevar_declaration( sym.node.fullname == 'typing.Protocol' and base.args or sym.node.fullname == 'typing_extensions.Protocol' and base.args): is_proto = sym.node.fullname != 'typing.Generic' - tvars = [] # type: TypeVarLikeList + tvars: TypeVarLikeList = [] for arg in unbound.args: tag = self.track_incomplete_refs() tvar = self.analyze_unbound_tvar(arg) @@ -1345,13 +1392,18 @@ def analyze_class_typevar_declaration( return tvars, is_proto return None - def analyze_unbound_tvar(self, t: Type) -> Optional[Tuple[str, TypeVarExpr]]: + def analyze_unbound_tvar(self, t: Type) -> Optional[Tuple[str, TypeVarLikeExpr]]: if not isinstance(t, UnboundType): return None unbound = t sym = self.lookup_qualified(unbound.name, unbound) if sym and isinstance(sym.node, PlaceholderNode): self.record_incomplete_ref() + if sym and isinstance(sym.node, ParamSpecExpr): + if sym.fullname and not self.tvar_scope.allow_binding(sym.fullname): + # It's bound by our type variable scope + return None + return unbound.name, sym.node if sym is None or not isinstance(sym.node, TypeVarExpr): return None elif sym.fullname and not self.tvar_scope.allow_binding(sym.fullname): @@ -1365,11 +1417,11 @@ def get_all_bases_tvars(self, base_type_exprs: List[Expression], removed: List[int]) -> TypeVarLikeList: """Return all type variable references in bases.""" - tvars = [] # type: TypeVarLikeList + tvars: TypeVarLikeList = [] for i, base_expr in enumerate(base_type_exprs): if i not in removed: try: - base = expr_to_unanalyzed_type(base_expr) + base = self.expr_to_unanalyzed_type(base_expr) except TypeTranslationError: # This error will be caught later. continue @@ -1489,7 +1541,7 @@ def configure_base_classes(self, related to the base classes: defn.info.bases, defn.info.mro, and miscellaneous others (at least tuple_type, fallback_to_any, and is_enum.) """ - base_types = [] # type: List[Instance] + base_types: List[Instance] = [] info = defn.info info.tuple_type = None @@ -1500,6 +1552,13 @@ def configure_base_classes(self, elif isinstance(base, Instance): if base.type.is_newtype: self.fail('Cannot subclass "NewType"', defn) + if self.enum_has_final_values(base): + # This means that are trying to subclass a non-default + # Enum class, with defined members. This is not possible. + # In runtime, it will raise. We need to mark this type as final. + # However, methods can be defined on a type: only values can't. + # We also don't count values with annotations only. + base.type.is_final = True base_types.append(base) elif isinstance(base, AnyType): if self.options.disallow_subclassing_any: @@ -1537,6 +1596,25 @@ def configure_base_classes(self, return self.calculate_class_mro(defn, self.object_type) + def enum_has_final_values(self, base: Instance) -> bool: + if ( + base.type.is_enum + and base.type.fullname not in ENUM_BASES + and base.type.names + and base.type.defn + ): + for sym in base.type.names.values(): + if isinstance(sym.node, (FuncBase, Decorator)): + continue # A method + if not isinstance(sym.node, Var): + return True # Can be a class + if self.is_stub_file or sym.node.has_explicit_value: + # Corner case: assignments like `x: int` are fine in `.py` files. + # But, not is `.pyi` files, because we don't know + # if there's aactually a value or not. + return True + return False + def configure_tuple_base_class(self, defn: ClassDef, base: TupleType, @@ -1598,7 +1676,7 @@ def update_metaclass(self, defn: ClassDef) -> None: """ # Look for "__metaclass__ = " in Python 2 - python2_meta_expr = None # type: Optional[Expression] + python2_meta_expr: Optional[Expression] = None if self.options.python_version[0] == 2: for body_node in defn.defs.body: if isinstance(body_node, ClassDef) and body_node.name == "__metaclass__": @@ -1610,7 +1688,7 @@ def update_metaclass(self, defn: ClassDef) -> None: python2_meta_expr = body_node.rvalue # Look for six.with_metaclass(M, B1, B2, ...) - with_meta_expr = None # type: Optional[Expression] + with_meta_expr: Optional[Expression] = None if len(defn.base_type_exprs) == 1: base_expr = defn.base_type_exprs[0] if isinstance(base_expr, CallExpr) and isinstance(base_expr.callee, RefExpr): @@ -1624,7 +1702,7 @@ def update_metaclass(self, defn: ClassDef) -> None: defn.base_type_exprs = base_expr.args[1:] # Look for @six.add_metaclass(M) - add_meta_expr = None # type: Optional[Expression] + add_meta_expr: Optional[Expression] = None for dec_expr in defn.decorators: if isinstance(dec_expr, CallExpr) and isinstance(dec_expr.callee, RefExpr): dec_expr.callee.accept(self) @@ -1774,6 +1852,12 @@ def visit_import_from(self, imp: ImportFrom) -> None: missing_submodule = False imported_id = as_id or id + # Modules imported in a stub file without using 'from Y import X as X' will + # not get exported. + # When implicit re-exporting is disabled, we have the same behavior as stubs. + use_implicit_reexport = not self.is_stub_file and self.options.implicit_reexport + module_public = use_implicit_reexport or (as_id is not None and id == as_id) + # If the module does not contain a symbol with the name 'id', # try checking if it's a module instead. if not node: @@ -1791,15 +1875,12 @@ def visit_import_from(self, imp: ImportFrom) -> None: fullname = module_id + '.' + id gvar = self.create_getattr_var(module.names['__getattr__'], imported_id, fullname) if gvar: - self.add_symbol(imported_id, gvar, imp) + self.add_symbol( + imported_id, gvar, imp, module_public=module_public, + module_hidden=not module_public + ) continue - # Modules imported in a stub file without using 'from Y import X as X' will - # not get exported. - # When implicit re-exporting is disabled, we have the same behavior as stubs. - use_implicit_reexport = not self.is_stub_file and self.options.implicit_reexport - module_public = use_implicit_reexport or (as_id is not None and id == as_id) - if node and not node.module_hidden: self.process_imported_symbol( node, module_id, id, imported_id, fullname, module_public, context=imp @@ -1865,7 +1946,9 @@ def report_missing_module_attribute( if self.is_incomplete_namespace(import_id): # We don't know whether the name will be there, since the namespace # is incomplete. Defer the current target. - self.mark_incomplete(imported_id, context) + self.mark_incomplete( + imported_id, context, module_public=module_public, module_hidden=module_hidden + ) return message = 'Module "{}" has no attribute "{}"'.format(import_id, source_id) # Suggest alternatives, if any match is found. @@ -1971,7 +2054,7 @@ def visit_import_all(self, i: ImportAll) -> None: def visit_assignment_expr(self, s: AssignmentExpr) -> None: s.value.accept(self) - self.analyze_lvalue(s.target, escape_comprehensions=True) + self.analyze_lvalue(s.target, escape_comprehensions=True, has_explicit_value=True) def visit_assignment_stmt(self, s: AssignmentStmt) -> None: self.statement = s @@ -2010,9 +2093,13 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: special_form = True elif self.analyze_enum_assign(s): special_form = True + if special_form: self.record_special_form_lvalue(s) return + # Clear the alias flag if assignment turns out not a special form after all. It + # may be set to True while there were still placeholders due to forward refs. + s.is_alias_def = False # OK, this is a regular assignment, perform the necessary analysis steps. s.is_final_def = self.unwrap_final(s) @@ -2025,6 +2112,8 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: if not s.type: self.process_module_assignment(s.lvalues, s.rvalue, s) self.process__all__(s) + self.process__deletable__(s) + self.process__slots__(s) def analyze_identity_global_assignment(self, s: AssignmentStmt) -> bool: """Special case 'X = X' in global scope. @@ -2096,7 +2185,7 @@ def should_wait_rhs(self, rv: Expression) -> bool: return self.should_wait_rhs(rv.callee) return False - def can_be_type_alias(self, rv: Expression) -> bool: + def can_be_type_alias(self, rv: Expression, allow_none: bool = False) -> bool: """Is this a valid r.h.s. for an alias definition? Note: this function should be only called for expressions where self.should_wait_rhs() @@ -2108,6 +2197,13 @@ def can_be_type_alias(self, rv: Expression) -> bool: return True if self.is_none_alias(rv): return True + if allow_none and isinstance(rv, NameExpr) and rv.fullname == 'builtins.None': + return True + if (isinstance(rv, OpExpr) + and rv.op == '|' + and self.can_be_type_alias(rv.left, allow_none=True) + and self.can_be_type_alias(rv.right, allow_none=True)): + return True return False def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: @@ -2251,37 +2347,55 @@ def analyze_lvalues(self, s: AssignmentStmt) -> None: assert isinstance(s.unanalyzed_type, UnboundType) if not s.unanalyzed_type.args: explicit = False + + if s.rvalue: + if isinstance(s.rvalue, TempNode): + has_explicit_value = not s.rvalue.no_rhs + else: + has_explicit_value = True + else: + has_explicit_value = False + for lval in s.lvalues: self.analyze_lvalue(lval, explicit_type=explicit, - is_final=s.is_final_def) + is_final=s.is_final_def, + has_explicit_value=has_explicit_value) def apply_dynamic_class_hook(self, s: AssignmentStmt) -> None: - if len(s.lvalues) > 1: - return - lval = s.lvalues[0] - if not isinstance(lval, NameExpr) or not isinstance(s.rvalue, CallExpr): + if not isinstance(s.rvalue, CallExpr): return - call = s.rvalue fname = None - if isinstance(call.callee, RefExpr): - fname = call.callee.fullname - # check if method call - if fname is None and isinstance(call.callee, MemberExpr): - callee_expr = call.callee.expr - if isinstance(callee_expr, RefExpr) and callee_expr.fullname: - method_name = call.callee.name - fname = callee_expr.fullname + '.' + method_name - if fname: - hook = self.plugin.get_dynamic_class_hook(fname) - if hook: - hook(DynamicClassDefContext(call, lval.name, self)) + call = s.rvalue + while True: + if isinstance(call.callee, RefExpr): + fname = call.callee.fullname + # check if method call + if fname is None and isinstance(call.callee, MemberExpr): + callee_expr = call.callee.expr + if isinstance(callee_expr, RefExpr) and callee_expr.fullname: + method_name = call.callee.name + fname = callee_expr.fullname + '.' + method_name + elif isinstance(callee_expr, CallExpr): + # check if chain call + call = callee_expr + continue + break + if not fname: + return + hook = self.plugin.get_dynamic_class_hook(fname) + if not hook: + return + for lval in s.lvalues: + if not isinstance(lval, NameExpr): + continue + hook(DynamicClassDefContext(call, lval.name, self)) def unwrap_final(self, s: AssignmentStmt) -> bool: """Strip Final[...] if present in an assignment. This is done to invoke type inference during type checking phase for this - assignment. Also, Final[...] desn't affect type in any way -- it is rather an + assignment. Also, Final[...] doesn't affect type in any way -- it is rather an access qualifier for given `Var`. Also perform various consistency checks. @@ -2361,10 +2475,30 @@ def store_final_status(self, s: AssignmentStmt) -> None: (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)): node.final_unset_in_class = True else: - # Special case: deferred initialization of a final attribute in __init__. - # In this case we just pretend this is a valid final definition to suppress - # errors about assigning to final attribute. for lval in self.flatten_lvalues(s.lvalues): + # Special case: we are working with an `Enum`: + # + # class MyEnum(Enum): + # key = 'some value' + # + # Here `key` is implicitly final. In runtime, code like + # + # MyEnum.key = 'modified' + # + # will fail with `AttributeError: Cannot reassign members.` + # That's why we need to replicate this. + if (isinstance(lval, NameExpr) and + isinstance(self.type, TypeInfo) and + self.type.is_enum): + cur_node = self.type.names.get(lval.name, None) + if (cur_node and isinstance(cur_node.node, Var) and + not (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)): + cur_node.node.is_final = True + s.is_final_def = True + + # Special case: deferred initialization of a final attribute in __init__. + # In this case we just pretend this is a valid final definition to suppress + # errors about assigning to final attribute. if isinstance(lval, MemberExpr) and self.is_self_member_ref(lval): assert self.type, "Self member outside a class" cur_node = self.type.names.get(lval.name, None) @@ -2379,7 +2513,7 @@ def store_final_status(self, s: AssignmentStmt) -> None: s.is_final_def = True def flatten_lvalues(self, lvalues: List[Expression]) -> List[Expression]: - res = [] # type: List[Expression] + res: List[Expression] = [] for lv in lvalues: if isinstance(lv, (TupleExpr, ListExpr)): res.extend(self.flatten_lvalues(lv.items)) @@ -2449,8 +2583,8 @@ def analyze_simple_literal_type(self, rvalue: Expression, is_final: bool) -> Opt if isinstance(rvalue, FloatExpr): return self.named_type_or_none('builtins.float') - value = None # type: Optional[LiteralValue] - type_name = None # type: Optional[str] + value: Optional[LiteralValue] = None + type_name: Optional[str] = None if isinstance(rvalue, IntExpr): value, type_name = rvalue.value, 'builtins.int' if isinstance(rvalue, StrExpr): @@ -2495,11 +2629,11 @@ def analyze_alias(self, rvalue: Expression, self.plugin, self.options, self.is_typeshed_stub_file, - allow_unnormalized=self.is_stub_file, + allow_new_syntax=self.is_stub_file, allow_placeholder=allow_placeholder, in_dynamic_func=dynamic, global_scope=global_scope) - typ = None # type: Optional[Type] + typ: Optional[Type] = None if res: typ, depends_on = res found_type_vars = typ.accept(TypeVarLikeQuery(self.lookup_qualified, self.tvar_scope)) @@ -2524,8 +2658,15 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: if len(s.lvalues) > 1 or not isinstance(lvalue, NameExpr): # First rule: Only simple assignments like Alias = ... create aliases. return False - if s.unanalyzed_type is not None: + + pep_613 = False + if s.unanalyzed_type is not None and isinstance(s.unanalyzed_type, UnboundType): + lookup = self.lookup(s.unanalyzed_type.name, s, suppress_errors=True) + if lookup and lookup.fullname in ("typing.TypeAlias", "typing_extensions.TypeAlias"): + pep_613 = True + if s.unanalyzed_type is not None and not pep_613: # Second rule: Explicit type (cls: Type[A] = A) always creates variable, not alias. + # unless using PEP 613 `cls: TypeAlias = A` return False existing = self.current_symbol_table().get(lvalue.name) @@ -2550,7 +2691,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: return False non_global_scope = self.type or self.is_func_scope() - if isinstance(s.rvalue, RefExpr) and non_global_scope: + if isinstance(s.rvalue, RefExpr) and non_global_scope and not pep_613: # Fourth rule (special case): Non-subscripted right hand side creates a variable # at class and function scopes. For example: # @@ -2563,14 +2704,14 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: # annotations (see the second rule). return False rvalue = s.rvalue - if not self.can_be_type_alias(rvalue): + if not self.can_be_type_alias(rvalue) and not pep_613: return False if existing and not isinstance(existing.node, (PlaceholderNode, TypeAlias)): # Cannot redefine existing node as type alias. return False - res = None # type: Optional[Type] + res: Optional[Type] = None if self.is_none_alias(rvalue): res = NoneType() alias_tvars, depends_on, qualified_tvars = \ @@ -2659,7 +2800,8 @@ def analyze_lvalue(self, nested: bool = False, explicit_type: bool = False, is_final: bool = False, - escape_comprehensions: bool = False) -> None: + escape_comprehensions: bool = False, + has_explicit_value: bool = False) -> None: """Analyze an lvalue or assignment target. Args: @@ -2673,7 +2815,11 @@ def analyze_lvalue(self, if escape_comprehensions: assert isinstance(lval, NameExpr), "assignment expression target must be NameExpr" if isinstance(lval, NameExpr): - self.analyze_name_lvalue(lval, explicit_type, is_final, escape_comprehensions) + self.analyze_name_lvalue( + lval, explicit_type, is_final, + escape_comprehensions, + has_explicit_value=has_explicit_value, + ) elif isinstance(lval, MemberExpr): self.analyze_member_lvalue(lval, explicit_type, is_final) if explicit_type and not self.is_self_member_ref(lval): @@ -2697,7 +2843,8 @@ def analyze_name_lvalue(self, lvalue: NameExpr, explicit_type: bool, is_final: bool, - escape_comprehensions: bool) -> None: + escape_comprehensions: bool, + has_explicit_value: bool) -> None: """Analyze an lvalue that targets a name expression. Arguments are similar to "analyze_lvalue". @@ -2714,13 +2861,20 @@ def analyze_name_lvalue(self, self.msg.cant_assign_to_final(name, self.type is not None, lvalue) kind = self.current_symbol_kind() - names = self.current_symbol_table() + names = self.current_symbol_table(escape_comprehensions=escape_comprehensions) existing = names.get(name) outer = self.is_global_or_nonlocal(name) + if kind == MDEF and isinstance(self.type, TypeInfo) and self.type.is_enum: + # Special case: we need to be sure that `Enum` keys are unique. + if existing: + self.fail('Attempted to reuse member name "{}" in Enum definition "{}"'.format( + name, self.type.name, + ), lvalue) + if (not existing or isinstance(existing.node, PlaceholderNode)) and not outer: # Define new variable. - var = self.make_name_lvalue_var(lvalue, kind, not explicit_type) + var = self.make_name_lvalue_var(lvalue, kind, not explicit_type, has_explicit_value) added = self.add_symbol(name, var, lvalue, escape_comprehensions=escape_comprehensions) # Only bind expression if we successfully added name to symbol table. if added: @@ -2771,7 +2925,9 @@ def is_alias_for_final_name(self, name: str) -> bool: existing = self.globals.get(orig_name) return existing is not None and is_final_node(existing.node) - def make_name_lvalue_var(self, lvalue: NameExpr, kind: int, inferred: bool) -> Var: + def make_name_lvalue_var( + self, lvalue: NameExpr, kind: int, inferred: bool, has_explicit_value: bool, + ) -> Var: """Return a Var node for an lvalue that is a name expression.""" v = Var(lvalue.name) v.set_line(lvalue) @@ -2786,6 +2942,7 @@ def make_name_lvalue_var(self, lvalue: NameExpr, kind: int, inferred: bool) -> V # fullanme should never stay None v._fullname = lvalue.name v.is_ready = False # Type not inferred yet + v.has_explicit_value = has_explicit_value return v def make_name_lvalue_point_to_existing_def( @@ -2829,7 +2986,14 @@ def analyze_tuple_or_list_lvalue(self, lval: TupleExpr, if len(star_exprs) == 1: star_exprs[0].valid = True for i in items: - self.analyze_lvalue(i, nested=True, explicit_type=explicit_type) + self.analyze_lvalue( + lval=i, + nested=True, + explicit_type=explicit_type, + # Lists and tuples always have explicit values defined: + # `a, b, c = value` + has_explicit_value=True, + ) def analyze_member_lvalue(self, lval: MemberExpr, explicit_type: bool, is_final: bool) -> None: """Analyze lvalue that is a member expression. @@ -3042,36 +3206,32 @@ def get_typevarlike_declaration(self, s: AssignmentStmt, def process_typevar_parameters(self, args: List[Expression], names: List[Optional[str]], - kinds: List[int], + kinds: List[ArgKind], num_values: int, context: Context) -> Optional[Tuple[int, Type]]: has_values = (num_values > 0) covariant = False contravariant = False - upper_bound = self.object_type() # type: Type + upper_bound: Type = self.object_type() for param_value, param_name, param_kind in zip(args, names, kinds): - if not param_kind == ARG_NAMED: - self.fail("Unexpected argument to TypeVar()", context) + if not param_kind.is_named(): + self.fail(message_registry.TYPEVAR_UNEXPECTED_ARGUMENT, context) return None if param_name == 'covariant': - if isinstance(param_value, NameExpr): - if param_value.name == 'True': - covariant = True - else: - self.fail("TypeVar 'covariant' may only be 'True'", context) - return None + if (isinstance(param_value, NameExpr) + and param_value.name in ('True', 'False')): + covariant = param_value.name == 'True' else: - self.fail("TypeVar 'covariant' may only be 'True'", context) + self.fail(message_registry.TYPEVAR_VARIANCE_DEF.format( + 'covariant'), context) return None elif param_name == 'contravariant': - if isinstance(param_value, NameExpr): - if param_value.name == 'True': - contravariant = True - else: - self.fail("TypeVar 'contravariant' may only be 'True'", context) - return None + if (isinstance(param_value, NameExpr) + and param_value.name in ('True', 'False')): + contravariant = param_value.name == 'True' else: - self.fail("TypeVar 'contravariant' may only be 'True'", context) + self.fail(message_registry.TYPEVAR_VARIANCE_DEF.format( + 'contravariant'), context) return None elif param_name == 'bound': if has_values: @@ -3093,11 +3253,11 @@ def process_typevar_parameters(self, args: List[Expression], analyzed = PlaceholderType(None, [], context.line) upper_bound = get_proper_type(analyzed) if isinstance(upper_bound, AnyType) and upper_bound.is_from_error: - self.fail('TypeVar "bound" must be a type', param_value) + self.fail(message_registry.TYPEVAR_BOUND_MUST_BE_TYPE, param_value) # Note: we do not return 'None' here -- we want to continue # using the AnyType as the upper bound. except TypeTranslationError: - self.fail('TypeVar "bound" must be a type', param_value) + self.fail(message_registry.TYPEVAR_BOUND_MUST_BE_TYPE, param_value) return None elif param_name == 'values': # Probably using obsolete syntax with values=(...). Explain the current syntax. @@ -3106,7 +3266,9 @@ def process_typevar_parameters(self, args: List[Expression], context) return None else: - self.fail('Unexpected argument to TypeVar(): "{}"'.format(param_name), context) + self.fail('{}: "{}"'.format( + message_registry.TYPEVAR_UNEXPECTED_ARGUMENT, param_name, + ), context) return None if covariant and contravariant: @@ -3131,8 +3293,6 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: In the future, ParamSpec may accept bounds and variance arguments, in which case more aggressive sharing of code with process_typevar_declaration should be pursued. """ - if not self.options.wip_pep_612: - return False call = self.get_typevarlike_declaration( s, ("typing_extensions.ParamSpec", "typing.ParamSpec") ) @@ -3152,11 +3312,15 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: # PEP 612 reserves the right to define bound, covariant and contravariant arguments to # ParamSpec in a later PEP. If and when that happens, we should do something # on the lines of process_typevar_parameters - paramspec_var = ParamSpecExpr( - name, self.qualified_name(name), self.object_type(), INVARIANT - ) - paramspec_var.line = call.line - call.analyzed = paramspec_var + + if not call.analyzed: + paramspec_var = ParamSpecExpr( + name, self.qualified_name(name), self.object_type(), INVARIANT + ) + paramspec_var.line = call.line + call.analyzed = paramspec_var + else: + assert isinstance(call.analyzed, ParamSpecExpr) self.add_symbol(name, call.analyzed, s) return True @@ -3187,10 +3351,10 @@ def basic_new_typeinfo(self, name: str, def analyze_value_types(self, items: List[Expression]) -> List[Type]: """Analyze types from values expressions in type variable definition.""" - result = [] # type: List[Type] + result: List[Type] = [] for node in items: try: - analyzed = self.anal_type(expr_to_unanalyzed_type(node), + analyzed = self.anal_type(self.expr_to_unanalyzed_type(node), allow_placeholder=True) if analyzed is None: # Type variables are special: we need to place them in the symbol table @@ -3214,6 +3378,12 @@ def check_classvar(self, s: AssignmentStmt) -> None: node = lvalue.node if isinstance(node, Var): node.is_classvar = True + analyzed = self.anal_type(s.type) + if analyzed is not None and get_type_vars(analyzed): + # This means that we have a type var defined inside of a ClassVar. + # This is not allowed by PEP526. + # See https://github.com/python/mypy/issues/11538 + self.fail(message_registry.CLASS_VAR_WITH_TYPEVARS, s) elif not isinstance(lvalue, MemberExpr) or self.is_self_member_ref(lvalue): # In case of member access, report error only when assigning to self # Other kinds of member assignments should be already reported @@ -3236,7 +3406,7 @@ def is_final_type(self, typ: Optional[Type]) -> bool: return sym.node.fullname in ('typing.Final', 'typing_extensions.Final') def fail_invalid_classvar(self, context: Context) -> None: - self.fail('ClassVar can only be used for assignments in class body', context) + self.fail(message_registry.CLASS_VAR_OUTSIDE_OF_CLASS, context) def process_module_assignment(self, lvals: List[Lvalue], rval: Expression, ctx: AssignmentStmt) -> None: @@ -3314,6 +3484,81 @@ def process__all__(self, s: AssignmentStmt) -> None: isinstance(s.rvalue, (ListExpr, TupleExpr))): self.add_exports(s.rvalue.items) + def process__deletable__(self, s: AssignmentStmt) -> None: + if not self.options.mypyc: + return + if (len(s.lvalues) == 1 and isinstance(s.lvalues[0], NameExpr) and + s.lvalues[0].name == '__deletable__' and s.lvalues[0].kind == MDEF): + rvalue = s.rvalue + if not isinstance(rvalue, (ListExpr, TupleExpr)): + self.fail('"__deletable__" must be initialized with a list or tuple expression', s) + return + items = rvalue.items + attrs = [] + for item in items: + if not isinstance(item, StrExpr): + self.fail('Invalid "__deletable__" item; string literal expected', item) + else: + attrs.append(item.value) + assert self.type + self.type.deletable_attributes = attrs + + def process__slots__(self, s: AssignmentStmt) -> None: + """ + Processing ``__slots__`` if defined in type. + + See: https://docs.python.org/3/reference/datamodel.html#slots + """ + # Later we can support `__slots__` defined as `__slots__ = other = ('a', 'b')` + if (isinstance(self.type, TypeInfo) and + len(s.lvalues) == 1 and isinstance(s.lvalues[0], NameExpr) and + s.lvalues[0].name == '__slots__' and s.lvalues[0].kind == MDEF): + + # We understand `__slots__` defined as string, tuple, list, set, and dict: + if not isinstance(s.rvalue, (StrExpr, ListExpr, TupleExpr, SetExpr, DictExpr)): + # For example, `__slots__` can be defined as a variable, + # we don't support it for now. + return + + if any(p.slots is None for p in self.type.mro[1:-1]): + # At least one type in mro (excluding `self` and `object`) + # does not have concrete `__slots__` defined. Ignoring. + return + + concrete_slots = True + rvalue: List[Expression] = [] + if isinstance(s.rvalue, StrExpr): + rvalue.append(s.rvalue) + elif isinstance(s.rvalue, (ListExpr, TupleExpr, SetExpr)): + rvalue.extend(s.rvalue.items) + else: + # We have a special treatment of `dict` with possible `{**kwargs}` usage. + # In this case we consider all `__slots__` to be non-concrete. + for key, _ in s.rvalue.items: + if concrete_slots and key is not None: + rvalue.append(key) + else: + concrete_slots = False + + slots = [] + for item in rvalue: + # Special case for `'__dict__'` value: + # when specified it will still allow any attribute assignment. + if isinstance(item, StrExpr) and item.value != '__dict__': + slots.append(item.value) + else: + concrete_slots = False + if not concrete_slots: + # Some slot items are dynamic, we don't want any false positives, + # so, we just pretend that this type does not have any slots at all. + return + + # We need to copy all slots from super types: + for super_type in self.type.mro[1:-1]: + assert super_type.slots is not None + slots.extend(super_type.slots) + self.type.slots = set(slots) + # # Misc statements # @@ -3430,7 +3675,7 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None: def visit_with_stmt(self, s: WithStmt) -> None: self.statement = s - types = [] # type: List[Type] + types: List[Type] = [] if s.unanalyzed_type: assert isinstance(s.unanalyzed_type, ProperType) @@ -3452,7 +3697,7 @@ def visit_with_stmt(self, s: WithStmt) -> None: # We have multiple targets and one type self.fail('Multiple types expected for multiple "with" targets', s) - new_types = [] # type: List[Type] + new_types: List[Type] = [] for e, n in zip(s.expr, s.target): e.accept(self) if n: @@ -3614,7 +3859,7 @@ def visit_call_expr(self, expr: CallExpr) -> None: return # Translate first argument to an unanalyzed type. try: - target = expr_to_unanalyzed_type(expr.args[0]) + target = self.expr_to_unanalyzed_type(expr.args[0]) except TypeTranslationError: self.fail('Cast target is not a type', expr) return @@ -3634,7 +3879,7 @@ def visit_call_expr(self, expr: CallExpr) -> None: elif refers_to_fullname(expr.callee, 'builtins.reveal_locals'): # Store the local variable names into the RevealExpr for use in the # type checking pass - local_nodes = [] # type: List[Var] + local_nodes: List[Var] = [] if self.is_module_scope(): # try to determine just the variable declarations in module scope # self.globals.values() contains SymbolTableNode's @@ -3672,7 +3917,7 @@ def visit_call_expr(self, expr: CallExpr) -> None: return # Translate first argument to an unanalyzed type. try: - target = expr_to_unanalyzed_type(expr.args[0]) + target = self.expr_to_unanalyzed_type(expr.args[0]) except TypeTranslationError: self.fail('Argument 1 to _promote is not a type', expr) return @@ -3844,7 +4089,8 @@ def analyze_type_application(self, expr: IndexExpr) -> None: # ...or directly. else: n = self.lookup_type_node(base) - if n and n.fullname in get_nongen_builtins(self.options.python_version): + if (n and n.fullname in get_nongen_builtins(self.options.python_version) and + not self.is_stub_file): self.fail(no_subscript_builtin_alias(n.fullname, propose_alt=False), expr) def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]]: @@ -3857,14 +4103,17 @@ def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]] self.analyze_type_expr(index) if self.found_incomplete_ref(tag): return None - types = [] # type: List[Type] + types: List[Type] = [] if isinstance(index, TupleExpr): items = index.items + is_tuple = isinstance(expr.base, RefExpr) and expr.base.fullname == 'builtins.tuple' + if is_tuple and len(items) == 2 and isinstance(items[-1], EllipsisExpr): + items = items[:-1] else: items = [index] for item in items: try: - typearg = expr_to_unanalyzed_type(item) + typearg = self.expr_to_unanalyzed_type(item) except TypeTranslationError: self.fail('Type expected within [...]', expr) return None @@ -3915,18 +4164,16 @@ def visit_set_comprehension(self, expr: SetComprehension) -> None: expr.generator.accept(self) def visit_dictionary_comprehension(self, expr: DictionaryComprehension) -> None: - self.enter(expr) - self.analyze_comp_for(expr) - expr.key.accept(self) - expr.value.accept(self) - self.leave() + with self.enter(expr): + self.analyze_comp_for(expr) + expr.key.accept(self) + expr.value.accept(self) self.analyze_comp_for_2(expr) def visit_generator_expr(self, expr: GeneratorExpr) -> None: - self.enter(expr) - self.analyze_comp_for(expr) - expr.left_expr.accept(self) - self.leave() + with self.enter(expr): + self.analyze_comp_for(expr) + expr.left_expr.accept(self) self.analyze_comp_for_2(expr) def analyze_comp_for(self, expr: Union[GeneratorExpr, @@ -4107,7 +4354,7 @@ def is_textually_before_statement(self, node: SymbolNode) -> bool: return line_diff > 0 def is_overloaded_item(self, node: SymbolNode, statement: Statement) -> bool: - """Check whehter the function belongs to the overloaded variants""" + """Check whether the function belongs to the overloaded variants""" if isinstance(node, OverloadedFuncDef) and isinstance(statement, FuncDef): in_items = statement in {item.func if isinstance(item, Decorator) else item for item in node.items} @@ -4171,7 +4418,7 @@ def lookup_qualified(self, name: str, ctx: Context, def lookup_type_node(self, expr: Expression) -> Optional[SymbolTableNode]: try: - t = expr_to_unanalyzed_type(expr) + t = self.expr_to_unanalyzed_type(expr) except TypeTranslationError: return None if isinstance(t, UnboundType): @@ -4253,22 +4500,10 @@ def create_getattr_var(self, getattr_defn: SymbolTableNode, return v return None - def lookup_fully_qualified(self, name: str) -> SymbolTableNode: - """Lookup a fully qualified name. - - Assume that the name is defined. This happens in the global namespace -- - the local module namespace is ignored. - - Note that this doesn't support visibility, module-level __getattr__, or - nested classes. - """ - parts = name.split('.') - n = self.modules[parts[0]] - for i in range(1, len(parts) - 1): - next_sym = n.names[parts[i]] - assert isinstance(next_sym.node, MypyFile) - n = next_sym.node - return n.names[parts[-1]] + def lookup_fully_qualified(self, fullname: str) -> SymbolTableNode: + ret = self.lookup_fully_qualified_or_none(fullname) + assert ret is not None + return ret def lookup_fully_qualified_or_none(self, fullname: str) -> Optional[SymbolTableNode]: """Lookup a fully qualified name that refers to a module-level definition. @@ -4293,20 +4528,14 @@ def lookup_fully_qualified_or_none(self, fullname: str) -> Optional[SymbolTableN self.record_incomplete_ref() return result - def builtin_type(self, fully_qualified_name: str) -> Instance: - sym = self.lookup_fully_qualified(fully_qualified_name) - node = sym.node - assert isinstance(node, TypeInfo) - return Instance(node, [AnyType(TypeOfAny.special_form)] * len(node.defn.type_vars)) - def object_type(self) -> Instance: - return self.named_type('__builtins__.object') + return self.named_type('builtins.object') def str_type(self) -> Instance: - return self.named_type('__builtins__.str') + return self.named_type('builtins.str') - def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> Instance: - sym = self.lookup_qualified(qualified_name, Context()) + def named_type(self, fullname: str, args: Optional[List[Type]] = None) -> Instance: + sym = self.lookup_fully_qualified(fullname) assert sym, "Internal error: attempted to construct unknown type" node = sym.node assert isinstance(node, TypeInfo) @@ -4315,9 +4544,9 @@ def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> return Instance(node, args) return Instance(node, [AnyType(TypeOfAny.special_form)] * len(node.defn.type_vars)) - def named_type_or_none(self, qualified_name: str, + def named_type_or_none(self, fullname: str, args: Optional[List[Type]] = None) -> Optional[Instance]: - sym = self.lookup_fully_qualified_or_none(qualified_name) + sym = self.lookup_fully_qualified_or_none(fullname) if not sym or isinstance(sym.node, PlaceholderNode): return None node = sym.node @@ -4422,7 +4651,11 @@ def add_symbol_table_node(self, names = self.current_symbol_table(escape_comprehensions=escape_comprehensions) existing = names.get(name) if isinstance(symbol.node, PlaceholderNode) and can_defer: - self.defer(context) + if context is not None: + self.process_placeholder(name, 'name', context) + else: + # see note in docstring describing None contexts + self.defer() if (existing is not None and context is not None and not is_valid_replacement(existing, symbol)): @@ -4660,7 +4893,9 @@ def qualified_name(self, name: str) -> str: else: return self.cur_mod_id + '.' + name - def enter(self, function: Union[FuncItem, GeneratorExpr, DictionaryComprehension]) -> None: + @contextmanager + def enter(self, + function: Union[FuncItem, GeneratorExpr, DictionaryComprehension]) -> Iterator[None]: """Enter a function, generator or comprehension scope.""" names = self.saved_locals.setdefault(function, SymbolTable()) self.locals.append(names) @@ -4671,14 +4906,15 @@ def enter(self, function: Union[FuncItem, GeneratorExpr, DictionaryComprehension # -1 since entering block will increment this to 0. self.block_depth.append(-1) self.missing_names.append(set()) - - def leave(self) -> None: - self.locals.pop() - self.is_comprehension_stack.pop() - self.global_decls.pop() - self.nonlocal_decls.pop() - self.block_depth.pop() - self.missing_names.pop() + try: + yield + finally: + self.locals.pop() + self.is_comprehension_stack.pop() + self.global_decls.pop() + self.nonlocal_decls.pop() + self.block_depth.pop() + self.missing_names.pop() def is_func_scope(self) -> bool: return self.locals[-1] is not None @@ -4803,7 +5039,7 @@ def already_defined(self, original_ctx: Optional[Union[SymbolTableNode, SymbolNode]], noun: str) -> None: if isinstance(original_ctx, SymbolTableNode): - node = original_ctx.node # type: Optional[SymbolNode] + node: Optional[SymbolNode] = original_ctx.node elif isinstance(original_ctx, SymbolNode): node = original_ctx else: @@ -4841,6 +5077,35 @@ def is_local_name(self, name: str) -> bool: """Does name look like reference to a definition in the current module?""" return self.is_defined_in_current_module(name) or '.' not in name + def in_checked_function(self) -> bool: + """Should we type-check the current function? + + - Yes if --check-untyped-defs is set. + - Yes outside functions. + - Yes in annotated functions. + - No otherwise. + """ + if self.options.check_untyped_defs or not self.function_stack: + return True + + current_index = len(self.function_stack) - 1 + while current_index >= 0: + current_func = self.function_stack[current_index] + if ( + isinstance(current_func, FuncItem) + and not isinstance(current_func, LambdaExpr) + ): + return not current_func.is_dynamic() + + # Special case, `lambda` inherits the "checked" state from its parent. + # Because `lambda` itself cannot be annotated. + # `lambdas` can be deeply nested, so we try to find at least one other parent. + current_index -= 1 + + # This means that we only have a stack of `lambda` functions, + # no regular functions. + return True + def fail(self, msg: str, ctx: Context, @@ -4848,10 +5113,7 @@ def fail(self, *, code: Optional[ErrorCode] = None, blocker: bool = False) -> None: - if (not serious and - not self.options.check_untyped_defs and - self.function_stack and - self.function_stack[-1].is_dynamic()): + if not serious and not self.in_checked_function(): return # In case it's a bug and we don't really have context assert ctx is not None, msg @@ -4861,9 +5123,7 @@ def fail_blocker(self, msg: str, ctx: Context) -> None: self.fail(msg, ctx, blocker=True) def note(self, msg: str, ctx: Context, code: Optional[ErrorCode] = None) -> None: - if (not self.options.check_untyped_defs and - self.function_stack and - self.function_stack[-1].is_dynamic()): + if not self.in_checked_function(): return self.errors.report(ctx.get_line(), ctx.get_column(), msg, severity='note', code=code) @@ -4891,7 +5151,7 @@ def expr_to_analyzed_type(self, assert info.tuple_type, "NamedTuple without tuple type" fallback = Instance(info, []) return TupleType(info.tuple_type.items, fallback=fallback) - typ = expr_to_unanalyzed_type(expr) + typ = self.expr_to_unanalyzed_type(expr) return self.anal_type(typ, report_invalid_types=report_invalid_types, allow_placeholder=allow_placeholder) @@ -4910,6 +5170,7 @@ def type_analyzer(self, *, allow_tuple_literal: bool = False, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, + allow_required: bool = False, report_invalid_types: bool = True) -> TypeAnalyser: if tvar_scope is None: tvar_scope = self.tvar_scope @@ -4921,18 +5182,23 @@ def type_analyzer(self, *, allow_unbound_tvars=allow_unbound_tvars, allow_tuple_literal=allow_tuple_literal, report_invalid_types=report_invalid_types, - allow_unnormalized=self.is_stub_file, - allow_placeholder=allow_placeholder) + allow_placeholder=allow_placeholder, + allow_required=allow_required, + allow_new_syntax=self.is_stub_file) tpan.in_dynamic_func = bool(self.function_stack and self.function_stack[-1].is_dynamic()) tpan.global_scope = not self.type and not self.function_stack return tpan + def expr_to_unanalyzed_type(self, node: Expression) -> ProperType: + return expr_to_unanalyzed_type(node, self.options, self.is_stub_file) + def anal_type(self, typ: Type, *, tvar_scope: Optional[TypeVarLikeScope] = None, allow_tuple_literal: bool = False, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, + allow_required: bool = False, report_invalid_types: bool = True, third_pass: bool = False) -> Optional[Type]: """Semantically analyze a type. @@ -4959,6 +5225,7 @@ def anal_type(self, allow_unbound_tvars=allow_unbound_tvars, allow_tuple_literal=allow_tuple_literal, allow_placeholder=allow_placeholder, + allow_required=allow_required, report_invalid_types=report_invalid_types) tag = self.track_incomplete_refs() typ = typ.accept(a) @@ -5051,7 +5318,7 @@ def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike: return sig.copy_modified(arg_types=[new] + sig.arg_types[1:]) elif isinstance(sig, Overloaded): return Overloaded([cast(CallableType, replace_implicit_first_type(i, new)) - for i in sig.items()]) + for i in sig.items]) else: assert False @@ -5089,7 +5356,7 @@ def find_duplicate(list: List[T]) -> Optional[T]: def remove_imported_names_from_symtable(names: SymbolTable, module: str) -> None: """Remove all imported names from the symbol table of a module.""" - removed = [] # type: List[str] + removed: List[str] = [] for name, node in names.items(): if node.node is None: continue @@ -5128,7 +5395,7 @@ def apply_semantic_analyzer_patches(patches: List[Tuple[int, Callable[[], None]] def names_modified_by_assignment(s: AssignmentStmt) -> List[NameExpr]: """Return all unqualified (short) names assigned to in an assignment statement.""" - result = [] # type: List[NameExpr] + result: List[NameExpr] = [] for lvalue in s.lvalues: result += names_modified_in_lvalue(lvalue) return result @@ -5141,7 +5408,7 @@ def names_modified_in_lvalue(lvalue: Lvalue) -> List[NameExpr]: elif isinstance(lvalue, StarExpr): return names_modified_in_lvalue(lvalue.expr) elif isinstance(lvalue, (ListExpr, TupleExpr)): - result = [] # type: List[NameExpr] + result: List[NameExpr] = [] for item in lvalue.items: result += names_modified_in_lvalue(item) return result diff --git a/mypy/semanal_classprop.py b/mypy/semanal_classprop.py index 8dc518662445..4be57b64342e 100644 --- a/mypy/semanal_classprop.py +++ b/mypy/semanal_classprop.py @@ -17,17 +17,17 @@ # These add extra ad-hoc edges to the subtyping relation. For example, # int is considered a subtype of float, even though there is no # subclass relationship. -TYPE_PROMOTIONS = { +TYPE_PROMOTIONS: Final = { 'builtins.int': 'float', 'builtins.float': 'complex', -} # type: Final +} # Hard coded type promotions for Python 3. # # Note that the bytearray -> bytes promotion is a little unsafe # as some functions only accept bytes objects. Here convenience # trumps safety. -TYPE_PROMOTIONS_PYTHON3 = TYPE_PROMOTIONS.copy() # type: Final +TYPE_PROMOTIONS_PYTHON3: Final = TYPE_PROMOTIONS.copy() TYPE_PROMOTIONS_PYTHON3.update({ 'builtins.bytearray': 'bytes', 'builtins.memoryview': 'bytes', @@ -38,7 +38,7 @@ # These promotions are unsafe, but we are doing them anyway # for convenience and also for Python 3 compatibility # (bytearray -> str). -TYPE_PROMOTIONS_PYTHON2 = TYPE_PROMOTIONS.copy() # type: Final +TYPE_PROMOTIONS_PYTHON2: Final = TYPE_PROMOTIONS.copy() TYPE_PROMOTIONS_PYTHON2.update({ 'builtins.str': 'unicode', 'builtins.bytearray': 'str', @@ -55,9 +55,9 @@ def calculate_class_abstract_status(typ: TypeInfo, is_stub_file: bool, errors: E """ if typ.typeddict_type: return # TypedDict can't be abstract - concrete = set() # type: Set[str] - abstract = [] # type: List[str] - abstract_in_this_class = [] # type: List[str] + concrete: Set[str] = set() + abstract: List[str] = [] + abstract_in_this_class: List[str] = [] if typ.is_newtype: # Special case: NewTypes are considered as always non-abstract, so they can be used as: # Config = NewType('Config', Mapping[str, str]) @@ -73,7 +73,7 @@ def calculate_class_abstract_status(typ: TypeInfo, is_stub_file: bool, errors: E # different items have a different abstract status, there # should be an error reported elsewhere. if node.items: # can be empty for invalid overloads - func = node.items[0] # type: Optional[Node] + func: Optional[Node] = node.items[0] else: func = None else: @@ -152,7 +152,7 @@ def add_type_promotion(info: TypeInfo, module_names: SymbolTable, options: Optio This includes things like 'int' being compatible with 'float'. """ defn = info.defn - promote_target = None # type: Optional[Type] + promote_target: Optional[Type] = None for decorator in defn.decorators: if isinstance(decorator, CallExpr): analyzed = decorator.analyzed diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index 295f142d90bf..5682f66298f6 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -4,6 +4,7 @@ """ from typing import List, Tuple, Optional, Union, cast +from typing_extensions import Final from mypy.nodes import ( Expression, Context, TypeInfo, AssignmentStmt, NameExpr, CallExpr, RefExpr, StrExpr, @@ -13,6 +14,15 @@ from mypy.semanal_shared import SemanticAnalyzerInterface from mypy.options import Options +# Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use +# enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. +ENUM_BASES: Final = frozenset(( + 'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag', +)) +ENUM_SPECIAL_PROPS: Final = frozenset(( + 'name', 'value', '_name_', '_value_', '_order_', '__order__', +)) + class EnumCallAnalyzer: def __init__(self, options: Options, api: SemanticAnalyzerInterface) -> None: @@ -62,7 +72,7 @@ class A(enum.Enum): if not isinstance(callee, RefExpr): return None fullname = callee.fullname - if fullname not in ('enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag'): + if fullname not in ENUM_BASES: return None items, values, ok = self.parse_enum_call_args(call, fullname.split('.')[-1]) if not ok: @@ -129,7 +139,7 @@ def parse_enum_call_args(self, call: CallExpr, return self.fail_enum_call_arg( "%s() expects a string literal as the first argument" % class_name, call) items = [] - values = [] # type: List[Optional[Expression]] + values: List[Optional[Expression]] = [] if isinstance(names, (StrExpr, UnicodeExpr)): fields = names.value for field in fields.replace(',', ' ').split(): diff --git a/mypy/semanal_infer.py b/mypy/semanal_infer.py index a869cdf29112..73a1077c5788 100644 --- a/mypy/semanal_infer.py +++ b/mypy/semanal_infer.py @@ -30,7 +30,7 @@ def infer_decorator_signature_if_simple(dec: Decorator, [ARG_POS], [None], AnyType(TypeOfAny.special_form), - analyzer.named_type('__builtins__.function'), + analyzer.named_type('builtins.function'), name=dec.var.name) elif isinstance(dec.func.type, CallableType): dec.var.type = dec.func.type @@ -47,7 +47,7 @@ def infer_decorator_signature_if_simple(dec: Decorator, if decorator_preserves_type: # No non-identity decorators left. We can trivially infer the type # of the function here. - dec.var.type = function_type(dec.func, analyzer.named_type('__builtins__.function')) + dec.var.type = function_type(dec.func, analyzer.named_type('builtins.function')) if dec.decorators: return_type = calculate_return_type(dec.decorators[0]) if return_type and isinstance(return_type, AnyType): @@ -58,8 +58,8 @@ def infer_decorator_signature_if_simple(dec: Decorator, if sig: # The outermost decorator always returns the same kind of function, # so we know that this is the type of the decorated function. - orig_sig = function_type(dec.func, analyzer.named_type('__builtins__.function')) - sig.name = orig_sig.items()[0].name + orig_sig = function_type(dec.func, analyzer.named_type('builtins.function')) + sig.name = orig_sig.items[0].name dec.var.type = sig diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index 58cfa261d69a..7e187945da48 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -24,10 +24,10 @@ will be incomplete. """ -import contextlib -from typing import List, Tuple, Optional, Union, Callable, Iterator -from typing_extensions import TYPE_CHECKING +from typing import List, Tuple, Optional, Union, Callable +from typing_extensions import TYPE_CHECKING, Final, TypeAlias as _TypeAlias +from mypy.backports import nullcontext from mypy.nodes import ( MypyFile, TypeInfo, FuncDef, Decorator, OverloadedFuncDef, Var ) @@ -51,16 +51,16 @@ from mypy.build import Graph, State -Patches = List[Tuple[int, Callable[[], None]]] +Patches: _TypeAlias = List[Tuple[int, Callable[[], None]]] # If we perform this many iterations, raise an exception since we are likely stuck. -MAX_ITERATIONS = 20 +MAX_ITERATIONS: Final = 20 # Number of passes over core modules before going on to the rest of the builtin SCC. -CORE_WARMUP = 2 -core_modules = ['typing', 'builtins', 'abc', 'collections'] +CORE_WARMUP: Final = 2 +core_modules: Final = ['typing', 'builtins', 'abc', 'collections'] def semantic_analysis_for_scc(graph: 'Graph', scc: List[str], errors: Errors) -> None: @@ -71,7 +71,7 @@ def semantic_analysis_for_scc(graph: 'Graph', scc: List[str], errors: Errors) -> The scc will be processed roughly in the order the modules are included in the list. """ - patches = [] # type: Patches + patches: Patches = [] # Note that functions can't define new module-level attributes # using 'global x', since module top levels are fully processed # before functions. This limitation is unlikely to go away soon. @@ -116,7 +116,7 @@ def semantic_analysis_for_targets( defined on self) removed by AST stripper that may need to be reintroduced here. They must be added before any methods are analyzed. """ - patches = [] # type: Patches + patches: Patches = [] if any(isinstance(n.node, MypyFile) for n in nodes): # Process module top level first (if needed). process_top_levels(graph, [state.id], patches) @@ -190,7 +190,7 @@ def process_top_levels(graph: 'Graph', scc: List[str], patches: Patches) -> None if final_iteration: # Give up. It's impossible to bind all names. state.manager.incomplete_namespaces.clear() - all_deferred = [] # type: List[str] + all_deferred: List[str] = [] any_progress = False while worklist: next_id = worklist.pop() @@ -249,7 +249,7 @@ def process_top_level_function(analyzer: 'SemanticAnalyzer', """Analyze single top-level function or method. Process the body of the function (including nested functions) again and again, - until all names have been resolved (ot iteration limit reached). + until all names have been resolved (or iteration limit reached). """ # We need one more iteration after incomplete is False (e.g. to report errors, if any). final_iteration = False @@ -289,7 +289,7 @@ def process_top_level_function(analyzer: 'SemanticAnalyzer', def get_all_leaf_targets(file: MypyFile) -> List[TargetInfo]: """Return all leaf targets in a symbol table (module-level and methods).""" - result = [] # type: List[TargetInfo] + result: List[TargetInfo] = [] for fullname, node, active_type in file.local_definitions(): if isinstance(node.node, (FuncDef, OverloadedFuncDef, Decorator)): result.append((fullname, node.node, active_type)) @@ -373,11 +373,11 @@ def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], stat with state.wrap_context(): with strict_optional_set(state.options.strict_optional): for target in targets: - func = None # type: Optional[Union[FuncDef, OverloadedFuncDef]] + func: Optional[Union[FuncDef, OverloadedFuncDef]] = None if isinstance(target.node, (FuncDef, OverloadedFuncDef)): func = target.node saved = (state.id, target.active_typeinfo, func) # module, class, function - with errors.scope.saved_scope(saved) if errors.scope else nothing(): + with errors.scope.saved_scope(saved) if errors.scope else nullcontext(): analyzer.recurse_into_functions = func is not None target.node.accept(analyzer) @@ -389,7 +389,7 @@ def calculate_class_properties(graph: 'Graph', scc: List[str], errors: Errors) - for _, node, _ in tree.local_definitions(): if isinstance(node.node, TypeInfo): saved = (module, node.node, None) # module, class, function - with errors.scope.saved_scope(saved) if errors.scope else nothing(): + with errors.scope.saved_scope(saved) if errors.scope else nullcontext(): calculate_class_abstract_status(node.node, tree.is_stub, errors) check_protocol_status(node.node, errors) calculate_class_vars(node.node) @@ -399,8 +399,3 @@ def calculate_class_properties(graph: 'Graph', scc: List[str], errors: Errors) - def check_blockers(graph: 'Graph', scc: List[str]) -> None: for module in scc: graph[module].check_blockers() - - -@contextlib.contextmanager -def nothing() -> Iterator[None]: - yield diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 4adeb56273c6..8930c63d2bef 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -8,7 +8,7 @@ from typing_extensions import Final from mypy.types import ( - Type, TupleType, AnyType, TypeOfAny, TypeVarDef, CallableType, TypeType, TypeVarType, + Type, TupleType, AnyType, TypeOfAny, CallableType, TypeType, TypeVarType, UnboundType, ) from mypy.semanal_shared import ( @@ -26,15 +26,26 @@ # Matches "_prohibited" in typing.py, but adds __annotations__, which works at runtime but can't # easily be supported in a static checker. -NAMEDTUPLE_PROHIBITED_NAMES = ('__new__', '__init__', '__slots__', '__getnewargs__', - '_fields', '_field_defaults', '_field_types', - '_make', '_replace', '_asdict', '_source', - '__annotations__') # type: Final +NAMEDTUPLE_PROHIBITED_NAMES: Final = ( + "__new__", + "__init__", + "__slots__", + "__getnewargs__", + "_fields", + "_field_defaults", + "_field_types", + "_make", + "_replace", + "_asdict", + "_source", + "__annotations__", +) -NAMEDTUP_CLASS_ERROR = ('Invalid statement in NamedTuple definition; ' - 'expected "field_name: field_type [= default]"') # type: Final +NAMEDTUP_CLASS_ERROR: Final = ( + "Invalid statement in NamedTuple definition; " 'expected "field_name: field_type [= default]"' +) -SELF_TVAR_NAME = '_NT' # type: Final +SELF_TVAR_NAME: Final = "_NT" class NamedTupleAnalyzer: @@ -87,9 +98,9 @@ def check_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool return [], [], {} if len(defn.base_type_exprs) > 1: self.fail('NamedTuple should be a single base', defn) - items = [] # type: List[str] - types = [] # type: List[Type] - default_items = {} # type: Dict[str, Expression] + items: List[str] = [] + types: List[Type] = [] + default_items: Dict[str, Expression] = {} for stmt in defn.defs.body: if not isinstance(stmt, AssignmentStmt): # Still allow pass or ... (for empty namedtuples). @@ -251,16 +262,17 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str Return None if the definition didn't typecheck. """ + type_name = 'NamedTuple' if fullname == 'typing.NamedTuple' else 'namedtuple' # TODO: Share code with check_argument_count in checkexpr.py? args = call.args if len(args) < 2: - self.fail("Too few arguments for namedtuple()", call) + self.fail('Too few arguments for "{}()"'.format(type_name), call) return None - defaults = [] # type: List[Expression] + defaults: List[Expression] = [] if len(args) > 2: # Typed namedtuple doesn't support additional arguments. if fullname == 'typing.NamedTuple': - self.fail("Too many arguments for NamedTuple()", call) + self.fail('Too many arguments for "NamedTuple()"', call) return None for i, arg_name in enumerate(call.arg_names[2:], 2): if arg_name == 'defaults': @@ -272,19 +284,19 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str else: self.fail( "List or tuple literal expected as the defaults argument to " - "namedtuple()", + "{}()".format(type_name), arg ) break if call.arg_kinds[:2] != [ARG_POS, ARG_POS]: - self.fail("Unexpected arguments to namedtuple()", call) + self.fail('Unexpected arguments to "{}()"'.format(type_name), call) return None if not isinstance(args[0], (StrExpr, BytesExpr, UnicodeExpr)): self.fail( - "namedtuple() expects a string literal as the first argument", call) + '"{}()" expects a string literal as the first argument'.format(type_name), call) return None typename = cast(Union[StrExpr, BytesExpr, UnicodeExpr], call.args[0]).value - types = [] # type: List[Type] + types: List[Type] = [] if not isinstance(args[1], (ListExpr, TupleExpr)): if (fullname == 'collections.namedtuple' and isinstance(args[1], (StrExpr, BytesExpr, UnicodeExpr))): @@ -292,7 +304,11 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str items = str_expr.value.replace(',', ' ').split() else: self.fail( - "List or tuple literal expected as the second argument to namedtuple()", call) + 'List or tuple literal expected as the second argument to "{}()"'.format( + type_name, + ), + call, + ) return None else: listexpr = args[1] @@ -300,7 +316,7 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str # The fields argument contains just names, with implicit Any types. if any(not isinstance(item, (StrExpr, BytesExpr, UnicodeExpr)) for item in listexpr.items): - self.fail("String literal expected as namedtuple() item", call) + self.fail('String literal expected as "namedtuple()" item', call) return None items = [cast(Union[StrExpr, BytesExpr, UnicodeExpr], item).value for item in listexpr.items] @@ -317,10 +333,10 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str types = [AnyType(TypeOfAny.unannotated) for _ in items] underscore = [item for item in items if item.startswith('_')] if underscore: - self.fail("namedtuple() field names cannot start with an underscore: " + self.fail('"{}()" field names cannot start with an underscore: '.format(type_name) + ', '.join(underscore), call) if len(defaults) > len(items): - self.fail("Too many defaults given in call to namedtuple()", call) + self.fail('Too many defaults given in call to "{}()"'.format(type_name), call) defaults = defaults[:len(items)] return items, types, defaults, typename, True @@ -331,21 +347,21 @@ def parse_namedtuple_fields_with_types(self, nodes: List[Expression], context: C Return (names, types, defaults, whether types are all ready), or None if error occurred. """ - items = [] # type: List[str] - types = [] # type: List[Type] + items: List[str] = [] + types: List[Type] = [] for item in nodes: if isinstance(item, TupleExpr): if len(item.items) != 2: - self.fail("Invalid NamedTuple field definition", item) + self.fail('Invalid "NamedTuple()" field definition', item) return None name, type_node = item.items if isinstance(name, (StrExpr, BytesExpr, UnicodeExpr)): items.append(name.value) else: - self.fail("Invalid NamedTuple() field name", item) + self.fail('Invalid "NamedTuple()" field name', item) return None try: - type = expr_to_unanalyzed_type(type_node) + type = expr_to_unanalyzed_type(type_node, self.options, self.api.is_stub_file) except TypeTranslationError: self.fail('Invalid field type', type_node) return None @@ -358,7 +374,7 @@ def parse_namedtuple_fields_with_types(self, nodes: List[Expression], context: C return [], [], [], False types.append(analyzed) else: - self.fail("Tuple expected as NamedTuple() field", item) + self.fail('Tuple expected as "NamedTuple()" field', item) return None return items, types, [], True @@ -368,19 +384,19 @@ def build_namedtuple_typeinfo(self, types: List[Type], default_items: Mapping[str, Expression], line: int) -> TypeInfo: - strtype = self.api.named_type('__builtins__.str') + strtype = self.api.named_type('builtins.str') implicit_any = AnyType(TypeOfAny.special_form) - basetuple_type = self.api.named_type('__builtins__.tuple', [implicit_any]) + basetuple_type = self.api.named_type('builtins.tuple', [implicit_any]) dictype = (self.api.named_type_or_none('builtins.dict', [strtype, implicit_any]) - or self.api.named_type('__builtins__.object')) + or self.api.named_type('builtins.object')) # Actual signature should return OrderedDict[str, Union[types]] ordereddictype = (self.api.named_type_or_none('builtins.dict', [strtype, implicit_any]) - or self.api.named_type('__builtins__.object')) - fallback = self.api.named_type('__builtins__.tuple', [implicit_any]) + or self.api.named_type('builtins.object')) + fallback = self.api.named_type('builtins.tuple', [implicit_any]) # Note: actual signature should accept an invariant version of Iterable[UnionType[types]]. # but it can't be expressed. 'new' and 'len' should be callable types. iterable_type = self.api.named_type_or_none('typing.Iterable', [implicit_any]) - function_type = self.api.named_type('__builtins__.function') + function_type = self.api.named_type('builtins.function') info = self.api.basic_new_typeinfo(name, fallback, line) info.is_named_tuple = True @@ -421,9 +437,9 @@ def add_field(var: Var, is_initialized_in_class: bool = False, add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True) add_field(Var('__doc__', strtype), is_initialized_in_class=True) - tvd = TypeVarDef(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, + tvd = TypeVarType(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, -1, [], info.tuple_type) - selftype = TypeVarType(tvd) + selftype = tvd def add_method(funcname: str, ret: Type, diff --git a/mypy/semanal_newtype.py b/mypy/semanal_newtype.py index 7af348dd281b..047df3d85b83 100644 --- a/mypy/semanal_newtype.py +++ b/mypy/semanal_newtype.py @@ -84,7 +84,7 @@ def process_newtype_declaration(self, s: AssignmentStmt) -> bool: self.fail(message.format(format_type(old_type)), s, code=codes.VALID_NEWTYPE) # Otherwise the error was already reported. old_type = AnyType(TypeOfAny.from_error) - object_type = self.api.named_type('__builtins__.object') + object_type = self.api.named_type('builtins.object') newtype_class_info = self.build_newtype_typeinfo(name, old_type, object_type, s.line) newtype_class_info.fallback_to_any = True @@ -160,7 +160,7 @@ def check_newtype_args(self, name: str, call: CallExpr, # Check second argument msg = "Argument 2 to NewType(...) must be a valid type" try: - unanalyzed_type = expr_to_unanalyzed_type(args[1]) + unanalyzed_type = expr_to_unanalyzed_type(args[1], self.options, self.api.is_stub_file) except TypeTranslationError: self.fail(msg, context) return None, False @@ -194,7 +194,7 @@ def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance, arg_kinds=[arg.kind for arg in args], arg_names=['self', 'item'], ret_type=NoneType(), - fallback=self.api.named_type('__builtins__.function'), + fallback=self.api.named_type('builtins.function'), name=name) init_func = FuncDef('__init__', args, Block([]), typ=signature) init_func.info = info diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index 60bcdb2cb928..3638d0878d8f 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -22,7 +22,7 @@ # (after the main pass): # Fix fallbacks (does joins) -PRIORITY_FALLBACKS = 1 # type: Final +PRIORITY_FALLBACKS: Final = 1 @trait @@ -101,11 +101,12 @@ def lookup(self, name: str, ctx: Context, raise NotImplementedError @abstractmethod - def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> Instance: + def named_type(self, fullname: str, + args: Optional[List[Type]] = None) -> Instance: raise NotImplementedError @abstractmethod - def named_type_or_none(self, qualified_name: str, + def named_type_or_none(self, fullname: str, args: Optional[List[Type]] = None) -> Optional[Instance]: raise NotImplementedError @@ -118,6 +119,7 @@ def anal_type(self, t: Type, *, tvar_scope: Optional[TypeVarLikeScope] = None, allow_tuple_literal: bool = False, allow_unbound_tvars: bool = False, + allow_required: bool = False, report_invalid_types: bool = True) -> Optional[Type]: raise NotImplementedError diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index 38a13c12b468..50e01145d60a 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -7,9 +7,10 @@ from typing import List, Optional, Set -from mypy.nodes import TypeInfo, Context, MypyFile, FuncItem, ClassDef, Block +from mypy.nodes import TypeInfo, Context, MypyFile, FuncItem, ClassDef, Block, FakeInfo from mypy.types import ( - Type, Instance, TypeVarType, AnyType, get_proper_types, TypeAliasType, get_proper_type + Type, Instance, TypeVarType, AnyType, get_proper_types, TypeAliasType, ParamSpecType, + get_proper_type ) from mypy.mixedtraverser import MixedTraverserVisitor from mypy.subtypes import is_subtype @@ -19,6 +20,7 @@ from mypy.options import Options from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes +from mypy.messages import format_type class TypeArgumentAnalyzer(MixedTraverserVisitor): @@ -31,13 +33,12 @@ def __init__(self, errors: Errors, options: Options, is_typeshed_file: bool) -> self.recurse_into_functions = True # Keep track of the type aliases already visited. This is needed to avoid # infinite recursion on types like A = Union[int, List[A]]. - self.seen_aliases = set() # type: Set[TypeAliasType] + self.seen_aliases: Set[TypeAliasType] = set() def visit_mypy_file(self, o: MypyFile) -> None: self.errors.set_file(o.path, o.fullname, scope=self.scope) - self.scope.enter_file(o.fullname) - super().visit_mypy_file(o) - self.scope.leave() + with self.scope.module_scope(o.fullname): + super().visit_mypy_file(o) def visit_func(self, defn: FuncItem) -> None: if not self.recurse_into_functions: @@ -67,22 +68,31 @@ def visit_instance(self, t: Instance) -> None: # Type argument counts were checked in the main semantic analyzer pass. We assume # that the counts are correct here. info = t.type + if isinstance(info, FakeInfo): + return # https://github.com/python/mypy/issues/11079 for (i, arg), tvar in zip(enumerate(t.args), info.defn.type_vars): - if tvar.values: - if isinstance(arg, TypeVarType): - arg_values = arg.values - if not arg_values: - self.fail('Type variable "{}" not valid as type ' - 'argument value for "{}"'.format( - arg.name, info.name), t, code=codes.TYPE_VAR) - continue - else: - arg_values = [arg] - self.check_type_var_values(info, arg_values, tvar.name, tvar.values, i + 1, t) - if not is_subtype(arg, tvar.upper_bound): - self.fail('Type argument "{}" of "{}" must be ' - 'a subtype of "{}"'.format( - arg, info.name, tvar.upper_bound), t, code=codes.TYPE_VAR) + if isinstance(tvar, TypeVarType): + if isinstance(arg, ParamSpecType): + # TODO: Better message + self.fail(f'Invalid location for ParamSpec "{arg.name}"', t) + continue + if tvar.values: + if isinstance(arg, TypeVarType): + arg_values = arg.values + if not arg_values: + self.fail( + message_registry.INVALID_TYPEVAR_AS_TYPEARG.format( + arg.name, info.name), + t, code=codes.TYPE_VAR) + continue + else: + arg_values = [arg] + self.check_type_var_values(info, arg_values, tvar.name, tvar.values, i + 1, t) + if not is_subtype(arg, tvar.upper_bound): + self.fail( + message_registry.INVALID_TYPEVAR_ARG_BOUND.format( + format_type(arg), info.name, format_type(tvar.upper_bound)), + t, code=codes.TYPE_VAR) super().visit_instance(t) def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str, @@ -92,8 +102,9 @@ def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: s not any(is_same_type(actual, value) for value in valids)): if len(actuals) > 1 or not isinstance(actual, Instance): - self.fail('Invalid type argument value for "{}"'.format( - type.name), context, code=codes.TYPE_VAR) + self.fail( + message_registry.INVALID_TYPEVAR_ARG_VALUE.format(type.name), + context, code=codes.TYPE_VAR) else: class_name = '"{}"'.format(type.name) actual_type_name = '"{}"'.format(actual.type.name) diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index 0b0891d83fb6..ffc6a7df3931 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -1,10 +1,12 @@ """Semantic analysis of TypedDict definitions.""" -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import Optional, List, Set, Tuple from typing_extensions import Final -from mypy.types import Type, AnyType, TypeOfAny, TypedDictType, TPDICT_NAMES +from mypy.types import ( + Type, AnyType, TypeOfAny, TypedDictType, TPDICT_NAMES, RequiredType, +) from mypy.nodes import ( CallExpr, TypedDictExpr, Expression, NameExpr, Context, StrExpr, BytesExpr, UnicodeExpr, ClassDef, RefExpr, TypeInfo, AssignmentStmt, PassStmt, ExpressionStmt, EllipsisExpr, TempNode, @@ -18,8 +20,9 @@ from mypy.errorcodes import ErrorCode from mypy import errorcodes as codes -TPDICT_CLASS_ERROR = ('Invalid statement in TypedDict definition; ' - 'expected "field_name: field_type"') # type: Final +TPDICT_CLASS_ERROR: Final = ( + "Invalid statement in TypedDict definition; " 'expected "field_name: field_type"' +) class TypedDictAnalyzer: @@ -66,16 +69,30 @@ def analyze_typeddict_classdef(self, defn: ClassDef) -> Tuple[bool, Optional[Typ defn.analyzed.line = defn.line defn.analyzed.column = defn.column return True, info + # Extending/merging existing TypedDicts - if any(not isinstance(expr, RefExpr) or - expr.fullname not in TPDICT_NAMES and - not self.is_typeddict(expr) for expr in defn.base_type_exprs): - self.fail("All bases of a new TypedDict must be TypedDict types", defn) - typeddict_bases = list(filter(self.is_typeddict, defn.base_type_exprs)) - keys = [] # type: List[str] + typeddict_bases = [] + typeddict_bases_set = set() + for expr in defn.base_type_exprs: + if isinstance(expr, RefExpr) and expr.fullname in TPDICT_NAMES: + if 'TypedDict' not in typeddict_bases_set: + typeddict_bases_set.add('TypedDict') + else: + self.fail('Duplicate base class "TypedDict"', defn) + elif isinstance(expr, RefExpr) and self.is_typeddict(expr): + assert expr.fullname + if expr.fullname not in typeddict_bases_set: + typeddict_bases_set.add(expr.fullname) + typeddict_bases.append(expr) + else: + assert isinstance(expr.node, TypeInfo) + self.fail('Duplicate base class "%s"' % expr.node.name, defn) + else: + self.fail("All bases of a new TypedDict must be TypedDict types", defn) + + keys: List[str] = [] types = [] required_keys = set() - # Iterate over bases in reverse order so that leftmost base class' keys take precedence for base in reversed(typeddict_bases): assert isinstance(base, RefExpr) @@ -121,8 +138,8 @@ def analyze_typeddict_classdef_fields( * List of types for each key * Set of required keys """ - fields = [] # type: List[str] - types = [] # type: List[Type] + fields: List[str] = [] + types: List[Type] = [] for stmt in defn.defs.body: if not isinstance(stmt, AssignmentStmt): # Still allow pass or ... (for empty TypedDict's). @@ -146,7 +163,7 @@ def analyze_typeddict_classdef_fields( if stmt.type is None: types.append(AnyType(TypeOfAny.unannotated)) else: - analyzed = self.api.anal_type(stmt.type) + analyzed = self.api.anal_type(stmt.type, allow_required=True) if analyzed is None: return None, [], set() # Need to defer types.append(analyzed) @@ -156,13 +173,28 @@ def analyze_typeddict_classdef_fields( elif not isinstance(stmt.rvalue, TempNode): # x: int assigns rvalue to TempNode(AnyType()) self.fail('Right hand side values are not supported in TypedDict', stmt) - total = True # type: Optional[bool] + total: Optional[bool] = True if 'total' in defn.keywords: total = self.api.parse_bool(defn.keywords['total']) if total is None: self.fail('Value of "total" must be True or False', defn) total = True - required_keys = set(fields) if total else set() + required_keys = { + field + for (field, t) in zip(fields, types) + if (total or ( + isinstance(t, RequiredType) and # type: ignore[misc] + t.required + )) and not ( + isinstance(t, RequiredType) and # type: ignore[misc] + not t.required + ) + } + types = [ # unwrap Required[T] to just T + t.item if isinstance(t, RequiredType) else t # type: ignore[misc] + for t in types + ] + return fields, types, required_keys def check_typeddict(self, @@ -206,7 +238,21 @@ def check_typeddict(self, if name != var_name or is_func_scope: # Give it a unique name derived from the line number. name += '@' + str(call.line) - required_keys = set(items) if total else set() + required_keys = { + field + for (field, t) in zip(items, types) + if (total or ( + isinstance(t, RequiredType) and # type: ignore[misc] + t.required + )) and not ( + isinstance(t, RequiredType) and # type: ignore[misc] + not t.required + ) + } + types = [ # unwrap Required[T] to just T + t.item if isinstance(t, RequiredType) else t # type: ignore[misc] + for t in types + ] info = self.build_typeddict_typeinfo(name, items, types, required_keys, call.line) info.line = node.line # Store generated TypeInfo under both names, see semanal_namedtuple for more details. @@ -243,7 +289,7 @@ def parse_typeddict_args( if not isinstance(args[1], DictExpr): return self.fail_typeddict_arg( "TypedDict() expects a dictionary literal as the second argument", call) - total = True # type: Optional[bool] + total: Optional[bool] = True if len(args) == 3: total = self.api.parse_bool(call.args[2]) if total is None: @@ -275,8 +321,8 @@ def parse_typeddict_fields_with_types( Return names, types, was there an error. If some type is not ready, return None. """ seen_keys = set() - items = [] # type: List[str] - types = [] # type: List[Type] + items: List[str] = [] + types: List[Type] = [] for (field_name_expr, field_type_expr) in dict_items: if isinstance(field_name_expr, (StrExpr, BytesExpr, UnicodeExpr)): key = field_name_expr.value @@ -289,11 +335,19 @@ def parse_typeddict_fields_with_types( self.fail_typeddict_arg("Invalid TypedDict() field name", name_context) return [], [], False try: - type = expr_to_unanalyzed_type(field_type_expr) + type = expr_to_unanalyzed_type(field_type_expr, self.options, + self.api.is_stub_file) except TypeTranslationError: - self.fail_typeddict_arg('Invalid field type', field_type_expr) + if (isinstance(field_type_expr, CallExpr) and + isinstance(field_type_expr.callee, RefExpr) and + field_type_expr.callee.fullname in TPDICT_NAMES): + self.fail_typeddict_arg( + 'Inline TypedDict types not supported; use assignment to define TypedDict', + field_type_expr) + else: + self.fail_typeddict_arg('Invalid field type', field_type_expr) return [], [], False - analyzed = self.api.anal_type(type) + analyzed = self.api.anal_type(type, allow_required=True) if analyzed is None: return None types.append(analyzed) @@ -326,3 +380,6 @@ def is_typeddict(self, expr: Expression) -> bool: def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None: self.api.fail(msg, ctx, code=code) + + def note(self, msg: str, ctx: Context) -> None: + self.api.note(msg, ctx) diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index f74f3f35c7e1..12add8efcb3a 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -54,12 +54,12 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method' from mypy.nodes import ( SymbolTable, TypeInfo, Var, SymbolNode, Decorator, TypeVarExpr, TypeAlias, - FuncBase, OverloadedFuncDef, FuncItem, MypyFile, UNBOUND_IMPORTED + FuncBase, OverloadedFuncDef, FuncItem, MypyFile, ParamSpecExpr, UNBOUND_IMPORTED ) from mypy.types import ( - Type, TypeGuardType, TypeVisitor, UnboundType, AnyType, NoneType, UninhabitedType, + Type, TypeVisitor, UnboundType, AnyType, NoneType, UninhabitedType, ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, - UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType + UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType, ParamSpecType ) from mypy.util import get_prefix @@ -128,7 +128,7 @@ def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> Dict[str, Sna things defined in other modules are represented just by the names of the targets. """ - result = {} # type: Dict[str, SnapshotItem] + result: Dict[str, SnapshotItem] = {} for name, symbol in table.items(): node = symbol.node # TODO: cross_ref? @@ -151,6 +151,10 @@ def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> Dict[str, Sna node.normalized, node.no_args, snapshot_optional_type(node.target)) + elif isinstance(node, ParamSpecExpr): + result[name] = ('ParamSpec', + node.variance, + snapshot_type(node.upper_bound)) else: assert symbol.kind != UNBOUND_IMPORTED if node and get_prefix(node.fullname) != name_prefix: @@ -213,7 +217,7 @@ def snapshot_definition(node: Optional[SymbolNode], # x: C[str] <- this is invalid, and needs to be re-checked if `T` changes. # An alternative would be to create both deps: <...> -> C, and <...> -> , # but this currently seems a bit ad hoc. - tuple(snapshot_type(TypeVarType(tdef)) for tdef in node.defn.type_vars), + tuple(snapshot_type(tdef) for tdef in node.defn.type_vars), [snapshot_type(base) for base in node.bases], snapshot_optional_type(node._promote)) prefix = node.fullname @@ -306,6 +310,13 @@ def visit_type_var(self, typ: TypeVarType) -> SnapshotItem: snapshot_type(typ.upper_bound), typ.variance) + def visit_param_spec(self, typ: ParamSpecType) -> SnapshotItem: + return ('ParamSpec', + typ.id.raw_id, + typ.id.meta_level, + typ.flavor, + snapshot_type(typ.upper_bound)) + def visit_callable_type(self, typ: CallableType) -> SnapshotItem: # FIX generics return ('CallableType', @@ -335,11 +346,8 @@ def visit_union_type(self, typ: UnionType) -> SnapshotItem: normalized = tuple(sorted(items)) return ('UnionType', normalized) - def visit_type_guard_type(self, typ: TypeGuardType) -> SnapshotItem: - return ('TypeGuardType', snapshot_type(typ.type_guard)) - def visit_overloaded(self, typ: Overloaded) -> SnapshotItem: - return ('Overloaded', snapshot_types(typ.items())) + return ('Overloaded', snapshot_types(typ.items)) def visit_partial_type(self, typ: PartialType) -> SnapshotItem: # A partial type is not fully defined, so the result is indeterminate. We shouldn't diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index 8b9726019224..8db2b302b844 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -57,9 +57,9 @@ from mypy.traverser import TraverserVisitor from mypy.types import ( Type, SyntheticTypeVisitor, Instance, AnyType, NoneType, CallableType, ErasedType, DeletedType, - TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType, - Overloaded, TypeVarDef, TypeList, CallableArgument, EllipsisType, StarType, LiteralType, - RawExpressionType, PartialType, PlaceholderType, TypeAliasType, TypeGuardType + TupleType, TypeType, TypedDictType, UnboundType, UninhabitedType, UnionType, + Overloaded, TypeVarType, TypeList, CallableArgument, EllipsisType, StarType, LiteralType, + RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType ) from mypy.util import get_prefix, replace_object_state from mypy.typestate import TypeState @@ -103,7 +103,7 @@ def replacement_map_from_symbol_table( the given module prefix. Don't recurse into other modules accessible through the symbol table. """ - replacements = {} # type: Dict[SymbolNode, SymbolNode] + replacements: Dict[SymbolNode, SymbolNode] = {} for name, node in old.items(): if (name in new and (node.kind == MDEF or node.node and get_prefix(node.node.fullname) == prefix)): @@ -173,7 +173,8 @@ def visit_class_def(self, node: ClassDef) -> None: node.defs.body = self.replace_statements(node.defs.body) info = node.info for tv in node.type_vars: - self.process_type_var_def(tv) + if isinstance(tv, TypeVarType): + self.process_type_var_def(tv) if info: if info.is_named_tuple: self.process_synthetic_type_info(info) @@ -188,7 +189,7 @@ def process_base_func(self, node: FuncBase) -> None: # Unanalyzed types can have AST node references self.fixup_type(node.unanalyzed_type) - def process_type_var_def(self, tv: TypeVarDef) -> None: + def process_type_var_def(self, tv: TypeVarType) -> None: for value in tv.values: self.fixup_type(value) self.fixup_type(tv.upper_bound) @@ -370,13 +371,13 @@ def visit_callable_type(self, typ: CallableType) -> None: if typ.fallback is not None: typ.fallback.accept(self) for tv in typ.variables: - if isinstance(tv, TypeVarDef): + if isinstance(tv, TypeVarType): tv.upper_bound.accept(self) for value in tv.values: value.accept(self) def visit_overloaded(self, t: Overloaded) -> None: - for item in t.items(): + for item in t.items: item.accept(self) # Fallback can be None for overloaded types that haven't been semantically analyzed. if t.fallback is not None: @@ -389,9 +390,6 @@ def visit_erased_type(self, t: ErasedType) -> None: def visit_deleted_type(self, typ: DeletedType) -> None: pass - def visit_type_guard_type(self, typ: TypeGuardType) -> None: - raise RuntimeError - def visit_partial_type(self, typ: PartialType) -> None: raise RuntimeError @@ -410,6 +408,9 @@ def visit_type_var(self, typ: TypeVarType) -> None: for value in typ.values: value.accept(self) + def visit_param_spec(self, typ: ParamSpecType) -> None: + pass + def visit_typeddict_type(self, typ: TypedDictType) -> None: for value_type in typ.items.values(): value_type.accept(self) diff --git a/mypy/server/aststrip.py b/mypy/server/aststrip.py index 8572314fc75a..4363223c1cf0 100644 --- a/mypy/server/aststrip.py +++ b/mypy/server/aststrip.py @@ -34,6 +34,7 @@ import contextlib from typing import Union, Iterator, Optional, Dict, Tuple +from mypy.backports import nullcontext from mypy.nodes import ( FuncDef, NameExpr, MemberExpr, RefExpr, MypyFile, ClassDef, AssignmentStmt, ImportFrom, CallExpr, Decorator, OverloadedFuncDef, Node, TupleExpr, ListExpr, @@ -71,7 +72,7 @@ def strip_target(node: Union[MypyFile, FuncDef, OverloadedFuncDef], class NodeStripVisitor(TraverserVisitor): def __init__(self, saved_class_attrs: SavedAttributes) -> None: # The current active class. - self.type = None # type: Optional[TypeInfo] + self.type: Optional[TypeInfo] = None # This is True at class scope, but not in methods. self.is_class_body = False # By default, process function definitions. If False, don't -- this is used for @@ -138,7 +139,7 @@ def visit_func_def(self, node: FuncDef) -> None: # See also #4814. assert isinstance(node.type, CallableType) node.type.variables = [] - with self.enter_method(node.info) if node.info else nothing(): + with self.enter_method(node.info) if node.info else nullcontext(): super().visit_func_def(node) def visit_decorator(self, node: Decorator) -> None: @@ -247,8 +248,3 @@ def enter_method(self, info: TypeInfo) -> Iterator[None]: yield self.type = old_type self.is_class_body = old_is_class_body - - -@contextlib.contextmanager -def nothing() -> Iterator[None]: - yield diff --git a/mypy/server/deps.py b/mypy/server/deps.py index 9aee82664bd2..cee12c9f8aab 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -89,7 +89,9 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a ComparisonExpr, GeneratorExpr, DictionaryComprehension, StarExpr, PrintStmt, ForStmt, WithStmt, TupleExpr, OperatorAssignmentStmt, DelStmt, YieldFromExpr, Decorator, Block, TypeInfo, FuncBase, OverloadedFuncDef, RefExpr, SuperExpr, Var, NamedTupleExpr, TypedDictExpr, - LDEF, MDEF, GDEF, TypeAliasExpr, NewTypeExpr, ImportAll, EnumCallExpr, AwaitExpr, + LDEF, MDEF, GDEF, TypeAliasExpr, NewTypeExpr, ImportAll, EnumCallExpr, AwaitExpr +) +from mypy.operators import ( op_methods, reverse_op_methods, ops_with_inplace_method, unary_op_methods ) from mypy.traverser import TraverserVisitor @@ -97,7 +99,7 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a Type, Instance, AnyType, NoneType, TypeVisitor, CallableType, DeletedType, PartialType, TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType, FunctionLike, Overloaded, TypeOfAny, LiteralType, ErasedType, get_proper_type, ProperType, - TypeAliasType, TypeGuardType + TypeAliasType, ParamSpecType ) from mypy.server.trigger import make_trigger, make_wildcard_trigger from mypy.util import correct_relative_import @@ -124,23 +126,21 @@ def get_dependencies_of_target(module_id: str, """Get dependencies of a target -- don't recursive into nested targets.""" # TODO: Add tests for this function. visitor = DependencyVisitor(type_map, python_version, module_tree.alias_deps) - visitor.scope.enter_file(module_id) - if isinstance(target, MypyFile): - # Only get dependencies of the top-level of the module. Don't recurse into - # functions. - for defn in target.defs: - # TODO: Recurse into top-level statements and class bodies but skip functions. - if not isinstance(defn, (ClassDef, Decorator, FuncDef, OverloadedFuncDef)): - defn.accept(visitor) - elif isinstance(target, FuncBase) and target.info: - # It's a method. - # TODO: Methods in nested classes. - visitor.scope.enter_class(target.info) - target.accept(visitor) - visitor.scope.leave() - else: - target.accept(visitor) - visitor.scope.leave() + with visitor.scope.module_scope(module_id): + if isinstance(target, MypyFile): + # Only get dependencies of the top-level of the module. Don't recurse into + # functions. + for defn in target.defs: + # TODO: Recurse into top-level statements and class bodies but skip functions. + if not isinstance(defn, (ClassDef, Decorator, FuncDef, OverloadedFuncDef)): + defn.accept(visitor) + elif isinstance(target, FuncBase) and target.info: + # It's a method. + # TODO: Methods in nested classes. + with visitor.scope.class_scope(target.info): + target.accept(visitor) + else: + target.accept(visitor) return visitor.map @@ -163,44 +163,42 @@ def __init__(self, # are preserved at alias expansion points in `semanal.py`, stored as an attribute # on MypyFile, and then passed here. self.alias_deps = alias_deps - self.map = {} # type: Dict[str, Set[str]] + self.map: Dict[str, Set[str]] = {} self.is_class = False self.is_package_init_file = False self.options = options def visit_mypy_file(self, o: MypyFile) -> None: - self.scope.enter_file(o.fullname) - self.is_package_init_file = o.is_package_init_file() - self.add_type_alias_deps(self.scope.current_target()) - for trigger, targets in o.plugin_deps.items(): - self.map.setdefault(trigger, set()).update(targets) - super().visit_mypy_file(o) - self.scope.leave() + with self.scope.module_scope(o.fullname): + self.is_package_init_file = o.is_package_init_file() + self.add_type_alias_deps(self.scope.current_target()) + for trigger, targets in o.plugin_deps.items(): + self.map.setdefault(trigger, set()).update(targets) + super().visit_mypy_file(o) def visit_func_def(self, o: FuncDef) -> None: - self.scope.enter_function(o) - target = self.scope.current_target() - if o.type: - if self.is_class and isinstance(o.type, FunctionLike): - signature = bind_self(o.type) # type: Type - else: - signature = o.type - for trigger in self.get_type_triggers(signature): - self.add_dependency(trigger) - self.add_dependency(trigger, target=make_trigger(target)) - if o.info: - for base in non_trivial_bases(o.info): - # Base class __init__/__new__ doesn't generate a logical - # dependency since the override can be incompatible. - if not self.use_logical_deps() or o.name not in ('__init__', '__new__'): - self.add_dependency(make_trigger(base.fullname + '.' + o.name)) - self.add_type_alias_deps(self.scope.current_target()) - super().visit_func_def(o) - variants = set(o.expanded) - {o} - for ex in variants: - if isinstance(ex, FuncDef): - super().visit_func_def(ex) - self.scope.leave() + with self.scope.function_scope(o): + target = self.scope.current_target() + if o.type: + if self.is_class and isinstance(o.type, FunctionLike): + signature: Type = bind_self(o.type) + else: + signature = o.type + for trigger in self.get_type_triggers(signature): + self.add_dependency(trigger) + self.add_dependency(trigger, target=make_trigger(target)) + if o.info: + for base in non_trivial_bases(o.info): + # Base class __init__/__new__ doesn't generate a logical + # dependency since the override can be incompatible. + if not self.use_logical_deps() or o.name not in ('__init__', '__new__'): + self.add_dependency(make_trigger(base.fullname + '.' + o.name)) + self.add_type_alias_deps(self.scope.current_target()) + super().visit_func_def(o) + variants = set(o.expanded) - {o} + for ex in variants: + if isinstance(ex, FuncDef): + super().visit_func_def(ex) def visit_decorator(self, o: Decorator) -> None: if not self.use_logical_deps(): @@ -217,7 +215,7 @@ def visit_decorator(self, o: Decorator) -> None: # then if `dec` is unannotated, then it will "spoil" `func` and consequently # all call sites, making them all `Any`. for d in o.decorators: - tname = None # type: Optional[str] + tname: Optional[str] = None if isinstance(d, RefExpr) and d.fullname is not None: tname = d.fullname if (isinstance(d, CallExpr) and isinstance(d.callee, RefExpr) and @@ -228,24 +226,22 @@ def visit_decorator(self, o: Decorator) -> None: super().visit_decorator(o) def visit_class_def(self, o: ClassDef) -> None: - self.scope.enter_class(o.info) - target = self.scope.current_full_target() - self.add_dependency(make_trigger(target), target) - old_is_class = self.is_class - self.is_class = True - # Add dependencies to type variables of a generic class. - for tv in o.type_vars: - self.add_dependency(make_trigger(tv.fullname), target) - self.process_type_info(o.info) - super().visit_class_def(o) - self.is_class = old_is_class - self.scope.leave() + with self.scope.class_scope(o.info): + target = self.scope.current_full_target() + self.add_dependency(make_trigger(target), target) + old_is_class = self.is_class + self.is_class = True + # Add dependencies to type variables of a generic class. + for tv in o.type_vars: + self.add_dependency(make_trigger(tv.fullname), target) + self.process_type_info(o.info) + super().visit_class_def(o) + self.is_class = old_is_class def visit_newtype_expr(self, o: NewTypeExpr) -> None: if o.info: - self.scope.enter_class(o.info) - self.process_type_info(o.info) - self.scope.leave() + with self.scope.class_scope(o.info): + self.process_type_info(o.info) def process_type_info(self, info: TypeInfo) -> None: target = self.scope.current_full_target() @@ -417,7 +413,7 @@ def visit_assignment_stmt(self, o: AssignmentStmt) -> None: # then it will make all points of use of `x` unchecked. if (isinstance(rvalue, CallExpr) and isinstance(rvalue.callee, RefExpr) and rvalue.callee.fullname is not None): - fname = None # type: Optional[str] + fname: Optional[str] = None if isinstance(rvalue.callee.node, TypeInfo): # use actual __init__ as a dependency source init = rvalue.callee.node.get('__init__') @@ -485,8 +481,11 @@ def get_non_partial_lvalue_type(self, lvalue: RefExpr) -> Type: return UninhabitedType() lvalue_type = get_proper_type(self.type_map[lvalue]) if isinstance(lvalue_type, PartialType): - if isinstance(lvalue.node, Var) and lvalue.node.type: - lvalue_type = get_proper_type(lvalue.node.type) + if isinstance(lvalue.node, Var): + if lvalue.node.type: + lvalue_type = get_proper_type(lvalue.node.type) + else: + lvalue_type = UninhabitedType() else: # Probably a secondary, non-definition assignment that doesn't # result in a non-partial type. We won't be able to infer any @@ -869,7 +868,7 @@ def get_type_triggers(typ: Type, use_logical_deps: bool) -> List[str]: class TypeTriggersVisitor(TypeVisitor[List[str]]): def __init__(self, use_logical_deps: bool) -> None: - self.deps = [] # type: List[str] + self.deps: List[str] = [] self.use_logical_deps = use_logical_deps def get_type_triggers(self, typ: Type) -> List[str]: @@ -915,7 +914,7 @@ def visit_callable_type(self, typ: CallableType) -> List[str]: def visit_overloaded(self, typ: Overloaded) -> List[str]: triggers = [] - for item in typ.items(): + for item in typ.items: triggers.extend(self.get_type_triggers(item)) return triggers @@ -955,6 +954,13 @@ def visit_type_var(self, typ: TypeVarType) -> List[str]: triggers.extend(self.get_type_triggers(val)) return triggers + def visit_param_spec(self, typ: ParamSpecType) -> List[str]: + triggers = [] + if typ.fullname: + triggers.append(make_trigger(typ.fullname)) + triggers.extend(self.get_type_triggers(typ.upper_bound)) + return triggers + def visit_typeddict_type(self, typ: TypedDictType) -> List[str]: triggers = [] for item in typ.items.values(): @@ -971,9 +977,6 @@ def visit_unbound_type(self, typ: UnboundType) -> List[str]: def visit_uninhabited_type(self, typ: UninhabitedType) -> List[str]: return [] - def visit_type_guard_type(self, typ: TypeGuardType) -> List[str]: - return typ.type_guard.accept(self) - def visit_union_type(self, typ: UnionType) -> List[str]: triggers = [] for item in typ.items: @@ -1001,7 +1004,7 @@ def dump_all_dependencies(modules: Dict[str, MypyFile], python_version: Tuple[int, int], options: Options) -> None: """Generate dependencies for all interesting modules and print them to stdout.""" - all_deps = {} # type: Dict[str, Set[str]] + all_deps: Dict[str, Set[str]] = {} for id, node in modules.items(): # Uncomment for debugging: # print('processing', id) diff --git a/mypy/server/mergecheck.py b/mypy/server/mergecheck.py index afa450fb5a75..476d1cc809f7 100644 --- a/mypy/server/mergecheck.py +++ b/mypy/server/mergecheck.py @@ -7,7 +7,7 @@ from mypy.server.objgraph import get_reachable_graph, get_path # If True, print more verbose output on failure. -DUMP_MISMATCH_NODES = False # type: Final +DUMP_MISMATCH_NODES: Final = False def check_consistency(o: object) -> None: @@ -19,7 +19,7 @@ def check_consistency(o: object) -> None: reachable = list(seen.values()) syms = [x for x in reachable if isinstance(x, SymbolNode)] - m = {} # type: Dict[str, SymbolNode] + m: Dict[str, SymbolNode] = {} for sym in syms: if isinstance(sym, FakeInfo): continue diff --git a/mypy/server/objgraph.py b/mypy/server/objgraph.py index a7b45f5ec81f..89f0ba79388b 100644 --- a/mypy/server/objgraph.py +++ b/mypy/server/objgraph.py @@ -7,46 +7,48 @@ from typing import List, Dict, Iterator, Tuple, Mapping from typing_extensions import Final -method_descriptor_type = type(object.__dir__) # type: Final -method_wrapper_type = type(object().__ne__) # type: Final -wrapper_descriptor_type = type(object.__ne__) # type: Final - -FUNCTION_TYPES = (types.BuiltinFunctionType, - types.FunctionType, - types.MethodType, - method_descriptor_type, - wrapper_descriptor_type, - method_wrapper_type) # type: Final - -ATTR_BLACKLIST = { +method_descriptor_type: Final = type(object.__dir__) +method_wrapper_type: Final = type(object().__ne__) +wrapper_descriptor_type: Final = type(object.__ne__) + +FUNCTION_TYPES: Final = ( + types.BuiltinFunctionType, + types.FunctionType, + types.MethodType, + method_descriptor_type, + wrapper_descriptor_type, + method_wrapper_type, +) + +ATTR_BLACKLIST: Final = { '__doc__', '__name__', '__class__', '__dict__', -} # type: Final +} # Instances of these types can't have references to other objects -ATOMIC_TYPE_BLACKLIST = { +ATOMIC_TYPE_BLACKLIST: Final = { bool, int, float, str, type(None), object, -} # type: Final +} # Don't look at most attributes of these types -COLLECTION_TYPE_BLACKLIST = { +COLLECTION_TYPE_BLACKLIST: Final = { list, set, dict, tuple, -} # type: Final +} # Don't return these objects -TYPE_BLACKLIST = { +TYPE_BLACKLIST: Final = { weakref.ReferenceType, -} # type: Final +} def isproperty(o: object, attr: str) -> bool: diff --git a/mypy/server/subexpr.py b/mypy/server/subexpr.py index cc645332d9d4..2fb0ef4ffaf1 100644 --- a/mypy/server/subexpr.py +++ b/mypy/server/subexpr.py @@ -20,7 +20,7 @@ def get_subexpressions(node: Node) -> List[Expression]: class SubexpressionFinder(TraverserVisitor): def __init__(self) -> None: - self.expressions = [] # type: List[Expression] + self.expressions: List[Expression] = [] def visit_int_expr(self, o: Expression) -> None: self.add(o) diff --git a/mypy/server/trigger.py b/mypy/server/trigger.py index c9f206d66a6d..c10264766ae6 100644 --- a/mypy/server/trigger.py +++ b/mypy/server/trigger.py @@ -5,7 +5,7 @@ # Used as a suffix for triggers to handle "from m import *" dependencies (see also # make_wildcard_trigger) -WILDCARD_TAG = '[wildcard]' # type: Final +WILDCARD_TAG: Final = "[wildcard]" def make_trigger(name: str) -> str: diff --git a/mypy/server/update.py b/mypy/server/update.py index 085c143fadd1..e82064c63a11 100644 --- a/mypy/server/update.py +++ b/mypy/server/update.py @@ -148,7 +148,7 @@ from mypy.util import module_prefix, split_target from mypy.typestate import TypeState -MAX_ITER = 1000 # type: Final +MAX_ITER: Final = 1000 SENSITIVE_INTERNAL_MODULES = tuple(core_modules) + ("mypy_extensions", "typing_extensions") @@ -173,22 +173,22 @@ def __init__(self, result: BuildResult) -> None: self.previous_targets_with_errors = manager.errors.targets() self.previous_messages = result.errors[:] # Module, if any, that had blocking errors in the last run as (id, path) tuple. - self.blocking_error = None # type: Optional[Tuple[str, str]] + self.blocking_error: Optional[Tuple[str, str]] = None # Module that we haven't processed yet but that are known to be stale. - self.stale = [] # type: List[Tuple[str, str]] + self.stale: List[Tuple[str, str]] = [] # Disable the cache so that load_graph doesn't try going back to disk # for the cache. self.manager.cache_enabled = False # Some hints to the test suite about what is going on: # Active triggers during the last update - self.triggered = [] # type: List[str] + self.triggered: List[str] = [] # Modules passed to update during the last update - self.changed_modules = [] # type: List[Tuple[str, str]] + self.changed_modules: List[Tuple[str, str]] = [] # Modules processed during the last update - self.updated_modules = [] # type: List[str] + self.updated_modules: List[str] = [] # Targets processed during last update (for testing only). - self.processed_targets = [] # type: List[str] + self.processed_targets: List[str] = [] def update(self, changed_modules: List[Tuple[str, str]], @@ -383,7 +383,7 @@ def update_module(self, t0 = time.time() # Record symbol table snapshot of old version the changed module. - old_snapshots = {} # type: Dict[str, Dict[str, SnapshotItem]] + old_snapshots: Dict[str, Dict[str, SnapshotItem]] = {} if module in manager.modules: snapshot = snapshot_symbol_table(module, manager.modules[module].names) old_snapshots[module] = snapshot @@ -439,7 +439,7 @@ def find_unloaded_deps(manager: BuildManager, graph: Dict[str, State], dependencies.) """ worklist = list(initial) - seen = set() # type: Set[str] + seen: Set[str] = set() unloaded = [] while worklist: node = worklist.pop() @@ -566,7 +566,7 @@ def restore(ids: List[str]) -> None: elif id in graph: del graph[id] - new_modules = [] # type: List[State] + new_modules: List[State] = [] try: if module in graph: del graph[module] @@ -613,7 +613,7 @@ def restore(ids: List[str]) -> None: return BlockedUpdate(module, path, remaining_modules, err.messages) # Merge old and new ASTs. - new_modules_dict = {module: state.tree} # type: Dict[str, Optional[MypyFile]] + new_modules_dict: Dict[str, Optional[MypyFile]] = {module: state.tree} replace_modules_with_new_variants(manager, graph, {orig_module: orig_tree}, new_modules_dict) t1 = time.time() @@ -687,7 +687,7 @@ def delete_module(module_id: str, def dedupe_modules(modules: List[Tuple[str, str]]) -> List[Tuple[str, str]]: - seen = set() # type: Set[str] + seen: Set[str] = set() result = [] for id, path in modules: if id not in seen: @@ -719,7 +719,7 @@ def calculate_active_triggers(manager: BuildManager, For example, if only the signature of function m.f is different in the new symbol table, return {''}. """ - names = set() # type: Set[str] + names: Set[str] = set() for id in new_modules: snapshot1 = old_snapshots.get(id) if snapshot1 is None: @@ -798,7 +798,7 @@ def propagate_changes_using_dependencies( """ num_iter = 0 - remaining_modules = [] # type: List[Tuple[str, str]] + remaining_modules: List[Tuple[str, str]] = [] # Propagate changes until nothing visible has changed during the last # iteration. @@ -856,11 +856,11 @@ def find_targets_recursive( * Dictionary from module id to a set of stale targets. * A set of module ids for unparsed modules with stale targets. """ - result = {} # type: Dict[str, Set[FineGrainedDeferredNode]] + result: Dict[str, Set[FineGrainedDeferredNode]] = {} worklist = triggers - processed = set() # type: Set[str] - stale_protos = set() # type: Set[TypeInfo] - unloaded_files = set() # type: Set[str] + processed: Set[str] = set() + stale_protos: Set[TypeInfo] = set() + unloaded_files: Set[str] = set() # Find AST nodes corresponding to each target. # @@ -950,7 +950,7 @@ def key(node: FineGrainedDeferredNode) -> int: manager.errors.add_error_info(info) # Strip semantic analysis information. - saved_attrs = {} # type: SavedAttributes + saved_attrs: SavedAttributes = {} for deferred in nodes: processed_targets.append(deferred.node.fullname) strip_target(deferred.node, saved_attrs) @@ -1055,8 +1055,8 @@ def not_found() -> None: components = rest.split('.') else: components = [] - node = modules[module] # type: Optional[SymbolNode] - file = None # type: Optional[MypyFile] + node: Optional[SymbolNode] = modules[module] + file: Optional[MypyFile] = None active_class = None for c in components: if isinstance(node, TypeInfo): @@ -1077,7 +1077,7 @@ def not_found() -> None: # A ClassDef target covers the body of the class and everything defined # within it. To get the body we include the entire surrounding target, # typically a module top-level, since we don't support processing class - # bodies as separate entitites for simplicity. + # bodies as separate entities for simplicity. assert file is not None if node.fullname != target: # This is a reference to a different TypeInfo, likely due to a stale dependency. @@ -1086,7 +1086,7 @@ def not_found() -> None: not_found() return [], None result = [FineGrainedDeferredNode(file, None)] - stale_info = None # type: Optional[TypeInfo] + stale_info: Optional[TypeInfo] = None if node.is_protocol: stale_info = node for name, symnode in node.names.items(): @@ -1140,15 +1140,15 @@ def target_from_node(module: str, return '%s.%s' % (module, node.name) -if sys.platform != 'win32': - INIT_SUFFIXES = ('/__init__.py', '/__init__.pyi') # type: Final +if sys.platform != "win32": + INIT_SUFFIXES: Final = ("/__init__.py", "/__init__.pyi") else: - INIT_SUFFIXES = ( + INIT_SUFFIXES: Final = ( os.sep + '__init__.py', os.sep + '__init__.pyi', os.altsep + '__init__.py', os.altsep + '__init__.pyi', - ) # type: Final + ) def refresh_suppressed_submodules( diff --git a/mypy/sharedparse.py b/mypy/sharedparse.py index 88e77ecd0dc2..d8bde1bd253b 100644 --- a/mypy/sharedparse.py +++ b/mypy/sharedparse.py @@ -4,7 +4,7 @@ """Shared logic between our three mypy parser files.""" -_NON_BINARY_MAGIC_METHODS = { +_NON_BINARY_MAGIC_METHODS: Final = { "__abs__", "__call__", "__complex__", @@ -37,16 +37,17 @@ "__setitem__", "__str__", "__unicode__", -} # type: Final +} -MAGIC_METHODS_ALLOWING_KWARGS = { +MAGIC_METHODS_ALLOWING_KWARGS: Final = { "__init__", "__init_subclass__", "__new__", "__call__", -} # type: Final + "__setattr__", +} -BINARY_MAGIC_METHODS = { +BINARY_MAGIC_METHODS: Final = { "__add__", "__and__", "__cmp__", @@ -97,13 +98,13 @@ "__sub__", "__truediv__", "__xor__", -} # type: Final +} assert not (_NON_BINARY_MAGIC_METHODS & BINARY_MAGIC_METHODS) -MAGIC_METHODS = _NON_BINARY_MAGIC_METHODS | BINARY_MAGIC_METHODS # type: Final +MAGIC_METHODS: Final = _NON_BINARY_MAGIC_METHODS | BINARY_MAGIC_METHODS -MAGIC_METHODS_POS_ARGS_ONLY = MAGIC_METHODS - MAGIC_METHODS_ALLOWING_KWARGS # type: Final +MAGIC_METHODS_POS_ARGS_ONLY: Final = MAGIC_METHODS - MAGIC_METHODS_ALLOWING_KWARGS def special_function_elide_names(name: str) -> bool: diff --git a/mypy/sitepkgs.py b/mypy/sitepkgs.py deleted file mode 100644 index 79dd5d80fcf6..000000000000 --- a/mypy/sitepkgs.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import print_function -"""This file is used to find the site packages of a Python executable, which may be Python 2. - -This file MUST remain compatible with Python 2. Since we cannot make any assumptions about the -Python being executed, this module should not use *any* dependencies outside of the standard -library found in Python 2. This file is run each mypy run, so it should be kept as fast as -possible. -""" - -if __name__ == '__main__': - import sys - sys.path = sys.path[1:] # we don't want to pick up mypy.types - -import site - -MYPY = False -if MYPY: - from typing import List - - -def getsitepackages(): - # type: () -> List[str] - if hasattr(site, 'getusersitepackages') and hasattr(site, 'getsitepackages'): - user_dir = site.getusersitepackages() - return site.getsitepackages() + [user_dir] - else: - from distutils.sysconfig import get_python_lib - return [get_python_lib()] - - -if __name__ == '__main__': - print(repr(getsitepackages())) diff --git a/mypy/solve.py b/mypy/solve.py index b89c8f35f350..8a3280e33c0b 100644 --- a/mypy/solve.py +++ b/mypy/solve.py @@ -22,17 +22,17 @@ def solve_constraints(vars: List[TypeVarId], constraints: List[Constraint], pick AnyType. """ # Collect a list of constraints for each type variable. - cmap = defaultdict(list) # type: Dict[TypeVarId, List[Constraint]] + cmap: Dict[TypeVarId, List[Constraint]] = defaultdict(list) for con in constraints: cmap[con.type_var].append(con) - res = [] # type: List[Optional[Type]] + res: List[Optional[Type]] = [] # Solve each type variable separately. for tvar in vars: - bottom = None # type: Optional[Type] - top = None # type: Optional[Type] - candidate = None # type: Optional[Type] + bottom: Optional[Type] = None + top: Optional[Type] = None + candidate: Optional[Type] = None # Process each constraint separately, and calculate the lower and upper # bounds based on constraints. Note that we assume that the constraint diff --git a/mypy/state.py b/mypy/state.py index 0351785d5db2..475559899da6 100644 --- a/mypy/state.py +++ b/mypy/state.py @@ -6,7 +6,7 @@ # Value varies by file being processed strict_optional = False -find_occurrences = None # type: Optional[Tuple[str, str]] +find_occurrences: Optional[Tuple[str, str]] = None @contextmanager @@ -14,5 +14,7 @@ def strict_optional_set(value: bool) -> Iterator[None]: global strict_optional saved = strict_optional strict_optional = value - yield - strict_optional = saved + try: + yield + finally: + strict_optional = saved diff --git a/mypy/stats.py b/mypy/stats.py index 17725ac86bdc..a9769b55e20d 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -24,19 +24,19 @@ from mypy.util import correct_relative_import from mypy.argmap import map_formals_to_actuals -TYPE_EMPTY = 0 # type: Final -TYPE_UNANALYZED = 1 # type: Final # type of non-typechecked code -TYPE_PRECISE = 2 # type: Final -TYPE_IMPRECISE = 3 # type: Final -TYPE_ANY = 4 # type: Final +TYPE_EMPTY: Final = 0 +TYPE_UNANALYZED: Final = 1 # type of non-typechecked code +TYPE_PRECISE: Final = 2 +TYPE_IMPRECISE: Final = 3 +TYPE_ANY: Final = 4 -precision_names = [ +precision_names: Final = [ 'empty', 'unanalyzed', 'precise', 'imprecise', 'any', -] # type: Final +] class StatisticsVisitor(TraverserVisitor): @@ -68,10 +68,10 @@ def __init__(self, self.line = -1 - self.line_map = {} # type: Dict[int, int] + self.line_map: Dict[int, int] = {} - self.type_of_any_counter = Counter() # type: typing.Counter[int] - self.any_line_map = {} # type: Dict[int, List[AnyType]] + self.type_of_any_counter: typing.Counter[int] = Counter() + self.any_line_map: Dict[int, List[AnyType]] = {} # For each scope (top level/function), whether the scope was type checked # (annotated function). @@ -79,7 +79,7 @@ def __init__(self, # TODO: Handle --check-untyped-defs self.checked_scopes = [True] - self.output = [] # type: List[str] + self.output: List[str] = [] TraverserVisitor.__init__(self) diff --git a/mypy/strconv.py b/mypy/strconv.py index 5cc890bd91dc..c63063af0776 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -24,7 +24,7 @@ class StrConv(NodeVisitor[str]): def __init__(self, show_ids: bool = False) -> None: self.show_ids = show_ids - self.id_mapper = None # type: Optional[IdMapper] + self.id_mapper: Optional[IdMapper] = None if show_ids: self.id_mapper = IdMapper() @@ -58,20 +58,20 @@ def func_helper(self, o: 'mypy.nodes.FuncItem') -> List[object]: array with information specific to methods, global functions or anonymous functions. """ - args = [] # type: List[Union[mypy.nodes.Var, Tuple[str, List[mypy.nodes.Node]]]] - extra = [] # type: List[Tuple[str, List[mypy.nodes.Var]]] + args: List[Union[mypy.nodes.Var, Tuple[str, List[mypy.nodes.Node]]]] = [] + extra: List[Tuple[str, List[mypy.nodes.Var]]] = [] for arg in o.arguments: - kind = arg.kind # type: int - if kind in (mypy.nodes.ARG_POS, mypy.nodes.ARG_NAMED): + kind: mypy.nodes.ArgKind = arg.kind + if kind.is_required(): args.append(arg.variable) - elif kind in (mypy.nodes.ARG_OPT, mypy.nodes.ARG_NAMED_OPT): + elif kind.is_optional(): assert arg.initializer is not None args.append(('default', [arg.variable, arg.initializer])) elif kind == mypy.nodes.ARG_STAR: extra.append(('VarArg', [arg.variable])) elif kind == mypy.nodes.ARG_STAR2: extra.append(('DictVarArg', [arg.variable])) - a = [] # type: List[Any] + a: List[Any] = [] if args: a.append(('Args', args)) if o.type: @@ -86,7 +86,7 @@ def func_helper(self, o: 'mypy.nodes.FuncItem') -> List[object]: def visit_mypy_file(self, o: 'mypy.nodes.MypyFile') -> str: # Skip implicit definitions. - a = [o.defs] # type: List[Any] + a: List[Any] = [o.defs] if o.is_bom: a.insert(0, 'BOM') # Omit path to special file with name "main". This is used to simplify @@ -141,7 +141,7 @@ def visit_func_def(self, o: 'mypy.nodes.FuncDef') -> str: return self.dump(a, o) def visit_overloaded_func_def(self, o: 'mypy.nodes.OverloadedFuncDef') -> str: - a = o.items[:] # type: Any + a: Any = o.items[:] if o.type: a.insert(0, o.type) if o.impl: @@ -203,7 +203,7 @@ def visit_expression_stmt(self, o: 'mypy.nodes.ExpressionStmt') -> str: return self.dump([o.expr], o) def visit_assignment_stmt(self, o: 'mypy.nodes.AssignmentStmt') -> str: - a = [] # type: List[Any] + a: List[Any] = [] if len(o.lvalues) > 1: a = [('Lvalues', o.lvalues)] else: @@ -217,13 +217,13 @@ def visit_operator_assignment_stmt(self, o: 'mypy.nodes.OperatorAssignmentStmt') return self.dump([o.op, o.lvalue, o.rvalue], o) def visit_while_stmt(self, o: 'mypy.nodes.WhileStmt') -> str: - a = [o.expr, o.body] # type: List[Any] + a: List[Any] = [o.expr, o.body] if o.else_body: a.append(('Else', o.else_body.body)) return self.dump(a, o) def visit_for_stmt(self, o: 'mypy.nodes.ForStmt') -> str: - a = [] # type: List[Any] + a: List[Any] = [] if o.is_async: a.append(('Async', '')) a.append(o.index) @@ -238,7 +238,7 @@ def visit_return_stmt(self, o: 'mypy.nodes.ReturnStmt') -> str: return self.dump([o.expr], o) def visit_if_stmt(self, o: 'mypy.nodes.IfStmt') -> str: - a = [] # type: List[Any] + a: List[Any] = [] for i in range(len(o.expr)): a.append(('If', [o.expr[i]])) a.append(('Then', o.body[i].body)) @@ -273,7 +273,7 @@ def visit_del_stmt(self, o: 'mypy.nodes.DelStmt') -> str: return self.dump([o.expr], o) def visit_try_stmt(self, o: 'mypy.nodes.TryStmt') -> str: - a = [o.body] # type: List[Any] + a: List[Any] = [o.body] for i in range(len(o.vars)): a.append(o.types[i]) @@ -289,7 +289,7 @@ def visit_try_stmt(self, o: 'mypy.nodes.TryStmt') -> str: return self.dump(a, o) def visit_with_stmt(self, o: 'mypy.nodes.WithStmt') -> str: - a = [] # type: List[Any] + a: List[Any] = [] if o.is_async: a.append(('Async', '')) for i in range(len(o.expr)): @@ -301,7 +301,7 @@ def visit_with_stmt(self, o: 'mypy.nodes.WithStmt') -> str: return self.dump(a + [o.body], o) def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> str: - a = o.args[:] # type: List[Any] + a: List[Any] = o.args[:] if o.target: a.append(('Target', [o.target])) if o.newline: @@ -393,8 +393,8 @@ def visit_yield_from_expr(self, o: 'mypy.nodes.YieldFromExpr') -> str: def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> str: if o.analyzed: return o.analyzed.accept(self) - args = [] # type: List[mypy.nodes.Expression] - extra = [] # type: List[Union[str, Tuple[str, List[Any]]]] + args: List[mypy.nodes.Expression] = [] + extra: List[Union[str, Tuple[str, List[Any]]]] = [] for i, kind in enumerate(o.arg_kinds): if kind in [mypy.nodes.ARG_POS, mypy.nodes.ARG_STAR]: args.append(o.args[i]) @@ -405,8 +405,8 @@ def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> str: elif kind == mypy.nodes.ARG_STAR2: extra.append(('DictVarArg', [o.args[i]])) else: - raise RuntimeError('unknown kind %d' % kind) - a = [o.callee, ('Args', args)] # type: List[Any] + raise RuntimeError("unknown kind %s" % kind) + a: List[Any] = [o.callee, ("Args", args)] return self.dump(a + extra, o) def visit_op_expr(self, o: 'mypy.nodes.OpExpr') -> str: @@ -456,7 +456,8 @@ def visit_type_application(self, o: 'mypy.nodes.TypeApplication') -> str: def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> str: import mypy.types - a = [] # type: List[Any] + + a: List[Any] = [] if o.variance == mypy.nodes.COVARIANT: a += ['Variance(COVARIANT)'] if o.variance == mypy.nodes.CONTRAVARIANT: @@ -469,7 +470,8 @@ def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> str: def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> str: import mypy.types - a = [] # type: List[Any] + + a: List[Any] = [] if o.variance == mypy.nodes.COVARIANT: a += ['Variance(COVARIANT)'] if o.variance == mypy.nodes.CONTRAVARIANT: @@ -522,7 +524,7 @@ def visit_conditional_expr(self, o: 'mypy.nodes.ConditionalExpr') -> str: return self.dump([('Condition', [o.cond]), o.if_expr, o.else_expr], o) def visit_slice_expr(self, o: 'mypy.nodes.SliceExpr') -> str: - a = [o.begin_index, o.end_index, o.stride] # type: List[Any] + a: List[Any] = [o.begin_index, o.end_index, o.stride] if not a[0]: a[0] = '' if not a[1]: @@ -550,7 +552,7 @@ def dump_tagged(nodes: Sequence[object], tag: Optional[str], str_conv: 'StrConv' """ from mypy.types import Type, TypeStrVisitor - a = [] # type: List[str] + a: List[str] = [] if tag: a.append(tag + '(') for n in nodes: diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 801e661440d2..1c31223d26a1 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -17,8 +17,8 @@ Sig = Tuple[str, str] -_TYPE_RE = re.compile(r'^[a-zA-Z_][\w\[\], ]*(\.[a-zA-Z_][\w\[\], ]*)*$') # type: Final -_ARG_NAME_RE = re.compile(r'\**[A-Za-z_][A-Za-z0-9_]*$') # type: Final +_TYPE_RE: Final = re.compile(r"^[a-zA-Z_][\w\[\], ]*(\.[a-zA-Z_][\w\[\], ]*)*$") +_ARG_NAME_RE: Final = re.compile(r"\**[A-Za-z_][A-Za-z0-9_]*$") def is_valid_type(s: str) -> bool: @@ -60,13 +60,13 @@ def __eq__(self, other: Any) -> bool: # States of the docstring parser. -STATE_INIT = 1 # type: Final -STATE_FUNCTION_NAME = 2 # type: Final -STATE_ARGUMENT_LIST = 3 # type: Final -STATE_ARGUMENT_TYPE = 4 # type: Final -STATE_ARGUMENT_DEFAULT = 5 # type: Final -STATE_RETURN_VALUE = 6 # type: Final -STATE_OPEN_BRACKET = 7 # type: Final # For generic types. +STATE_INIT: Final = 1 +STATE_FUNCTION_NAME: Final = 2 +STATE_ARGUMENT_LIST: Final = 3 +STATE_ARGUMENT_TYPE: Final = 4 +STATE_ARGUMENT_DEFAULT: Final = 5 +STATE_RETURN_VALUE: Final = 6 +STATE_OPEN_BRACKET: Final = 7 # For generic types. class DocStringParser: @@ -77,14 +77,14 @@ def __init__(self, function_name: str) -> None: self.function_name = function_name self.state = [STATE_INIT] self.accumulator = "" - self.arg_type = None # type: Optional[str] + self.arg_type: Optional[str] = None self.arg_name = "" - self.arg_default = None # type: Optional[str] + self.arg_default: Optional[str] = None self.ret_type = "Any" self.found = False - self.args = [] # type: List[ArgSig] + self.args: List[ArgSig] = [] # Valid signatures found so far. - self.signatures = [] # type: List[FunctionSig] + self.signatures: List[FunctionSig] = [] def add_token(self, token: tokenize.TokenInfo) -> None: """Process next token from the token stream.""" @@ -148,13 +148,16 @@ def add_token(self, token: tokenize.TokenInfo) -> None: if token.string == ')': self.state.pop() - try: - self.args.append(ArgSig(name=self.arg_name, type=self.arg_type, - default=bool(self.arg_default))) - except ValueError: - # wrong type, use Any - self.args.append(ArgSig(name=self.arg_name, type=None, - default=bool(self.arg_default))) + + # arg_name is empty when there are no args. e.g. func() + if self.arg_name: + try: + self.args.append(ArgSig(name=self.arg_name, type=self.arg_type, + default=bool(self.arg_default))) + except ValueError: + # wrong type, use Any + self.args.append(ArgSig(name=self.arg_name, type=None, + default=bool(self.arg_default))) self.arg_name = "" self.arg_type = None self.arg_default = None @@ -303,7 +306,7 @@ def parse_signature(sig: str) -> Optional[Tuple[str, def build_signature(positional: Sequence[str], optional: Sequence[str]) -> str: """Build function signature from lists of positional and optional argument names.""" - args = [] # type: MutableSequence[str] + args: MutableSequence[str] = [] args.extend(positional) for arg in optional: if arg.startswith('*'): @@ -342,7 +345,7 @@ def parse_all_signatures(lines: Sequence[str]) -> Tuple[List[Sig], def find_unique_signatures(sigs: Sequence[Sig]) -> List[Sig]: """Remove names with duplicate found signatures.""" - sig_map = {} # type: MutableMapping[str, List[str]] + sig_map: MutableMapping[str, List[str]] = {} for name, sig in sigs: sig_map.setdefault(name, []).append(sig) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index a12cd969e9ca..b0a2c4e64587 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -60,7 +60,6 @@ import mypy.build import mypy.parse -import mypy.errors import mypy.traverser import mypy.mixedtraverser import mypy.util @@ -72,8 +71,8 @@ Expression, IntExpr, UnaryExpr, StrExpr, BytesExpr, NameExpr, FloatExpr, MemberExpr, TupleExpr, ListExpr, ComparisonExpr, CallExpr, IndexExpr, EllipsisExpr, ClassDef, MypyFile, Decorator, AssignmentStmt, TypeInfo, - IfStmt, ImportAll, ImportFrom, Import, FuncDef, FuncBase, TempNode, Block, - Statement, OverloadedFuncDef, ARG_POS, ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT + IfStmt, ImportAll, ImportFrom, Import, FuncDef, FuncBase, Block, + Statement, OverloadedFuncDef, ARG_POS, ARG_STAR, ARG_STAR2, ARG_NAMED, ) from mypy.stubgenc import generate_stub_for_c_module from mypy.stubutil import ( @@ -85,43 +84,43 @@ from mypy.options import Options as MypyOptions from mypy.types import ( Type, TypeStrVisitor, CallableType, UnboundType, NoneType, TupleType, TypeList, Instance, - AnyType + AnyType, get_proper_type ) from mypy.visitor import NodeVisitor from mypy.find_sources import create_source_list, InvalidSourceList from mypy.build import build from mypy.errors import CompileError, Errors -from mypy.traverser import has_return_statement +from mypy.traverser import all_yield_expressions, has_return_statement, has_yield_expression from mypy.moduleinspect import ModuleInspect # Common ways of naming package containing vendored modules. -VENDOR_PACKAGES = [ +VENDOR_PACKAGES: Final = [ 'packages', 'vendor', 'vendored', '_vendor', '_vendored_packages', -] # type: Final +] # Avoid some file names that are unnecessary or likely to cause trouble (\n for end of path). -BLACKLIST = [ +BLACKLIST: Final = [ '/six.py\n', # Likely vendored six; too dynamic for us to handle '/vendored/', # Vendored packages '/vendor/', # Vendored packages '/_vendor/', '/_vendored_packages/', -] # type: Final +] # Special-cased names that are implicitly exported from the stub (from m import y as y). -EXTRA_EXPORTED = { +EXTRA_EXPORTED: Final = { 'pyasn1_modules.rfc2437.univ', 'pyasn1_modules.rfc2459.char', 'pyasn1_modules.rfc2459.univ', -} # type: Final +} # These names should be omitted from generated stubs. -IGNORED_DUNDERS = { +IGNORED_DUNDERS: Final = { '__all__', '__author__', '__version__', @@ -137,10 +136,10 @@ '__getstate__', '__setstate__', '__slots__', -} # type: Final +} # These methods are expected to always return a non-trivial value. -METHODS_WITH_RETURN_VALUE = { +METHODS_WITH_RETURN_VALUE: Final = { '__ne__', '__eq__', '__lt__', @@ -149,7 +148,7 @@ '__ge__', '__hash__', '__iter__', -} # type: Final +} class Options: @@ -202,7 +201,7 @@ def __init__(self, module: str, path: Optional[str] = None, runtime_all: Optional[List[str]] = None) -> None: self.source = BuildSource(path, module, None) self.runtime_all = runtime_all - self.ast = None # type: Optional[MypyFile] + self.ast: Optional[MypyFile] = None @property def module(self) -> str: @@ -215,17 +214,17 @@ def path(self) -> Optional[str]: # What was generated previously in the stub file. We keep track of these to generate # nicely formatted output (add empty line between non-empty classes, for example). -EMPTY = 'EMPTY' # type: Final -FUNC = 'FUNC' # type: Final -CLASS = 'CLASS' # type: Final -EMPTY_CLASS = 'EMPTY_CLASS' # type: Final -VAR = 'VAR' # type: Final -NOT_IN_ALL = 'NOT_IN_ALL' # type: Final +EMPTY: Final = "EMPTY" +FUNC: Final = "FUNC" +CLASS: Final = "CLASS" +EMPTY_CLASS: Final = "EMPTY_CLASS" +VAR: Final = "VAR" +NOT_IN_ALL: Final = "NOT_IN_ALL" # Indicates that we failed to generate a reasonable output # for a given node. These should be manually replaced by a user. -ERROR_MARKER = '' # type: Final +ERROR_MARKER: Final = "" class AnnotationPrinter(TypeStrVisitor): @@ -256,7 +255,7 @@ def visit_unbound_type(self, t: UnboundType) -> str: s = t.name self.stubgen.import_tracker.require_name(s) if t.args: - s += '[{}]'.format(self.list_str(t.args)) + s += '[{}]'.format(self.args_str(t.args)) return s def visit_none_type(self, t: NoneType) -> str: @@ -265,6 +264,22 @@ def visit_none_type(self, t: NoneType) -> str: def visit_type_list(self, t: TypeList) -> str: return '[{}]'.format(self.list_str(t.items)) + def args_str(self, args: Iterable[Type]) -> str: + """Convert an array of arguments to strings and join the results with commas. + + The main difference from list_str is the preservation of quotes for string + arguments + """ + types = ['builtins.bytes', 'builtins.unicode'] + res = [] + for arg in args: + arg_str = arg.accept(self) + if isinstance(arg, UnboundType) and arg.original_str_fallback in types: + res.append("'{}'".format(arg_str)) + else: + res.append(arg_str) + return ', '.join(res) + class AliasPrinter(NodeVisitor[str]): """Visitor used to collect type aliases _and_ type variable definitions. @@ -290,7 +305,7 @@ def visit_call_expr(self, node: CallExpr) -> str: elif kind == ARG_NAMED: args.append('{}={}'.format(name, arg.accept(self))) else: - raise ValueError("Unknown argument kind %d in call" % kind) + raise ValueError("Unknown argument kind %s in call" % kind) return "{}({})".format(callee, ", ".join(args)) def visit_name_expr(self, node: NameExpr) -> str: @@ -298,7 +313,7 @@ def visit_name_expr(self, node: NameExpr) -> str: return node.name def visit_member_expr(self, o: MemberExpr) -> str: - node = o # type: Expression + node: Expression = o trailer = '' while isinstance(node, MemberExpr): trailer = '.' + node.name + trailer @@ -337,27 +352,27 @@ def __init__(self) -> None: # 'import m' ==> module_for['m'] == None # 'import pkg.m' ==> module_for['pkg.m'] == None # ==> module_for['pkg'] == None - self.module_for = {} # type: Dict[str, Optional[str]] + self.module_for: Dict[str, Optional[str]] = {} # direct_imports['foo'] is the module path used when the name 'foo' was added to the # namespace. # import foo.bar.baz ==> direct_imports['foo'] == 'foo.bar.baz' # ==> direct_imports['foo.bar'] == 'foo.bar.baz' # ==> direct_imports['foo.bar.baz'] == 'foo.bar.baz' - self.direct_imports = {} # type: Dict[str, str] + self.direct_imports: Dict[str, str] = {} # reverse_alias['foo'] is the name that 'foo' had originally when imported with an # alias; examples # 'import numpy as np' ==> reverse_alias['np'] == 'numpy' # 'import foo.bar as bar' ==> reverse_alias['bar'] == 'foo.bar' # 'from decimal import Decimal as D' ==> reverse_alias['D'] == 'Decimal' - self.reverse_alias = {} # type: Dict[str, str] + self.reverse_alias: Dict[str, str] = {} # required_names is the set of names that are actually used in a type annotation - self.required_names = set() # type: Set[str] + self.required_names: Set[str] = set() # Names that should be reexported if they come from another module - self.reexports = set() # type: Set[str] + self.reexports: Set[str] = set() def add_import_from(self, module: str, names: List[Tuple[str, Optional[str]]]) -> None: for name, alias in names: @@ -405,7 +420,7 @@ def import_lines(self) -> List[str]: # To summarize multiple names imported from a same module, we collect those # in the `module_map` dictionary, mapping a module path to the list of names that should # be imported from it. the names can also be alias in the form 'original as alias' - module_map = defaultdict(list) # type: Mapping[str, List[str]] + module_map: Mapping[str, List[str]] = defaultdict(list) for name in sorted(self.required_names): # If we haven't seen this name in an import statement, ignore it @@ -452,7 +467,7 @@ class DefinitionFinder(mypy.traverser.TraverserVisitor): def __init__(self) -> None: # Short names of things defined at the top level. - self.names = set() # type: Set[str] + self.names: Set[str] = set() def visit_class_def(self, o: ClassDef) -> None: # Don't recurse into classes, as we only keep track of top-level definitions. @@ -476,7 +491,7 @@ class ReferenceFinder(mypy.mixedtraverser.MixedTraverserVisitor): def __init__(self) -> None: # Short names of things defined at the top level. - self.refs = set() # type: Set[str] + self.refs: Set[str] = set() def visit_block(self, block: Block) -> None: if not block.is_unreachable: @@ -518,16 +533,16 @@ def __init__(self, export_less: bool = False) -> None: # Best known value of __all__. self._all_ = _all_ - self._output = [] # type: List[str] - self._decorators = [] # type: List[str] - self._import_lines = [] # type: List[str] + self._output: List[str] = [] + self._decorators: List[str] = [] + self._import_lines: List[str] = [] # Current indent level (indent is hardcoded to 4 spaces). self._indent = '' # Stack of defined variables (per scope). - self._vars = [[]] # type: List[List[str]] + self._vars: List[List[str]] = [[]] # What was generated previously in the stub file. self._state = EMPTY - self._toplevel_names = [] # type: List[str] + self._toplevel_names: List[str] = [] self._pyversion = pyversion self._include_private = include_private self.import_tracker = ImportTracker() @@ -536,27 +551,31 @@ def __init__(self, # Disable implicit exports of package-internal imports? self.export_less = export_less # Add imports that could be implicitly generated - self.import_tracker.add_import_from("collections", [("namedtuple", None)]) + self.import_tracker.add_import_from("typing", [("NamedTuple", None)]) # Names in __all__ are required for name in _all_ or (): if name not in IGNORED_DUNDERS: self.import_tracker.reexport(name) - self.defined_names = set() # type: Set[str] + self.defined_names: Set[str] = set() # Short names of methods defined in the body of the current class - self.method_names = set() # type: Set[str] + self.method_names: Set[str] = set() def visit_mypy_file(self, o: MypyFile) -> None: self.module = o.fullname # Current module being processed self.path = o.path self.defined_names = find_defined_names(o) self.referenced_names = find_referenced_names(o) - typing_imports = ["Any", "Optional", "TypeVar"] - for t in typing_imports: - if t not in self.defined_names: - alias = None - else: - alias = '_' + t - self.import_tracker.add_import_from("typing", [(t, alias)]) + known_imports = { + "typing": ["Any", "TypeVar"], + "collections.abc": ["Generator"], + } + for pkg, imports in known_imports.items(): + for t in imports: + if t not in self.defined_names: + alias = None + else: + alias = '_' + t + self.import_tracker.add_import_from(pkg, [(t, alias)]) super().visit_mypy_file(o) undefined_names = [name for name in self._all_ or [] if name not in self._toplevel_names] @@ -613,7 +632,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, self.clear_decorators() self.add("%s%sdef %s(" % (self._indent, 'async ' if o.is_coroutine else '', o.name)) self.record_name(o.name) - args = [] # type: List[str] + args: List[str] = [] for i, arg_ in enumerate(o.arguments): var = arg_.variable kind = arg_.kind @@ -624,26 +643,23 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, # name their 0th argument other than self/cls is_self_arg = i == 0 and name == 'self' is_cls_arg = i == 0 and name == 'cls' - if (annotated_type is None - and not arg_.initializer - and not is_self_arg - and not is_cls_arg): - self.add_typing_import("Any") - annotation = ": {}".format(self.typing_name("Any")) - elif annotated_type and not is_self_arg and not is_cls_arg: - annotation = ": {}".format(self.print_annotation(annotated_type)) - else: - annotation = "" + annotation = "" + if annotated_type and not is_self_arg and not is_cls_arg: + # Luckily, an argument explicitly annotated with "Any" has + # type "UnboundType" and will not match. + if not isinstance(get_proper_type(annotated_type), AnyType): + annotation = ": {}".format(self.print_annotation(annotated_type)) if arg_.initializer: - initializer = '...' - if kind in (ARG_NAMED, ARG_NAMED_OPT) and not any(arg.startswith('*') - for arg in args): + if kind.is_named() and not any(arg.startswith('*') for arg in args): args.append('*') if not annotation: - typename = self.get_str_type_of_node(arg_.initializer, True) - annotation = ': {} = ...'.format(typename) + typename = self.get_str_type_of_node(arg_.initializer, True, False) + if typename == '': + annotation = '=...' + else: + annotation = ': {} = ...'.format(typename) else: - annotation += '={}'.format(initializer) + annotation += ' = ...' arg = name + annotation elif kind == ARG_STAR: arg = '*%s%s' % (name, annotation) @@ -654,12 +670,33 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, args.append(arg) retname = None if o.name != '__init__' and isinstance(o.unanalyzed_type, CallableType): - retname = self.print_annotation(o.unanalyzed_type.ret_type) + if isinstance(get_proper_type(o.unanalyzed_type.ret_type), AnyType): + # Luckily, a return type explicitly annotated with "Any" has + # type "UnboundType" and will enter the else branch. + retname = None # implicit Any + else: + retname = self.print_annotation(o.unanalyzed_type.ret_type) elif isinstance(o, FuncDef) and (o.is_abstract or o.name in METHODS_WITH_RETURN_VALUE): # Always assume abstract methods return Any unless explicitly annotated. Also # some dunder methods should not have a None return type. - retname = self.typing_name('Any') - self.add_typing_import("Any") + retname = None # implicit Any + elif has_yield_expression(o): + self.add_abc_import('Generator') + yield_name = 'None' + send_name = 'None' + return_name = 'None' + for expr, in_assignment in all_yield_expressions(o): + if expr.expr is not None and not self.is_none_expr(expr.expr): + self.add_typing_import('Any') + yield_name = 'Any' + if in_assignment: + self.add_typing_import('Any') + send_name = 'Any' + if has_return_statement(o): + self.add_typing_import('Any') + return_name = 'Any' + generator_name = self.typing_name('Generator') + retname = f'{generator_name}[{yield_name}, {send_name}, {return_name}]' elif not has_return_statement(o) and not is_abstract: retname = 'None' retfield = '' @@ -670,6 +707,9 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, self.add("){}: ...\n".format(retfield)) self._state = FUNC + def is_none_expr(self, expr: Expression) -> bool: + return isinstance(expr, NameExpr) and expr.name == "None" + def visit_decorator(self, o: Decorator) -> None: if self.is_private_name(o.func.name, o.func.fullname): return @@ -678,7 +718,7 @@ def visit_decorator(self, o: Decorator) -> None: self.visit_func_def(o.func, is_abstract=is_abstract) def process_decorator(self, o: Decorator) -> Tuple[bool, bool]: - """Process a series of decorataors. + """Process a series of decorators. Only preserve certain special decorators such as @abstractmethod. @@ -792,7 +832,7 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> def visit_class_def(self, o: ClassDef) -> None: self.method_names = find_method_names(o.defs.body) - sep = None # type: Optional[int] + sep: Optional[int] = None if not self._indent and self._state != EMPTY: sep = len(self._output) self.add('\n') @@ -830,7 +870,7 @@ def visit_class_def(self, o: ClassDef) -> None: def get_base_types(self, cdef: ClassDef) -> List[str]: """Get list of base classes for a class.""" - base_types = [] # type: List[str] + base_types: List[str] = [] for base in cdef.base_type_exprs: if isinstance(base, NameExpr): if base.name != 'object': @@ -866,7 +906,7 @@ def visit_assignment_stmt(self, o: AssignmentStmt) -> None: if isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr): items = lvalue.items if isinstance(o.unanalyzed_type, TupleType): # type: ignore - annotations = o.unanalyzed_type.items # type: Iterable[Optional[Type]] + annotations: Iterable[Optional[Type]] = o.unanalyzed_type.items else: annotations = [None] * len(items) else: @@ -900,18 +940,24 @@ def is_namedtuple(self, expr: Expression) -> bool: def process_namedtuple(self, lvalue: NameExpr, rvalue: CallExpr) -> None: if self._state != EMPTY: self.add('\n') - name = repr(getattr(rvalue.args[0], 'value', ERROR_MARKER)) if isinstance(rvalue.args[1], StrExpr): - items = repr(rvalue.args[1].value) + items = rvalue.args[1].value.replace(',', ' ').split() elif isinstance(rvalue.args[1], (ListExpr, TupleExpr)): list_items = cast(List[StrExpr], rvalue.args[1].items) - items = '[%s]' % ', '.join(repr(item.value) for item in list_items) + items = [item.value for item in list_items] else: self.add('%s%s: Any' % (self._indent, lvalue.name)) self.import_tracker.require_name('Any') return - self.import_tracker.require_name('namedtuple') - self.add('%s%s = namedtuple(%s, %s)\n' % (self._indent, lvalue.name, name, items)) + self.import_tracker.require_name('NamedTuple') + self.add('{}class {}(NamedTuple):'.format(self._indent, lvalue.name)) + if len(items) == 0: + self.add(' ...\n') + else: + self.import_tracker.require_name('Any') + self.add('\n') + for item in items: + self.add('{} {}: Any\n'.format(self._indent, item)) self._state = CLASS def is_alias_expression(self, expr: Expression, top_level: bool = True) -> bool: @@ -978,7 +1024,7 @@ def visit_import_all(self, o: ImportAll) -> None: self.add_import_line('from %s%s import *\n' % ('.' * o.relative, o.id)) def visit_import_from(self, o: ImportFrom) -> None: - exported_names = set() # type: Set[str] + exported_names: Set[str] = set() import_names = [] module, relative = translate_module_name(o.id, o.relative) if self.module: @@ -1031,7 +1077,7 @@ def visit_import_from(self, o: ImportFrom) -> None: self.record_name(alias or name) if self._all_: - # Include import froms that import names defined in __all__. + # Include "import from"s that import names defined in __all__. names = [name for name, alias in o.names if name in self._all_ and alias is None and name not in IGNORED_DUNDERS] exported_names.update(names) @@ -1070,9 +1116,7 @@ def get_init(self, lvalue: str, rvalue: Expression, typename += '[{}]'.format(final_arg) else: typename = self.get_str_type_of_node(rvalue) - has_rhs = not (isinstance(rvalue, TempNode) and rvalue.no_rhs) - initializer = " = ..." if has_rhs and not self.is_top_level() else "" - return '%s%s: %s%s\n' % (self._indent, lvalue, typename, initializer) + return '%s%s: %s\n' % (self._indent, lvalue, typename) def add(self, string: str) -> None: """Add text to generated stub.""" @@ -1101,6 +1145,14 @@ def add_typing_import(self, name: str) -> None: name = self.typing_name(name) self.import_tracker.require_name(name) + def add_abc_import(self, name: str) -> None: + """Add a name to be imported from collections.abc, unless it's imported already. + + The import will be internal to the stub. + """ + name = self.typing_name(name) + self.import_tracker.require_name(name) + def add_import_line(self, line: str) -> None: """Add a line of text to the import section, unless it's already there.""" if line not in self._import_lines: @@ -1144,7 +1196,8 @@ def is_private_member(self, fullname: str) -> bool: return False def get_str_type_of_node(self, rvalue: Expression, - can_infer_optional: bool = False) -> str: + can_infer_optional: bool = False, + can_be_any: bool = True) -> str: if isinstance(rvalue, IntExpr): return 'int' if isinstance(rvalue, StrExpr): @@ -1159,12 +1212,13 @@ def get_str_type_of_node(self, rvalue: Expression, return 'bool' if can_infer_optional and \ isinstance(rvalue, NameExpr) and rvalue.name == 'None': - self.add_typing_import('Optional') self.add_typing_import('Any') - return '{}[{}]'.format(self.typing_name('Optional'), - self.typing_name('Any')) - self.add_typing_import('Any') - return self.typing_name('Any') + return '{} | None'.format(self.typing_name('Any')) + if can_be_any: + self.add_typing_import('Any') + return self.typing_name('Any') + else: + return '' def print_annotation(self, t: Type) -> str: printer = AnnotationPrinter(self) @@ -1203,7 +1257,7 @@ def find_method_names(defs: List[Statement]) -> Set[str]: class SelfTraverser(mypy.traverser.TraverserVisitor): def __init__(self) -> None: - self.results = [] # type: List[Tuple[str, Expression]] + self.results: List[Tuple[str, Expression]] = [] def visit_assignment_stmt(self, o: AssignmentStmt) -> None: lvalue = o.lvalues[0] @@ -1260,7 +1314,7 @@ def collect_build_targets(options: Options, mypy_opts: MypyOptions) -> Tuple[Lis options.packages, options.search_path, options.pyversion) - c_modules = [] # type: List[StubSource] + c_modules: List[StubSource] = [] else: # Using imports is the default, since we can also find C modules. py_modules, c_modules = find_module_paths_using_imports(options.modules, @@ -1295,8 +1349,8 @@ def find_module_paths_using_imports(modules: List[str], This function uses runtime Python imports to get the information. """ with ModuleInspect() as inspect: - py_modules = [] # type: List[StubSource] - c_modules = [] # type: List[StubSource] + py_modules: List[StubSource] = [] + c_modules: List[StubSource] = [] found = list(walk_packages(inspect, packages, verbose)) modules = modules + found modules = [mod @@ -1370,7 +1424,7 @@ def find_module_paths_using_search(modules: List[str], packages: List[str], This is used if user passes --no-import, and will not find C modules. Exit if some of the modules or packages can't be found. """ - result = [] # type: List[StubSource] + result: List[StubSource] = [] typeshed_path = default_lib_path(mypy.build.default_data_dir(), pyversion, None) search_paths = SearchPaths(('.',) + tuple(search_path), (), (), tuple(typeshed_path)) cache = FindModuleCache(search_paths, fscache=None, options=None) @@ -1487,8 +1541,8 @@ def collect_docs_signatures(doc_dir: str) -> Tuple[Dict[str, str], Dict[str, str Return a tuple (function signatures, class signatures). Currently only used for C modules. """ - all_sigs = [] # type: List[Sig] - all_class_sigs = [] # type: List[Sig] + all_sigs: List[Sig] = [] + all_class_sigs: List[Sig] = [] for path in glob.glob('%s/*.rst' % doc_dir): with open(path) as f: loc_sigs, loc_class_sigs = parse_all_signatures(f.readlines()) @@ -1607,7 +1661,7 @@ def parse_options(args: List[str]) -> Options: ns = parser.parse_args(args) - pyversion = defaults.PYTHON2_VERSION if ns.py2 else defaults.PYTHON3_VERSION + pyversion = defaults.PYTHON2_VERSION if ns.py2 else sys.version_info[:2] if not ns.interpreter: ns.interpreter = sys.executable if pyversion[0] == 3 else default_py2_interpreter() if ns.modules + ns.packages and ns.files: diff --git a/mypy/stubgenc.py b/mypy/stubgenc.py index 279deb19c96f..0eeb39f102dc 100755 --- a/mypy/stubgenc.py +++ b/mypy/stubgenc.py @@ -10,6 +10,7 @@ import re from typing import List, Dict, Tuple, Optional, Mapping, Any, Set from types import ModuleType +from typing_extensions import Final from mypy.moduleinspect import is_c_module from mypy.stubdoc import ( @@ -19,7 +20,7 @@ ) # Members of the typing module to consider for importing by default. -_DEFAULT_TYPING_IMPORTS = ( +_DEFAULT_TYPING_IMPORTS: Final = ( 'Any', 'Callable', 'ClassVar', @@ -50,15 +51,15 @@ def generate_stub_for_c_module(module_name: str, subdir = os.path.dirname(target) if subdir and not os.path.isdir(subdir): os.makedirs(subdir) - imports = [] # type: List[str] - functions = [] # type: List[str] + imports: List[str] = [] + functions: List[str] = [] done = set() items = sorted(module.__dict__.items(), key=lambda x: x[0]) for name, obj in items: if is_c_function(obj): generate_c_function_stub(module, name, obj, functions, imports=imports, sigs=sigs) done.add(name) - types = [] # type: List[str] + types: List[str] = [] for name, obj in items: if name.startswith('__') and name.endswith('__'): continue @@ -159,11 +160,19 @@ def generate_c_function_stub(module: ModuleType, ret_type = 'None' if name == '__init__' and class_name else 'Any' - if (name in ('__new__', '__init__') and name not in sigs and class_name and - class_name in class_sigs): - inferred = [FunctionSig(name=name, - args=infer_arg_sig_from_anon_docstring(class_sigs[class_name]), - ret_type=ret_type)] # type: Optional[List[FunctionSig]] + if ( + name in ("__new__", "__init__") + and name not in sigs + and class_name + and class_name in class_sigs + ): + inferred: Optional[List[FunctionSig]] = [ + FunctionSig( + name=name, + args=infer_arg_sig_from_anon_docstring(class_sigs[class_name]), + ret_type=ret_type, + ) + ] else: docstr = getattr(obj, '__doc__', None) inferred = infer_sig_from_docstring(docstr, name) @@ -174,12 +183,17 @@ def generate_c_function_stub(module: ModuleType, del inferred[-1] if not inferred: if class_name and name not in sigs: - inferred = [FunctionSig(name, args=infer_method_sig(name), ret_type=ret_type)] + inferred = [FunctionSig(name, args=infer_method_sig(name, self_var), + ret_type=ret_type)] else: inferred = [FunctionSig(name=name, args=infer_arg_sig_from_anon_docstring( sigs.get(name, '(*args, **kwargs)')), ret_type=ret_type)] + elif class_name and self_var: + args = inferred[0].args + if not args or args[0].name != self_var: + args.insert(0, ArgSig(name=self_var)) is_overloaded = len(inferred) > 1 if inferred else False if is_overloaded: @@ -310,14 +324,14 @@ def generate_c_type_stub(module: ModuleType, """ # typeshed gives obj.__dict__ the not quite correct type Dict[str, Any] # (it could be a mappingproxy!), which makes mypyc mad, so obfuscate it. - obj_dict = getattr(obj, '__dict__') # type: Mapping[str, Any] # noqa + obj_dict: Mapping[str, Any] = getattr(obj, "__dict__") # noqa items = sorted(obj_dict.items(), key=lambda x: method_name_sort_key(x[0])) - methods = [] # type: List[str] - types = [] # type: List[str] - static_properties = [] # type: List[str] - rw_properties = [] # type: List[str] - ro_properties = [] # type: List[str] - done = set() # type: Set[str] + methods: List[str] = [] + types: List[str] = [] + static_properties: List[str] = [] + rw_properties: List[str] = [] + ro_properties: List[str] = [] + done: Set[str] = set() for attr, value in items: if is_c_method(value) or is_c_classmethod(value): done.add(attr) @@ -365,7 +379,7 @@ def generate_c_type_stub(module: ModuleType, # remove the class itself all_bases = all_bases[1:] # Remove base classes of other bases as redundant. - bases = [] # type: List[type] + bases: List[type] = [] for base in all_bases: if not any(issubclass(b, base) for b in bases): bases.append(base) @@ -430,8 +444,8 @@ def is_skipped_attribute(attr: str) -> bool: ) -def infer_method_sig(name: str) -> List[ArgSig]: - args = None # type: Optional[List[ArgSig]] +def infer_method_sig(name: str, self_var: Optional[str] = None) -> List[ArgSig]: + args: Optional[List[ArgSig]] = None if name.startswith('__') and name.endswith('__'): name = name[2:-2] if name in ('hash', 'iter', 'next', 'sizeof', 'copy', 'deepcopy', 'reduce', 'getinitargs', @@ -479,4 +493,4 @@ def infer_method_sig(name: str) -> List[ArgSig]: if args is None: args = [ArgSig(name='*args'), ArgSig(name='**kwargs')] - return [ArgSig(name='self')] + args + return [ArgSig(name=self_var or 'self')] + args diff --git a/mypy/stubinfo.py b/mypy/stubinfo.py index e5c6d68c6df9..9945a12c121f 100644 --- a/mypy/stubinfo.py +++ b/mypy/stubinfo.py @@ -1,84 +1,92 @@ +from typing import Optional + + +class StubInfo: + def __init__(self, name: str, py_version: Optional[int] = None) -> None: + self.name = name + # If None, compatible with py2+py3, if 2/3, only compatible with py2/py3 + self.py_version = py_version + + +def is_legacy_bundled_package(prefix: str, py_version: int) -> bool: + if prefix not in legacy_bundled_packages: + return False + package_ver = legacy_bundled_packages[prefix].py_version + return package_ver is None or package_ver == py_version + + # Stubs for these third-party packages used to be shipped with mypy. # # Map package name to PyPI stub distribution name. +# +# Package name can have one or two components ('a' or 'a.b'). legacy_bundled_packages = { - 'aiofiles': 'types-aiofiles', - 'atomicwrites': 'types-atomicwrites', - 'attr': 'types-attrs', - 'backports': 'types-backports', - 'backports_abc': 'types-backports_abc', - 'bleach': 'types-bleach', - 'boto': 'types-boto', - 'cachetools': 'types-cachetools', - 'certifi': 'types-certifi', - 'characteristic': 'types-characteristic', - 'chardet': 'types-chardet', - 'click': 'types-click', - 'click_spinner': 'types-click-spinner', - 'concurrent': 'types-futures', - 'contextvars': 'types-contextvars', - 'croniter': 'types-croniter', - 'Crypto': 'types-pycrypto', - 'cryptography': 'types-cryptography', - 'dataclasses': 'types-dataclasses', - 'dateparser': 'types-dateparser', - 'datetimerange': 'types-DateTimeRange', - 'dateutil': 'types-python-dateutil', - 'decorator': 'types-decorator', - 'deprecated': 'types-Deprecated', - 'docutils': 'types-docutils', - 'emoji': 'types-emoji', - 'enum': 'types-enum34', - 'fb303': 'types-fb303', - 'filelock': 'types-filelock', - 'first': 'types-first', - 'flask': 'types-Flask', - 'freezegun': 'types-freezegun', - 'frozendict': 'types-frozendict', - 'geoip2': 'types-geoip2', - 'gflags': 'types-python-gflags', - 'google': 'types-protobuf', - 'ipaddress': 'types-ipaddress', - 'itsdangerous': 'types-itsdangerous', - 'jinja2': 'types-Jinja2', - 'jwt': 'types-jwt', - 'kazoo': 'types-kazoo', - 'markdown': 'types-Markdown', - 'markupsafe': 'types-MarkupSafe', - 'maxminddb': 'types-maxminddb', - 'mock': 'types-mock', - 'OpenSSL': 'types-openssl-python', - 'orjson': 'types-orjson', - 'paramiko': 'types-paramiko', - 'pathlib2': 'types-pathlib2', - 'pkg_resources': 'types-pkg_resources', - 'polib': 'types-polib', - 'pycurl': 'types-pycurl', - 'pymssql': 'types-pymssql', - 'pymysql': 'types-PyMySQL', - 'pynamodb': 'types-pynamodb', - 'pyre_extensions': 'types-pyre-extensions', - 'pyrfc3339': 'types-pyRFC3339', - 'python2': 'types-six', - 'pytz': 'types-pytz', - 'pyVmomi': 'types-pyvmomi', - 'redis': 'types-redis', - 'requests': 'types-requests', - 'retry': 'types-retry', - 'routes': 'types-Routes', - 'scribe': 'types-scribe', - 'simplejson': 'types-simplejson', - 'singledispatch': 'types-singledispatch', - 'six': 'types-six', - 'slugify': 'types-python-slugify', - 'tabulate': 'types-tabulate', - 'termcolor': 'types-termcolor', - 'toml': 'types-toml', - 'tornado': 'types-tornado', - 'typed_ast': 'types-typed-ast', - 'tzlocal': 'types-tzlocal', - 'ujson': 'types-ujson', - 'waitress': 'types-waitress', - 'werkzeug': 'types-Werkzeug', - 'yaml': 'types-PyYAML', + 'aiofiles': StubInfo('types-aiofiles', py_version=3), + 'atomicwrites': StubInfo('types-atomicwrites'), + 'attr': StubInfo('types-attrs'), + 'backports': StubInfo('types-backports'), + 'backports_abc': StubInfo('types-backports_abc'), + 'bleach': StubInfo('types-bleach'), + 'boto': StubInfo('types-boto'), + 'cachetools': StubInfo('types-cachetools'), + 'certifi': StubInfo('types-certifi'), + 'characteristic': StubInfo('types-characteristic'), + 'chardet': StubInfo('types-chardet'), + 'click_spinner': StubInfo('types-click-spinner'), + 'concurrent': StubInfo('types-futures', py_version=2), + 'contextvars': StubInfo('types-contextvars', py_version=3), + 'croniter': StubInfo('types-croniter'), + 'dataclasses': StubInfo('types-dataclasses', py_version=3), + 'dateparser': StubInfo('types-dateparser'), + 'datetimerange': StubInfo('types-DateTimeRange'), + 'dateutil': StubInfo('types-python-dateutil'), + 'decorator': StubInfo('types-decorator'), + 'deprecated': StubInfo('types-Deprecated'), + 'docutils': StubInfo('types-docutils', py_version=3), + 'emoji': StubInfo('types-emoji'), + 'enum': StubInfo('types-enum34', py_version=2), + 'fb303': StubInfo('types-fb303', py_version=2), + 'filelock': StubInfo('types-filelock', py_version=3), + 'first': StubInfo('types-first'), + 'freezegun': StubInfo('types-freezegun', py_version=3), + 'frozendict': StubInfo('types-frozendict', py_version=3), + 'geoip2': StubInfo('types-geoip2'), + 'gflags': StubInfo('types-python-gflags'), + 'google.protobuf': StubInfo('types-protobuf'), + 'ipaddress': StubInfo('types-ipaddress', py_version=2), + 'kazoo': StubInfo('types-kazoo', py_version=2), + 'markdown': StubInfo('types-Markdown'), + 'maxminddb': StubInfo('types-maxminddb'), + 'mock': StubInfo('types-mock'), + 'OpenSSL': StubInfo('types-pyOpenSSL'), + 'orjson': StubInfo('types-orjson', py_version=3), + 'paramiko': StubInfo('types-paramiko'), + 'pathlib2': StubInfo('types-pathlib2', py_version=2), + 'pkg_resources': StubInfo('types-setuptools', py_version=3), + 'polib': StubInfo('types-polib'), + 'pycurl': StubInfo('types-pycurl'), + 'pymssql': StubInfo('types-pymssql', py_version=2), + 'pymysql': StubInfo('types-PyMySQL'), + 'pyrfc3339': StubInfo('types-pyRFC3339', py_version=3), + 'python2': StubInfo('types-six'), + 'pytz': StubInfo('types-pytz'), + 'pyVmomi': StubInfo('types-pyvmomi'), + 'redis': StubInfo('types-redis'), + 'requests': StubInfo('types-requests'), + 'retry': StubInfo('types-retry'), + 'routes': StubInfo('types-Routes', py_version=2), + 'scribe': StubInfo('types-scribe', py_version=2), + 'simplejson': StubInfo('types-simplejson'), + 'singledispatch': StubInfo('types-singledispatch'), + 'six': StubInfo('types-six'), + 'slugify': StubInfo('types-python-slugify'), + 'tabulate': StubInfo('types-tabulate'), + 'termcolor': StubInfo('types-termcolor'), + 'toml': StubInfo('types-toml'), + 'tornado': StubInfo('types-tornado', py_version=2), + 'typed_ast': StubInfo('types-typed-ast', py_version=3), + 'tzlocal': StubInfo('types-tzlocal'), + 'ujson': StubInfo('types-ujson'), + 'waitress': StubInfo('types-waitress', py_version=3), + 'yaml': StubInfo('types-PyYAML'), } diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 7915e14f1551..7228afaed446 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -38,17 +38,7 @@ def __repr__(self) -> str: MISSING = Missing() T = TypeVar("T") -if sys.version_info >= (3, 5, 3): - MaybeMissing = Union[T, Missing] -else: - # work around a bug in 3.5.2 and earlier's typing.py - class MaybeMissingMeta(type): - def __getitem__(self, arg: Any) -> Any: - return Union[arg, Missing] - - class MaybeMissing(metaclass=MaybeMissingMeta): # type: ignore - pass - +MaybeMissing = Union[T, Missing] _formatter = FancyFormatter(sys.stdout, sys.stderr, False) @@ -107,7 +97,7 @@ def get_description(self, concise: bool = False) -> str: return _style(self.object_desc, bold=True) + " " + self.message stub_line = None - stub_file = None # type: None + stub_file: None = None if not isinstance(self.stub_object, Missing): stub_line = self.stub_object.line # TODO: Find a way of getting the stub file @@ -171,6 +161,10 @@ def test_module(module_name: str) -> Iterator[Error]: with warnings.catch_warnings(): warnings.simplefilter("ignore") runtime = importlib.import_module(module_name) + # Also run the equivalent of `from module import *` + # This could have the additional effect of loading not-yet-loaded submodules + # mentioned in __all__ + __import__(module_name, fromlist=["*"]) except Exception as e: yield Error([module_name], "failed to import: {}".format(e), stub, MISSING) return @@ -182,7 +176,7 @@ def test_module(module_name: str) -> Iterator[Error]: @singledispatch def verify( - stub: nodes.Node, runtime: MaybeMissing[Any], object_path: List[str] + stub: MaybeMissing[nodes.Node], runtime: MaybeMissing[Any], object_path: List[str] ) -> Iterator[Error]: """Entry point for comparing a stub to a runtime object. @@ -206,28 +200,44 @@ def verify_mypyfile( yield Error(object_path, "is not a module", stub, runtime) return - # Check things in the stub that are public + # Check things in the stub to_check = set( m for m, o in stub.names.items() - if o.module_public and (not m.startswith("_") or hasattr(runtime, m)) + if not o.module_hidden and (not m.startswith("_") or hasattr(runtime, m)) ) - runtime_public_contents = [ - m - for m in dir(runtime) - if not m.startswith("_") - # Ensure that the object's module is `runtime`, e.g. so that we don't pick up reexported - # modules and infinitely recurse. Unfortunately, there's no way to detect an explicit - # reexport missing from the stubs (that isn't specified in __all__) - and getattr(getattr(runtime, m), "__module__", None) == runtime.__name__ - ] - # Check all things declared in module's __all__, falling back to runtime_public_contents - to_check.update(getattr(runtime, "__all__", runtime_public_contents)) + + def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: + obj = getattr(r, attr) + obj_mod = getattr(obj, "__module__", None) + if obj_mod is not None: + return obj_mod == r.__name__ + return not isinstance(obj, types.ModuleType) + + runtime_public_contents = ( + runtime.__all__ + if hasattr(runtime, "__all__") + else [ + m + for m in dir(runtime) + if not m.startswith("_") + # Ensure that the object's module is `runtime`, since in the absence of __all__ we + # don't have a good way to detect re-exports at runtime. + and _belongs_to_runtime(runtime, m) + ] + ) + # Check all things declared in module's __all__, falling back to our best guess + to_check.update(runtime_public_contents) to_check.difference_update({"__file__", "__doc__", "__name__", "__builtins__", "__package__"}) for entry in sorted(to_check): + stub_entry = stub.names[entry].node if entry in stub.names else MISSING + if isinstance(stub_entry, nodes.MypyFile): + # Don't recursively check exported modules, since that leads to infinite recursion + continue + assert stub_entry is not None yield from verify( - stub.names[entry].node if entry in stub.names else MISSING, + stub_entry, getattr(runtime, entry, MISSING), object_path + [entry], ) @@ -257,8 +267,10 @@ def verify_typeinfo( mangled_entry = entry if entry.startswith("__") and not entry.endswith("__"): mangled_entry = "_{}{}".format(stub.name, entry) + stub_to_verify = next((t.names[entry].node for t in stub.mro if entry in t.names), MISSING) + assert stub_to_verify is not None yield from verify( - next((t.names[entry].node for t in stub.mro if entry in t.names), MISSING), + stub_to_verify, getattr(runtime, mangled_entry, MISSING), object_path + [entry], ) @@ -340,7 +352,7 @@ def _verify_arg_default_value( ) -> Iterator[str]: """Checks whether argument default values are compatible.""" if runtime_arg.default != inspect.Parameter.empty: - if stub_arg.kind not in (nodes.ARG_OPT, nodes.ARG_NAMED_OPT): + if stub_arg.kind.is_required(): yield ( 'runtime argument "{}" has a default value but stub argument does not'.format( runtime_arg.name @@ -369,7 +381,7 @@ def _verify_arg_default_value( ) ) else: - if stub_arg.kind in (nodes.ARG_OPT, nodes.ARG_NAMED_OPT): + if stub_arg.kind.is_optional(): yield ( 'stub argument "{}" has a default value but runtime argument does not'.format( stub_arg.variable.name @@ -388,10 +400,10 @@ def maybe_strip_cls(name: str, args: List[nodes.Argument]) -> List[nodes.Argumen class Signature(Generic[T]): def __init__(self) -> None: - self.pos = [] # type: List[T] - self.kwonly = {} # type: Dict[str, T] - self.varpos = None # type: Optional[T] - self.varkw = None # type: Optional[T] + self.pos: List[T] = [] + self.kwonly: Dict[str, T] = {} + self.varpos: Optional[T] = None + self.varkw: Optional[T] = None def __str__(self) -> str: def get_name(arg: Any) -> str: @@ -412,7 +424,7 @@ def has_default(arg: Any) -> bool: if isinstance(arg, inspect.Parameter): return arg.default != inspect.Parameter.empty if isinstance(arg, nodes.Argument): - return arg.kind in (nodes.ARG_OPT, nodes.ARG_NAMED_OPT) + return arg.kind.is_optional() raise AssertionError def get_desc(arg: Any) -> str: @@ -436,12 +448,12 @@ def get_desc(arg: Any) -> str: @staticmethod def from_funcitem(stub: nodes.FuncItem) -> "Signature[nodes.Argument]": - stub_sig = Signature() # type: Signature[nodes.Argument] + stub_sig: Signature[nodes.Argument] = Signature() stub_args = maybe_strip_cls(stub.name, stub.arguments) for stub_arg in stub_args: - if stub_arg.kind in (nodes.ARG_POS, nodes.ARG_OPT): + if stub_arg.kind.is_positional(): stub_sig.pos.append(stub_arg) - elif stub_arg.kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT): + elif stub_arg.kind.is_named(): stub_sig.kwonly[stub_arg.variable.name] = stub_arg elif stub_arg.kind == nodes.ARG_STAR: stub_sig.varpos = stub_arg @@ -453,7 +465,7 @@ def from_funcitem(stub: nodes.FuncItem) -> "Signature[nodes.Argument]": @staticmethod def from_inspect_signature(signature: inspect.Signature) -> "Signature[inspect.Parameter]": - runtime_sig = Signature() # type: Signature[inspect.Parameter] + runtime_sig: Signature[inspect.Parameter] = Signature() for runtime_arg in signature.parameters.values(): if runtime_arg.kind in ( inspect.Parameter.POSITIONAL_ONLY, @@ -483,7 +495,7 @@ def from_overloadedfuncdef(stub: nodes.OverloadedFuncDef) -> "Signature[nodes.Ar # For most dunder methods, just assume all args are positional-only assume_positional_only = is_dunder(stub.name, exclude_special=True) - all_args = {} # type: Dict[str, List[Tuple[nodes.Argument, int]]] + all_args: Dict[str, List[Tuple[nodes.Argument, int]]] = {} for func in map(_resolve_funcitem_from_decorator, stub.items): assert func is not None args = maybe_strip_cls(stub.name, func.arguments) @@ -508,7 +520,7 @@ def get_type(arg_name: str) -> mypy.types.ProperType: ] return mypy.typeops.make_simplified_union([t for t in all_types if t]) - def get_kind(arg_name: str) -> int: + def get_kind(arg_name: str) -> nodes.ArgKind: kinds = {arg.kind for arg, _ in all_args[arg_name]} if nodes.ARG_STAR in kinds: return nodes.ARG_STAR @@ -527,7 +539,7 @@ def get_kind(arg_name: str) -> int: return nodes.ARG_OPT if is_pos else nodes.ARG_NAMED_OPT return nodes.ARG_POS if is_pos else nodes.ARG_NAMED - sig = Signature() # type: Signature[nodes.Argument] + sig: Signature[nodes.Argument] = Signature() for arg_name in sorted(all_args, key=get_position): # example_arg_name gives us a real name (in case we had a fake index-based name) example_arg_name = all_args[arg_name][0][0].variable.name @@ -537,9 +549,9 @@ def get_kind(arg_name: str) -> int: initializer=None, kind=get_kind(arg_name), ) - if arg.kind in (nodes.ARG_POS, nodes.ARG_OPT): + if arg.kind.is_positional(): sig.pos.append(arg) - elif arg.kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT): + elif arg.kind.is_named(): sig.kwonly[arg.variable.name] = arg elif arg.kind == nodes.ARG_STAR: sig.varpos = arg @@ -652,11 +664,7 @@ def verify_funcitem( yield Error(object_path, "is not present at runtime", stub, runtime) return - if ( - not isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType)) - and not isinstance(runtime, (types.MethodType, types.BuiltinMethodType)) - and not inspect.ismethoddescriptor(runtime) - ): + if not is_probably_a_function(runtime): yield Error(object_path, "is not a function", stub, runtime) if not callable(runtime): return @@ -664,11 +672,8 @@ def verify_funcitem( for message in _verify_static_class_methods(stub, runtime, object_path): yield Error(object_path, "is inconsistent, " + message, stub, runtime) - try: - signature = inspect.signature(runtime) - except (ValueError, RuntimeError): - # inspect.signature throws sometimes - # catch RuntimeError because of https://bugs.python.org/issue39504 + signature = safe_inspect_signature(runtime) + if not signature: return stub_sig = Signature.from_funcitem(stub) @@ -736,11 +741,7 @@ def verify_overloadedfuncdef( # We get here in cases of overloads from property.setter return - if ( - not isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType)) - and not isinstance(runtime, (types.MethodType, types.BuiltinMethodType)) - and not inspect.ismethoddescriptor(runtime) - ): + if not is_probably_a_function(runtime): yield Error(object_path, "is not a function", stub, runtime) if not callable(runtime): return @@ -748,9 +749,8 @@ def verify_overloadedfuncdef( for message in _verify_static_class_methods(stub, runtime, object_path): yield Error(object_path, "is inconsistent, " + message, stub, runtime) - try: - signature = inspect.signature(runtime) - except ValueError: + signature = safe_inspect_signature(runtime) + if not signature: return stub_sig = Signature.from_overloadedfuncdef(stub) @@ -839,7 +839,7 @@ def apply_decorator_to_funcitem( # anything else when running on typeshed's stdlib. return None - func = dec.func # type: nodes.FuncItem + func: nodes.FuncItem = dec.func for decorator in dec.original_decorators: resulting_func = apply_decorator_to_funcitem(decorator, func) if resulting_func is None: @@ -869,8 +869,31 @@ def verify_decorator( def verify_typealias( stub: nodes.TypeAlias, runtime: MaybeMissing[Any], object_path: List[str] ) -> Iterator[Error]: - if False: - yield None + if isinstance(runtime, Missing): + # ignore type aliases that don't have a runtime counterpart + return + stub_target = mypy.types.get_proper_type(stub.target) + if isinstance(stub_target, mypy.types.Instance): + yield from verify(stub_target.type, runtime, object_path) + return + if isinstance(stub_target, mypy.types.UnionType): + if not getattr(runtime, "__origin__", None) is Union: + yield Error(object_path, "is not a Union", stub, runtime, stub_desc=str(stub_target)) + # could check Union contents here... + return + if isinstance(stub_target, mypy.types.TupleType): + if tuple not in getattr(runtime, "__mro__", ()): + yield Error( + object_path, "is not a subclass of tuple", stub, runtime, + stub_desc=str(stub_target) + ) + # could check Tuple contents here... + return + if isinstance(stub_target, mypy.types.AnyType): + return + yield Error( + object_path, "is not a recognised type alias", stub, runtime, stub_desc=str(stub_target) + ) SPECIAL_DUNDERS = ("__init__", "__new__", "__call__", "__init_subclass__", "__class_getitem__") @@ -887,6 +910,25 @@ def is_dunder(name: str, exclude_special: bool = False) -> bool: return name.startswith("__") and name.endswith("__") +def is_probably_a_function(runtime: Any) -> bool: + return ( + isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType)) + or isinstance(runtime, (types.MethodType, types.BuiltinMethodType)) + or (inspect.ismethoddescriptor(runtime) and callable(runtime)) + ) + + +def safe_inspect_signature(runtime: Any) -> Optional[inspect.Signature]: + try: + return inspect.signature(runtime) + except Exception: + # inspect.signature throws ValueError all the time + # catch RuntimeError because of https://bugs.python.org/issue39504 + # catch TypeError because of https://github.com/python/typeshed/pull/5762 + # catch AttributeError because of inspect.signature(_curses.window.border) + return None + + def is_subtype_helper(left: mypy.types.Type, right: mypy.types.Type) -> bool: """Checks whether ``left`` is a subtype of ``right``.""" left = mypy.types.get_proper_type(left) @@ -929,8 +971,8 @@ def anytype() -> mypy.types.AnyType: type_info = builtins.names["function"].node assert isinstance(type_info, nodes.TypeInfo) fallback = mypy.types.Instance(type_info, [anytype()]) - try: - signature = inspect.signature(runtime) + signature = safe_inspect_signature(runtime) + if signature: arg_types = [] arg_kinds = [] arg_names = [] @@ -952,7 +994,7 @@ def anytype() -> mypy.types.AnyType: arg_kinds.append(nodes.ARG_STAR2) else: raise AssertionError - except ValueError: + else: arg_types = [anytype(), anytype()] arg_kinds = [nodes.ARG_STAR, nodes.ARG_STAR2] arg_names = [None, None] @@ -999,7 +1041,7 @@ def anytype() -> mypy.types.AnyType: return fallback -_all_stubs = {} # type: Dict[str, nodes.MypyFile] +_all_stubs: Dict[str, nodes.MypyFile] = {} def build_stubs(modules: List[str], options: Options, find_submodules: bool = False) -> List[str]: @@ -1069,7 +1111,7 @@ def get_typeshed_stdlib_modules(custom_typeshed_dir: Optional[str]) -> List[str] """Returns a list of stdlib modules in typeshed (for current Python version).""" stdlib_py_versions = mypy.modulefinder.load_stdlib_py_versions(custom_typeshed_dir) packages = set() - # Typeshed doesn't cover Python 3.5. + # Typeshed's minimum supported Python 3 is Python 3.6 if sys.version_info < (3, 6): version_info = (3, 6) else: @@ -1198,7 +1240,11 @@ def parse_options(args: List[str]) -> argparse.Namespace: description="Compares stubs to objects introspected from the runtime." ) parser.add_argument("modules", nargs="*", help="Modules to test") - parser.add_argument("--concise", action="store_true", help="Make output concise") + parser.add_argument( + "--concise", + action="store_true", + help="Makes stubtest's output more concise, one line per error", + ) parser.add_argument( "--ignore-missing-stub", action="store_true", @@ -1209,12 +1255,6 @@ def parse_options(args: List[str]) -> argparse.Namespace: action="store_true", help="Ignore errors for whether an argument should or shouldn't be positional-only", ) - parser.add_argument( - "--custom-typeshed-dir", metavar="DIR", help="Use the custom typeshed in DIR" - ) - parser.add_argument( - "--check-typeshed", action="store_true", help="Check all stdlib modules in typeshed" - ) parser.add_argument( "--allowlist", "--whitelist", @@ -1223,7 +1263,8 @@ def parse_options(args: List[str]) -> argparse.Namespace: default=[], help=( "Use file as an allowlist. Can be passed multiple times to combine multiple " - "allowlists. Allowlists can be created with --generate-allowlist" + "allowlists. Allowlists can be created with --generate-allowlist. Allowlists " + "support regular expressions." ), ) parser.add_argument( @@ -1238,19 +1279,20 @@ def parse_options(args: List[str]) -> argparse.Namespace: action="store_true", help="Ignore unused allowlist entries", ) - config_group = parser.add_argument_group( - title='mypy config file', - description="Use a config file instead of command line arguments. " - "Plugins and mypy path are the only supported " - "configurations.", - ) - config_group.add_argument( - '--mypy-config-file', + parser.add_argument( + "--mypy-config-file", + metavar="FILE", help=( - "An existing mypy configuration file, currently used by stubtest to help " - "determine mypy path and plugins" + "Use specified mypy config file to determine mypy plugins " + "and mypy path" ), ) + parser.add_argument( + "--custom-typeshed-dir", metavar="DIR", help="Use the custom typeshed in DIR" + ) + parser.add_argument( + "--check-typeshed", action="store_true", help="Check all stdlib modules in typeshed" + ) return parser.parse_args(args) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index ffcaf8f2bc92..f90009445b09 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1,13 +1,13 @@ from contextlib import contextmanager from typing import Any, List, Optional, Callable, Tuple, Iterator, Set, Union, cast, TypeVar -from typing_extensions import Final +from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.types import ( - Type, AnyType, TypeGuardType, UnboundType, TypeVisitor, FormalArgument, NoneType, + Type, AnyType, UnboundType, TypeVisitor, FormalArgument, NoneType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, - FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType + FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType ) import mypy.applytype import mypy.constraints @@ -18,7 +18,7 @@ # import mypy.solve from mypy.nodes import ( FuncBase, Var, Decorator, OverloadedFuncDef, TypeInfo, CONTRAVARIANT, COVARIANT, - ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2 + ) from mypy.maptype import map_instance_to_supertype from mypy.expandtype import expand_type_by_instance @@ -26,11 +26,11 @@ from mypy import state # Flags for detected protocol members -IS_SETTABLE = 1 # type: Final -IS_CLASSVAR = 2 # type: Final -IS_CLASS_OR_STATIC = 3 # type: Final +IS_SETTABLE: Final = 1 +IS_CLASSVAR: Final = 2 +IS_CLASS_OR_STATIC: Final = 3 -TypeParameterChecker = Callable[[Type, Type, int], bool] +TypeParameterChecker: _TypeAlias = Callable[[Type, Type, int], bool] def check_type_parameter(lefta: Type, righta: Type, variance: int) -> bool: @@ -125,7 +125,10 @@ def _is_subtype(left: Type, right: Type, # of a union of all enum items as literal types. Only do it if # the previous check didn't succeed, since recombining can be # expensive. - if not is_subtype_of_item and isinstance(left, Instance) and left.type.is_enum: + # `bool` is a special case, because `bool` is `Literal[True, False]`. + if (not is_subtype_of_item + and isinstance(left, Instance) + and (left.type.is_enum or left.type.fullname == 'builtins.bool')): right = UnionType(mypy.typeops.try_contracting_literals_in_union(right.items)) is_subtype_of_item = any(is_subtype(orig_left, item, ignore_type_params=ignore_type_params, @@ -263,13 +266,23 @@ def visit_instance(self, left: Instance) -> bool: rname = right.type.fullname # Always try a nominal check if possible, # there might be errors that a user wants to silence *once*. - if ((left.type.has_base(rname) or rname == 'builtins.object') and - not self.ignore_declared_variance): + # NamedTuples are a special case, because `NamedTuple` is not listed + # in `TypeInfo.mro`, so when `(a: NamedTuple) -> None` is used, + # we need to check for `is_named_tuple` property + if ((left.type.has_base(rname) or rname == 'builtins.object' + or (rname == 'typing.NamedTuple' + and any(l.is_named_tuple for l in left.type.mro))) + and not self.ignore_declared_variance): # Map left type to corresponding right instances. t = map_instance_to_supertype(left, right.type) - nominal = all(self.check_type_parameter(lefta, righta, tvar.variance) - for lefta, righta, tvar in - zip(t.args, right.args, right.type.defn.type_vars)) + nominal = True + for lefta, righta, tvar in zip(t.args, right.args, right.type.defn.type_vars): + if isinstance(tvar, TypeVarType): + if not self.check_type_parameter(lefta, righta, tvar.variance): + nominal = False + else: + if not is_equivalent(lefta, righta): + nominal = False if nominal: TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) return nominal @@ -287,6 +300,8 @@ def visit_instance(self, left: Instance) -> bool: return True if isinstance(item, Instance): return is_named_instance(item, 'builtins.object') + if isinstance(right, LiteralType) and left.last_known_value is not None: + return self._is_subtype(left.last_known_value, right) if isinstance(right, CallableType): # Special case: Instance can be a subtype of Callable. call = find_member('__call__', left, left, is_operator=True) @@ -305,15 +320,32 @@ def visit_type_var(self, left: TypeVarType) -> bool: return True return self._is_subtype(left.upper_bound, self.right) + def visit_param_spec(self, left: ParamSpecType) -> bool: + right = self.right + if ( + isinstance(right, ParamSpecType) + and right.id == left.id + and right.flavor == left.flavor + ): + return True + return self._is_subtype(left.upper_bound, self.right) + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): + if left.type_guard is not None and right.type_guard is not None: + if not self._is_subtype(left.type_guard, right.type_guard): + return False + elif right.type_guard is not None and left.type_guard is None: + # This means that one function has `TypeGuard` and other does not. + # They are not compatible. See https://github.com/python/mypy/issues/11307 + return False return is_callable_compatible( left, right, is_compat=self._is_subtype, ignore_pos_arg_names=self.ignore_pos_arg_names) elif isinstance(right, Overloaded): - return all(self._is_subtype(left, item) for item in right.items()) + return all(self._is_subtype(left, item) for item in right.items) elif isinstance(right, Instance): if right.type.is_protocol and right.type.protocol_members == ['__call__']: # OK, a callable can implement a protocol with a single `__call__` member. @@ -411,7 +443,7 @@ def visit_overloaded(self, left: Overloaded) -> bool: return True return self._is_subtype(left.fallback, right) elif isinstance(right, CallableType): - for item in left.items(): + for item in left.items: if self._is_subtype(item, right): return True return False @@ -425,10 +457,10 @@ def visit_overloaded(self, left: Overloaded) -> bool: matched_overloads = set() possible_invalid_overloads = set() - for right_index, right_item in enumerate(right.items()): + for right_index, right_item in enumerate(right.items): found_match = False - for left_index, left_item in enumerate(left.items()): + for left_index, left_item in enumerate(left.items): subtype_match = self._is_subtype(left_item, right_item) # Order matters: we need to make sure that the index of @@ -468,19 +500,22 @@ def visit_overloaded(self, left: Overloaded) -> bool: # All the items must have the same type object status, so # it's sufficient to query only (any) one of them. # This is unsound, we don't check all the __init__ signatures. - return left.is_type_obj() and self._is_subtype(left.items()[0], right) + return left.is_type_obj() and self._is_subtype(left.items[0], right) else: return False def visit_union_type(self, left: UnionType) -> bool: return all(self._is_subtype(item, self.orig_right) for item in left.items) - def visit_type_guard_type(self, left: TypeGuardType) -> bool: - raise RuntimeError("TypeGuard should not appear here") - def visit_partial_type(self, left: PartialType) -> bool: # This is indeterminate as we don't really know the complete type yet. - raise RuntimeError + if left.type is None: + # Special case, partial `None`. This might happen when defining + # class-level attributes with explicit `None`. + # We can still recover from this. + # https://github.com/python/mypy/issues/11105 + return self.visit_none_type(NoneType()) + raise RuntimeError(f'Partial type "{left}" cannot be checked with "issubtype()"') def visit_type_type(self, left: TypeType) -> bool: right = self.right @@ -547,8 +582,7 @@ def f(self) -> A: ... return False assuming = right.type.assuming_proper if proper_subtype else right.type.assuming for (l, r) in reversed(assuming): - if (mypy.sametypes.is_same_type(l, left) - and mypy.sametypes.is_same_type(r, right)): + if l == left and r == right: return True with pop_on_exit(assuming, left, right): for member in right.type.protocol_members: @@ -619,6 +653,8 @@ def find_member(name: str, info = itype.type method = info.get_method(name) if method: + if isinstance(method, Decorator): + return find_node_type(method.var, itype, subtype) if method.is_property: assert isinstance(method, OverloadedFuncDef) dec = method.items[0] @@ -628,12 +664,7 @@ def find_member(name: str, else: # don't have such method, maybe variable or decorator? node = info.get(name) - if not node: - v = None - else: - v = node.node - if isinstance(v, Decorator): - v = v.var + v = node.node if node else None if isinstance(v, Var): return find_node_type(v, itype, subtype) if (not v and name not in ['__getattr__', '__setattr__', '__getattribute__'] and @@ -645,9 +676,13 @@ def find_member(name: str, # structural subtyping. method = info.get_method(method_name) if method and method.info.fullname != 'builtins.object': - getattr_type = get_proper_type(find_node_type(method, itype, subtype)) + if isinstance(method, Decorator): + getattr_type = get_proper_type(find_node_type(method.var, itype, subtype)) + else: + getattr_type = get_proper_type(find_node_type(method, itype, subtype)) if isinstance(getattr_type, CallableType): return getattr_type.ret_type + return getattr_type if itype.type.fallback_to_any: return AnyType(TypeOfAny.special_form) return None @@ -667,8 +702,10 @@ def get_member_flags(name: str, info: TypeInfo) -> Set[int]: method = info.get_method(name) setattr_meth = info.get_method('__setattr__') if method: - # this could be settable property - if method.is_property: + if isinstance(method, Decorator): + if method.var.is_staticmethod or method.var.is_classmethod: + return {IS_CLASS_OR_STATIC} + elif method.is_property: # this could be settable property assert isinstance(method, OverloadedFuncDef) dec = method.items[0] assert isinstance(dec, Decorator) @@ -681,9 +718,6 @@ def get_member_flags(name: str, info: TypeInfo) -> Set[int]: return {IS_SETTABLE} return set() v = node.node - if isinstance(v, Decorator): - if v.var.is_staticmethod or v.var.is_classmethod: - return {IS_CLASS_OR_STATIC} # just a variable if isinstance(v, Var) and not v.is_property: flags = {IS_SETTABLE} @@ -700,8 +734,9 @@ def find_node_type(node: Union[Var, FuncBase], itype: Instance, subtype: Type) - from mypy.typeops import bind_self if isinstance(node, FuncBase): - typ = mypy.typeops.function_type( - node, fallback=Instance(itype.type.mro[-1], [])) # type: Optional[Type] + typ: Optional[Type] = mypy.typeops.function_type( + node, fallback=Instance(itype.type.mro[-1], []) + ) else: typ = node.type typ = get_proper_type(typ) @@ -713,7 +748,8 @@ def find_node_type(node: Union[Var, FuncBase], itype: Instance, subtype: Type) - and node.is_initialized_in_class and not node.is_staticmethod)): assert isinstance(typ, FunctionLike) - signature = bind_self(typ, subtype) + signature = bind_self(typ, subtype, + is_classmethod=isinstance(node, Var) and node.is_classmethod) if node.is_property: assert isinstance(signature, CallableType) typ = signature.ret_type @@ -728,7 +764,7 @@ def non_method_protocol_members(tp: TypeInfo) -> List[str]: """Find all non-callable members of a protocol.""" assert tp.is_protocol - result = [] # type: List[str] + result: List[str] = [] anytype = AnyType(TypeOfAny.special_form) instance = Instance(tp, [anytype] * len(tp.defn.type_vars)) @@ -949,8 +985,8 @@ def _incompatible(left_arg: Optional[FormalArgument], i = right_star.pos assert i is not None - while i < len(left.arg_kinds) and left.arg_kinds[i] in (ARG_POS, ARG_OPT): - if allow_partial_overlap and left.arg_kinds[i] == ARG_OPT: + while i < len(left.arg_kinds) and left.arg_kinds[i].is_positional(): + if allow_partial_overlap and left.arg_kinds[i].is_optional(): break left_by_position = left.argument_by_position(i) @@ -969,7 +1005,7 @@ def _incompatible(left_arg: Optional[FormalArgument], right_names = {name for name in right.arg_names if name is not None} left_only_names = set() for name, kind in zip(left.arg_names, left.arg_kinds): - if name is None or kind in (ARG_STAR, ARG_STAR2) or name in right_names: + if name is None or kind.is_star() or name in right_names: continue left_only_names.add(name) @@ -1081,7 +1117,7 @@ def unify_generic_callable(type: CallableType, target: CallableType, if return_constraint_direction is None: return_constraint_direction = mypy.constraints.SUBTYPE_OF - constraints = [] # type: List[mypy.constraints.Constraint] + constraints: List[mypy.constraints.Constraint] = [] for arg_type, target_arg_type in zip(type.arg_types, target.arg_types): c = mypy.constraints.infer_constraints( arg_type, target_arg_type, mypy.constraints.SUPERTYPE_OF) @@ -1126,6 +1162,8 @@ def restrict_subtype_away(t: Type, s: Type, *, ignore_promotions: bool = False) if (isinstance(get_proper_type(item), AnyType) or not covers_at_runtime(item, s, ignore_promotions))] return UnionType.make_union(new_items) + elif covers_at_runtime(t, s, ignore_promotions): + return UninhabitedType() else: return t @@ -1286,8 +1324,13 @@ def check_argument(leftarg: Type, rightarg: Type, variance: int) -> bool: assert isinstance(erased, Instance) left = erased - nominal = all(check_argument(ta, ra, tvar.variance) for ta, ra, tvar in - zip(left.args, right.args, right.type.defn.type_vars)) + nominal = True + for ta, ra, tvar in zip(left.args, right.args, right.type.defn.type_vars): + if isinstance(tvar, TypeVarType): + nominal = nominal and check_argument(ta, ra, tvar.variance) + else: + nominal = nominal and mypy.sametypes.is_same_type(ta, ra) + if nominal: TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) return nominal @@ -1310,13 +1353,23 @@ def visit_type_var(self, left: TypeVarType) -> bool: return True return self._is_proper_subtype(left.upper_bound, self.right) + def visit_param_spec(self, left: ParamSpecType) -> bool: + right = self.right + if ( + isinstance(right, ParamSpecType) + and right.id == left.id + and right.flavor == left.flavor + ): + return True + return self._is_proper_subtype(left.upper_bound, self.right) + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): return is_callable_compatible(left, right, is_compat=self._is_proper_subtype) elif isinstance(right, Overloaded): return all(self._is_proper_subtype(left, item) - for item in right.items()) + for item in right.items) elif isinstance(right, Instance): return self._is_proper_subtype(left.fallback, right) elif isinstance(right, TypeType): @@ -1377,14 +1430,6 @@ def visit_overloaded(self, left: Overloaded) -> bool: def visit_union_type(self, left: UnionType) -> bool: return all([self._is_proper_subtype(item, self.orig_right) for item in left.items]) - def visit_type_guard_type(self, left: TypeGuardType) -> bool: - if isinstance(self.right, TypeGuardType): - # TypeGuard[bool] is a subtype of TypeGuard[int] - return self._is_proper_subtype(left.type_guard, self.right.type_guard) - else: - # TypeGuards aren't a subtype of anything else for now (but see #10489) - return False - def visit_partial_type(self, left: PartialType) -> bool: # TODO: What's the right thing to do here? return False diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 8df180d825b4..87b54814c637 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -37,7 +37,7 @@ ) from mypy.build import State, Graph from mypy.nodes import ( - ARG_STAR, ARG_NAMED, ARG_STAR2, ARG_NAMED_OPT, FuncDef, MypyFile, SymbolTable, + ArgKind, ARG_STAR, ARG_STAR2, FuncDef, MypyFile, SymbolTable, Decorator, RefExpr, SymbolNode, TypeInfo, Expression, ReturnStmt, CallExpr, reverse_builtin_aliases, @@ -70,7 +70,7 @@ 'Callsite', [('path', str), ('line', int), - ('arg_kinds', List[List[int]]), + ('arg_kinds', List[List[ArgKind]]), ('callee_arg_names', List[Optional[str]]), ('arg_names', List[List[Optional[str]]]), ('arg_types', List[List[Type]])]) @@ -86,7 +86,7 @@ def __init__(self, target: str) -> None: self.target = target # List of call sites found by dmypy suggest: # (path, line, , , ) - self.mystery_hits = [] # type: List[Callsite] + self.mystery_hits: List[Callsite] = [] def get_function_hook(self, fullname: str ) -> Optional[Callable[[FunctionContext], Type]]: @@ -119,7 +119,7 @@ class ReturnFinder(TraverserVisitor): """Visitor for finding all types returned from a function.""" def __init__(self, typemap: Dict[Expression, Type]) -> None: self.typemap = typemap - self.return_types = [] # type: List[Type] + self.return_types: List[Type] = [] def visit_return_stmt(self, o: ReturnStmt) -> None: if o.expr is not None and o.expr in self.typemap: @@ -144,9 +144,7 @@ class ArgUseFinder(TraverserVisitor): """ def __init__(self, func: FuncDef, typemap: Dict[Expression, Type]) -> None: self.typemap = typemap - self.arg_types = { - arg.variable: [] for arg in func.arguments - } # type: Dict[SymbolNode, List[Type]] + self.arg_types: Dict[SymbolNode, List[Type]] = {arg.variable: [] for arg in func.arguments} def visit_call_expr(self, o: CallExpr) -> None: if not any(isinstance(e, RefExpr) and e.node in self.arg_types for e in o.args): @@ -290,7 +288,7 @@ def get_trivial_type(self, fdef: FuncDef) -> CallableType: fdef.arg_kinds, fdef.arg_names, AnyType(TypeOfAny.suggestion_engine), - self.builtin_type('builtins.function')) + self.named_type('builtins.function')) def get_starting_type(self, fdef: FuncDef) -> CallableType: if isinstance(fdef.type, CallableType): @@ -303,7 +301,7 @@ def get_args(self, is_method: bool, callsites: List[Callsite], uses: List[List[Type]]) -> List[List[Type]]: """Produce a list of type suggestions for each argument type.""" - types = [] # type: List[List[Type]] + types: List[List[Type]] = [] for i in range(len(base.arg_kinds)): # Make self args Any but this will get overridden somewhere in the checker if i == 0 and is_method: @@ -353,7 +351,7 @@ def get_default_arg_types(self, state: State, fdef: FuncDef) -> List[Optional[Ty def add_adjustments(self, typs: List[Type]) -> List[Type]: if not self.try_text or self.manager.options.python_version[0] != 2: return typs - translator = StrToText(self.builtin_type) + translator = StrToText(self.named_type) return dedup(typs + [tp.accept(translator) for tp in typs]) def get_guesses(self, is_method: bool, base: CallableType, defaults: List[Optional[Type]], @@ -470,10 +468,10 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: return self.pyannotate_signature(mod, is_method, best) def format_args(self, - arg_kinds: List[List[int]], + arg_kinds: List[List[ArgKind]], arg_names: List[List[Optional[str]]], arg_types: List[List[Type]]) -> str: - args = [] # type: List[str] + args: List[str] = [] for i in range(len(arg_types)): for kind, name, typ in zip(arg_kinds[i], arg_names[i], arg_types[i]): arg = self.format_type(None, typ) @@ -481,7 +479,7 @@ def format_args(self, arg = '*' + arg elif kind == ARG_STAR2: arg = '**' + arg - elif kind in (ARG_NAMED, ARG_NAMED_OPT): + elif kind.is_named(): if name: arg = "%s=%s" % (name, arg) args.append(arg) @@ -496,7 +494,7 @@ def find_node(self, key: str) -> Tuple[str, str, FuncDef]: e.g., path/to/file.py:42 """ # TODO: Also return OverloadedFuncDef -- currently these are ignored. - node = None # type: Optional[SymbolNode] + node: Optional[SymbolNode] = None if ':' in key: if key.count(':') > 1: raise SuggestionFailure( @@ -535,7 +533,7 @@ def find_node_by_module_and_name(self, modname: str, tail: str) -> Optional[Symb # N.B. This is reimplemented from update's lookup_target # basically just to produce better error messages. - names = tree.names # type: SymbolTable + names: SymbolTable = tree.names # Look through any classes components = tail.split('.') @@ -543,7 +541,7 @@ def find_node_by_module_and_name(self, modname: str, tail: str) -> Optional[Symb if component not in names: raise SuggestionFailure("Unknown class %s.%s" % (modname, '.'.join(components[:i + 1]))) - node = names[component].node # type: Optional[SymbolNode] + node: Optional[SymbolNode] = names[component].node if not isinstance(node, TypeInfo): raise SuggestionFailure("Object %s.%s is not a class" % (modname, '.'.join(components[:i + 1]))) @@ -574,8 +572,8 @@ def find_node_by_file_and_line(self, file: str, line: int) -> Tuple[str, SymbolN raise SuggestionFailure('Unknown module: ' + modname) # We must be sure about any edits in this file as this might affect the line numbers. tree = self.ensure_loaded(self.fgmanager.graph[modname], force=True) - node = None # type: Optional[SymbolNode] - closest_line = None # type: Optional[int] + node: Optional[SymbolNode] = None + closest_line: Optional[int] = None # TODO: Handle nested functions. for _, sym, _ in tree.local_definitions(): if isinstance(sym.node, (FuncDef, Decorator)): @@ -606,7 +604,7 @@ def extract_from_decorator(self, node: Decorator) -> Optional[FuncDef]: if not isinstance(typ, FunctionLike): return None - for ct in typ.items(): + for ct in typ.items: if not (len(ct.arg_types) == 1 and isinstance(ct.arg_types[0], TypeVarType) and ct.arg_types[0] == ct.ret_type): @@ -650,8 +648,8 @@ def ensure_loaded(self, state: State, force: bool = False) -> MypyFile: assert state.tree is not None return state.tree - def builtin_type(self, s: str) -> Instance: - return self.manager.semantic_analyzer.builtin_type(s) + def named_type(self, s: str) -> Instance: + return self.manager.semantic_analyzer.named_type(s) def json_suggestion(self, mod: str, func_name: str, node: FuncDef, suggestion: PyAnnotateSignature) -> str: @@ -765,8 +763,7 @@ def any_score_callable(t: CallableType, is_method: bool, ignore_return: bool) -> def is_tricky_callable(t: CallableType) -> bool: """Is t a callable that we need to put a ... in for syntax reasons?""" - return t.is_ellipsis_args or any( - k in (ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT) for k in t.arg_kinds) + return t.is_ellipsis_args or any(k.is_star() or k.is_named() for k in t.arg_kinds) class TypeFormatter(TypeStrVisitor): @@ -853,8 +850,8 @@ def visit_callable_type(self, t: CallableType) -> str: class StrToText(TypeTranslator): - def __init__(self, builtin_type: Callable[[str], Instance]) -> None: - self.text_type = builtin_type('builtins.unicode') + def __init__(self, named_type: Callable[[str], Instance]) -> None: + self.text_type = named_type('builtins.unicode') def visit_type_alias_type(self, t: TypeAliasType) -> Type: exp_t = get_proper_type(t) @@ -1020,7 +1017,7 @@ def refine_callable(t: CallableType, s: CallableType) -> CallableType: def dedup(old: List[T]) -> List[T]: - new = [] # type: List[T] + new: List[T] = [] for x in old: if x not in new: new.append(x) diff --git a/mypy/test/config.py b/mypy/test/config.py index 001161661c5a..d76eadd72ed8 100644 --- a/mypy/test/config.py +++ b/mypy/test/config.py @@ -11,9 +11,6 @@ test_data_prefix = os.path.join(PREFIX, 'test-data', 'unit') package_path = os.path.join(PREFIX, 'test-data', 'packages') -assert os.path.isdir(test_data_prefix), \ - 'Test data prefix ({}) not set correctly'.format(test_data_prefix) - # Temp directory used for the temp files created when running test cases. # This is *within* the tempfile.TemporaryDirectory that is chroot'ed per testcase. # It is also hard-coded in numerous places, so don't change it. diff --git a/mypy/test/data.py b/mypy/test/data.py index 6bf164d7623d..e886b11ffa8e 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -18,7 +18,7 @@ # File modify/create operation: copy module contents from source_path. UpdateFile = NamedTuple('UpdateFile', [('module', str), - ('source_path', str), + ('content', str), ('target_path', str)]) # File delete operation: delete module file. @@ -43,15 +43,15 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: out_section_missing = case.suite.required_out_section normalize_output = True - files = [] # type: List[Tuple[str, str]] # path and contents - output_files = [] # type: List[Tuple[str, str]] # path and contents for output files - output = [] # type: List[str] # Regular output errors - output2 = {} # type: Dict[int, List[str]] # Output errors for incremental, runs 2+ - deleted_paths = {} # type: Dict[int, Set[str]] # from run number of paths - stale_modules = {} # type: Dict[int, Set[str]] # from run number to module names - rechecked_modules = {} # type: Dict[ int, Set[str]] # from run number module names - triggered = [] # type: List[str] # Active triggers (one line per incremental step) - targets = {} # type: Dict[int, List[str]] # Fine-grained targets (per fine-grained update) + files: List[Tuple[str, str]] = [] # path and contents + output_files: List[Tuple[str, str]] = [] # path and contents for output files + output: List[str] = [] # Regular output errors + output2: Dict[int, List[str]] = {} # Output errors for incremental, runs 2+ + deleted_paths: Dict[int, Set[str]] = {} # from run number of paths + stale_modules: Dict[int, Set[str]] = {} # from run number to module names + rechecked_modules: Dict[int, Set[str]] = {} # from run number module names + triggered: List[str] = [] # Active triggers (one line per incremental step) + targets: Dict[int, List[str]] = {} # Fine-grained targets (per fine-grained update) # Process the parsed items. Each item has a header of form [id args], # optionally followed by lines of text. @@ -114,9 +114,11 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: if arg == 'skip-path-normalization': normalize_output = False if arg.startswith("version"): - if arg[7:9] != ">=": + compare_op = arg[7:9] + if compare_op not in {">=", "=="}: raise ValueError( - "{}, line {}: Only >= version checks are currently supported".format( + "{}, line {}: Only >= and == version checks are currently supported" + .format( case.file, item.line ) ) @@ -127,9 +129,17 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: raise ValueError( '{}, line {}: "{}" is not a valid python version'.format( case.file, item.line, version_str)) - if not sys.version_info >= version: - version_check = False - + if compare_op == ">=": + version_check = sys.version_info >= version + elif compare_op == "==": + if not 1 < len(version) < 4: + raise ValueError( + '{}, line {}: Only minor or patch version checks ' + 'are currently supported with "==": "{}"'.format( + case.file, item.line, version_str + ) + ) + version_check = sys.version_info[:len(version)] == version if version_check: tmp_output = [expand_variables(line) for line in item.data] if os.path.sep == '\\' and normalize_output: @@ -188,31 +198,31 @@ class DataDrivenTestCase(pytest.Item): """Holds parsed data-driven test cases, and handles directory setup and teardown.""" # Override parent member type - parent = None # type: DataSuiteCollector + parent: "DataSuiteCollector" - input = None # type: List[str] - output = None # type: List[str] # Output for the first pass - output2 = None # type: Dict[int, List[str]] # Output for runs 2+, indexed by run number + input: List[str] + output: List[str] # Output for the first pass + output2: Dict[int, List[str]] # Output for runs 2+, indexed by run number # full path of test suite file = '' line = 0 # (file path, file content) tuples - files = None # type: List[Tuple[str, str]] - expected_stale_modules = None # type: Dict[int, Set[str]] - expected_rechecked_modules = None # type: Dict[int, Set[str]] - expected_fine_grained_targets = None # type: Dict[int, List[str]] + files: List[Tuple[str, str]] + expected_stale_modules: Dict[int, Set[str]] + expected_rechecked_modules: Dict[int, Set[str]] + expected_fine_grained_targets: Dict[int, List[str]] # Whether or not we should normalize the output to standardize things like # forward vs backward slashes in file paths for Windows vs Linux. normalize_output = True # Extra attributes used by some tests. - last_line = None # type: int - output_files = None # type: List[Tuple[str, str]] # Path and contents for output files - deleted_paths = None # type: Dict[int, Set[str]] # Mapping run number -> paths - triggered = None # type: List[str] # Active triggers (one line per incremental step) + last_line: int + output_files: List[Tuple[str, str]] # Path and contents for output files + deleted_paths: Dict[int, Set[str]] # Mapping run number -> paths + triggered: List[str] # Active triggers (one line per incremental step) def __init__(self, parent: 'DataSuiteCollector', @@ -223,6 +233,7 @@ def __init__(self, only_when: str, platform: Optional[str], skip: bool, + xfail: bool, data: str, line: int) -> None: super().__init__(name, parent) @@ -234,21 +245,27 @@ def __init__(self, or (platform == 'posix' and sys.platform == 'win32')): skip = True self.skip = skip + self.xfail = xfail self.data = data self.line = line - self.old_cwd = None # type: Optional[str] - self.tmpdir = None # type: Optional[tempfile.TemporaryDirectory[str]] + self.old_cwd: Optional[str] = None + self.tmpdir: Optional[tempfile.TemporaryDirectory[str]] = None def runtest(self) -> None: if self.skip: pytest.skip() - suite = self.parent.obj() + # TODO: add a better error message for when someone uses skip and xfail at the same time + elif self.xfail: + self.add_marker(pytest.mark.xfail) + parent = self.getparent(DataSuiteCollector) + assert parent is not None, 'Should not happen' + suite = parent.obj() suite.setup() try: suite.run_case(self) except Exception: # As a debugging aid, support copying the contents of the tmp directory somewhere - save_dir = self.config.getoption('--save-failures-to', None) # type: Optional[str] + save_dir: Optional[str] = self.config.getoption("--save-failures-to", None) if save_dir: assert self.tmpdir is not None target_dir = os.path.join(save_dir, os.path.basename(self.tmpdir.name)) @@ -265,11 +282,35 @@ def setup(self) -> None: self.tmpdir = tempfile.TemporaryDirectory(prefix='mypy-test-') os.chdir(self.tmpdir.name) os.mkdir(test_temp_dir) + + # Precalculate steps for find_steps() + steps: Dict[int, List[FileOperation]] = {} + for path, content in self.files: - dir = os.path.dirname(path) - os.makedirs(dir, exist_ok=True) - with open(path, 'w', encoding='utf8') as f: - f.write(content) + m = re.match(r'.*\.([0-9]+)$', path) + if m: + # Skip writing subsequent incremental steps - rather + # store them as operations. + num = int(m.group(1)) + assert num >= 2 + target_path = re.sub(r'\.[0-9]+$', '', path) + module = module_from_path(target_path) + operation = UpdateFile(module, content, target_path) + steps.setdefault(num, []).append(operation) + else: + # Write the first incremental steps + dir = os.path.dirname(path) + os.makedirs(dir, exist_ok=True) + with open(path, 'w', encoding='utf8') as f: + f.write(content) + + for num, paths in self.deleted_paths.items(): + assert num >= 2 + for path in paths: + module = module_from_path(path) + steps.setdefault(num, []).append(DeleteFile(module, path)) + max_step = max(steps) if steps else 2 + self.steps = [steps.get(num, []) for num in range(2, max_step + 1)] def teardown(self) -> None: assert self.old_cwd is not None and self.tmpdir is not None, \ @@ -307,30 +348,13 @@ def find_steps(self) -> List[List[FileOperation]]: Defaults to having two steps if there aern't any operations. """ - steps = {} # type: Dict[int, List[FileOperation]] - for path, _ in self.files: - m = re.match(r'.*\.([0-9]+)$', path) - if m: - num = int(m.group(1)) - assert num >= 2 - target_path = re.sub(r'\.[0-9]+$', '', path) - module = module_from_path(target_path) - operation = UpdateFile(module, path, target_path) - steps.setdefault(num, []).append(operation) - for num, paths in self.deleted_paths.items(): - assert num >= 2 - for path in paths: - module = module_from_path(path) - steps.setdefault(num, []).append(DeleteFile(module, path)) - max_step = max(steps) if steps else 2 - return [steps.get(num, []) for num in range(2, max_step + 1)] + return self.steps def module_from_path(path: str) -> str: path = re.sub(r'\.pyi?$', '', path) # We can have a mix of Unix-style and Windows-style separators. parts = re.split(r'[/\\]', path) - assert parts[0] == test_temp_dir del parts[0] module = '.'.join(parts) module = re.sub(r'\.__init__$', '', module) @@ -345,11 +369,11 @@ class TestItem: .. data .. """ - id = '' - arg = '' # type: Optional[str] + id = "" + arg: Optional[str] = "" # Text data, array of 8-bit strings - data = None # type: List[str] + data: List[str] file = '' line = 0 # Line number in file @@ -366,11 +390,11 @@ def parse_test_data(raw_data: str, name: str) -> List[TestItem]: """Parse a list of lines that represent a sequence of test items.""" lines = ['', '[case ' + name + ']'] + raw_data.split('\n') - ret = [] # type: List[TestItem] - data = [] # type: List[str] + ret: List[TestItem] = [] + data: List[str] = [] - id = None # type: Optional[str] - arg = None # type: Optional[str] + id: Optional[str] = None + arg: Optional[str] = None i = 0 i0 = 0 @@ -414,7 +438,7 @@ def strip_list(l: List[str]) -> List[str]: lines from the end of the array. """ - r = [] # type: List[str] + r: List[str] = [] for s in l: # Strip spaces at end of line r.append(re.sub(r'\s+$', '', s)) @@ -426,7 +450,7 @@ def strip_list(l: List[str]) -> List[str]: def collapse_line_continuation(l: List[str]) -> List[str]: - r = [] # type: List[str] + r: List[str] = [] cont = False for s in l: ss = re.sub(r'\\$', '', s) @@ -538,12 +562,12 @@ def pytest_pycollect_makeitem(collector: Any, name: str, # The collect method of the returned DataSuiteCollector instance will be called later, # with self.obj being obj. return DataSuiteCollector.from_parent( # type: ignore[no-untyped-call] - parent=collector, name=name + parent=collector, name=name, ) return None -def split_test_cases(parent: 'DataSuiteCollector', suite: 'DataSuite', +def split_test_cases(parent: 'DataFileCollector', suite: 'DataSuite', file: str) -> Iterator['DataDrivenTestCase']: """Iterate over raw test cases in file, at collection time, ignoring sub items. @@ -552,17 +576,25 @@ def split_test_cases(parent: 'DataSuiteCollector', suite: 'DataSuite', """ with open(file, encoding='utf-8') as f: data = f.read() + # number of groups in the below regex + NUM_GROUPS = 7 cases = re.split(r'^\[case ([a-zA-Z_0-9]+)' r'(-writescache)?' r'(-only_when_cache|-only_when_nocache)?' r'(-posix|-windows)?' r'(-skip)?' + r'(-xfail)?' r'\][ \t]*$\n', data, flags=re.DOTALL | re.MULTILINE) line_no = cases[0].count('\n') + 1 - for i in range(1, len(cases), 6): - name, writescache, only_when, platform_flag, skip, data = cases[i:i + 6] + test_names = set() + for i in range(1, len(cases), NUM_GROUPS): + name, writescache, only_when, platform_flag, skip, xfail, data = cases[i:i + NUM_GROUPS] + if name in test_names: + raise RuntimeError('Found a duplicate test name "{}" in {} on line {}'.format( + name, parent.name, line_no, + )) platform = platform_flag[1:] if platform_flag else None yield DataDrivenTestCase.from_parent( parent=parent, @@ -573,20 +605,52 @@ def split_test_cases(parent: 'DataSuiteCollector', suite: 'DataSuite', only_when=only_when, platform=platform, skip=bool(skip), + xfail=bool(xfail), data=data, line=line_no, ) line_no += data.count('\n') + 1 + # Record existing tests to prevent duplicates: + test_names.update({name}) + class DataSuiteCollector(pytest.Class): - def collect(self) -> Iterator[pytest.Item]: + def collect(self) -> Iterator['DataFileCollector']: """Called by pytest on each of the object returned from pytest_pycollect_makeitem""" # obj is the object for which pytest_pycollect_makeitem returned self. - suite = self.obj # type: DataSuite - for f in suite.files: - yield from split_test_cases(self, suite, os.path.join(suite.data_prefix, f)) + suite: DataSuite = self.obj + + assert os.path.isdir(suite.data_prefix), \ + 'Test data prefix ({}) not set correctly'.format(suite.data_prefix) + + for data_file in suite.files: + yield DataFileCollector.from_parent(parent=self, name=data_file) + + +class DataFileCollector(pytest.Collector): + """Represents a single `.test` data driven test file. + + More context: https://github.com/python/mypy/issues/11662 + """ + parent: DataSuiteCollector + + @classmethod # We have to fight with pytest here: + def from_parent( # type: ignore[override] + cls, + parent: DataSuiteCollector, + *, + name: str, + ) -> 'DataFileCollector': + return super().from_parent(parent, name=name) + + def collect(self) -> Iterator['DataDrivenTestCase']: + yield from split_test_cases( + parent=self, + suite=self.parent.obj, + file=os.path.join(self.parent.obj.data_prefix, self.name), + ) def add_test_name_suffix(name: str, suffix: str) -> str: @@ -617,7 +681,7 @@ def has_stable_flags(testcase: DataDrivenTestCase) -> bool: class DataSuite: # option fields - class variables - files = None # type: List[str] + files: List[str] base_path = test_temp_dir diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index 077c2f369cda..fbd44bca868b 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -5,7 +5,7 @@ import shutil import contextlib -from typing import List, Iterable, Dict, Tuple, Callable, Any, Optional, Iterator +from typing import List, Iterable, Dict, Tuple, Callable, Any, Iterator, Union from mypy import defaults import mypy.api as api @@ -18,7 +18,9 @@ from mypy.main import process_options from mypy.options import Options -from mypy.test.data import DataDrivenTestCase, fix_cobertura_filename +from mypy.test.data import ( + DataDrivenTestCase, fix_cobertura_filename, UpdateFile, DeleteFile +) from mypy.test.config import test_temp_dir import mypy.version @@ -50,6 +52,7 @@ def assert_string_arrays_equal(expected: List[str], actual: List[str], Display any differences in a human-readable form. """ + __tracebackhide__ = True actual = clean_up(actual) actual = [line.replace("can't", "cannot") for line in actual] @@ -151,7 +154,7 @@ def update_testcase_output(testcase: DataDrivenTestCase, output: List[str]) -> N data_lines = f.read().splitlines() test = '\n'.join(data_lines[testcase.line:testcase.last_line]) - mapping = {} # type: Dict[str, List[str]] + mapping: Dict[str, List[str]] = {} for old, new in zip(testcase.output, output): PREFIX = 'error:' ind = old.find(PREFIX) @@ -326,18 +329,6 @@ def retry_on_error(func: Callable[[], Any], max_wait: float = 1.0) -> None: raise time.sleep(wait_time) -# TODO: assert_true and assert_false are redundant - use plain assert - - -def assert_true(b: bool, msg: Optional[str] = None) -> None: - if not b: - raise AssertionError(msg) - - -def assert_false(b: bool, msg: Optional[str] = None) -> None: - if b: - raise AssertionError(msg) - def good_repr(obj: object) -> str: if isinstance(obj, str): @@ -352,6 +343,7 @@ def good_repr(obj: object) -> str: def assert_equal(a: object, b: object, fmt: str = '{} != {}') -> None: + __tracebackhide__ = True if a != b: raise AssertionError(fmt.format(good_repr(a), good_repr(b))) @@ -364,6 +356,7 @@ def typename(t: type) -> str: def assert_type(typ: type, value: object) -> None: + __tracebackhide__ = True if type(value) != typ: raise AssertionError('Invalid type {}, expected {}'.format( typename(type(value)), typename(typ))) @@ -413,7 +406,7 @@ def split_lines(*streams: bytes) -> List[str]: ] -def copy_and_fudge_mtime(source_path: str, target_path: str) -> None: +def write_and_fudge_mtime(content: str, target_path: str) -> None: # In some systems, mtime has a resolution of 1 second which can # cause annoying-to-debug issues when a file has the same size # after a change. We manually set the mtime to circumvent this. @@ -425,13 +418,33 @@ def copy_and_fudge_mtime(source_path: str, target_path: str) -> None: if os.path.isfile(target_path): new_time = os.stat(target_path).st_mtime + 1 - # Use retries to work around potential flakiness on Windows (AppVeyor). - retry_on_error(lambda: shutil.copy(source_path, target_path)) + dir = os.path.dirname(target_path) + os.makedirs(dir, exist_ok=True) + with open(target_path, "w", encoding="utf-8") as target: + target.write(content) if new_time: os.utime(target_path, times=(new_time, new_time)) +def perform_file_operations( + operations: List[Union[UpdateFile, DeleteFile]]) -> None: + for op in operations: + if isinstance(op, UpdateFile): + # Modify/create file + write_and_fudge_mtime(op.content, op.target_path) + else: + # Delete file/directory + if os.path.isdir(op.path): + # Sanity check to avoid unexpected deletions + assert op.path.startswith('tmp') + shutil.rmtree(op.path) + else: + # Use retries to work around potential flakiness on Windows (AppVeyor). + path = op.path + retry_on_error(lambda: os.remove(path)) + + def check_test_output_files(testcase: DataDrivenTestCase, step: int, strip_prefix: str = '') -> None: diff --git a/mypy/test/test_find_sources.py b/mypy/test/test_find_sources.py index ba5b613a0948..53da9c384bd2 100644 --- a/mypy/test/test_find_sources.py +++ b/mypy/test/test_find_sources.py @@ -7,7 +7,6 @@ from mypy.find_sources import InvalidSourceList, SourceFinder, create_source_list from mypy.fscache import FileSystemCache -from mypy.modulefinder import BuildSource from mypy.options import Options from mypy.modulefinder import BuildSource @@ -299,7 +298,7 @@ def test_find_sources_exclude(self) -> None: } # file name - options.exclude = r"/f\.py$" + options.exclude = [r"/f\.py$"] fscache = FakeFSCache(files) assert find_sources(["/"], options, fscache) == [ ("a2", "/pkg"), @@ -310,7 +309,7 @@ def test_find_sources_exclude(self) -> None: assert find_sources(["/pkg/a2/b/f.py"], options, fscache) == [('a2.b.f', '/pkg')] # directory name - options.exclude = "/a1/" + options.exclude = ["/a1/"] fscache = FakeFSCache(files) assert find_sources(["/"], options, fscache) == [ ("a2", "/pkg"), @@ -324,13 +323,13 @@ def test_find_sources_exclude(self) -> None: with pytest.raises(InvalidSourceList): find_sources(["/pkg/a1/b"], options, fscache) - options.exclude = "/a1/$" + options.exclude = ["/a1/$"] assert find_sources(["/pkg/a1"], options, fscache) == [ ('e', '/pkg/a1/b/c/d'), ('f', '/pkg/a1/b') ] # paths - options.exclude = "/pkg/a1/" + options.exclude = ["/pkg/a1/"] fscache = FakeFSCache(files) assert find_sources(["/"], options, fscache) == [ ("a2", "/pkg"), @@ -340,15 +339,17 @@ def test_find_sources_exclude(self) -> None: with pytest.raises(InvalidSourceList): find_sources(["/pkg/a1"], options, fscache) - options.exclude = "/(a1|a3)/" - fscache = FakeFSCache(files) - assert find_sources(["/"], options, fscache) == [ - ("a2", "/pkg"), - ("a2.b.c.d.e", "/pkg"), - ("a2.b.f", "/pkg"), - ] + # OR two patterns together + for orred in [["/(a1|a3)/"], ["a1", "a3"], ["a3", "a1"]]: + options.exclude = orred + fscache = FakeFSCache(files) + assert find_sources(["/"], options, fscache) == [ + ("a2", "/pkg"), + ("a2.b.c.d.e", "/pkg"), + ("a2.b.f", "/pkg"), + ] - options.exclude = "b/c/" + options.exclude = ["b/c/"] fscache = FakeFSCache(files) assert find_sources(["/"], options, fscache) == [ ("a2", "/pkg"), @@ -357,19 +358,22 @@ def test_find_sources_exclude(self) -> None: ] # nothing should be ignored as a result of this - options.exclude = "|".join(( + big_exclude1 = [ "/pkg/a/", "/2", "/1", "/pk/", "/kg", "/g.py", "/bc", "/xxx/pkg/a2/b/f.py" "xxx/pkg/a2/b/f.py", - )) - fscache = FakeFSCache(files) - assert len(find_sources(["/"], options, fscache)) == len(files) - - files = { - "pkg/a1/b/c/d/e.py", - "pkg/a1/b/f.py", - "pkg/a2/__init__.py", - "pkg/a2/b/c/d/e.py", - "pkg/a2/b/f.py", - } - fscache = FakeFSCache(files) - assert len(find_sources(["."], options, fscache)) == len(files) + ] + big_exclude2 = ["|".join(big_exclude1)] + for big_exclude in [big_exclude1, big_exclude2]: + options.exclude = big_exclude + fscache = FakeFSCache(files) + assert len(find_sources(["/"], options, fscache)) == len(files) + + files = { + "pkg/a1/b/c/d/e.py", + "pkg/a1/b/f.py", + "pkg/a2/__init__.py", + "pkg/a2/b/c/d/e.py", + "pkg/a2/b/f.py", + } + fscache = FakeFSCache(files) + assert len(find_sources(["."], options, fscache)) == len(files) diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 8a1fb669276e..355a400168f6 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -2,7 +2,6 @@ import os import re -import shutil import sys from typing import Dict, List, Set, Tuple @@ -12,12 +11,12 @@ from mypy.modulefinder import BuildSource, SearchPaths, FindModuleCache from mypy.test.config import test_temp_dir, test_data_prefix from mypy.test.data import ( - DataDrivenTestCase, DataSuite, FileOperation, UpdateFile, module_from_path + DataDrivenTestCase, DataSuite, FileOperation, module_from_path ) from mypy.test.helpers import ( assert_string_arrays_equal, normalize_error_messages, assert_module_equivalence, - retry_on_error, update_testcase_output, parse_options, - copy_and_fudge_mtime, assert_target_equivalence, check_test_output_files + update_testcase_output, parse_options, + assert_target_equivalence, check_test_output_files, perform_file_operations, ) from mypy.errors import CompileError from mypy.semanal_main import core_modules @@ -95,6 +94,9 @@ 'check-generic-alias.test', 'check-typeguard.test', 'check-functools.test', + 'check-singledispatch.test', + 'check-slots.test', + 'check-formatting.test', ] # Tests that use Python 3.8-only AST features (like expression-scoped ignores): @@ -102,6 +104,8 @@ typecheck_files.append('check-python38.test') if sys.version_info >= (3, 9): typecheck_files.append('check-python39.test') +if sys.version_info >= (3, 10): + typecheck_files.append('check-python310.test') # Special tests for platforms with case-insensitive filesystems. if sys.platform in ('darwin', 'win32'): @@ -155,19 +159,7 @@ def run_case_once(self, testcase: DataDrivenTestCase, break elif incremental_step > 1: # In runs 2+, copy *.[num] files to * files. - for op in operations: - if isinstance(op, UpdateFile): - # Modify/create file - copy_and_fudge_mtime(op.source_path, op.target_path) - else: - # Delete file/directory - path = op.path - if os.path.isdir(path): - # Sanity check to avoid unexpected deletions - assert path.startswith('tmp') - shutil.rmtree(path) - # Use retries to work around potential flakiness on Windows (AppVeyor). - retry_on_error(lambda: os.remove(path)) + perform_file_operations(operations) # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) diff --git a/mypy/test/testdaemon.py b/mypy/test/testdaemon.py index 641bd8a70372..804a562e71f1 100644 --- a/mypy/test/testdaemon.py +++ b/mypy/test/testdaemon.py @@ -64,7 +64,7 @@ def parse_script(input: List[str]) -> List[List[str]]: The remaining lines are expected output. """ steps = [] - step = [] # type: List[str] + step: List[str] = [] for line in input: if line.startswith('$'): if step: diff --git a/mypy/test/testdeps.py b/mypy/test/testdeps.py index ea58d49533fc..0b6f4958db75 100644 --- a/mypy/test/testdeps.py +++ b/mypy/test/testdeps.py @@ -49,7 +49,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: if not a: a = ['Unknown compile error (likely syntax error in test case or fixture)'] else: - deps = defaultdict(set) # type: DefaultDict[str, Set[str]] + deps: DefaultDict[str, Set[str]] = defaultdict(set) for module in files: if module in dumped_modules or dump_all and module not in ('abc', 'typing', diff --git a/mypy/test/testerrorstream.py b/mypy/test/testerrorstream.py index a9fbb95a7643..278fc1152504 100644 --- a/mypy/test/testerrorstream.py +++ b/mypy/test/testerrorstream.py @@ -26,7 +26,7 @@ def test_error_stream(testcase: DataDrivenTestCase) -> None: options = Options() options.show_traceback = True - logged_messages = [] # type: List[str] + logged_messages: List[str] = [] def flush_errors(msgs: List[str], serious: bool) -> None: if msgs: diff --git a/mypy/test/testfinegrained.py b/mypy/test/testfinegrained.py index f95748db0a24..ed99b4aeae13 100644 --- a/mypy/test/testfinegrained.py +++ b/mypy/test/testfinegrained.py @@ -14,7 +14,6 @@ import os import re -import shutil from typing import List, Dict, Any, Tuple, Union, cast @@ -27,8 +26,8 @@ DataDrivenTestCase, DataSuite, UpdateFile, DeleteFile ) from mypy.test.helpers import ( - assert_string_arrays_equal, parse_options, copy_and_fudge_mtime, assert_module_equivalence, - assert_target_equivalence + assert_string_arrays_equal, parse_options, assert_module_equivalence, + assert_target_equivalence, perform_file_operations, ) from mypy.server.mergecheck import check_consistency from mypy.dmypy_util import DEFAULT_STATUS_FILE @@ -211,18 +210,7 @@ def perform_step(self, Return (mypy output, triggered targets). """ - for op in operations: - if isinstance(op, UpdateFile): - # Modify/create file - copy_and_fudge_mtime(op.source_path, op.target_path) - else: - # Delete file/directory - if os.path.isdir(op.path): - # Sanity check to avoid unexpected deletions - assert op.path.startswith('tmp') - shutil.rmtree(op.path) - else: - os.remove(op.path) + perform_file_operations(operations) sources = self.parse_sources(main_src, step, options) if step <= num_regular_incremental_steps: @@ -230,9 +218,9 @@ def perform_step(self, else: new_messages = self.run_check(server, sources) - updated = [] # type: List[str] - changed = [] # type: List[str] - targets = [] # type: List[str] + updated: List[str] = [] + changed: List[str] = [] + targets: List[str] = [] triggered = [] if server.fine_grained_manager: if CHECK_CONSISTENCY: @@ -309,7 +297,7 @@ def parse_sources(self, program_text: str, allow_empty_dir=True) def maybe_suggest(self, step: int, server: Server, src: str, tmp_dir: str) -> List[str]: - output = [] # type: List[str] + output: List[str] = [] targets = self.get_suggest(src, step) for flags, target in targets: json = '--json' in flags diff --git a/mypy/test/testgraph.py b/mypy/test/testgraph.py index 3a6a8f70899a..d713828ca44c 100644 --- a/mypy/test/testgraph.py +++ b/mypy/test/testgraph.py @@ -22,16 +22,13 @@ def test_topsort(self) -> None: b = frozenset({'B'}) c = frozenset({'C'}) d = frozenset({'D'}) - data = {a: {b, c}, b: {d}, c: {d}} # type: Dict[AbstractSet[str], Set[AbstractSet[str]]] + data: Dict[AbstractSet[str], Set[AbstractSet[str]]] = {a: {b, c}, b: {d}, c: {d}} res = list(topsort(data)) assert_equal(res, [{d}, {b, c}, {a}]) def test_scc(self) -> None: - vertices = {'A', 'B', 'C', 'D'} - edges = {'A': ['B', 'C'], - 'B': ['C'], - 'C': ['B', 'D'], - 'D': []} # type: Dict[str, List[str]] + vertices = {"A", "B", "C", "D"} + edges: Dict[str, List[str]] = {"A": ["B", "C"], "B": ["C"], "C": ["B", "D"], "D": []} sccs = set(frozenset(x) for x in strongly_connected_components(vertices, edges)) assert_equal(sccs, {frozenset({'A'}), diff --git a/mypy/test/testinfer.py b/mypy/test/testinfer.py index 0c2f55bc69ad..afb66a7d09e1 100644 --- a/mypy/test/testinfer.py +++ b/mypy/test/testinfer.py @@ -6,7 +6,7 @@ from mypy.argmap import map_actuals_to_formals from mypy.checker import group_comparison_operands, DisjointDict from mypy.literals import Key -from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, ARG_NAMED, NameExpr +from mypy.nodes import ArgKind, ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, ARG_NAMED, NameExpr from mypy.types import AnyType, TupleType, Type, TypeOfAny from mypy.test.typefixture import TypeFixture @@ -170,8 +170,8 @@ def test_special_cases(self) -> None: [[0]]) def assert_map(self, - caller_kinds_: List[Union[int, str]], - callee_kinds_: List[Union[int, Tuple[int, str]]], + caller_kinds_: List[Union[ArgKind, str]], + callee_kinds_: List[Union[ArgKind, Tuple[ArgKind, str]]], expected: List[List[int]], ) -> None: caller_kinds, caller_names = expand_caller_kinds(caller_kinds_) @@ -185,8 +185,8 @@ def assert_map(self, assert_equal(result, expected) def assert_vararg_map(self, - caller_kinds: List[int], - callee_kinds: List[int], + caller_kinds: List[ArgKind], + callee_kinds: List[ArgKind], expected: List[List[int]], vararg_type: Type, ) -> None: @@ -199,10 +199,10 @@ def assert_vararg_map(self, assert_equal(result, expected) -def expand_caller_kinds(kinds_or_names: List[Union[int, str]] - ) -> Tuple[List[int], List[Optional[str]]]: +def expand_caller_kinds(kinds_or_names: List[Union[ArgKind, str]] + ) -> Tuple[List[ArgKind], List[Optional[str]]]: kinds = [] - names = [] # type: List[Optional[str]] + names: List[Optional[str]] = [] for k in kinds_or_names: if isinstance(k, str): kinds.append(ARG_NAMED) @@ -213,10 +213,10 @@ def expand_caller_kinds(kinds_or_names: List[Union[int, str]] return kinds, names -def expand_callee_kinds(kinds_and_names: List[Union[int, Tuple[int, str]]] - ) -> Tuple[List[int], List[Optional[str]]]: +def expand_callee_kinds(kinds_and_names: List[Union[ArgKind, Tuple[ArgKind, str]]] + ) -> Tuple[List[ArgKind], List[Optional[str]]]: kinds = [] - names = [] # type: List[Optional[str]] + names: List[Optional[str]] = [] for v in kinds_and_names: if isinstance(v, tuple): kinds.append(v[0]) @@ -287,7 +287,7 @@ def test_merge_with_multiple_overlaps(self) -> None: class OperandComparisonGroupingSuite(Suite): """Test cases for checker.group_comparison_operands.""" def literal_keymap(self, assignable_operands: Dict[int, NameExpr]) -> Dict[int, Key]: - output = {} # type: Dict[int, Key] + output: Dict[int, Key] = {} for index, expr in assignable_operands.items(): output[index] = ('FakeExpr', expr.name) return output @@ -437,10 +437,10 @@ def test_single_pair(self) -> None: single_comparison = [('==', x0, x1)] expected_output = [('==', [0, 1])] - assignable_combinations = [ + assignable_combinations: List[Dict[int, NameExpr]] = [ {}, {0: x0}, {1: x1}, {0: x0, 1: x1}, - ] # type: List[Dict[int, NameExpr]] - to_group_by = [set(), {'=='}, {'is'}] # type: List[Set[str]] + ] + to_group_by: List[Set[str]] = [set(), {"=="}, {"is"}] for combo in assignable_combinations: for operators in to_group_by: diff --git a/mypy/test/testipc.py b/mypy/test/testipc.py index 7dd829a59079..462fd44c8800 100644 --- a/mypy/test/testipc.py +++ b/mypy/test/testipc.py @@ -23,7 +23,7 @@ def server(msg: str, q: 'Queue[str]') -> None: class IPCTests(TestCase): def test_transaction_large(self) -> None: - queue = Queue() # type: Queue[str] + queue: Queue[str] = Queue() msg = 't' * 200000 # longer than the max read size of 100_000 p = Process(target=server, args=(msg, queue), daemon=True) p.start() @@ -36,7 +36,7 @@ def test_transaction_large(self) -> None: p.join() def test_connect_twice(self) -> None: - queue = Queue() # type: Queue[str] + queue: Queue[str] = Queue() msg = 'this is a test message' p = Process(target=server, args=(msg, queue), daemon=True) p.start() diff --git a/mypy/test/testmerge.py b/mypy/test/testmerge.py index c7fcbda01c04..92562d10134d 100644 --- a/mypy/test/testmerge.py +++ b/mypy/test/testmerge.py @@ -49,7 +49,7 @@ def setup(self) -> None: super().setup() self.str_conv = StrConv(show_ids=True) assert self.str_conv.id_mapper is not None - self.id_mapper = self.str_conv.id_mapper # type: IdMapper + self.id_mapper: IdMapper = self.str_conv.id_mapper self.type_str_conv = TypeStrVisitor(self.id_mapper) def run_case(self, testcase: DataDrivenTestCase) -> None: diff --git a/mypy/test/testmodulefinder.py b/mypy/test/testmodulefinder.py index 4f839f641e7b..d26e7c1efe0c 100644 --- a/mypy/test/testmodulefinder.py +++ b/mypy/test/testmodulefinder.py @@ -184,6 +184,13 @@ def test__packages_with_ns(self) -> None: ("ns_pkg_untyped.b.c", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), ("ns_pkg_untyped.a.a_var", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + # Namespace package without stub package + ("ns_pkg_w_stubs", self.path("ns_pkg_w_stubs")), + ("ns_pkg_w_stubs.typed", self.path("ns_pkg_w_stubs-stubs", "typed", "__init__.pyi")), + ("ns_pkg_w_stubs.typed_inline", + self.path("ns_pkg_w_stubs", "typed_inline", "__init__.py")), + ("ns_pkg_w_stubs.untyped", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + # Regular package with py.typed ("pkg_typed", self.path("pkg_typed", "__init__.py")), ("pkg_typed.a", self.path("pkg_typed", "a.py")), @@ -239,6 +246,13 @@ def test__packages_without_ns(self) -> None: ("ns_pkg_untyped.b.c", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), ("ns_pkg_untyped.a.a_var", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + # Namespace package without stub package + ("ns_pkg_w_stubs", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + ("ns_pkg_w_stubs.typed", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + ("ns_pkg_w_stubs.typed_inline", + self.path("ns_pkg_w_stubs", "typed_inline", "__init__.py")), + ("ns_pkg_w_stubs.untyped", ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS), + # Regular package with py.typed ("pkg_typed", self.path("pkg_typed", "__init__.py")), ("pkg_typed.a", self.path("pkg_typed", "a.py")), diff --git a/mypy/test/testpep561.py b/mypy/test/testpep561.py index ba5be621e066..d30d94c49bee 100644 --- a/mypy/test/testpep561.py +++ b/mypy/test/testpep561.py @@ -13,31 +13,18 @@ from mypy.util import try_find_python2_interpreter from mypy.test.data import DataDrivenTestCase, DataSuite from mypy.test.config import test_temp_dir -from mypy.test.helpers import assert_string_arrays_equal +from mypy.test.helpers import assert_string_arrays_equal, perform_file_operations # NOTE: options.use_builtins_fixtures should not be set in these # tests, otherwise mypy will ignore installed third-party packages. -_NAMESPACE_PROGRAM = """ -{import_style} -from typedpkg_ns.ns.dne import dne - -af("abc") -bf(False) -dne(123) - -af(False) -bf(2) -dne("abc") -""" - - class PEP561Suite(DataSuite): files = [ 'pep561.test', ] + base_path = '.' def run_case(self, test_case: DataDrivenTestCase) -> None: test_pep561(test_case) @@ -75,7 +62,7 @@ def install_package(pkg: str, working_dir = os.path.join(package_path, pkg) with tempfile.TemporaryDirectory() as dir: if use_pip: - install_cmd = [python_executable, '-m', 'pip', 'install', '-b', '{}'.format(dir)] + install_cmd = [python_executable, '-m', 'pip', 'install'] if editable: install_cmd.append('-e') install_cmd.append('.') @@ -85,16 +72,22 @@ def install_package(pkg: str, install_cmd.append('develop') else: install_cmd.append('install') - proc = subprocess.run(install_cmd, cwd=working_dir, stdout=PIPE, stderr=PIPE) + # Note that newer versions of pip (21.3+) don't + # follow this env variable, but this is for compatibility + env = {'PIP_BUILD': dir} + # Inherit environment for Windows + env.update(os.environ) + proc = subprocess.run(install_cmd, + cwd=working_dir, + stdout=PIPE, + stderr=PIPE, + env=env) if proc.returncode != 0: raise Exception(proc.stdout.decode('utf-8') + proc.stderr.decode('utf-8')) def test_pep561(testcase: DataDrivenTestCase) -> None: """Test running mypy on files that depend on PEP 561 packages.""" - if (sys.platform == 'darwin' and hasattr(sys, 'base_prefix') and - sys.base_prefix != sys.prefix): - pytest.skip() assert testcase.old_cwd is not None, "test was not properly set up" if 'python2' in testcase.name.lower(): python = try_find_python2_interpreter() @@ -102,6 +95,7 @@ def test_pep561(testcase: DataDrivenTestCase) -> None: pytest.skip() else: python = sys.executable + assert python is not None, "Should be impossible" pkgs, pip_args = parse_pkgs(testcase.input[0]) mypy_args = parse_mypy_args(testcase.input[1]) @@ -118,34 +112,30 @@ def test_pep561(testcase: DataDrivenTestCase) -> None: for pkg in pkgs: install_package(pkg, python_executable, use_pip, editable) - if venv_dir is not None: - old_dir = os.getcwd() - os.chdir(venv_dir) - try: - cmd_line = list(mypy_args) - has_program = not ('-p' in cmd_line or '--package' in cmd_line) - if has_program: - program = testcase.name + '.py' - with open(program, 'w', encoding='utf-8') as f: - for s in testcase.input: - f.write('{}\n'.format(s)) - cmd_line.append(program) - cmd_line.extend(['--no-incremental', '--no-error-summary']) - if python_executable != sys.executable: - cmd_line.append('--python-executable={}'.format(python_executable)) - if testcase.files != []: - for name, content in testcase.files: - if 'mypy.ini' in name: - with open('mypy.ini', 'w') as m: - m.write(content) - elif 'pyproject.toml' in name: - with open('pyproject.toml', 'w') as m: - m.write(content) + cmd_line = list(mypy_args) + has_program = not ('-p' in cmd_line or '--package' in cmd_line) + if has_program: + program = testcase.name + '.py' + with open(program, 'w', encoding='utf-8') as f: + for s in testcase.input: + f.write('{}\n'.format(s)) + cmd_line.append(program) + + cmd_line.extend(['--no-error-summary']) + if python_executable != sys.executable: + cmd_line.append('--python-executable={}'.format(python_executable)) + + steps = testcase.find_steps() + if steps != [[]]: + steps = [[]] + steps # type: ignore[operator,assignment] + + for i, operations in enumerate(steps): + perform_file_operations(operations) + output = [] # Type check the module out, err, returncode = mypy.api.run(cmd_line) - if has_program: - os.remove(program) + # split lines, remove newlines, and remove directory of test case for line in (out + err).splitlines(): if line.startswith(test_temp_dir + os.sep): @@ -154,12 +144,15 @@ def test_pep561(testcase: DataDrivenTestCase) -> None: # Normalize paths so that the output is the same on Windows and Linux/macOS. line = line.replace(test_temp_dir + os.sep, test_temp_dir + '/') output.append(line.rstrip("\r\n")) - assert_string_arrays_equal([line for line in testcase.output], output, - 'Invalid output ({}, line {})'.format( - testcase.file, testcase.line)) - finally: - if venv_dir is not None: - os.chdir(old_dir) + iter_count = '' if i == 0 else ' on iteration {}'.format(i + 1) + expected = testcase.output if i == 0 else testcase.output2.get(i + 1, []) + + assert_string_arrays_equal(expected, output, + 'Invalid output ({}, line {}){}'.format( + testcase.file, testcase.line, iter_count)) + + if has_program: + os.remove(program) def parse_pkgs(comment: str) -> Tuple[List[str], List[str]]: @@ -177,9 +170,6 @@ def parse_mypy_args(line: str) -> List[str]: return m.group(1).split() -@pytest.mark.skipif(sys.platform == 'darwin' and hasattr(sys, 'base_prefix') and - sys.base_prefix != sys.prefix, - reason="Temporarily skip to avoid having a virtualenv within a venv.") def test_mypy_path_is_respected() -> None: assert False packages = 'packages' diff --git a/mypy/test/testpythoneval.py b/mypy/test/testpythoneval.py index ae4b79c54faa..61e6d7fb839f 100644 --- a/mypy/test/testpythoneval.py +++ b/mypy/test/testpythoneval.py @@ -72,6 +72,10 @@ def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None interpreter = python3_path mypy_cmdline.append('--python-version={}'.format('.'.join(map(str, PYTHON3_VERSION)))) + m = re.search('# flags: (.*)$', '\n'.join(testcase.input), re.MULTILINE) + if m: + mypy_cmdline.extend(m.group(1).split()) + # Write the program to a file. program = '_' + testcase.name + '.py' program_path = os.path.join(test_temp_dir, program) diff --git a/mypy/test/testsamples.py b/mypy/test/testsamples.py index 24c7702a274b..27b26af16f36 100644 --- a/mypy/test/testsamples.py +++ b/mypy/test/testsamples.py @@ -16,9 +16,9 @@ def test_samples(self) -> None: run_mypy(mypy_args + [f]) def test_stdlibsamples(self) -> None: - seen = set() # type: Set[str] + seen: Set[str] = set() stdlibsamples_dir = os.path.join('test-data', 'stdlib-samples', '3.2', 'test') - modules = [] # type: List[str] + modules: List[str] = [] for f in find_files(stdlibsamples_dir, prefix='test_', suffix='.py'): if f not in seen: seen.add(f) diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index e42a84e8365b..a71bac53619d 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -20,19 +20,22 @@ # Semantic analyzer test cases: dump parse tree # Semantic analysis test case description files. -semanal_files = ['semanal-basic.test', - 'semanal-expressions.test', - 'semanal-classes.test', - 'semanal-types.test', - 'semanal-typealiases.test', - 'semanal-modules.test', - 'semanal-statements.test', - 'semanal-abstractclasses.test', - 'semanal-namedtuple.test', - 'semanal-typeddict.test', - 'semenal-literal.test', - 'semanal-classvar.test', - 'semanal-python2.test'] +semanal_files = [ + 'semanal-basic.test', + 'semanal-expressions.test', + 'semanal-classes.test', + 'semanal-types.test', + 'semanal-typealiases.test', + 'semanal-modules.test', + 'semanal-statements.test', + 'semanal-abstractclasses.test', + 'semanal-namedtuple.test', + 'semanal-typeddict.test', + 'semenal-literal.test', + 'semanal-classvar.test', + 'semanal-python2.test', + 'semanal-lambda.test', +] def get_semanal_options(program_text: str, testcase: DataDrivenTestCase) -> Options: @@ -195,7 +198,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: class TypeInfoMap(Dict[str, TypeInfo]): def __str__(self) -> str: - a = ['TypeInfoMap('] # type: List[str] + a: List[str] = ["TypeInfoMap("] for x, y in sorted(self.items()): if isinstance(x, str) and (not x.startswith('builtins.') and not x.startswith('typing.') and diff --git a/mypy/test/testsolve.py b/mypy/test/testsolve.py index 172e4e4743c4..fd4189277907 100644 --- a/mypy/test/testsolve.py +++ b/mypy/test/testsolve.py @@ -115,7 +115,7 @@ def assert_solve(self, constraints: List[Constraint], results: List[Union[None, Type, Tuple[Type, Type]]], ) -> None: - res = [] # type: List[Optional[Type]] + res: List[Optional[Type]] = [] for r in results: if isinstance(r, tuple): res.append(r[0]) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 62feb0784a42..c999e3c82643 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -187,6 +187,8 @@ def test_find_unique_signatures(self) -> None: def test_infer_sig_from_docstring(self) -> None: assert_equal(infer_sig_from_docstring('\nfunc(x) - y', 'func'), [FunctionSig(name='func', args=[ArgSig(name='x')], ret_type='Any')]) + assert_equal(infer_sig_from_docstring('\nfunc(x)', 'func'), + [FunctionSig(name='func', args=[ArgSig(name='x')], ret_type='Any')]) assert_equal(infer_sig_from_docstring('\nfunc(x, Y_a=None)', 'func'), [FunctionSig(name='func', @@ -218,6 +220,13 @@ def test_infer_sig_from_docstring(self) -> None: [FunctionSig(name='func', args=[ArgSig(name='x', type='int', default=True)], ret_type='Any')]) + assert_equal(infer_sig_from_docstring('\nfunc(x=3)', 'func'), + [FunctionSig(name='func', args=[ArgSig(name='x', type=None, default=True)], + ret_type='Any')]) + + assert_equal(infer_sig_from_docstring('\nfunc() -> int', 'func'), + [FunctionSig(name='func', args=[], ret_type='int')]) + assert_equal(infer_sig_from_docstring('\nfunc(x: int=3) -> int', 'func'), [FunctionSig(name='func', args=[ArgSig(name='x', type='int', default=True)], ret_type='int')]) @@ -577,7 +586,7 @@ def run_case_inner(self, testcase: DataDrivenTestCase) -> None: if not testcase.name.endswith('_semanal'): options.parse_only = True generate_stubs(options) - a = [] # type: List[str] + a: List[str] = [] for module in modules: fnam = module_to_path(out_dir, module) self.add_file(fnam, a, header=len(modules) > 1) @@ -659,9 +668,9 @@ def test_infer_unary_op_sig(self) -> None: assert_equal(infer_method_sig('__%s__' % op), [self_arg]) def test_generate_c_type_stub_no_crash_for_object(self) -> None: - output = [] # type: List[str] + output: List[str] = [] mod = ModuleType('module', '') # any module is fine - imports = [] # type: List[str] + imports: List[str] = [] generate_c_type_stub(mod, 'alias', object, output, imports) assert_equal(imports, []) assert_equal(output[0], 'class alias:') @@ -671,8 +680,8 @@ def test_generate_c_type_stub_variable_type_annotation(self) -> None: class TestClassVariableCls: x = 1 - output = [] # type: List[str] - imports = [] # type: List[str] + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('module', '') # any module is fine generate_c_type_stub(mod, 'C', TestClassVariableCls, output, imports) assert_equal(imports, []) @@ -682,16 +691,16 @@ def test_generate_c_type_inheritance(self) -> None: class TestClass(KeyError): pass - output = [] # type: List[str] - imports = [] # type: List[str] + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('module, ') generate_c_type_stub(mod, 'C', TestClass, output, imports) assert_equal(output, ['class C(KeyError): ...', ]) assert_equal(imports, []) def test_generate_c_type_inheritance_same_module(self) -> None: - output = [] # type: List[str] - imports = [] # type: List[str] + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestBaseClass.__module__, '') generate_c_type_stub(mod, 'C', TestClass, output, imports) assert_equal(output, ['class C(TestBaseClass): ...', ]) @@ -703,8 +712,8 @@ def test_generate_c_type_inheritance_other_module(self) -> None: class TestClass(argparse.Action): pass - output = [] # type: List[str] - imports = [] # type: List[str] + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('module', '') generate_c_type_stub(mod, 'C', TestClass, output, imports) assert_equal(output, ['class C(argparse.Action): ...', ]) @@ -713,8 +722,9 @@ class TestClass(argparse.Action): def test_generate_c_type_inheritance_builtin_type(self) -> None: class TestClass(type): pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('module', '') generate_c_type_stub(mod, 'C', TestClass, output, imports) assert_equal(output, ['class C(type): ...', ]) @@ -727,6 +737,22 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: int) """ pass + + output: List[str] = [] + imports: List[str] = [] + mod = ModuleType(TestClass.__module__, '') + generate_c_function_stub(mod, 'test', TestClass.test, output, imports, + self_var='self', class_name='TestClass') + assert_equal(output, ['def test(self, arg0: int) -> Any: ...']) + assert_equal(imports, []) + + def test_generate_c_type_with_docstring_no_self_arg(self) -> None: + class TestClass: + def test(self, arg0: str) -> None: + """ + test(arg0: int) + """ + pass output = [] # type: List[str] imports = [] # type: List[str] mod = ModuleType(TestClass.__module__, '') @@ -735,6 +761,19 @@ def test(self, arg0: str) -> None: assert_equal(output, ['def test(self, arg0: int) -> Any: ...']) assert_equal(imports, []) + def test_generate_c_type_classmethod(self) -> None: + class TestClass: + @classmethod + def test(cls, arg0: str) -> None: + pass + output = [] # type: List[str] + imports = [] # type: List[str] + mod = ModuleType(TestClass.__module__, '') + generate_c_function_stub(mod, 'test', TestClass.test, output, imports, + self_var='cls', class_name='TestClass') + assert_equal(output, ['def test(cls, *args, **kwargs) -> Any: ...']) + assert_equal(imports, []) + def test_generate_c_type_with_docstring_empty_default(self) -> None: class TestClass: def test(self, arg0: str = "") -> None: @@ -742,8 +781,9 @@ def test(self, arg0: str = "") -> None: test(self: TestClass, arg0: str = "") """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -759,8 +799,9 @@ def test(arg0: str) -> None: test(arg0: argparse.Action) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(self.__module__, '') generate_c_function_stub(mod, 'test', test, output, imports) assert_equal(output, ['def test(arg0: argparse.Action) -> Any: ...']) @@ -777,8 +818,9 @@ def test(arg0: str) -> None: test(arg0: argparse.Action) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('argparse', '') generate_c_function_stub(mod, 'test', test, output, imports) assert_equal(output, ['def test(arg0: Action) -> Any: ...']) @@ -791,8 +833,9 @@ def test(arg0: str) -> None: test(arg0: str) -> argparse.Action """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(self.__module__, '') generate_c_function_stub(mod, 'test', test, output, imports) assert_equal(output, ['def test(arg0: str) -> argparse.Action: ...']) @@ -807,8 +850,9 @@ def test(arg0: str) -> None: test(arg0: str) -> argparse.Action """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType('argparse', '') generate_c_function_stub(mod, 'test', test, output, imports) assert_equal(output, ['def test(arg0: str) -> Action: ...']) @@ -824,7 +868,7 @@ def get_attribute(self) -> None: pass attribute = property(get_attribute, doc="") - output = [] # type: List[str] + output: List[str] = [] generate_c_property_stub('attribute', TestClass.attribute, [], [], output, readonly=True) assert_equal(output, ['@property', 'def attribute(self) -> str: ...']) @@ -835,8 +879,9 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: List[int]) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -850,8 +895,9 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: Dict[str, int]) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -865,8 +911,9 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: Dict[str, List[int]]) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -880,8 +927,9 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: Dict[argparse.Action, int]) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -895,8 +943,9 @@ def test(self, arg0: str) -> None: test(self: TestClass, arg0: Dict[str, argparse.Action]) """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, 'test', TestClass.test, output, imports, self_var='self', class_name='TestClass') @@ -915,8 +964,9 @@ def __init__(self, arg0: str) -> None: 2. __init__(self: TestClass, arg0: str, arg1: str) -> None """ pass - output = [] # type: List[str] - imports = [] # type: List[str] + + output: List[str] = [] + imports: List[str] = [] mod = ModuleType(TestClass.__module__, '') generate_c_function_stub(mod, '__init__', TestClass.__init__, output, imports, self_var='self', class_name='TestClass') diff --git a/mypy/test/teststubinfo.py b/mypy/test/teststubinfo.py new file mode 100644 index 000000000000..62346ce2bc9f --- /dev/null +++ b/mypy/test/teststubinfo.py @@ -0,0 +1,18 @@ +import unittest + +from mypy.stubinfo import is_legacy_bundled_package + + +class TestStubInfo(unittest.TestCase): + def test_is_legacy_bundled_packages(self) -> None: + assert not is_legacy_bundled_package('foobar_asdf', 2) + assert not is_legacy_bundled_package('foobar_asdf', 3) + + assert is_legacy_bundled_package('certifi', 2) + assert is_legacy_bundled_package('certifi', 3) + + assert is_legacy_bundled_package('scribe', 2) + assert not is_legacy_bundled_package('scribe', 3) + + assert not is_legacy_bundled_package('dataclasses', 2) + assert is_legacy_bundled_package('dataclasses', 3) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 0ce5df00aafd..e6eb8465c665 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -52,6 +52,8 @@ class bool(int): ... class str: ... class bytes: ... +class list(Sequence[T]): ... + def property(f: T) -> T: ... def classmethod(f: T) -> T: ... def staticmethod(f: T) -> T: ... @@ -571,6 +573,30 @@ def __init__(self): error=None, ) + @collect_cases + def test_type_alias(self) -> Iterator[Case]: + yield Case( + stub=""" + class X: + def f(self) -> None: ... + Y = X + """, + runtime=""" + class X: + def f(self) -> None: ... + class Y: ... + """, + error="Y.f", + ) + yield Case( + stub=""" + from typing import Tuple + A = Tuple[int, str] + """, + runtime="A = (int, str)", + error="A", + ) + @collect_cases def test_enum(self) -> Iterator[Case]: yield Case( @@ -624,7 +650,7 @@ def h(x: str): ... runtime="", error="h", ) - yield Case("", "__all__ = []", None) # dummy case + yield Case(stub="", runtime="__all__ = []", error=None) # dummy case yield Case(stub="", runtime="__all__ += ['y']\ny = 5", error="y") yield Case(stub="", runtime="__all__ += ['g']\ndef g(): pass", error="g") # Here we should only check that runtime has B, since the stub explicitly re-exports it @@ -636,6 +662,20 @@ def h(x: str): ... def test_missing_no_runtime_all(self) -> Iterator[Case]: yield Case(stub="", runtime="import sys", error=None) yield Case(stub="", runtime="def g(): ...", error="g") + yield Case(stub="", runtime="CONSTANT = 0", error="CONSTANT") + + @collect_cases + def test_non_public_1(self) -> Iterator[Case]: + yield Case(stub="__all__: list[str]", runtime="", error=None) # dummy case + yield Case(stub="_f: int", runtime="def _f(): ...", error="_f") + + @collect_cases + def test_non_public_2(self) -> Iterator[Case]: + yield Case( + stub="__all__: list[str] = ['f']", runtime="__all__ = ['f']", error=None + ) + yield Case(stub="f: int", runtime="def f(): ...", error="f") + yield Case(stub="g: int", runtime="def g(): ...", error="g") @collect_cases def test_special_dunders(self) -> Iterator[Case]: diff --git a/mypy/test/testsubtypes.py b/mypy/test/testsubtypes.py index 876f3eaf3c74..5776d67a5184 100644 --- a/mypy/test/testsubtypes.py +++ b/mypy/test/testsubtypes.py @@ -1,4 +1,4 @@ -from mypy.test.helpers import Suite, assert_true, skip +from mypy.test.helpers import Suite, skip from mypy.nodes import CONTRAVARIANT, INVARIANT, COVARIANT from mypy.subtypes import is_subtype from mypy.test.typefixture import TypeFixture, InterfaceTypeFixture @@ -188,10 +188,10 @@ def test_type_callable_subtyping(self) -> None: # * generic function types def assert_subtype(self, s: Type, t: Type) -> None: - assert_true(is_subtype(s, t), '{} not subtype of {}'.format(s, t)) + assert is_subtype(s, t), '{} not subtype of {}'.format(s, t) def assert_not_subtype(self, s: Type, t: Type) -> None: - assert_true(not is_subtype(s, t), '{} subtype of {}'.format(s, t)) + assert not is_subtype(s, t), '{} subtype of {}'.format(s, t) def assert_strict_subtype(self, s: Type, t: Type) -> None: self.assert_subtype(s, t) diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 07c8682f10ea..0d37fe795bbc 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -2,7 +2,7 @@ from typing import List, Tuple -from mypy.test.helpers import Suite, assert_equal, assert_true, assert_false, assert_type, skip +from mypy.test.helpers import Suite, assert_equal, assert_type, skip from mypy.erasetype import erase_type from mypy.expandtype import expand_type from mypy.join import join_types, join_simple @@ -10,7 +10,7 @@ from mypy.sametypes import is_same_type from mypy.indirection import TypeIndirectionVisitor from mypy.types import ( - UnboundType, AnyType, CallableType, TupleType, TypeVarDef, Type, Instance, NoneType, + UnboundType, AnyType, CallableType, TupleType, TypeVarType, Type, Instance, NoneType, Overloaded, TypeType, UnionType, UninhabitedType, TypeVarId, TypeOfAny, get_proper_type ) from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, CONTRAVARIANT, INVARIANT, COVARIANT @@ -77,18 +77,18 @@ def test_tuple_type(self) -> None: self.fx.std_tuple)), 'Tuple[X?, Any]') def test_type_variable_binding(self) -> None: - assert_equal(str(TypeVarDef('X', 'X', 1, [], self.fx.o)), 'X') - assert_equal(str(TypeVarDef('X', 'X', 1, [self.x, self.y], self.fx.o)), - 'X in (X?, Y?)') + assert_equal(str(TypeVarType('X', 'X', 1, [], self.fx.o)), 'X`1') + assert_equal(str(TypeVarType('X', 'X', 1, [self.x, self.y], self.fx.o)), + 'X`1') def test_generic_function_type(self) -> None: c = CallableType([self.x, self.y], [ARG_POS, ARG_POS], [None, None], self.y, self.function, name=None, - variables=[TypeVarDef('X', 'X', -1, [], self.fx.o)]) + variables=[TypeVarType('X', 'X', -1, [], self.fx.o)]) assert_equal(str(c), 'def [X] (X?, Y?) -> Y?') - v = [TypeVarDef('Y', 'Y', -1, [], self.fx.o), - TypeVarDef('X', 'X', -2, [], self.fx.o)] + v = [TypeVarType('Y', 'Y', -1, [], self.fx.o), + TypeVarType('X', 'X', -2, [], self.fx.o)] c2 = CallableType([], [], [], NoneType(), self.function, name=None, variables=v) assert_equal(str(c2), 'def [Y, X] ()') @@ -225,75 +225,75 @@ def assert_erase(self, orig: Type, result: Type) -> None: def test_is_more_precise(self) -> None: fx = self.fx - assert_true(is_more_precise(fx.b, fx.a)) - assert_true(is_more_precise(fx.b, fx.b)) - assert_true(is_more_precise(fx.b, fx.b)) - assert_true(is_more_precise(fx.b, fx.anyt)) - assert_true(is_more_precise(self.tuple(fx.b, fx.a), - self.tuple(fx.b, fx.a))) - assert_true(is_more_precise(self.tuple(fx.b, fx.b), - self.tuple(fx.b, fx.a))) - - assert_false(is_more_precise(fx.a, fx.b)) - assert_false(is_more_precise(fx.anyt, fx.b)) + assert is_more_precise(fx.b, fx.a) + assert is_more_precise(fx.b, fx.b) + assert is_more_precise(fx.b, fx.b) + assert is_more_precise(fx.b, fx.anyt) + assert is_more_precise(self.tuple(fx.b, fx.a), + self.tuple(fx.b, fx.a)) + assert is_more_precise(self.tuple(fx.b, fx.b), + self.tuple(fx.b, fx.a)) + + assert not is_more_precise(fx.a, fx.b) + assert not is_more_precise(fx.anyt, fx.b) # is_proper_subtype def test_is_proper_subtype(self) -> None: fx = self.fx - assert_true(is_proper_subtype(fx.a, fx.a)) - assert_true(is_proper_subtype(fx.b, fx.a)) - assert_true(is_proper_subtype(fx.b, fx.o)) - assert_true(is_proper_subtype(fx.b, fx.o)) + assert is_proper_subtype(fx.a, fx.a) + assert is_proper_subtype(fx.b, fx.a) + assert is_proper_subtype(fx.b, fx.o) + assert is_proper_subtype(fx.b, fx.o) - assert_false(is_proper_subtype(fx.a, fx.b)) - assert_false(is_proper_subtype(fx.o, fx.b)) + assert not is_proper_subtype(fx.a, fx.b) + assert not is_proper_subtype(fx.o, fx.b) - assert_true(is_proper_subtype(fx.anyt, fx.anyt)) - assert_false(is_proper_subtype(fx.a, fx.anyt)) - assert_false(is_proper_subtype(fx.anyt, fx.a)) + assert is_proper_subtype(fx.anyt, fx.anyt) + assert not is_proper_subtype(fx.a, fx.anyt) + assert not is_proper_subtype(fx.anyt, fx.a) - assert_true(is_proper_subtype(fx.ga, fx.ga)) - assert_true(is_proper_subtype(fx.gdyn, fx.gdyn)) - assert_false(is_proper_subtype(fx.ga, fx.gdyn)) - assert_false(is_proper_subtype(fx.gdyn, fx.ga)) + assert is_proper_subtype(fx.ga, fx.ga) + assert is_proper_subtype(fx.gdyn, fx.gdyn) + assert not is_proper_subtype(fx.ga, fx.gdyn) + assert not is_proper_subtype(fx.gdyn, fx.ga) - assert_true(is_proper_subtype(fx.t, fx.t)) - assert_false(is_proper_subtype(fx.t, fx.s)) + assert is_proper_subtype(fx.t, fx.t) + assert not is_proper_subtype(fx.t, fx.s) - assert_true(is_proper_subtype(fx.a, UnionType([fx.a, fx.b]))) - assert_true(is_proper_subtype(UnionType([fx.a, fx.b]), - UnionType([fx.a, fx.b, fx.c]))) - assert_false(is_proper_subtype(UnionType([fx.a, fx.b]), - UnionType([fx.b, fx.c]))) + assert is_proper_subtype(fx.a, UnionType([fx.a, fx.b])) + assert is_proper_subtype(UnionType([fx.a, fx.b]), + UnionType([fx.a, fx.b, fx.c])) + assert not is_proper_subtype(UnionType([fx.a, fx.b]), + UnionType([fx.b, fx.c])) def test_is_proper_subtype_covariance(self) -> None: fx_co = self.fx_co - assert_true(is_proper_subtype(fx_co.gsab, fx_co.gb)) - assert_true(is_proper_subtype(fx_co.gsab, fx_co.ga)) - assert_false(is_proper_subtype(fx_co.gsaa, fx_co.gb)) - assert_true(is_proper_subtype(fx_co.gb, fx_co.ga)) - assert_false(is_proper_subtype(fx_co.ga, fx_co.gb)) + assert is_proper_subtype(fx_co.gsab, fx_co.gb) + assert is_proper_subtype(fx_co.gsab, fx_co.ga) + assert not is_proper_subtype(fx_co.gsaa, fx_co.gb) + assert is_proper_subtype(fx_co.gb, fx_co.ga) + assert not is_proper_subtype(fx_co.ga, fx_co.gb) def test_is_proper_subtype_contravariance(self) -> None: fx_contra = self.fx_contra - assert_true(is_proper_subtype(fx_contra.gsab, fx_contra.gb)) - assert_false(is_proper_subtype(fx_contra.gsab, fx_contra.ga)) - assert_true(is_proper_subtype(fx_contra.gsaa, fx_contra.gb)) - assert_false(is_proper_subtype(fx_contra.gb, fx_contra.ga)) - assert_true(is_proper_subtype(fx_contra.ga, fx_contra.gb)) + assert is_proper_subtype(fx_contra.gsab, fx_contra.gb) + assert not is_proper_subtype(fx_contra.gsab, fx_contra.ga) + assert is_proper_subtype(fx_contra.gsaa, fx_contra.gb) + assert not is_proper_subtype(fx_contra.gb, fx_contra.ga) + assert is_proper_subtype(fx_contra.ga, fx_contra.gb) def test_is_proper_subtype_invariance(self) -> None: fx = self.fx - assert_true(is_proper_subtype(fx.gsab, fx.gb)) - assert_false(is_proper_subtype(fx.gsab, fx.ga)) - assert_false(is_proper_subtype(fx.gsaa, fx.gb)) - assert_false(is_proper_subtype(fx.gb, fx.ga)) - assert_false(is_proper_subtype(fx.ga, fx.gb)) + assert is_proper_subtype(fx.gsab, fx.gb) + assert not is_proper_subtype(fx.gsab, fx.ga) + assert not is_proper_subtype(fx.gsaa, fx.gb) + assert not is_proper_subtype(fx.gb, fx.ga) + assert not is_proper_subtype(fx.ga, fx.gb) def test_is_proper_subtype_and_subtype_literal_types(self) -> None: fx = self.fx @@ -302,79 +302,79 @@ def test_is_proper_subtype_and_subtype_literal_types(self) -> None: lit2 = fx.lit2 lit3 = fx.lit3 - assert_true(is_proper_subtype(lit1, fx.a)) - assert_false(is_proper_subtype(lit1, fx.d)) - assert_false(is_proper_subtype(fx.a, lit1)) - assert_true(is_proper_subtype(fx.uninhabited, lit1)) - assert_false(is_proper_subtype(lit1, fx.uninhabited)) - assert_true(is_proper_subtype(lit1, lit1)) - assert_false(is_proper_subtype(lit1, lit2)) - assert_false(is_proper_subtype(lit2, lit3)) - - assert_true(is_subtype(lit1, fx.a)) - assert_false(is_subtype(lit1, fx.d)) - assert_false(is_subtype(fx.a, lit1)) - assert_true(is_subtype(fx.uninhabited, lit1)) - assert_false(is_subtype(lit1, fx.uninhabited)) - assert_true(is_subtype(lit1, lit1)) - assert_false(is_subtype(lit1, lit2)) - assert_false(is_subtype(lit2, lit3)) - - assert_false(is_proper_subtype(lit1, fx.anyt)) - assert_false(is_proper_subtype(fx.anyt, lit1)) - - assert_true(is_subtype(lit1, fx.anyt)) - assert_true(is_subtype(fx.anyt, lit1)) + assert is_proper_subtype(lit1, fx.a) + assert not is_proper_subtype(lit1, fx.d) + assert not is_proper_subtype(fx.a, lit1) + assert is_proper_subtype(fx.uninhabited, lit1) + assert not is_proper_subtype(lit1, fx.uninhabited) + assert is_proper_subtype(lit1, lit1) + assert not is_proper_subtype(lit1, lit2) + assert not is_proper_subtype(lit2, lit3) + + assert is_subtype(lit1, fx.a) + assert not is_subtype(lit1, fx.d) + assert not is_subtype(fx.a, lit1) + assert is_subtype(fx.uninhabited, lit1) + assert not is_subtype(lit1, fx.uninhabited) + assert is_subtype(lit1, lit1) + assert not is_subtype(lit1, lit2) + assert not is_subtype(lit2, lit3) + + assert not is_proper_subtype(lit1, fx.anyt) + assert not is_proper_subtype(fx.anyt, lit1) + + assert is_subtype(lit1, fx.anyt) + assert is_subtype(fx.anyt, lit1) def test_subtype_aliases(self) -> None: A1, _ = self.fx.def_alias_1(self.fx.a) AA1, _ = self.fx.def_alias_1(self.fx.a) - assert_true(is_subtype(A1, AA1)) - assert_true(is_subtype(AA1, A1)) + assert is_subtype(A1, AA1) + assert is_subtype(AA1, A1) A2, _ = self.fx.def_alias_2(self.fx.a) AA2, _ = self.fx.def_alias_2(self.fx.a) - assert_true(is_subtype(A2, AA2)) - assert_true(is_subtype(AA2, A2)) + assert is_subtype(A2, AA2) + assert is_subtype(AA2, A2) B1, _ = self.fx.def_alias_1(self.fx.b) B2, _ = self.fx.def_alias_2(self.fx.b) - assert_true(is_subtype(B1, A1)) - assert_true(is_subtype(B2, A2)) - assert_false(is_subtype(A1, B1)) - assert_false(is_subtype(A2, B2)) + assert is_subtype(B1, A1) + assert is_subtype(B2, A2) + assert not is_subtype(A1, B1) + assert not is_subtype(A2, B2) - assert_false(is_subtype(A2, A1)) - assert_true(is_subtype(A1, A2)) + assert not is_subtype(A2, A1) + assert is_subtype(A1, A2) # can_be_true / can_be_false def test_empty_tuple_always_false(self) -> None: tuple_type = self.tuple() - assert_true(tuple_type.can_be_false) - assert_false(tuple_type.can_be_true) + assert tuple_type.can_be_false + assert not tuple_type.can_be_true def test_nonempty_tuple_always_true(self) -> None: tuple_type = self.tuple(AnyType(TypeOfAny.special_form), AnyType(TypeOfAny.special_form)) - assert_true(tuple_type.can_be_true) - assert_false(tuple_type.can_be_false) + assert tuple_type.can_be_true + assert not tuple_type.can_be_false def test_union_can_be_true_if_any_true(self) -> None: union_type = UnionType([self.fx.a, self.tuple()]) - assert_true(union_type.can_be_true) + assert union_type.can_be_true def test_union_can_not_be_true_if_none_true(self) -> None: union_type = UnionType([self.tuple(), self.tuple()]) - assert_false(union_type.can_be_true) + assert not union_type.can_be_true def test_union_can_be_false_if_any_false(self) -> None: union_type = UnionType([self.fx.a, self.tuple()]) - assert_true(union_type.can_be_false) + assert union_type.can_be_false def test_union_can_not_be_false_if_none_false(self) -> None: union_type = UnionType([self.tuple(self.fx.a), self.tuple(self.fx.d)]) - assert_false(union_type.can_be_false) + assert not union_type.can_be_false # true_only / false_only @@ -385,16 +385,16 @@ def test_true_only_of_false_type_is_uninhabited(self) -> None: def test_true_only_of_true_type_is_idempotent(self) -> None: always_true = self.tuple(AnyType(TypeOfAny.special_form)) to = true_only(always_true) - assert_true(always_true is to) + assert always_true is to def test_true_only_of_instance(self) -> None: to = true_only(self.fx.a) assert_equal(str(to), "A") - assert_true(to.can_be_true) - assert_false(to.can_be_false) + assert to.can_be_true + assert not to.can_be_false assert_type(Instance, to) # The original class still can be false - assert_true(self.fx.a.can_be_false) + assert self.fx.a.can_be_false def test_true_only_of_union(self) -> None: tup_type = self.tuple(AnyType(TypeOfAny.special_form)) @@ -404,9 +404,9 @@ def test_true_only_of_union(self) -> None: to = true_only(union_type) assert isinstance(to, UnionType) assert_equal(len(to.items), 2) - assert_true(to.items[0].can_be_true) - assert_false(to.items[0].can_be_false) - assert_true(to.items[1] is tup_type) + assert to.items[0].can_be_true + assert not to.items[0].can_be_false + assert to.items[1] is tup_type def test_false_only_of_true_type_is_uninhabited(self) -> None: with strict_optional_set(True): @@ -424,16 +424,16 @@ def test_false_only_tuple(self) -> None: def test_false_only_of_false_type_is_idempotent(self) -> None: always_false = NoneType() fo = false_only(always_false) - assert_true(always_false is fo) + assert always_false is fo def test_false_only_of_instance(self) -> None: fo = false_only(self.fx.a) assert_equal(str(fo), "A") - assert_false(fo.can_be_true) - assert_true(fo.can_be_false) + assert not fo.can_be_true + assert fo.can_be_false assert_type(Instance, fo) # The original class still can be true - assert_true(self.fx.a.can_be_true) + assert self.fx.a.can_be_true def test_false_only_of_union(self) -> None: with strict_optional_set(True): @@ -446,9 +446,9 @@ def test_false_only_of_union(self) -> None: fo = false_only(union_type) assert isinstance(fo, UnionType) assert_equal(len(fo.items), 2) - assert_false(fo.items[0].can_be_true) - assert_true(fo.items[0].can_be_false) - assert_true(fo.items[1] is tup_type) + assert not fo.items[0].can_be_true + assert fo.items[0].can_be_false + assert fo.items[1] is tup_type def test_simplified_union(self) -> None: fx = self.fx @@ -494,10 +494,10 @@ def callable(self, vars: List[str], *a: Type) -> CallableType: argument types a1, ... an and return type r and type arguments vars. """ - tv = [] # type: List[TypeVarDef] + tv: List[TypeVarType] = [] n = -1 for v in vars: - tv.append(TypeVarDef(v, v, n, [], self.fx.o)) + tv.append(TypeVarType(v, v, n, [], self.fx.o)) n -= 1 return CallableType(list(a[:-1]), [ARG_POS] * (len(a) - 1), @@ -510,7 +510,9 @@ def callable(self, vars: List[str], *a: Type) -> CallableType: class JoinSuite(Suite): def setUp(self) -> None: - self.fx = TypeFixture() + self.fx = TypeFixture(INVARIANT) + self.fx_co = TypeFixture(COVARIANT) + self.fx_contra = TypeFixture(CONTRAVARIANT) def test_trivial_cases(self) -> None: for simple in self.fx.a, self.fx.o, self.fx.b: @@ -609,16 +611,16 @@ def test_mixed_truth_restricted_type_simple(self) -> None: true_a = true_only(self.fx.a) false_o = false_only(self.fx.o) j = join_simple(self.fx.o, true_a, false_o) - assert_true(j.can_be_true) - assert_true(j.can_be_false) + assert j.can_be_true + assert j.can_be_false def test_mixed_truth_restricted_type(self) -> None: # join_types against differently restricted truthiness types drops restrictions. true_any = true_only(AnyType(TypeOfAny.special_form)) false_o = false_only(self.fx.o) j = join_types(true_any, false_o) - assert_true(j.can_be_true) - assert_true(j.can_be_false) + assert j.can_be_true + assert j.can_be_false def test_other_mixed_types(self) -> None: # In general, joining unrelated types produces object. @@ -630,11 +632,6 @@ def test_other_mixed_types(self) -> None: self.assert_join(t1, t2, self.fx.o) def test_simple_generics(self) -> None: - self.assert_join(self.fx.ga, self.fx.ga, self.fx.ga) - self.assert_join(self.fx.ga, self.fx.gb, self.fx.ga) - self.assert_join(self.fx.ga, self.fx.gd, self.fx.o) - self.assert_join(self.fx.ga, self.fx.g2a, self.fx.o) - self.assert_join(self.fx.ga, self.fx.nonet, self.fx.ga) self.assert_join(self.fx.ga, self.fx.anyt, self.fx.anyt) @@ -642,23 +639,43 @@ def test_simple_generics(self) -> None: self.callable(self.fx.a, self.fx.b)]: self.assert_join(t, self.fx.ga, self.fx.o) + def test_generics_invariant(self) -> None: + self.assert_join(self.fx.ga, self.fx.ga, self.fx.ga) + self.assert_join(self.fx.ga, self.fx.gb, self.fx.o) + self.assert_join(self.fx.ga, self.fx.gd, self.fx.o) + self.assert_join(self.fx.ga, self.fx.g2a, self.fx.o) + + def test_generics_covariant(self) -> None: + self.assert_join(self.fx_co.ga, self.fx_co.ga, self.fx_co.ga) + self.assert_join(self.fx_co.ga, self.fx_co.gb, self.fx_co.ga) + self.assert_join(self.fx_co.ga, self.fx_co.gd, self.fx_co.go) + self.assert_join(self.fx_co.ga, self.fx_co.g2a, self.fx_co.o) + + def test_generics_contravariant(self) -> None: + self.assert_join(self.fx_contra.ga, self.fx_contra.ga, self.fx_contra.ga) + # TODO: this can be more precise than "object", see a comment in mypy/join.py + self.assert_join(self.fx_contra.ga, self.fx_contra.gb, self.fx_contra.o) + self.assert_join(self.fx_contra.ga, self.fx_contra.g2a, self.fx_contra.o) + def test_generics_with_multiple_args(self) -> None: - self.assert_join(self.fx.hab, self.fx.hab, self.fx.hab) - self.assert_join(self.fx.hab, self.fx.hbb, self.fx.hab) - self.assert_join(self.fx.had, self.fx.haa, self.fx.o) + self.assert_join(self.fx_co.hab, self.fx_co.hab, self.fx_co.hab) + self.assert_join(self.fx_co.hab, self.fx_co.hbb, self.fx_co.hab) + self.assert_join(self.fx_co.had, self.fx_co.haa, self.fx_co.hao) def test_generics_with_inheritance(self) -> None: - self.assert_join(self.fx.gsab, self.fx.gb, self.fx.gb) - self.assert_join(self.fx.gsba, self.fx.gb, self.fx.ga) - self.assert_join(self.fx.gsab, self.fx.gd, self.fx.o) + self.assert_join(self.fx_co.gsab, self.fx_co.gb, self.fx_co.gb) + self.assert_join(self.fx_co.gsba, self.fx_co.gb, self.fx_co.ga) + self.assert_join(self.fx_co.gsab, self.fx_co.gd, self.fx_co.go) def test_generics_with_inheritance_and_shared_supertype(self) -> None: - self.assert_join(self.fx.gsba, self.fx.gs2a, self.fx.ga) - self.assert_join(self.fx.gsab, self.fx.gs2a, self.fx.ga) - self.assert_join(self.fx.gsab, self.fx.gs2d, self.fx.o) + self.assert_join(self.fx_co.gsba, self.fx_co.gs2a, self.fx_co.ga) + self.assert_join(self.fx_co.gsab, self.fx_co.gs2a, self.fx_co.ga) + self.assert_join(self.fx_co.gsab, self.fx_co.gs2d, self.fx_co.go) def test_generic_types_and_any(self) -> None: self.assert_join(self.fx.gdyn, self.fx.ga, self.fx.gdyn) + self.assert_join(self.fx_co.gdyn, self.fx_co.ga, self.fx_co.gdyn) + self.assert_join(self.fx_contra.gdyn, self.fx_contra.ga, self.fx_contra.gdyn) def test_callables_with_any(self) -> None: self.assert_join(self.callable(self.fx.a, self.fx.a, self.fx.anyt, @@ -737,7 +754,7 @@ def test_simple_type_objects(self) -> None: self.assert_join(t1, t1, t1) j = join_types(t1, t1) assert isinstance(j, CallableType) - assert_true(j.is_type_obj()) + assert j.is_type_obj() self.assert_join(t1, t2, tr) self.assert_join(t1, self.fx.type_type, self.fx.type_type) @@ -802,10 +819,8 @@ def assert_simple_join(self, s: Type, t: Type, join: Type) -> None: expected = str(join) assert_equal(actual, expected, 'join({}, {}) == {{}} ({{}} expected)'.format(s, t)) - assert_true(is_subtype(s, result), - '{} not subtype of {}'.format(s, result)) - assert_true(is_subtype(t, result), - '{} not subtype of {}'.format(t, result)) + assert is_subtype(s, result), '{} not subtype of {}'.format(s, result) + assert is_subtype(t, result), '{} not subtype of {}'.format(t, result) def tuple(self, *a: Type) -> TupleType: return TupleType(list(a), self.fx.std_tuple) @@ -998,8 +1013,8 @@ def test_literal_type(self) -> None: self.assert_meet(lit1, self.fx.anyt, lit1) self.assert_meet(lit1, self.fx.o, lit1) - assert_true(is_same_type(lit1, narrow_declared_type(lit1, a))) - assert_true(is_same_type(lit2, narrow_declared_type(lit2, a))) + assert is_same_type(lit1, narrow_declared_type(lit1, a)) + assert is_same_type(lit2, narrow_declared_type(lit2, a)) # FIX generic interfaces + ranges @@ -1019,10 +1034,8 @@ def assert_simple_meet(self, s: Type, t: Type, meet: Type) -> None: expected = str(meet) assert_equal(actual, expected, 'meet({}, {}) == {{}} ({{}} expected)'.format(s, t)) - assert_true(is_subtype(result, s), - '{} not subtype of {}'.format(result, s)) - assert_true(is_subtype(result, t), - '{} not subtype of {}'.format(result, t)) + assert is_subtype(result, s), '{} not subtype of {}'.format(result, s) + assert is_subtype(result, t), '{} not subtype of {}'.format(result, t) def tuple(self, *a: Type) -> TupleType: return TupleType(list(a), self.fx.std_tuple) @@ -1042,6 +1055,7 @@ def setUp(self) -> None: self.fx = TypeFixture() def test_literal_type(self) -> None: + a = self.fx.a b = self.fx.b # Reminder: b is a subclass of a lit1 = self.fx.lit1 @@ -1051,6 +1065,7 @@ def test_literal_type(self) -> None: self.assert_same(lit1, lit1) self.assert_same(UnionType([lit1, lit2]), UnionType([lit1, lit2])) self.assert_same(UnionType([lit1, lit2]), UnionType([lit2, lit1])) + self.assert_same(UnionType([a, b]), UnionType([b, a])) self.assert_not_same(lit1, b) self.assert_not_same(lit1, lit2) self.assert_not_same(lit1, lit3) diff --git a/mypy/test/typefixture.py b/mypy/test/typefixture.py index 753462ca218f..1a5dd8164136 100644 --- a/mypy/test/typefixture.py +++ b/mypy/test/typefixture.py @@ -5,13 +5,15 @@ from typing import List, Optional, Tuple +from mypy.semanal_shared import set_callable_name from mypy.types import ( - Type, TypeVarType, AnyType, NoneType, Instance, CallableType, TypeVarDef, TypeType, - UninhabitedType, TypeOfAny, TypeAliasType, UnionType, LiteralType + Type, AnyType, NoneType, Instance, CallableType, TypeVarType, TypeType, + UninhabitedType, TypeOfAny, TypeAliasType, UnionType, LiteralType, + TypeVarLikeType ) from mypy.nodes import ( - TypeInfo, ClassDef, Block, ARG_POS, ARG_OPT, ARG_STAR, SymbolTable, - COVARIANT, TypeAlias + TypeInfo, ClassDef, FuncDef, Block, ARG_POS, ARG_OPT, ARG_STAR, SymbolTable, + COVARIANT, TypeAlias, SymbolTableNode, MDEF, ) @@ -30,7 +32,7 @@ def __init__(self, variance: int = COVARIANT) -> None: def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, variance: int) -> TypeVarType: - return TypeVarType(TypeVarDef(name, name, id, values, upper_bound, variance)) + return TypeVarType(name, name, id, values, upper_bound, variance) self.t = make_type_var('T', 1, [], self.o, variance) # T`1 (type variable) self.tf = make_type_var('T', -1, [], self.o, variance) # T`-1 (type variable) @@ -62,6 +64,7 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, typevars=['T'], variances=[COVARIANT]) # class tuple self.type_typei = self.make_type_info('builtins.type') # class type + self.bool_type_info = self.make_type_info('builtins.bool') self.functioni = self.make_type_info('builtins.function') # function TODO self.ai = self.make_type_info('A', mro=[self.oi]) # class A self.bi = self.make_type_info('B', mro=[self.ai, self.oi]) # class B(A) @@ -129,6 +132,7 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.gtf2 = Instance(self.gi, [self.tf2]) # G[T`-2] self.gs = Instance(self.gi, [self.s]) # G[S] self.gdyn = Instance(self.gi, [self.anyt]) # G[Any] + self.gn = Instance(self.gi, [NoneType()]) # G[None] self.g2a = Instance(self.g2i, [self.a]) # G2[A] @@ -145,6 +149,7 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.hbb = Instance(self.hi, [self.b, self.b]) # H[B, B] self.hts = Instance(self.hi, [self.t, self.s]) # H[T, S] self.had = Instance(self.hi, [self.a, self.d]) # H[A, D] + self.hao = Instance(self.hi, [self.a, self.o]) # H[A, object] self.lsta = Instance(self.std_listi, [self.a]) # List[A] self.lstb = Instance(self.std_listi, [self.b]) # List[B] @@ -163,6 +168,15 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.type_t = TypeType.make_normalized(self.t) self.type_any = TypeType.make_normalized(self.anyt) + self._add_bool_dunder(self.bool_type_info) + self._add_bool_dunder(self.ai) + + def _add_bool_dunder(self, type_info: TypeInfo) -> None: + signature = CallableType([], [], [], Instance(self.bool_type_info, []), self.function) + bool_func = FuncDef('__bool__', [], Block([])) + bool_func.type = set_callable_name(signature, bool_func) + type_info.names[bool_func.name] = SymbolTableNode(MDEF, bool_func) + # Helper methods def callable(self, *a: Type) -> CallableType: @@ -221,13 +235,13 @@ def make_type_info(self, name: str, module_name = '__main__' if typevars: - v = [] # type: List[TypeVarDef] + v: List[TypeVarLikeType] = [] for id, n in enumerate(typevars, 1): if variances: variance = variances[id - 1] else: variance = COVARIANT - v.append(TypeVarDef(n, n, id, [], self.o, variance=variance)) + v.append(TypeVarType(n, n, id, [], self.o, variance=variance)) class_def.type_vars = v info = TypeInfo(SymbolTable(), class_def, module_name) diff --git a/mypy/test/visitors.py b/mypy/test/visitors.py index 2ba4ab52d135..b1a84e3529e1 100644 --- a/mypy/test/visitors.py +++ b/mypy/test/visitors.py @@ -20,7 +20,7 @@ # from testtypegen class SkippedNodeSearcher(TraverserVisitor): def __init__(self) -> None: - self.nodes = set() # type: Set[Expression] + self.nodes: Set[Expression] = set() self.is_typing = False def visit_mypy_file(self, f: MypyFile) -> None: diff --git a/mypy/traverser.py b/mypy/traverser.py index c4834c9acb6b..a5f993bd2fa5 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -1,6 +1,6 @@ """Generic node traverser visitor""" -from typing import List +from typing import List, Tuple from mypy_extensions import mypyc_attr from mypy.visitor import NodeVisitor @@ -319,9 +319,22 @@ def has_return_statement(fdef: FuncBase) -> bool: return seeker.found -class ReturnCollector(TraverserVisitor): +class YieldSeeker(TraverserVisitor): + def __init__(self) -> None: + self.found = False + + def visit_yield_expr(self, o: YieldExpr) -> None: + self.found = True + + +def has_yield_expression(fdef: FuncBase) -> bool: + seeker = YieldSeeker() + fdef.accept(seeker) + return seeker.found + + +class FuncCollectorBase(TraverserVisitor): def __init__(self) -> None: - self.return_statements = [] # type: List[ReturnStmt] self.inside_func = False def visit_func_def(self, defn: FuncDef) -> None: @@ -330,6 +343,12 @@ def visit_func_def(self, defn: FuncDef) -> None: super().visit_func_def(defn) self.inside_func = False + +class ReturnCollector(FuncCollectorBase): + def __init__(self) -> None: + super().__init__() + self.return_statements: List[ReturnStmt] = [] + def visit_return_stmt(self, stmt: ReturnStmt) -> None: self.return_statements.append(stmt) @@ -338,3 +357,24 @@ def all_return_statements(node: Node) -> List[ReturnStmt]: v = ReturnCollector() node.accept(v) return v.return_statements + + +class YieldCollector(FuncCollectorBase): + def __init__(self) -> None: + super().__init__() + self.in_assignment = False + self.yield_expressions: List[Tuple[YieldExpr, bool]] = [] + + def visit_assignment_stmt(self, stmt: AssignmentStmt) -> None: + self.in_assignment = True + super().visit_assignment_stmt(stmt) + self.in_assignment = False + + def visit_yield_expr(self, expr: YieldExpr) -> None: + self.yield_expressions.append((expr, self.in_assignment)) + + +def all_yield_expressions(node: Node) -> List[Tuple[YieldExpr, bool]]: + v = YieldCollector() + node.accept(v) + return v.yield_expressions diff --git a/mypy/treetransform.py b/mypy/treetransform.py index bd8a623455f7..cdd4f604be86 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -55,12 +55,12 @@ def __init__(self) -> None: self.test_only = False # There may be multiple references to a Var node. Keep track of # Var translations using a dictionary. - self.var_map = {} # type: Dict[Var, Var] + self.var_map: Dict[Var, Var] = {} # These are uninitialized placeholder nodes used temporarily for nested # functions while we are transforming a top-level function. This maps an # untransformed node to a placeholder (which will later become the # transformed node). - self.func_placeholder_map = {} # type: Dict[FuncDef, FuncDef] + self.func_placeholder_map: Dict[FuncDef, FuncDef] = {} def visit_mypy_file(self, node: MypyFile) -> MypyFile: assert self.test_only, "This visitor should not be used for whole files." @@ -596,7 +596,7 @@ def names(self, names: List[NameExpr]) -> List[NameExpr]: return [self.duplicate_name(name) for name in names] def optional_names(self, names: Iterable[Optional[NameExpr]]) -> List[Optional[NameExpr]]: - result = [] # type: List[Optional[NameExpr]] + result: List[Optional[NameExpr]] = [] for name in names: if name: result.append(self.duplicate_name(name)) diff --git a/mypy/tvar_scope.py b/mypy/tvar_scope.py index 4c7a165036a2..0d8be7845e52 100644 --- a/mypy/tvar_scope.py +++ b/mypy/tvar_scope.py @@ -1,12 +1,12 @@ from typing import Optional, Dict, Union -from mypy.types import TypeVarLikeDef, TypeVarDef, ParamSpecDef +from mypy.types import TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor from mypy.nodes import ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode class TypeVarLikeScope: """Scope that holds bindings for type variables and parameter specifications. - Node fullname -> TypeVarLikeDef. + Node fullname -> TypeVarLikeType. """ def __init__(self, @@ -21,7 +21,7 @@ def __init__(self, prohibited: Type variables that aren't strictly in scope exactly, but can't be bound because they're part of an outer class's scope. """ - self.scope = {} # type: Dict[str, TypeVarLikeDef] + self.scope: Dict[str, TypeVarLikeType] = {} self.parent = parent self.func_id = 0 self.class_id = 0 @@ -33,7 +33,7 @@ def __init__(self, def get_function_scope(self) -> 'Optional[TypeVarLikeScope]': """Get the nearest parent that's a function scope, not a class scope""" - it = self # type: Optional[TypeVarLikeScope] + it: Optional[TypeVarLikeScope] = self while it is not None and it.is_class_scope: it = it.parent return it @@ -55,7 +55,7 @@ def class_frame(self) -> 'TypeVarLikeScope': """A new scope frame for binding a class. Prohibits *this* class's tvars""" return TypeVarLikeScope(self.get_function_scope(), True, self) - def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeDef: + def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeType: if self.is_class_scope: self.class_id += 1 i = self.class_id @@ -63,7 +63,7 @@ def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeDef: self.func_id -= 1 i = self.func_id if isinstance(tvar_expr, TypeVarExpr): - tvar_def = TypeVarDef( + tvar_def: TypeVarLikeType = TypeVarType( name, tvar_expr.fullname, i, @@ -72,12 +72,14 @@ def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeDef: variance=tvar_expr.variance, line=tvar_expr.line, column=tvar_expr.column - ) # type: TypeVarLikeDef + ) elif isinstance(tvar_expr, ParamSpecExpr): - tvar_def = ParamSpecDef( + tvar_def = ParamSpecType( name, tvar_expr.fullname, i, + flavor=ParamSpecFlavor.BARE, + upper_bound=tvar_expr.upper_bound, line=tvar_expr.line, column=tvar_expr.column ) @@ -86,10 +88,10 @@ def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeDef: self.scope[tvar_expr.fullname] = tvar_def return tvar_def - def bind_existing(self, tvar_def: TypeVarLikeDef) -> None: + def bind_existing(self, tvar_def: TypeVarLikeType) -> None: self.scope[tvar_def.fullname] = tvar_def - def get_binding(self, item: Union[str, SymbolTableNode]) -> Optional[TypeVarLikeDef]: + def get_binding(self, item: Union[str, SymbolTableNode]) -> Optional[TypeVarLikeType]: fullname = item.fullname if isinstance(item, SymbolTableNode) else item assert fullname is not None if fullname in self.scope: diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index a0e6299a5a8a..99821fa62640 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -12,18 +12,18 @@ """ from abc import abstractmethod -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import Generic, TypeVar, cast, Any, List, Callable, Iterable, Optional, Set, Sequence from mypy_extensions import trait, mypyc_attr T = TypeVar('T') from mypy.types import ( - Type, AnyType, CallableType, Overloaded, TupleType, TypeGuardType, TypedDictType, LiteralType, + Type, AnyType, CallableType, Overloaded, TupleType, TypedDictType, LiteralType, RawExpressionType, Instance, NoneType, TypeType, - UnionType, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarLikeDef, + UnionType, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarLikeType, UnboundType, ErasedType, StarType, EllipsisType, TypeList, CallableArgument, - PlaceholderType, TypeAliasType, get_proper_type + PlaceholderType, TypeAliasType, ParamSpecType, get_proper_type ) @@ -63,6 +63,10 @@ def visit_deleted_type(self, t: DeletedType) -> T: def visit_type_var(self, t: TypeVarType) -> T: pass + @abstractmethod + def visit_param_spec(self, t: ParamSpecType) -> T: + pass + @abstractmethod def visit_instance(self, t: Instance) -> T: pass @@ -103,10 +107,6 @@ def visit_type_type(self, t: TypeType) -> T: def visit_type_alias_type(self, t: TypeAliasType) -> T: pass - @abstractmethod - def visit_type_guard_type(self, t: TypeGuardType) -> T: - pass - @trait @mypyc_attr(allow_interpreted_subclasses=True) @@ -167,7 +167,7 @@ def visit_deleted_type(self, t: DeletedType) -> Type: return t def visit_instance(self, t: Instance) -> Type: - last_known_value = None # type: Optional[LiteralType] + last_known_value: Optional[LiteralType] = None if t.last_known_value is not None: raw_last_known_value = t.last_known_value.accept(self) assert isinstance(raw_last_known_value, LiteralType) # type: ignore @@ -183,6 +183,9 @@ def visit_instance(self, t: Instance) -> Type: def visit_type_var(self, t: TypeVarType) -> Type: return t + def visit_param_spec(self, t: ParamSpecType) -> Type: + return t + def visit_partial_type(self, t: PartialType) -> Type: return t @@ -224,16 +227,13 @@ def visit_union_type(self, t: UnionType) -> Type: def translate_types(self, types: Iterable[Type]) -> List[Type]: return [t.accept(self) for t in types] - def visit_type_guard_type(self, t: TypeGuardType) -> Type: - return TypeGuardType(t.type_guard.accept(self)) - def translate_variables(self, - variables: Sequence[TypeVarLikeDef]) -> Sequence[TypeVarLikeDef]: + variables: Sequence[TypeVarLikeType]) -> Sequence[TypeVarLikeType]: return variables def visit_overloaded(self, t: Overloaded) -> Type: - items = [] # type: List[CallableType] - for item in t.items(): + items: List[CallableType] = [] + for item in t.items: new = item.accept(self) assert isinstance(new, CallableType) # type: ignore items.append(new) @@ -269,7 +269,7 @@ def __init__(self, strategy: Callable[[Iterable[T]], T]) -> None: self.strategy = strategy # Keep track of the type aliases already visited. This is needed to avoid # infinite recursion on types like A = Union[int, List[A]]. - self.seen_aliases = set() # type: Set[TypeAliasType] + self.seen_aliases: Set[TypeAliasType] = set() def visit_unbound_type(self, t: UnboundType) -> T: return self.query_types(t.args) @@ -298,6 +298,9 @@ def visit_deleted_type(self, t: DeletedType) -> T: def visit_type_var(self, t: TypeVarType) -> T: return self.query_types([t.upper_bound] + t.values) + def visit_param_spec(self, t: ParamSpecType) -> T: + return self.strategy([]) + def visit_partial_type(self, t: PartialType) -> T: return self.strategy([]) @@ -326,11 +329,8 @@ def visit_star_type(self, t: StarType) -> T: def visit_union_type(self, t: UnionType) -> T: return self.query_types(t.items) - def visit_type_guard_type(self, t: TypeGuardType) -> T: - return t.type_guard.accept(self) - def visit_overloaded(self, t: Overloaded) -> T: - return self.query_types(t.items()) + return self.query_types(t.items) def visit_type_type(self, t: TypeType) -> T: return t.item.accept(self) @@ -350,7 +350,7 @@ def query_types(self, types: Iterable[Type]) -> T: Use the strategy to combine the results. Skip type aliases already visited types to avoid infinite recursion. """ - res = [] # type: List[T] + res: List[T] = [] for t in types: if isinstance(t, TypeAliasType): # Avoid infinite recursion for recursive type aliases. diff --git a/mypy/typeanal.py b/mypy/typeanal.py index d9e7764ba3f8..f7b584eadae8 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -3,7 +3,7 @@ import itertools from itertools import chain from contextlib import contextmanager -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import Callable, List, Optional, Set, Tuple, Iterator, TypeVar, Iterable, Sequence from typing_extensions import Final @@ -12,16 +12,17 @@ from mypy.messages import MessageBuilder, quote_type_string, format_type_bare from mypy.options import Options from mypy.types import ( - Type, UnboundType, TypeVarType, TupleType, TypedDictType, UnionType, Instance, AnyType, - CallableType, NoneType, ErasedType, DeletedType, TypeList, TypeVarDef, SyntheticTypeVisitor, - StarType, PartialType, EllipsisType, UninhabitedType, TypeType, TypeGuardType, - CallableArgument, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, - PlaceholderType, Overloaded, get_proper_type, TypeAliasType, TypeVarLikeDef, ParamSpecDef + Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType, + CallableType, NoneType, ErasedType, DeletedType, TypeList, TypeVarType, SyntheticTypeVisitor, + StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, + TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, + PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, + TypeVarLikeType, ParamSpecType, ParamSpecFlavor, callable_with_ellipsis ) from mypy.nodes import ( TypeInfo, Context, SymbolTableNode, Var, Expression, - get_nongen_builtins, check_arg_names, check_arg_kinds, ARG_POS, ARG_NAMED, + get_nongen_builtins, check_arg_names, check_arg_kinds, ArgKind, ARG_POS, ARG_NAMED, ARG_OPT, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, TypeVarExpr, TypeVarLikeExpr, ParamSpecExpr, TypeAlias, PlaceholderNode, SYMBOL_FUNCBASE_TYPES, Decorator, MypyFile ) @@ -35,7 +36,7 @@ T = TypeVar('T') -type_constructors = { +type_constructors: Final = { 'typing.Callable', 'typing.Optional', 'typing.Tuple', @@ -45,22 +46,22 @@ 'typing_extensions.Literal', 'typing.Annotated', 'typing_extensions.Annotated', -} # type: Final +} -ARG_KINDS_BY_CONSTRUCTOR = { +ARG_KINDS_BY_CONSTRUCTOR: Final = { 'mypy_extensions.Arg': ARG_POS, 'mypy_extensions.DefaultArg': ARG_OPT, 'mypy_extensions.NamedArg': ARG_NAMED, 'mypy_extensions.DefaultNamedArg': ARG_NAMED_OPT, 'mypy_extensions.VarArg': ARG_STAR, 'mypy_extensions.KwArg': ARG_STAR2, -} # type: Final +} -GENERIC_STUB_NOT_AT_RUNTIME_TYPES = { +GENERIC_STUB_NOT_AT_RUNTIME_TYPES: Final = { 'queue.Queue', 'builtins._PathLike', 'asyncio.futures.Future', -} # type: Final +} def analyze_type_alias(node: Expression, @@ -69,7 +70,7 @@ def analyze_type_alias(node: Expression, plugin: Plugin, options: Options, is_typeshed_stub: bool, - allow_unnormalized: bool = False, + allow_new_syntax: bool = False, allow_placeholder: bool = False, in_dynamic_func: bool = False, global_scope: bool = True) -> Optional[Tuple[Type, Set[str]]]: @@ -80,12 +81,12 @@ def analyze_type_alias(node: Expression, Return None otherwise. 'node' must have been semantically analyzed. """ try: - type = expr_to_unanalyzed_type(node) + type = expr_to_unanalyzed_type(node, options, allow_new_syntax) except TypeTranslationError: api.fail('Invalid type alias: expression is not a valid type', node) return None analyzer = TypeAnalyser(api, tvar_scope, plugin, options, is_typeshed_stub, - allow_unnormalized=allow_unnormalized, defining_alias=True, + allow_new_syntax=allow_new_syntax, defining_alias=True, allow_placeholder=allow_placeholder) analyzer.in_dynamic_func = in_dynamic_func analyzer.global_scope = global_scope @@ -114,9 +115,9 @@ class TypeAnalyser(SyntheticTypeVisitor[Type], TypeAnalyzerPluginInterface): """ # Is this called from an untyped function definition? - in_dynamic_func = False # type: bool + in_dynamic_func: bool = False # Is this called from global scope? - global_scope = True # type: bool + global_scope: bool = True def __init__(self, api: SemanticAnalyzerCoreInterface, @@ -126,9 +127,10 @@ def __init__(self, is_typeshed_stub: bool, *, defining_alias: bool = False, allow_tuple_literal: bool = False, - allow_unnormalized: bool = False, + allow_new_syntax: bool = False, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, + allow_required: bool = False, report_invalid_types: bool = True) -> None: self.api = api self.lookup_qualified = api.lookup_qualified @@ -141,13 +143,15 @@ def __init__(self, self.allow_tuple_literal = allow_tuple_literal # Positive if we are analyzing arguments of another (outer) type self.nesting_level = 0 - # Should we allow unnormalized types like `list[int]` - # (currently allowed in stubs)? - self.allow_unnormalized = allow_unnormalized + # Should we allow new type syntax when targeting older Python versions + # like 'list[int]' or 'X | Y' (allowed in stubs)? + self.allow_new_syntax = allow_new_syntax # Should we accept unbound type variables (always OK in aliases)? self.allow_unbound_tvars = allow_unbound_tvars or defining_alias # If false, record incomplete ref if we generate PlaceholderType. self.allow_placeholder = allow_placeholder + # Are we in a context where Required[] is allowed? + self.allow_required = allow_required # Should we report an error whenever we encounter a RawExpressionType outside # of a Literal context: e.g. whenever we encounter an invalid type? Normally, # we want to report an error, but the caller may want to do more specialized @@ -157,7 +161,7 @@ def __init__(self, self.options = options self.is_typeshed_stub = is_typeshed_stub # Names of type aliases encountered while analysing a type will be collected here. - self.aliases_used = set() # type: Set[str] + self.aliases_used: Set[str] = set() def visit_unbound_type(self, t: UnboundType, defining_literal: bool = False) -> Type: typ = self.visit_unbound_type_nonoptional(t, defining_literal) @@ -199,7 +203,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) return hook(AnalyzeTypeContext(t, t, self)) if (fullname in get_nongen_builtins(self.options.python_version) and t.args and - not self.allow_unnormalized and + not self.allow_new_syntax and not self.api.is_future_flag_set("annotations")): self.fail(no_subscript_builtin_alias(fullname, propose_alt=not self.defining_alias), t) @@ -208,22 +212,27 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) if tvar_def is None: self.fail('ParamSpec "{}" is unbound'.format(t.name), t) return AnyType(TypeOfAny.from_error) - self.fail('Invalid location for ParamSpec "{}"'.format(t.name), t) - self.note( - 'You can use ParamSpec as the first argument to Callable, e.g., ' - "'Callable[{}, int]'".format(t.name), - t + assert isinstance(tvar_def, ParamSpecType) + if len(t.args) > 0: + self.fail('ParamSpec "{}" used with arguments'.format(t.name), t) + # Change the line number + return ParamSpecType( + tvar_def.name, tvar_def.fullname, tvar_def.id, tvar_def.flavor, + tvar_def.upper_bound, line=t.line, column=t.column, ) - return AnyType(TypeOfAny.from_error) if isinstance(sym.node, TypeVarExpr) and tvar_def is not None and self.defining_alias: self.fail('Can\'t use bound type variable "{}"' ' to define generic alias'.format(t.name), t) return AnyType(TypeOfAny.from_error) if isinstance(sym.node, TypeVarExpr) and tvar_def is not None: - assert isinstance(tvar_def, TypeVarDef) + assert isinstance(tvar_def, TypeVarType) if len(t.args) > 0: self.fail('Type variable "{}" used with arguments'.format(t.name), t) - return TypeVarType(tvar_def, t.line) + # Change the line number + return TypeVarType( + tvar_def.name, tvar_def.fullname, tvar_def.id, tvar_def.values, + tvar_def.upper_bound, tvar_def.variance, line=t.line, column=t.column, + ) special = self.try_analyze_special_unbound_type(t, fullname) if special is not None: return special @@ -253,6 +262,8 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) return res elif isinstance(node, TypeInfo): return self.analyze_type_with_type_info(node, t.args, t) + elif node.fullname in ("typing_extensions.TypeAlias", "typing.TypeAlias"): + return AnyType(TypeOfAny.special_form) else: return self.analyze_unbound_type_without_type_info(t, sym, defining_literal) else: # sym is None @@ -281,7 +292,8 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt return AnyType(TypeOfAny.from_error) elif (fullname == 'typing.Tuple' or (fullname == 'builtins.tuple' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations')))): + self.api.is_future_flag_set('annotations') or + self.allow_new_syntax))): # Tuple is special because it is involved in builtin import cycle # and may be not ready when used. sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') @@ -324,8 +336,8 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt # To prevent assignment of 'builtins.type' inferred as 'builtins.object' # See https://github.com/python/mypy/issues/9476 for more information return None - type_str = 'Type[...]' if fullname == 'typing.Type' else 'type[...]' if len(t.args) != 1: + type_str = 'Type[...]' if fullname == 'typing.Type' else 'type[...]' self.fail(type_str + ' must have exactly one type argument', t) item = self.anal_type(t.args[0]) return TypeType.make_normalized(item, line=t.line) @@ -348,6 +360,22 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt " and at least one annotation", t) return AnyType(TypeOfAny.from_error) return self.anal_type(t.args[0]) + elif fullname in ('typing_extensions.Required', 'typing.Required'): + if not self.allow_required: + self.fail("Required[] can be only used in a TypedDict definition", t) + return AnyType(TypeOfAny.from_error) + if len(t.args) != 1: + self.fail("Required[] must have exactly one type argument", t) + return AnyType(TypeOfAny.from_error) + return RequiredType(self.anal_type(t.args[0]), required=True) + elif fullname in ('typing_extensions.NotRequired', 'typing.NotRequired'): + if not self.allow_required: + self.fail("NotRequired[] can be only used in a TypedDict definition", t) + return AnyType(TypeOfAny.from_error) + if len(t.args) != 1: + self.fail("NotRequired[] must have exactly one type argument", t) + return AnyType(TypeOfAny.from_error) + return RequiredType(self.anal_type(t.args[0]), required=False) elif self.anal_type_guard_arg(t, fullname) is not None: # In most contexts, TypeGuard[...] acts as an alias for bool (ignoring its args) return self.named_type('builtins.bool') @@ -373,7 +401,8 @@ def analyze_type_with_type_info( # checked only later, since we do not always know the # valid count at this point. Thus we may construct an # Instance with an invalid number of type arguments. - instance = Instance(info, self.anal_array(args), ctx.line, ctx.column) + instance = Instance(info, self.anal_array(args, allow_param_spec=True), + ctx.line, ctx.column) # Check type argument count. if len(instance.args) != len(info.type_vars) and not self.defining_alias: fix_instance(instance, self.fail, self.note, @@ -458,7 +487,7 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl # to make sure there are no remaining semanal-only types, then give up. t = t.copy_modified(args=self.anal_array(t.args)) # TODO: Move this message building logic to messages.py. - notes = [] # type: List[str] + notes: List[str] = [] if isinstance(sym.node, Var): notes.append('See https://mypy.readthedocs.io/en/' 'stable/common_issues.html#variables-vs-type-aliases') @@ -523,6 +552,9 @@ def visit_type_alias_type(self, t: TypeAliasType) -> Type: def visit_type_var(self, t: TypeVarType) -> Type: return t + def visit_param_spec(self, t: ParamSpecType) -> Type: + return t + def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type: # Every Callable can bind its own type variables, if they're not in the outer scope with self.tvar_scope_frame(): @@ -531,7 +563,15 @@ def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type: else: variables = self.bind_function_type_variables(t, t) special = self.anal_type_guard(t.ret_type) - ret = t.copy_modified(arg_types=self.anal_array(t.arg_types, nested=nested), + arg_kinds = t.arg_kinds + if len(arg_kinds) >= 2 and arg_kinds[-2] == ARG_STAR and arg_kinds[-1] == ARG_STAR2: + arg_types = self.anal_array(t.arg_types[:-2], nested=nested) + [ + self.anal_star_arg_type(t.arg_types[-2], ARG_STAR, nested=nested), + self.anal_star_arg_type(t.arg_types[-1], ARG_STAR2, nested=nested), + ] + else: + arg_types = self.anal_array(t.arg_types, nested=nested) + ret = t.copy_modified(arg_types=arg_types, ret_type=self.anal_type(t.ret_type, nested=nested), # If the fallback isn't filled in yet, # its type will be the falsey FakeInfo @@ -542,9 +582,6 @@ def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type: ) return ret - def visit_type_guard_type(self, t: TypeGuardType) -> Type: - return t - def anal_type_guard(self, t: Type) -> Optional[Type]: if isinstance(t, UnboundType): sym = self.lookup_qualified(t.name, t) @@ -561,6 +598,26 @@ def anal_type_guard_arg(self, t: UnboundType, fullname: str) -> Optional[Type]: return self.anal_type(t.args[0]) return None + def anal_star_arg_type(self, t: Type, kind: ArgKind, nested: bool) -> Type: + """Analyze signature argument type for *args and **kwargs argument.""" + # TODO: Check that suffix and kind match + if isinstance(t, UnboundType) and t.name and '.' in t.name and not t.args: + components = t.name.split('.') + sym = self.lookup_qualified('.'.join(components[:-1]), t) + if sym is not None and isinstance(sym.node, ParamSpecExpr): + tvar_def = self.tvar_scope.get_binding(sym) + if isinstance(tvar_def, ParamSpecType): + if kind == ARG_STAR: + flavor = ParamSpecFlavor.ARGS + elif kind == ARG_STAR2: + flavor = ParamSpecFlavor.KWARGS + else: + assert False, kind + return ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, flavor, + upper_bound=self.named_type('builtins.object'), + line=t.line, column=t.column) + return self.anal_type(t, nested=nested) + def visit_overloaded(self, t: Overloaded) -> Type: # Overloaded types are manually constructed in semanal.py by analyzing the # AST and combining together the Callable types this visitor converts. @@ -686,17 +743,20 @@ def analyze_callable_args_for_paramspec( if sym is None: return None tvar_def = self.tvar_scope.get_binding(sym) - if not isinstance(tvar_def, ParamSpecDef): + if not isinstance(tvar_def, ParamSpecType): return None - # TODO(shantanu): construct correct type for paramspec + # TODO: Use tuple[...] or Mapping[..] instead? + obj = self.named_type('builtins.object') return CallableType( - [AnyType(TypeOfAny.explicit), AnyType(TypeOfAny.explicit)], + [ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS, + upper_bound=obj), + ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS, + upper_bound=obj)], [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None], ret_type=ret_type, fallback=fallback, - is_ellipsis_args=True ) def analyze_callable_type(self, t: UnboundType) -> Type: @@ -704,12 +764,7 @@ def analyze_callable_type(self, t: UnboundType) -> Type: if len(t.args) == 0: # Callable (bare). Treat as Callable[..., Any]. any_type = self.get_omitted_any(t) - ret = CallableType([any_type, any_type], - [nodes.ARG_STAR, nodes.ARG_STAR2], - [None, None], - ret_type=any_type, - fallback=fallback, - is_ellipsis_args=True) + ret = callable_with_ellipsis(any_type, any_type, fallback) elif len(t.args) == 2: callable_args = t.args[0] ret_type = t.args[1] @@ -726,13 +781,9 @@ def analyze_callable_type(self, t: UnboundType) -> Type: fallback=fallback) elif isinstance(callable_args, EllipsisType): # Callable[..., RET] (with literal ellipsis; accept arbitrary arguments) - ret = CallableType([AnyType(TypeOfAny.explicit), - AnyType(TypeOfAny.explicit)], - [nodes.ARG_STAR, nodes.ARG_STAR2], - [None, None], - ret_type=ret_type, - fallback=fallback, - is_ellipsis_args=True) + ret = callable_with_ellipsis(AnyType(TypeOfAny.explicit), + ret_type=ret_type, + fallback=fallback) else: # Callable[P, RET] (where P is ParamSpec) maybe_ret = self.analyze_callable_args_for_paramspec( @@ -742,7 +793,7 @@ def analyze_callable_type(self, t: UnboundType) -> Type: ) if maybe_ret is None: # Callable[?, RET] (where ? is something invalid) - # TODO(shantanu): change error to mention paramspec, once we actually have some + # TODO(PEP612): change error to mention paramspec, once we actually have some # support for it self.fail('The first argument to Callable must be a list of types or "..."', t) return AnyType(TypeOfAny.from_error) @@ -754,11 +805,11 @@ def analyze_callable_type(self, t: UnboundType) -> Type: return ret.accept(self) def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], - List[int], + List[ArgKind], List[Optional[str]]]]: - args = [] # type: List[Type] - kinds = [] # type: List[int] - names = [] # type: List[Optional[str]] + args: List[Type] = [] + kinds: List[ArgKind] = [] + names: List[Optional[str]] = [] for arg in arglist.items: if isinstance(arg, CallableArgument): args.append(arg.typ) @@ -777,7 +828,7 @@ def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], assert found.fullname is not None kind = ARG_KINDS_BY_CONSTRUCTOR[found.fullname] kinds.append(kind) - if arg.name is not None and kind in {ARG_STAR, ARG_STAR2}: + if arg.name is not None and kind.is_star(): self.fail("{} arguments should not have names".format( arg.constructor), arg) return None @@ -795,7 +846,7 @@ def analyze_literal_type(self, t: UnboundType) -> Type: self.fail('Literal[...] must have at least one parameter', t) return AnyType(TypeOfAny.from_error) - output = [] # type: List[Type] + output: List[Type] = [] for i, arg in enumerate(t.args): analyzed_types = self.analyze_literal_param(i + 1, arg, t) if analyzed_types is None: @@ -832,7 +883,7 @@ def analyze_literal_param(self, idx: int, arg: Type, ctx: Context) -> Optional[L # # 1. If the user attempts use an explicit Any as a parameter # 2. If the user is trying to use an enum value imported from a module with - # no type hints, giving it an an implicit type of 'Any' + # no type hints, giving it an implicit type of 'Any' # 3. If there's some other underlying problem with the parameter. # # We report an error in only the first two cases. In the third case, we assume @@ -897,8 +948,8 @@ def tvar_scope_frame(self) -> Iterator[None]: def infer_type_variables(self, type: CallableType) -> List[Tuple[str, TypeVarLikeExpr]]: """Return list of unique type variables referred to in a callable.""" - names = [] # type: List[str] - tvars = [] # type: List[TypeVarLikeExpr] + names: List[str] = [] + tvars: List[TypeVarLikeExpr] = [] for arg in type.arg_types: for name, tvar_expr in arg.accept( TypeVarLikeQuery(self.lookup_qualified, self.tvar_scope) @@ -920,7 +971,7 @@ def infer_type_variables(self, def bind_function_type_variables( self, fun_type: CallableType, defn: Context - ) -> Sequence[TypeVarLikeDef]: + ) -> Sequence[TypeVarLikeType]: """Find the type variables of the function type and bind them in our tvar_scope""" if fun_type.variables: for var in fun_type.variables: @@ -934,7 +985,7 @@ def bind_function_type_variables( # Do not define a new type variable if already defined in scope. typevars = [(name, tvar) for name, tvar in typevars if not self.is_defined_type_var(name, defn)] - defs = [] # type: List[TypeVarLikeDef] + defs: List[TypeVarLikeType] = [] for name, tvar in typevars: if not self.tvar_scope.allow_binding(tvar.fullname): self.fail('Type variable "{}" is bound by an outer class'.format(name), defn) @@ -951,24 +1002,40 @@ def is_defined_type_var(self, tvar: str, context: Context) -> bool: return False return self.tvar_scope.get_binding(tvar_node) is not None - def anal_array(self, a: Iterable[Type], nested: bool = True) -> List[Type]: - res = [] # type: List[Type] + def anal_array(self, + a: Iterable[Type], + nested: bool = True, *, + allow_param_spec: bool = False) -> List[Type]: + res: List[Type] = [] for t in a: - res.append(self.anal_type(t, nested)) + res.append(self.anal_type(t, nested, allow_param_spec=allow_param_spec)) return res - def anal_type(self, t: Type, nested: bool = True) -> Type: + def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = False) -> Type: if nested: self.nesting_level += 1 + old_allow_required = self.allow_required + self.allow_required = False try: - return t.accept(self) + analyzed = t.accept(self) finally: if nested: self.nesting_level -= 1 + self.allow_required = old_allow_required + if (not allow_param_spec + and isinstance(analyzed, ParamSpecType) + and analyzed.flavor == ParamSpecFlavor.BARE): + self.fail('Invalid location for ParamSpec "{}"'.format(analyzed.name), t) + self.note( + 'You can use ParamSpec as the first argument to Callable, e.g., ' + "'Callable[{}, int]'".format(analyzed.name), + t + ) + return analyzed - def anal_var_def(self, var_def: TypeVarLikeDef) -> TypeVarLikeDef: - if isinstance(var_def, TypeVarDef): - return TypeVarDef( + def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType: + if isinstance(var_def, TypeVarType): + return TypeVarType( var_def.name, var_def.fullname, var_def.id.raw_id, @@ -980,7 +1047,7 @@ def anal_var_def(self, var_def: TypeVarLikeDef) -> TypeVarLikeDef: else: return var_def - def anal_var_defs(self, var_defs: Sequence[TypeVarLikeDef]) -> List[TypeVarLikeDef]: + def anal_var_defs(self, var_defs: Sequence[TypeVarLikeType]) -> List[TypeVarLikeType]: return [self.anal_var_def(vd) for vd in var_defs] def named_type_with_normalized_str(self, fully_qualified_name: str) -> Instance: @@ -1069,7 +1136,7 @@ def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback, """ if len(t.args) == 0: if use_generic_error: - fullname = None # type: Optional[str] + fullname: Optional[str] = None else: fullname = t.type.fullname any_type = get_omitted_any(disallow_any, fail, note, t, python_version, fullname, @@ -1168,8 +1235,8 @@ def set_any_tvars(node: TypeAlias, def remove_dups(tvars: Iterable[T]) -> List[T]: # Get unique elements in order of appearance - all_tvars = set() # type: Set[T] - new_tvars = [] # type: List[T] + all_tvars: Set[T] = set() + new_tvars: List[T] = [] for t in tvars: if t not in all_tvars: new_tvars.append(t) @@ -1182,6 +1249,7 @@ def flatten_tvars(ll: Iterable[List[T]]) -> List[T]: class TypeVarLikeQuery(TypeQuery[TypeVarLikeList]): + """Find TypeVar and ParamSpec references in an unbound type.""" def __init__(self, lookup: Callable[[str, Context], Optional[SymbolTableNode]], @@ -1204,7 +1272,17 @@ def _seems_like_callable(self, type: UnboundType) -> bool: def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList: name = t.name - node = self.lookup(name, t) + node = None + # Special case P.args and P.kwargs for ParamSpecs only. + if name.endswith('args'): + if name.endswith('.args') or name.endswith('.kwargs'): + base = '.'.join(name.split('.')[:-1]) + n = self.lookup(base, t) + if n is not None and isinstance(n.node, ParamSpecExpr): + node = n + name = base + if node is None: + node = self.lookup(name, t) if node and isinstance(node.node, TypeVarLikeExpr) and ( self.include_bound_tvars or self.scope.get_binding(node) is None): assert isinstance(node.node, TypeVarLikeExpr) @@ -1213,6 +1291,9 @@ def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList: return [] elif node and node.fullname in ('typing_extensions.Literal', 'typing.Literal'): return [] + elif node and node.fullname in ('typing_extensions.Annotated', 'typing.Annotated'): + # Don't query the second argument to Annotated for TypeVars + return self.query_types([t.args[0]]) else: return super().visit_unbound_type(t) @@ -1289,7 +1370,7 @@ def visit_any(self, t: AnyType) -> List[AnyType]: @classmethod def combine_lists_strategy(cls, it: Iterable[List[AnyType]]) -> List[AnyType]: - result = [] # type: List[AnyType] + result: List[AnyType] = [] for l in it: result.extend(l) return result diff --git a/mypy/typeops.py b/mypy/typeops.py index 56a6002d1e40..9ba170b4b822 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -11,18 +11,17 @@ import sys from mypy.types import ( - TupleType, Instance, FunctionLike, Type, CallableType, TypeVarDef, TypeVarLikeDef, Overloaded, + TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, TypedDictType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, - copy_type, TypeAliasType, TypeQuery + copy_type, TypeAliasType, TypeQuery, ParamSpecType ) from mypy.nodes import ( - FuncBase, FuncItem, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS, + FuncBase, FuncItem, FuncDef, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS, Expression, StrExpr, Var, Decorator, SYMBOL_FUNCBASE_TYPES ) from mypy.maptype import map_instance_to_supertype from mypy.expandtype import expand_type_by_instance, expand_type -from mypy.sharedparse import argument_elide_name from mypy.typevars import fill_typevars @@ -77,9 +76,9 @@ def type_object_type_from_function(signature: FunctionLike, default_self = fill_typevars(info) if not is_new and not info.is_newtype: orig_self_types = [(it.arg_types[0] if it.arg_types and it.arg_types[0] != default_self - and it.arg_kinds[0] == ARG_POS else None) for it in signature.items()] + and it.arg_kinds[0] == ARG_POS else None) for it in signature.items] else: - orig_self_types = [None] * len(signature.items()) + orig_self_types = [None] * len(signature.items) # The __init__ method might come from a generic superclass 'def_info' # with type variables that do not map identically to the type variables of @@ -94,7 +93,7 @@ def type_object_type_from_function(signature: FunctionLike, signature = bind_self(signature, original_type=default_self, is_classmethod=is_new) signature = cast(FunctionLike, map_type_from_supertype(signature, info, def_info)) - special_sig = None # type: Optional[str] + special_sig: Optional[str] = None if def_info.fullname == 'builtins.dict': # Special signature! special_sig = 'dict' @@ -104,8 +103,8 @@ def type_object_type_from_function(signature: FunctionLike, else: # Overloaded __init__/__new__. assert isinstance(signature, Overloaded) - items = [] # type: List[CallableType] - for item, orig_self in zip(signature.items(), orig_self_types): + items: List[CallableType] = [] + for item, orig_self in zip(signature.items, orig_self_types): items.append(class_callable(item, info, fallback, special_sig, is_new, orig_self)) return Overloaded(items) @@ -114,7 +113,7 @@ def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance, special_sig: Optional[str], is_new: bool, orig_self_type: Optional[Type] = None) -> CallableType: """Create a type object type based on the signature of __init__.""" - variables = [] # type: List[TypeVarLikeDef] + variables: List[TypeVarLikeType] = [] variables.extend(info.defn.type_vars) variables.extend(init_type.variables) @@ -130,7 +129,7 @@ def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance, # if it is actually returning a subtype of what we would return otherwise. and is_subtype(explicit_type, default_ret_type, ignore_type_params=True) ): - ret_type = explicit_type # type: Type + ret_type: Type = explicit_type else: ret_type = default_ret_type @@ -210,11 +209,9 @@ class B(A): pass b = B().copy() # type: B """ - from mypy.infer import infer_type_arguments - if isinstance(method, Overloaded): return cast(F, Overloaded([bind_self(c, original_type, is_classmethod) - for c in method.items()])) + for c in method.items])) assert isinstance(method, CallableType) func = method if not func.arg_types: @@ -229,8 +226,10 @@ class B(A): pass return cast(F, func) self_param_type = get_proper_type(func.arg_types[0]) - variables = [] # type: Sequence[TypeVarLikeDef] + variables: Sequence[TypeVarLikeType] = [] if func.variables and supported_self_type(self_param_type): + from mypy.infer import infer_type_arguments + if original_type is None: # TODO: type check method override (see #7861). original_type = erase_to_bound(self_param_type) @@ -314,6 +313,17 @@ def callable_corresponding_argument(typ: CallableType, return by_name if by_name is not None else by_pos +def is_simple_literal(t: ProperType) -> bool: + """ + Whether a type is a simple enough literal to allow for fast Union simplification + + For now this means enum or string + """ + return isinstance(t, LiteralType) and ( + t.fallback.type.is_enum or t.fallback.type.fullname == 'builtins.str' + ) + + def make_simplified_union(items: Sequence[Type], line: int = -1, column: int = -1, *, keep_erased: bool = False, @@ -337,7 +347,7 @@ def make_simplified_union(items: Sequence[Type], """ items = get_proper_types(items) while any(isinstance(typ, UnionType) for typ in items): - all_items = [] # type: List[ProperType] + all_items: List[ProperType] = [] for typ in items: if isinstance(typ, UnionType): all_items.extend(get_proper_types(typ.items)) @@ -347,37 +357,55 @@ def make_simplified_union(items: Sequence[Type], from mypy.subtypes import is_proper_subtype - removed = set() # type: Set[int] - - # Avoid slow nested for loop for Union of Literal of strings (issue #9169) - if all((isinstance(item, LiteralType) and - item.fallback.type.fullname == 'builtins.str') - for item in items): - seen = set() # type: Set[str] - for index, item in enumerate(items): + removed: Set[int] = set() + seen: Set[Tuple[str, str]] = set() + + # NB: having a separate fast path for Union of Literal and slow path for other things + # would arguably be cleaner, however it breaks down when simplifying the Union of two + # different enum types as try_expanding_enum_to_union works recursively and will + # trigger intermediate simplifications that would render the fast path useless + for i, item in enumerate(items): + if i in removed: + continue + # Avoid slow nested for loop for Union of Literal of strings/enums (issue #9169) + if is_simple_literal(item): assert isinstance(item, LiteralType) assert isinstance(item.value, str) - if item.value in seen: - removed.add(index) - seen.add(item.value) + k = (item.value, item.fallback.type.fullname) + if k in seen: + removed.add(i) + continue - else: - for i, ti in enumerate(items): - if i in removed: continue - # Keep track of the truishness info for deleted subtypes which can be relevant - cbt = cbf = False - for j, tj in enumerate(items): - if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased) and \ - is_redundant_literal_instance(ti, tj): - # We found a redundant item in the union. - removed.add(j) - cbt = cbt or tj.can_be_true - cbf = cbf or tj.can_be_false - # if deleted subtypes had more general truthiness, use that - if not ti.can_be_true and cbt: - items[i] = true_or_false(ti) - elif not ti.can_be_false and cbf: - items[i] = true_or_false(ti) + # NB: one would naively expect that it would be safe to skip the slow path + # always for literals. One would be sorely mistaken. Indeed, some simplifications + # such as that of None/Optional when strict optional is false, do require that we + # proceed with the slow path. Thankfully, all literals will have the same subtype + # relationship to non-literal types, so we only need to do that walk for the first + # literal, which keeps the fast path fast even in the presence of a mixture of + # literals and other types. + safe_skip = len(seen) > 0 + seen.add(k) + if safe_skip: + continue + # Keep track of the truishness info for deleted subtypes which can be relevant + cbt = cbf = False + for j, tj in enumerate(items): + # NB: we don't need to check literals as the fast path above takes care of that + if ( + i != j + and not is_simple_literal(tj) + and is_proper_subtype(tj, item, keep_erased_types=keep_erased) + and is_redundant_literal_instance(item, tj) # XXX? + ): + # We found a redundant item in the union. + removed.add(j) + cbt = cbt or tj.can_be_true + cbf = cbf or tj.can_be_false + # if deleted subtypes had more general truthiness, use that + if not item.can_be_true and cbt: + items[i] = true_or_false(item) + elif not item.can_be_false and cbf: + items[i] = true_or_false(item) simplified_set = [items[i] for i in range(len(items)) if i not in removed] @@ -388,11 +416,11 @@ def make_simplified_union(items: Sequence[Type], return UnionType.make_union(simplified_set, line, column) -def get_type_special_method_bool_ret_type(t: Type) -> Optional[Type]: +def _get_type_special_method_bool_ret_type(t: Type) -> Optional[Type]: t = get_proper_type(t) if isinstance(t, Instance): - bool_method = t.type.names.get("__bool__", None) + bool_method = t.type.get("__bool__") if bool_method: callee = get_proper_type(bool_method.type) if isinstance(callee, CallableType): @@ -419,7 +447,7 @@ def true_only(t: Type) -> ProperType: can_be_true_items = [item for item in new_items if item.can_be_true] return make_simplified_union(can_be_true_items, line=t.line, column=t.column) else: - ret_type = get_type_special_method_bool_ret_type(t) + ret_type = _get_type_special_method_bool_ret_type(t) if ret_type and ret_type.can_be_false and not ret_type.can_be_true: new_t = copy_type(t) @@ -454,7 +482,7 @@ def false_only(t: Type) -> ProperType: can_be_false_items = [item for item in new_items if item.can_be_false] return make_simplified_union(can_be_false_items, line=t.line, column=t.column) else: - ret_type = get_type_special_method_bool_ret_type(t) + ret_type = _get_type_special_method_bool_ret_type(t) if ret_type and ret_type.can_be_true and not ret_type.can_be_false: new_t = copy_type(t) @@ -482,9 +510,11 @@ def true_or_false(t: Type) -> ProperType: return new_t -def erase_def_to_union_or_bound(tdef: TypeVarLikeDef) -> Type: - # TODO(shantanu): fix for ParamSpecDef - assert isinstance(tdef, TypeVarDef) +def erase_def_to_union_or_bound(tdef: TypeVarLikeType) -> Type: + # TODO(PEP612): fix for ParamSpecType + if isinstance(tdef, ParamSpecType): + return AnyType(TypeOfAny.from_error) + assert isinstance(tdef, TypeVarType) if tdef.values: return make_simplified_union(tdef.values) else: @@ -525,7 +555,7 @@ def callable_type(fdef: FuncItem, fallback: Instance, ret_type: Optional[Type] = None) -> CallableType: # TODO: somewhat unfortunate duplication with prepare_method_signature in semanal if fdef.info and not fdef.is_static and fdef.arg_names: - self_type = fill_typevars(fdef.info) # type: Type + self_type: Type = fill_typevars(fdef.info) if fdef.is_class or fdef.name == '__new__': self_type = TypeType.make_normalized(self_type) args = [self_type] + [AnyType(TypeOfAny.unannotated)] * (len(fdef.arg_names)-1) @@ -535,13 +565,15 @@ def callable_type(fdef: FuncItem, fallback: Instance, return CallableType( args, fdef.arg_kinds, - [None if argument_elide_name(n) else n for n in fdef.arg_names], + fdef.arg_names, ret_type or AnyType(TypeOfAny.unannotated), fallback, name=fdef.name, line=fdef.line, column=fdef.column, implicit=True, + # We need this for better error messages, like missing `self` note: + definition=fdef if isinstance(fdef, FuncDef) else None, ) @@ -600,13 +632,13 @@ def try_getting_literals_from_type(typ: Type, typ = get_proper_type(typ) if isinstance(typ, Instance) and typ.last_known_value is not None: - possible_literals = [typ.last_known_value] # type: List[Type] + possible_literals: List[Type] = [typ.last_known_value] elif isinstance(typ, UnionType): possible_literals = list(typ.items) else: possible_literals = [typ] - literals = [] # type: List[T] + literals: List[T] = [] for lit in get_proper_types(possible_literals): if isinstance(lit, LiteralType) and lit.fallback.type.fullname == target_fullname: val = lit.value @@ -669,7 +701,7 @@ def is_singleton_type(typ: Type) -> bool: ) -def try_expanding_enum_to_union(typ: Type, target_fullname: str) -> ProperType: +def try_expanding_sum_type_to_union(typ: Type, target_fullname: str) -> ProperType: """Attempts to recursively expand any enum Instances with the given target_fullname into a Union of all of its component LiteralTypes. @@ -691,28 +723,34 @@ class Status(Enum): typ = get_proper_type(typ) if isinstance(typ, UnionType): - items = [try_expanding_enum_to_union(item, target_fullname) for item in typ.items] + items = [try_expanding_sum_type_to_union(item, target_fullname) for item in typ.items] return make_simplified_union(items, contract_literals=False) - elif isinstance(typ, Instance) and typ.type.is_enum and typ.type.fullname == target_fullname: - new_items = [] - for name, symbol in typ.type.names.items(): - if not isinstance(symbol.node, Var): - continue - # Skip "_order_" and "__order__", since Enum will remove it - if name in ("_order_", "__order__"): - continue - new_items.append(LiteralType(name, typ)) - # SymbolTables are really just dicts, and dicts are guaranteed to preserve - # insertion order only starting with Python 3.7. So, we sort these for older - # versions of Python to help make tests deterministic. - # - # We could probably skip the sort for Python 3.6 since people probably run mypy - # only using CPython, but we might as well for the sake of full correctness. - if sys.version_info < (3, 7): - new_items.sort(key=lambda lit: lit.value) - return make_simplified_union(new_items, contract_literals=False) - else: - return typ + elif isinstance(typ, Instance) and typ.type.fullname == target_fullname: + if typ.type.is_enum: + new_items = [] + for name, symbol in typ.type.names.items(): + if not isinstance(symbol.node, Var): + continue + # Skip "_order_" and "__order__", since Enum will remove it + if name in ("_order_", "__order__"): + continue + new_items.append(LiteralType(name, typ)) + # SymbolTables are really just dicts, and dicts are guaranteed to preserve + # insertion order only starting with Python 3.7. So, we sort these for older + # versions of Python to help make tests deterministic. + # + # We could probably skip the sort for Python 3.6 since people probably run mypy + # only using CPython, but we might as well for the sake of full correctness. + if sys.version_info < (3, 7): + new_items.sort(key=lambda lit: lit.value) + return make_simplified_union(new_items, contract_literals=False) + elif typ.type.fullname == "builtins.bool": + return make_simplified_union( + [LiteralType(True, typ), LiteralType(False, typ)], + contract_literals=False + ) + + return typ def try_contracting_literals_in_union(types: Sequence[Type]) -> List[ProperType]: @@ -721,18 +759,23 @@ def try_contracting_literals_in_union(types: Sequence[Type]) -> List[ProperType] Will replace the first instance of the literal with the sum type and remove all others. - if we call `try_contracting_union(Literal[Color.RED, Color.BLUE, Color.YELLOW])`, + If we call `try_contracting_union(Literal[Color.RED, Color.BLUE, Color.YELLOW])`, this function will return Color. + + We also treat `Literal[True, False]` as `bool`. """ proper_types = [get_proper_type(typ) for typ in types] - sum_types = {} # type: Dict[str, Tuple[Set[Any], List[int]]] + sum_types: Dict[str, Tuple[Set[Any], List[int]]] = {} marked_for_deletion = set() for idx, typ in enumerate(proper_types): if isinstance(typ, LiteralType): fullname = typ.fallback.type.fullname - if typ.fallback.type.is_enum: + if typ.fallback.type.is_enum or isinstance(typ.value, bool): if fullname not in sum_types: - sum_types[fullname] = (set(get_enum_values(typ.fallback)), []) + sum_types[fullname] = (set(get_enum_values(typ.fallback)) + if typ.fallback.type.is_enum + else set((True, False)), + []) literals, indexes = sum_types[fullname] literals.discard(typ.value) indexes.append(idx) diff --git a/mypy/types.py b/mypy/types.py index d9c71fbcf7ee..14eefea7dd81 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -3,19 +3,19 @@ import copy import sys from abc import abstractmethod -from mypy.ordered_dict import OrderedDict from typing import ( Any, TypeVar, Dict, List, Tuple, cast, Set, Optional, Union, Iterable, NamedTuple, - Sequence, Iterator, overload + Sequence ) -from typing_extensions import ClassVar, Final, TYPE_CHECKING, overload +from typing_extensions import ClassVar, Final, TYPE_CHECKING, overload, TypeAlias as _TypeAlias +from mypy.backports import OrderedDict import mypy.nodes from mypy import state from mypy.nodes import ( - INVARIANT, SymbolNode, ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT, - FuncDef, + INVARIANT, SymbolNode, FuncDef, + ArgKind, ARG_POS, ARG_STAR, ARG_STAR2, ) from mypy.util import IdMapper from mypy.bogus_type import Bogus @@ -23,7 +23,7 @@ T = TypeVar('T') -JsonDict = Dict[str, Any] +JsonDict: _TypeAlias = Dict[str, Any] # The set of all valid expressions that can currently be contained # inside of a Literal[...]. @@ -52,7 +52,7 @@ # Note: Although "Literal[None]" is a valid type, we internally always convert # such a type directly into "None". So, "None" is not a valid parameter of # LiteralType and is omitted from this list. -LiteralValue = Union[int, str, bool] +LiteralValue: _TypeAlias = Union[int, str, bool] # If we only import type_visitor in the middle of the file, mypy @@ -68,45 +68,52 @@ ) # Supported names of TypedDict type constructors. -TPDICT_NAMES = ('typing.TypedDict', - 'typing_extensions.TypedDict', - 'mypy_extensions.TypedDict') # type: Final +TPDICT_NAMES: Final = ( + "typing.TypedDict", + "typing_extensions.TypedDict", + "mypy_extensions.TypedDict", +) # Supported fallback instance type names for TypedDict types. -TPDICT_FB_NAMES = ('typing._TypedDict', - 'typing_extensions._TypedDict', - 'mypy_extensions._TypedDict') # type: Final +TPDICT_FB_NAMES: Final = ( + "typing._TypedDict", + "typing_extensions._TypedDict", + "mypy_extensions._TypedDict", +) # A placeholder used for Bogus[...] parameters -_dummy = object() # type: Final[Any] +_dummy: Final[Any] = object() class TypeOfAny: """ This class describes different types of Any. Each 'Any' can be of only one type at a time. """ + + __slots__ = () + # Was this Any type inferred without a type annotation? - unannotated = 1 # type: Final + unannotated: Final = 1 # Does this Any come from an explicit type annotation? - explicit = 2 # type: Final + explicit: Final = 2 # Does this come from an unfollowed import? See --disallow-any-unimported option - from_unimported_type = 3 # type: Final + from_unimported_type: Final = 3 # Does this Any type come from omitted generics? - from_omitted_generics = 4 # type: Final + from_omitted_generics: Final = 4 # Does this Any come from an error? - from_error = 5 # type: Final + from_error: Final = 5 # Is this a type that can't be represented in mypy's type system? For instance, type of # call to NewType...). Even though these types aren't real Anys, we treat them as such. # Also used for variables named '_'. - special_form = 6 # type: Final + special_form: Final = 6 # Does this Any come from interaction with another Any? - from_another_any = 7 # type: Final + from_another_any: Final = 7 # Does this Any come from an implementation limitation/bug? - implementation_artifact = 8 # type: Final + implementation_artifact: Final = 8 # Does this Any come from use in the suggestion engine? This is # used to ignore Anys inserted by the suggestion engine when # generating constraints. - suggestion_engine = 9 # type: Final + suggestion_engine: Final = 9 def deserialize_type(data: Union[JsonDict, str]) -> 'Type': @@ -123,6 +130,15 @@ class Type(mypy.nodes.Context): """Abstract base class for all types.""" __slots__ = ('can_be_true', 'can_be_false') + # 'can_be_true' and 'can_be_false' mean whether the value of the + # expression can be true or false in a boolean context. They are useful + # when inferring the type of logic expressions like `x and y`. + # + # For example: + # * the literal `False` can't be true while `True` can. + # * a value with type `bool` can be true or false. + # * `None` can't be true + # * ... def __init__(self, line: int = -1, column: int = -1) -> None: super().__init__(line, column) @@ -172,7 +188,7 @@ def __init__(self, alias: Optional[mypy.nodes.TypeAlias], args: List[Type], line: int = -1, column: int = -1) -> None: self.alias = alias self.args = args - self.type_ref = None # type: Optional[str] + self.type_ref: Optional[str] = None super().__init__(line, column) def _expand_once(self) -> Type: @@ -245,15 +261,17 @@ def __eq__(self, other: object) -> bool: def serialize(self) -> JsonDict: assert self.alias is not None - data = {'.class': 'TypeAliasType', - 'type_ref': self.alias.fullname, - 'args': [arg.serialize() for arg in self.args]} # type: JsonDict + data: JsonDict = { + ".class": "TypeAliasType", + "type_ref": self.alias.fullname, + "args": [arg.serialize() for arg in self.args], + } return data @classmethod def deserialize(cls, data: JsonDict) -> 'TypeAliasType': assert data['.class'] == 'TypeAliasType' - args = [] # type: List[Type] + args: List[Type] = [] if 'args' in data: args_list = data['args'] assert isinstance(args_list, list) @@ -270,15 +288,11 @@ def copy_modified(self, *, self.line, self.column) -class ProperType(Type): - """Not a type alias. - - Every type except TypeAliasType must inherit from this type. - """ +class TypeGuardedType(Type): + """Only used by find_isinstance_check() etc.""" + __slots__ = ('type_guard',) -class TypeGuardType(ProperType): - """Only used by find_instance_check() etc.""" def __init__(self, type_guard: Type): super().__init__(line=type_guard.line, column=type_guard.column) self.type_guard = type_guard @@ -286,8 +300,29 @@ def __init__(self, type_guard: Type): def __repr__(self) -> str: return "TypeGuard({})".format(self.type_guard) - def accept(self, visitor: 'TypeVisitor[T]') -> T: - return visitor.visit_type_guard_type(self) + +class RequiredType(Type): + """Required[T] or NotRequired[T]. Only usable at top-level of a TypedDict definition.""" + + def __init__(self, item: Type, *, required: bool) -> None: + super().__init__(line=item.line, column=item.column) + self.item = item + self.required = required + + def __repr__(self) -> str: + if self.required: + return "Required[{}]".format(self.item) + else: + return "NotRequired[{}]".format(self.item) + + +class ProperType(Type): + """Not a type alias. + + Every type except TypeAliasType must inherit from this type. + """ + + __slots__ = () class TypeVarId: @@ -302,14 +337,14 @@ class TypeVarId: # function type variables. # Metavariables are allocated unique ids starting from 1. - raw_id = 0 # type: int + raw_id: int = 0 # Level of the variable in type inference. Currently either 0 for # declared types, or 1 for type inference metavariables. - meta_level = 0 # type: int + meta_level: int = 0 # Class variable used for allocating fresh ids for metavariables. - next_raw_id = 1 # type: ClassVar[int] + next_raw_id: ClassVar[int] = 1 def __init__(self, raw_id: int, meta_level: int = 0) -> None: self.raw_id = raw_id @@ -341,13 +376,18 @@ def is_meta_var(self) -> bool: return self.meta_level > 0 -class TypeVarLikeDef(mypy.nodes.Context): - name = '' # Name (may be qualified) - fullname = '' # Fully qualified name - id = None # type: TypeVarId +class TypeVarLikeType(ProperType): + + __slots__ = ('name', 'fullname', 'id', 'upper_bound') + + name: str # Name (may be qualified) + fullname: str # Fully qualified name + id: TypeVarId + upper_bound: Type def __init__( - self, name: str, fullname: str, id: Union[TypeVarId, int], line: int = -1, column: int = -1 + self, name: str, fullname: str, id: Union[TypeVarId, int], upper_bound: Type, + line: int = -1, column: int = -1 ) -> None: super().__init__(line, column) self.name = name @@ -355,50 +395,52 @@ def __init__( if isinstance(id, int): id = TypeVarId(id) self.id = id - - def __repr__(self) -> str: - return self.name + self.upper_bound = upper_bound def serialize(self) -> JsonDict: raise NotImplementedError @classmethod - def deserialize(cls, data: JsonDict) -> 'TypeVarLikeDef': + def deserialize(cls, data: JsonDict) -> 'TypeVarLikeType': raise NotImplementedError -class TypeVarDef(TypeVarLikeDef): - """Definition of a single type variable.""" - values = None # type: List[Type] # Value restriction, empty list if no restriction - upper_bound = None # type: Type - variance = INVARIANT # type: int +class TypeVarType(TypeVarLikeType): + """Type that refers to a type variable.""" + + __slots__ = ('values', 'variance') + + values: List[Type] # Value restriction, empty list if no restriction + variance: int def __init__(self, name: str, fullname: str, id: Union[TypeVarId, int], values: List[Type], upper_bound: Type, variance: int = INVARIANT, line: int = -1, column: int = -1) -> None: - super().__init__(name, fullname, id, line, column) + super().__init__(name, fullname, id, upper_bound, line, column) assert values is not None, "No restrictions must be represented by empty list" self.values = values - self.upper_bound = upper_bound self.variance = variance @staticmethod - def new_unification_variable(old: 'TypeVarDef') -> 'TypeVarDef': + def new_unification_variable(old: 'TypeVarType') -> 'TypeVarType': new_id = TypeVarId.new(meta_level=1) - return TypeVarDef(old.name, old.fullname, new_id, old.values, + return TypeVarType(old.name, old.fullname, new_id, old.values, old.upper_bound, old.variance, old.line, old.column) - def __repr__(self) -> str: - if self.values: - return '{} in {}'.format(self.name, tuple(self.values)) - elif not is_named_instance(self.upper_bound, 'builtins.object'): - return '{} <: {}'.format(self.name, self.upper_bound) - else: - return self.name + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return visitor.visit_type_var(self) + + def __hash__(self) -> int: + return hash(self.id) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, TypeVarType): + return NotImplemented + return self.id == other.id def serialize(self) -> JsonDict: assert not self.id.is_meta_var() - return {'.class': 'TypeVarDef', + return {'.class': 'TypeVarType', 'name': self.name, 'fullname': self.fullname, 'id': self.id.raw_id, @@ -408,36 +450,106 @@ def serialize(self) -> JsonDict: } @classmethod - def deserialize(cls, data: JsonDict) -> 'TypeVarDef': - assert data['.class'] == 'TypeVarDef' - return TypeVarDef(data['name'], - data['fullname'], - data['id'], - [deserialize_type(v) for v in data['values']], - deserialize_type(data['upper_bound']), - data['variance'], - ) + def deserialize(cls, data: JsonDict) -> 'TypeVarType': + assert data['.class'] == 'TypeVarType' + return TypeVarType( + data['name'], + data['fullname'], + data['id'], + [deserialize_type(v) for v in data['values']], + deserialize_type(data['upper_bound']), + data['variance'], + ) + + +class ParamSpecFlavor: + # Simple ParamSpec reference such as "P" + BARE: Final = 0 + # P.args + ARGS: Final = 1 + # P.kwargs + KWARGS: Final = 2 + + +class ParamSpecType(TypeVarLikeType): + """Type that refers to a ParamSpec. + + A ParamSpec is a type variable that represents the parameter + types, names and kinds of a callable (i.e., the signature without + the return type). + This can be one of these forms + * P (ParamSpecFlavor.BARE) + * P.args (ParamSpecFlavor.ARGS) + * P.kwargs (ParamSpecFLavor.KWARGS) -class ParamSpecDef(TypeVarLikeDef): - """Definition of a single ParamSpec variable.""" + The upper_bound is really used as a fallback type -- it's shared + with TypeVarType for simplicity. It can't be specified by the user + and the value is directly derived from the flavor (currently + always just 'object'). + """ + + __slots__ = ('flavor',) + + flavor: int + + def __init__( + self, name: str, fullname: str, id: Union[TypeVarId, int], flavor: int, + upper_bound: Type, *, line: int = -1, column: int = -1 + ) -> None: + super().__init__(name, fullname, id, upper_bound, line=line, column=column) + self.flavor = flavor + + @staticmethod + def new_unification_variable(old: 'ParamSpecType') -> 'ParamSpecType': + new_id = TypeVarId.new(meta_level=1) + return ParamSpecType(old.name, old.fullname, new_id, old.flavor, old.upper_bound, + line=old.line, column=old.column) + + def with_flavor(self, flavor: int) -> 'ParamSpecType': + return ParamSpecType(self.name, self.fullname, self.id, flavor, + upper_bound=self.upper_bound) + + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return visitor.visit_param_spec(self) + + def name_with_suffix(self) -> str: + n = self.name + if self.flavor == ParamSpecFlavor.ARGS: + return f'{n}.args' + elif self.flavor == ParamSpecFlavor.KWARGS: + return f'{n}.kwargs' + return n + + def __hash__(self) -> int: + return hash((self.id, self.flavor)) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, ParamSpecType): + return NotImplemented + # Upper bound can be ignored, since it's determined by flavor. + return self.id == other.id and self.flavor == other.flavor def serialize(self) -> JsonDict: assert not self.id.is_meta_var() return { - '.class': 'ParamSpecDef', + '.class': 'ParamSpecType', 'name': self.name, 'fullname': self.fullname, 'id': self.id.raw_id, + 'flavor': self.flavor, + 'upper_bound': self.upper_bound.serialize(), } @classmethod - def deserialize(cls, data: JsonDict) -> 'ParamSpecDef': - assert data['.class'] == 'ParamSpecDef' - return ParamSpecDef( + def deserialize(cls, data: JsonDict) -> 'ParamSpecType': + assert data['.class'] == 'ParamSpecType' + return ParamSpecType( data['name'], data['fullname'], data['id'], + data['flavor'], + deserialize_type(data['upper_bound']), ) @@ -535,9 +647,12 @@ class CallableArgument(ProperType): Note that this is a synthetic type for helping parse ASTs, not a real type. """ - typ = None # type: Type - name = None # type: Optional[str] - constructor = None # type: Optional[str] + + __slots__ = ('typ', 'name', 'constructor') + + typ: Type + name: Optional[str] + constructor: Optional[str] def __init__(self, typ: Type, name: Optional[str], constructor: Optional[str], line: int = -1, column: int = -1) -> None: @@ -563,7 +678,9 @@ class TypeList(ProperType): types before they are processed into Callable types. """ - items = None # type: List[Type] + __slots__ = ('items',) + + items: List[Type] def __init__(self, items: List[Type], line: int = -1, column: int = -1) -> None: super().__init__(line, column) @@ -663,15 +780,18 @@ class UninhabitedType(ProperType): is_subtype(UninhabitedType, T) = True """ - is_noreturn = False # Does this come from a NoReturn? Purely for error messages. + __slots__ = ('ambiguous', 'is_noreturn',) + + is_noreturn: bool # Does this come from a NoReturn? Purely for error messages. # It is important to track whether this is an actual NoReturn type, or just a result # of ambiguous type inference, in the latter case we don't want to mark a branch as # unreachable in binder. - ambiguous = False # Is this a result of inference for a variable without constraints? + ambiguous: bool # Is this a result of inference for a variable without constraints? def __init__(self, is_noreturn: bool = False, line: int = -1, column: int = -1) -> None: super().__init__(line, column) self.is_noreturn = is_noreturn + self.ambiguous = False def can_be_true_default(self) -> bool: return False @@ -742,6 +862,8 @@ class ErasedType(ProperType): it is ignored during type inference. """ + __slots__ = () + def accept(self, visitor: 'TypeVisitor[T]') -> T: return visitor.visit_erased_type(self) @@ -752,7 +874,9 @@ class DeletedType(ProperType): These can be used as lvalues but not rvalues. """ - source = '' # type: Optional[str] # May be None; name that generated this value + __slots__ = ('source',) + + source: Optional[str] # May be None; name that generated this value def __init__(self, source: Optional[str] = None, line: int = -1, column: int = -1) -> None: super().__init__(line, column) @@ -772,7 +896,7 @@ def deserialize(cls, data: JsonDict) -> 'DeletedType': # Fake TypeInfo to be used as a placeholder during Instance de-serialization. -NOT_READY = mypy.nodes.FakeInfo('De-serialization failure: TypeInfo not fixed') # type: Final +NOT_READY: Final = mypy.nodes.FakeInfo("De-serialization failure: TypeInfo not fixed") class Instance(ProperType): @@ -789,7 +913,7 @@ def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], super().__init__(line, column) self.type = typ self.args = tuple(args) - self.type_ref = None # type: Optional[str] + self.type_ref: Optional[str] = None # True if result of type variable substitution self.erased = erased @@ -860,10 +984,11 @@ def serialize(self) -> Union[JsonDict, str]: type_ref = self.type.fullname if not self.args and not self.last_known_value: return type_ref - data = {'.class': 'Instance', - } # type: JsonDict - data['type_ref'] = type_ref - data['args'] = [arg.serialize() for arg in self.args] + data: JsonDict = { + ".class": "Instance", + } + data["type_ref"] = type_ref + data["args"] = [arg.serialize() for arg in self.args] if self.last_known_value is not None: data['last_known_value'] = self.last_known_value.serialize() return data @@ -875,7 +1000,7 @@ def deserialize(cls, data: Union[JsonDict, str]) -> 'Instance': inst.type_ref = data return inst assert data['.class'] == 'Instance' - args = [] # type: List[Type] + args: List[Type] = [] if 'args' in data: args_list = data['args'] assert isinstance(args_list, list) @@ -903,61 +1028,6 @@ def has_readable_member(self, name: str) -> bool: return self.type.has_readable_member(name) -class TypeVarType(ProperType): - """A type variable type. - - This refers to either a class type variable (id > 0) or a function - type variable (id < 0). - """ - - __slots__ = ('name', 'fullname', 'id', 'values', 'upper_bound', 'variance') - - def __init__(self, binder: TypeVarDef, line: int = -1, column: int = -1) -> None: - super().__init__(line, column) - self.name = binder.name # Name of the type variable (for messages and debugging) - self.fullname = binder.fullname # type: str - self.id = binder.id # type: TypeVarId - # Value restriction, empty list if no restriction - self.values = binder.values # type: List[Type] - # Upper bound for values - self.upper_bound = binder.upper_bound # type: Type - # See comments in TypeVarDef for more about variance. - self.variance = binder.variance # type: int - - def accept(self, visitor: 'TypeVisitor[T]') -> T: - return visitor.visit_type_var(self) - - def __hash__(self) -> int: - return hash(self.id) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, TypeVarType): - return NotImplemented - return self.id == other.id - - def serialize(self) -> JsonDict: - assert not self.id.is_meta_var() - return {'.class': 'TypeVarType', - 'name': self.name, - 'fullname': self.fullname, - 'id': self.id.raw_id, - 'values': [v.serialize() for v in self.values], - 'upper_bound': self.upper_bound.serialize(), - 'variance': self.variance, - } - - @classmethod - def deserialize(cls, data: JsonDict) -> 'TypeVarType': - assert data['.class'] == 'TypeVarType' - tvdef = TypeVarDef(data['name'], - data['fullname'], - data['id'], - [deserialize_type(v) for v in data['values']], - deserialize_type(data['upper_bound']), - data['variance']) - return TypeVarType(tvdef) - - class FunctionLike(ProperType): """Abstract base class for function types.""" @@ -966,9 +1036,7 @@ class FunctionLike(ProperType): def __init__(self, line: int = -1, column: int = -1) -> None: super().__init__(line, column) self.can_be_false = False - if TYPE_CHECKING: # we don't want a runtime None value - # Corresponding instance type (e.g. builtins.type) - self.fallback = cast(Instance, None) + self.fallback: Instance @abstractmethod def is_type_obj(self) -> bool: pass @@ -976,6 +1044,7 @@ def is_type_obj(self) -> bool: pass @abstractmethod def type_object(self) -> mypy.nodes.TypeInfo: pass + @property @abstractmethod def items(self) -> List['CallableType']: pass @@ -1023,13 +1092,13 @@ class CallableType(FunctionLike): def __init__(self, arg_types: Sequence[Type], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Sequence[Optional[str]], ret_type: Type, fallback: Instance, name: Optional[str] = None, definition: Optional[SymbolNode] = None, - variables: Optional[Sequence[TypeVarLikeDef]] = None, + variables: Optional[Sequence[TypeVarLikeType]] = None, line: int = -1, column: int = -1, is_ellipsis_args: bool = False, @@ -1068,22 +1137,29 @@ def __init__(self, # after serialization, but it is useful in error messages. # TODO: decide how to add more info here (file, line, column) # without changing interface hash. - self.def_extras = {'first_arg': definition.arg_names[0] - if definition.arg_names and definition.info and - not definition.is_static else None} + self.def_extras = { + 'first_arg': ( + definition.arguments[0].variable.name + if (getattr(definition, 'arguments', None) + and definition.arg_names + and definition.info + and not definition.is_static) + else None + ), + } else: self.def_extras = {} self.type_guard = type_guard def copy_modified(self, arg_types: Bogus[Sequence[Type]] = _dummy, - arg_kinds: Bogus[List[int]] = _dummy, + arg_kinds: Bogus[List[ArgKind]] = _dummy, arg_names: Bogus[List[Optional[str]]] = _dummy, ret_type: Bogus[Type] = _dummy, fallback: Bogus[Instance] = _dummy, name: Bogus[Optional[str]] = _dummy, definition: Bogus[SymbolNode] = _dummy, - variables: Bogus[Sequence[TypeVarLikeDef]] = _dummy, + variables: Bogus[Sequence[TypeVarLikeType]] = _dummy, line: Bogus[int] = _dummy, column: Bogus[int] = _dummy, is_ellipsis_args: Bogus[bool] = _dummy, @@ -1168,10 +1244,9 @@ def max_possible_positional_args(self) -> int: This takes into account *arg and **kwargs but excludes keyword-only args.""" if self.is_var_arg or self.is_kw_arg: return sys.maxsize - blacklist = (ARG_NAMED, ARG_NAMED_OPT) - return len([kind not in blacklist for kind in self.arg_kinds]) + return sum([kind.is_positional() for kind in self.arg_kinds]) - def formal_arguments(self, include_star_args: bool = False) -> Iterator[FormalArgument]: + def formal_arguments(self, include_star_args: bool = False) -> List[FormalArgument]: """Yields the formal arguments corresponding to this callable, ignoring *arg and **kwargs. To handle *args and **kwargs, use the 'callable.var_args' and 'callable.kw_args' fields, @@ -1179,21 +1254,25 @@ def formal_arguments(self, include_star_args: bool = False) -> Iterator[FormalAr If you really want to include star args in the yielded output, set the 'include_star_args' parameter to 'True'.""" + args = [] done_with_positional = False for i in range(len(self.arg_types)): kind = self.arg_kinds[i] - if kind in (ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT): + if kind.is_named() or kind.is_star(): done_with_positional = True - if not include_star_args and kind in (ARG_STAR, ARG_STAR2): + if not include_star_args and kind.is_star(): continue - required = kind in (ARG_POS, ARG_NAMED) + required = kind.is_required() pos = None if done_with_positional else i - yield FormalArgument( + arg = FormalArgument( self.arg_names[i], pos, self.arg_types[i], - required) + required + ) + args.append(arg) + return args def argument_by_name(self, name: Optional[str]) -> Optional[FormalArgument]: if name is None: @@ -1202,13 +1281,13 @@ def argument_by_name(self, name: Optional[str]) -> Optional[FormalArgument]: for i, (arg_name, kind, typ) in enumerate( zip(self.arg_names, self.arg_kinds, self.arg_types)): # No more positional arguments after these. - if kind in (ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT): + if kind.is_named() or kind.is_star(): seen_star = True - if kind == ARG_STAR or kind == ARG_STAR2: + if kind.is_star(): continue if arg_name == name: position = None if seen_star else i - return FormalArgument(name, position, typ, kind in (ARG_POS, ARG_NAMED)) + return FormalArgument(name, position, typ, kind.is_required()) return self.try_synthesizing_arg_from_kwarg(name) def argument_by_position(self, position: Optional[int]) -> Optional[FormalArgument]: @@ -1221,7 +1300,7 @@ def argument_by_position(self, position: Optional[int]) -> Optional[FormalArgume self.arg_kinds[position], self.arg_types[position], ) - if kind in (ARG_POS, ARG_OPT): + if kind.is_positional(): return FormalArgument(name, position, typ, kind == ARG_POS) else: return self.try_synthesizing_arg_from_vararg(position) @@ -1242,6 +1321,7 @@ def try_synthesizing_arg_from_vararg(self, else: return None + @property def items(self) -> List['CallableType']: return [self] @@ -1249,11 +1329,32 @@ def is_generic(self) -> bool: return bool(self.variables) def type_var_ids(self) -> List[TypeVarId]: - a = [] # type: List[TypeVarId] + a: List[TypeVarId] = [] for tv in self.variables: a.append(tv.id) return a + def param_spec(self) -> Optional[ParamSpecType]: + """Return ParamSpec if callable can be called with one. + + A Callable accepting ParamSpec P args (*args, **kwargs) must have the + two final parameters like this: *args: P.args, **kwargs: P.kwargs. + """ + if len(self.arg_types) < 2: + return None + if self.arg_kinds[-2] != ARG_STAR or self.arg_kinds[-1] != ARG_STAR2: + return None + arg_type = self.arg_types[-2] + if not isinstance(arg_type, ParamSpecType): + return None + return ParamSpecType(arg_type.name, arg_type.fullname, arg_type.id, ParamSpecFlavor.BARE, + arg_type.upper_bound) + + def expand_param_spec(self, c: 'CallableType') -> 'CallableType': + return self.copy_modified(arg_types=self.arg_types[:-2] + c.arg_types, + arg_kinds=self.arg_kinds[:-2] + c.arg_kinds, + arg_names=self.arg_names[:-2] + c.arg_names) + def __hash__(self) -> int: return hash((self.ret_type, self.is_type_obj(), self.is_ellipsis_args, self.name, @@ -1276,7 +1377,7 @@ def serialize(self) -> JsonDict: # generic functions for non-generic functions. return {'.class': 'CallableType', 'arg_types': [t.serialize() for t in self.arg_types], - 'arg_kinds': self.arg_kinds, + 'arg_kinds': [int(x.value) for x in self.arg_kinds], 'arg_names': self.arg_names, 'ret_type': self.ret_type.serialize(), 'fallback': self.fallback.serialize(), @@ -1295,21 +1396,21 @@ def serialize(self) -> JsonDict: def deserialize(cls, data: JsonDict) -> 'CallableType': assert data['.class'] == 'CallableType' # TODO: Set definition to the containing SymbolNode? - return CallableType([deserialize_type(t) for t in data['arg_types']], - data['arg_kinds'], - data['arg_names'], - deserialize_type(data['ret_type']), - Instance.deserialize(data['fallback']), - name=data['name'], - variables=[TypeVarDef.deserialize(v) for v in data['variables']], - is_ellipsis_args=data['is_ellipsis_args'], - implicit=data['implicit'], - bound_args=[(None if t is None else deserialize_type(t)) - for t in data['bound_args']], - def_extras=data['def_extras'], - type_guard=(deserialize_type(data['type_guard']) - if data['type_guard'] is not None else None), - ) + return CallableType( + [deserialize_type(t) for t in data['arg_types']], + [ArgKind(x) for x in data['arg_kinds']], + data['arg_names'], + deserialize_type(data['ret_type']), + Instance.deserialize(data['fallback']), + name=data['name'], + variables=[cast(TypeVarLikeType, deserialize_type(v)) for v in data['variables']], + is_ellipsis_args=data['is_ellipsis_args'], + implicit=data['implicit'], + bound_args=[(None if t is None else deserialize_type(t)) for t in data['bound_args']], + def_extras=data['def_extras'], + type_guard=(deserialize_type(data['type_guard']) + if data['type_guard'] is not None else None), + ) class Overloaded(FunctionLike): @@ -1321,13 +1422,16 @@ class Overloaded(FunctionLike): implementation. """ - _items = None # type: List[CallableType] # Must not be empty + __slots__ = ('_items', 'fallback') + + _items: List[CallableType] # Must not be empty def __init__(self, items: List[CallableType]) -> None: super().__init__(items[0].line, items[0].column) self._items = items self.fallback = items[0].fallback + @property def items(self) -> List[CallableType]: return self._items @@ -1345,7 +1449,7 @@ def type_object(self) -> mypy.nodes.TypeInfo: return self._items[0].type_object() def with_name(self, name: str) -> 'Overloaded': - ni = [] # type: List[CallableType] + ni: List[CallableType] = [] for it in self._items: ni.append(it.with_name(name)) return Overloaded(ni) @@ -1357,16 +1461,16 @@ def accept(self, visitor: 'TypeVisitor[T]') -> T: return visitor.visit_overloaded(self) def __hash__(self) -> int: - return hash(tuple(self.items())) + return hash(tuple(self.items)) def __eq__(self, other: object) -> bool: if not isinstance(other, Overloaded): return NotImplemented - return self.items() == other.items() + return self.items == other.items def serialize(self) -> JsonDict: return {'.class': 'Overloaded', - 'items': [t.serialize() for t in self.items()], + 'items': [t.serialize() for t in self.items], } @classmethod @@ -1388,9 +1492,11 @@ class TupleType(ProperType): implicit: If True, derived from a tuple expression (t,....) instead of Tuple[t, ...] """ - items = None # type: List[Type] - partial_fallback = None # type: Instance - implicit = False + __slots__ = ('items', 'partial_fallback', 'implicit') + + items: List[Type] + partial_fallback: Instance + implicit: bool def __init__(self, items: List[Type], fallback: Instance, line: int = -1, column: int = -1, implicit: bool = False) -> None: @@ -1463,9 +1569,11 @@ class TypedDictType(ProperType): TODO: The fallback structure is perhaps overly complicated. """ - items = None # type: OrderedDict[str, Type] # item_name -> item_type - required_keys = None # type: Set[str] - fallback = None # type: Instance + __slots__ = ('items', 'required_keys', 'fallback') + + items: "OrderedDict[str, Type]" # item_name -> item_type + required_keys: Set[str] + fallback: Instance def __init__(self, items: 'OrderedDict[str, Type]', required_keys: Set[str], fallback: Instance, line: int = -1, column: int = -1) -> None: @@ -1600,6 +1708,9 @@ class RawExpressionType(ProperType): ], ) """ + + __slots__ = ('literal_value', 'base_type_name', 'note') + def __init__(self, literal_value: Optional[LiteralValue], base_type_name: str, @@ -1727,7 +1838,9 @@ class StarType(ProperType): This is not a real type but a syntactic AST construct. """ - type = None # type: Type + __slots__ = ('type',) + + type: Type def __init__(self, type: Type, line: int = -1, column: int = -1) -> None: super().__init__(line, column) @@ -1832,12 +1945,14 @@ class PartialType(ProperType): x = 1 # Infer actual type int for x """ + __slots__ = ('type', 'var', 'value_type') + # None for the 'None' partial type; otherwise a generic class - type = None # type: Optional[mypy.nodes.TypeInfo] - var = None # type: mypy.nodes.Var + type: Optional[mypy.nodes.TypeInfo] + var: mypy.nodes.Var # For partial defaultdict[K, V], the type V (K is unknown). If V is generic, # the type argument is Any and will be replaced later. - value_type = None # type: Optional[Instance] + value_type: Optional[Instance] def __init__(self, type: 'Optional[mypy.nodes.TypeInfo]', @@ -1860,6 +1975,8 @@ class EllipsisType(ProperType): A semantically analyzed type will never have ellipsis types. """ + __slots__ = () + def accept(self, visitor: 'TypeVisitor[T]') -> T: assert isinstance(visitor, SyntheticTypeVisitor) return visitor.visit_ellipsis_type(self) @@ -1896,9 +2013,11 @@ class TypeType(ProperType): assumption). """ + __slots__ = ('item',) + # This can't be everything, but it can be a class reference, # a generic class instance, a union, Any, a type variable... - item = None # type: ProperType + item: ProperType def __init__(self, item: Bogus[Union[Instance, AnyType, TypeVarType, TupleType, NoneType, CallableType]], *, @@ -1955,6 +2074,8 @@ class str(Sequence[str]): ... exist. """ + __slots__ = ('fullname', 'args') + def __init__(self, fullname: Optional[str], args: List[Type], line: int) -> None: super().__init__(line) self.fullname = fullname # Must be a valid full name of an actual node (or None). @@ -1987,6 +2108,8 @@ def get_proper_type(typ: Optional[Type]) -> Optional[ProperType]: """ if typ is None: return None + if isinstance(typ, TypeGuardedType): # type: ignore[misc] + typ = typ.type_guard while isinstance(typ, TypeAliasType): typ = typ._expand_once() assert isinstance(typ, ProperType), typ @@ -2096,13 +2219,28 @@ def visit_type_var(self, t: TypeVarType) -> str: s += '(upper_bound={})'.format(t.upper_bound.accept(self)) return s + def visit_param_spec(self, t: ParamSpecType) -> str: + if t.name is None: + # Anonymous type variable type (only numeric id). + s = f'`{t.id}' + else: + # Named type variable type. + s = f'{t.name_with_suffix()}`{t.id}' + return s + def visit_callable_type(self, t: CallableType) -> str: + param_spec = t.param_spec() + if param_spec is not None: + num_skip = 2 + else: + num_skip = 0 + s = '' bare_asterisk = False - for i in range(len(t.arg_types)): + for i in range(len(t.arg_types) - num_skip): if s != '': s += ', ' - if t.arg_kinds[i] in (ARG_NAMED, ARG_NAMED_OPT) and not bare_asterisk: + if t.arg_kinds[i].is_named() and not bare_asterisk: s += '*, ' bare_asterisk = True if t.arg_kinds[i] == ARG_STAR: @@ -2113,9 +2251,15 @@ def visit_callable_type(self, t: CallableType) -> str: if name: s += name + ': ' s += t.arg_types[i].accept(self) - if t.arg_kinds[i] in (ARG_OPT, ARG_NAMED_OPT): + if t.arg_kinds[i].is_optional(): s += ' =' + if param_spec is not None: + n = param_spec.name + if s: + s += ', ' + s += f'*{n}.args, **{n}.kwargs' + s = '({})'.format(s) if not isinstance(get_proper_type(t.ret_type), NoneType): @@ -2127,8 +2271,8 @@ def visit_callable_type(self, t: CallableType) -> str: if t.variables: vs = [] for var in t.variables: - if isinstance(var, TypeVarDef): - # We reimplement TypeVarDef.__repr__ here in order to support id_mapper. + if isinstance(var, TypeVarType): + # We reimplement TypeVarType.__repr__ here in order to support id_mapper. if var.values: vals = '({})'.format(', '.join(val.accept(self) for val in var.values)) vs.append('{} in {}'.format(var.name, vals)) @@ -2137,15 +2281,15 @@ def visit_callable_type(self, t: CallableType) -> str: else: vs.append(var.name) else: - # For other TypeVarLikeDefs, just use the repr - vs.append(repr(var)) + # For other TypeVarLikeTypes, just use the name + vs.append(var.name) s = '{} {}'.format('[{}]'.format(', '.join(vs)), s) return 'def {}'.format(s) def visit_overloaded(self, t: Overloaded) -> str: a = [] - for i in t.items(): + for i in t.items: a.append(i.accept(self)) return 'Overload({})'.format(', '.join(a)) @@ -2186,9 +2330,6 @@ def visit_union_type(self, t: UnionType) -> str: s = self.list_str(t.items) return 'Union[{}]'.format(s) - def visit_type_guard_type(self, t: TypeGuardType) -> str: - return 'TypeGuard[{}]'.format(t.type_guard.accept(self)) - def visit_partial_type(self, t: PartialType) -> str: if t.type is None: return '' @@ -2251,7 +2392,7 @@ def strip_type(typ: Type) -> ProperType: return typ.copy_modified(name=None) elif isinstance(typ, Overloaded): return Overloaded([cast(CallableType, strip_type(item)) - for item in typ.items()]) + for item in typ.items]) else: return typ @@ -2324,9 +2465,10 @@ def flatten_nested_unions(types: Iterable[Type], # This and similar functions on unions can cause infinite recursion # if passed a "pathological" alias like A = Union[int, A] or similar. # TODO: ban such aliases in semantic analyzer. - flat_items = [] # type: List[Type] + flat_items: List[Type] = [] if handle_type_alias_type: types = get_proper_types(types) + # TODO: avoid duplicate types in unions (e.g. using hash) for tp in types: if isinstance(tp, ProperType) and isinstance(tp, UnionType): flat_items.extend(flatten_nested_unions(tp.items, @@ -2351,6 +2493,16 @@ def union_items(typ: Type) -> List[ProperType]: return [typ] +def is_union_with_any(tp: Type) -> bool: + """Is this a union with Any or a plain Any type?""" + tp = get_proper_type(tp) + if isinstance(tp, AnyType): + return True + if not isinstance(tp, UnionType): + return False + return any(is_union_with_any(t) for t in get_proper_types(tp.items)) + + def is_generic_instance(tp: Type) -> bool: tp = get_proper_type(tp) return isinstance(tp, Instance) and bool(tp.args) @@ -2382,10 +2534,22 @@ def is_literal_type(typ: ProperType, fallback_fullname: str, value: LiteralValue return typ.value == value -names = globals().copy() # type: Final +names: Final = globals().copy() names.pop('NOT_READY', None) -deserialize_map = { +deserialize_map: Final = { key: obj.deserialize for key, obj in names.items() if isinstance(obj, type) and issubclass(obj, Type) and obj is not Type -} # type: Final +} + + +def callable_with_ellipsis(any_type: AnyType, + ret_type: Type, + fallback: Instance) -> CallableType: + """Construct type Callable[..., ret_type].""" + return CallableType([any_type, any_type], + [ARG_STAR, ARG_STAR2], + [None, None], + ret_type=ret_type, + fallback=fallback, + is_ellipsis_args=True) diff --git a/mypy/typeshed/LICENSE b/mypy/typeshed/LICENSE new file mode 100644 index 000000000000..e5833ae4231d --- /dev/null +++ b/mypy/typeshed/LICENSE @@ -0,0 +1,238 @@ +The "typeshed" project is licensed under the terms of the Apache license, as +reproduced below. + += = = = = + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += = = = = + +Parts of typeshed are licensed under different licenses (like the MIT +license), reproduced below. + += = = = = + +The MIT License + +Copyright (c) 2015 Jukka Lehtosalo and contributors + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + += = = = = + diff --git a/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi b/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi index 28fc4de0409b..46946aa37c46 100644 --- a/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi +++ b/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi @@ -1,6 +1,6 @@ import mimetools import SocketServer -from typing import Any, BinaryIO, Callable, Mapping, Optional, Tuple, Union +from typing import Any, BinaryIO, Callable, Mapping, Tuple class HTTPServer(SocketServer.TCPServer): server_name: str @@ -27,15 +27,15 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): def __init__(self, request: bytes, client_address: Tuple[str, int], server: SocketServer.BaseServer) -> None: ... def handle(self) -> None: ... def handle_one_request(self) -> None: ... - def send_error(self, code: int, message: Optional[str] = ...) -> None: ... - def send_response(self, code: int, message: Optional[str] = ...) -> None: ... + def send_error(self, code: int, message: str | None = ...) -> None: ... + def send_response(self, code: int, message: str | None = ...) -> None: ... def send_header(self, keyword: str, value: str) -> None: ... def end_headers(self) -> None: ... def flush_headers(self) -> None: ... - def log_request(self, code: Union[int, str] = ..., size: Union[int, str] = ...) -> None: ... + def log_request(self, code: int | str = ..., size: int | str = ...) -> None: ... def log_error(self, format: str, *args: Any) -> None: ... def log_message(self, format: str, *args: Any) -> None: ... def version_string(self) -> str: ... - def date_time_string(self, timestamp: Optional[int] = ...) -> str: ... + def date_time_string(self, timestamp: int | None = ...) -> str: ... def log_date_time_string(self) -> str: ... def address_string(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/ConfigParser.pyi b/mypy/typeshed/stdlib/@python2/ConfigParser.pyi index 05c90ed2c248..89167b3e7ec8 100644 --- a/mypy/typeshed/stdlib/@python2/ConfigParser.pyi +++ b/mypy/typeshed/stdlib/@python2/ConfigParser.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsNoArgReadline -from typing import IO, Any, Dict, List, Optional, Sequence, Tuple, Union +from typing import IO, Any, Dict, List, Sequence, Tuple DEFAULTSECT: str MAX_INTERPOLATION_DEPTH: int @@ -65,7 +65,7 @@ class RawConfigParser: def add_section(self, section: str) -> None: ... def has_section(self, section: str) -> bool: ... def options(self, section: str) -> List[str]: ... - def read(self, filenames: Union[str, Sequence[str]]) -> List[str]: ... + def read(self, filenames: str | Sequence[str]) -> List[str]: ... def readfp(self, fp: SupportsNoArgReadline[str], filename: str = ...) -> None: ... def get(self, section: str, option: str) -> str: ... def items(self, section: str) -> List[Tuple[Any, Any]]: ... @@ -84,8 +84,8 @@ class RawConfigParser: class ConfigParser(RawConfigParser): _KEYCRE: Any - def get(self, section: str, option: str, raw: bool = ..., vars: Optional[Dict[Any, Any]] = ...) -> Any: ... - def items(self, section: str, raw: bool = ..., vars: Optional[Dict[Any, Any]] = ...) -> List[Tuple[str, Any]]: ... + def get(self, section: str, option: str, raw: bool = ..., vars: Dict[Any, Any] | None = ...) -> Any: ... + def items(self, section: str, raw: bool = ..., vars: Dict[Any, Any] | None = ...) -> List[Tuple[str, Any]]: ... def _interpolate(self, section: str, option: str, rawval: Any, vars: Any) -> str: ... def _interpolation_replace(self, match: Any) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/Cookie.pyi b/mypy/typeshed/stdlib/@python2/Cookie.pyi index 91dd93221c73..3d01c3c66152 100644 --- a/mypy/typeshed/stdlib/@python2/Cookie.pyi +++ b/mypy/typeshed/stdlib/@python2/Cookie.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict class CookieError(Exception): ... @@ -10,17 +10,17 @@ class Morsel(Dict[Any, Any]): value: Any coded_value: Any def set(self, key, val, coded_val, LegalChars=..., idmap=..., translate=...): ... - def output(self, attrs: Optional[Any] = ..., header=...): ... - def js_output(self, attrs: Optional[Any] = ...): ... - def OutputString(self, attrs: Optional[Any] = ...): ... + def output(self, attrs: Any | None = ..., header=...): ... + def js_output(self, attrs: Any | None = ...): ... + def OutputString(self, attrs: Any | None = ...): ... class BaseCookie(Dict[Any, Any]): def value_decode(self, val): ... def value_encode(self, val): ... - def __init__(self, input: Optional[Any] = ...): ... + def __init__(self, input: Any | None = ...): ... def __setitem__(self, key, value): ... - def output(self, attrs: Optional[Any] = ..., header=..., sep=...): ... - def js_output(self, attrs: Optional[Any] = ...): ... + def output(self, attrs: Any | None = ..., header=..., sep=...): ... + def js_output(self, attrs: Any | None = ...): ... def load(self, rawdata): ... class SimpleCookie(BaseCookie): @@ -28,12 +28,12 @@ class SimpleCookie(BaseCookie): def value_encode(self, val): ... class SerialCookie(BaseCookie): - def __init__(self, input: Optional[Any] = ...): ... + def __init__(self, input: Any | None = ...): ... def value_decode(self, val): ... def value_encode(self, val): ... class SmartCookie(BaseCookie): - def __init__(self, input: Optional[Any] = ...): ... + def __init__(self, input: Any | None = ...): ... def value_decode(self, val): ... def value_encode(self, val): ... diff --git a/mypy/typeshed/stdlib/@python2/Queue.pyi b/mypy/typeshed/stdlib/@python2/Queue.pyi index 98dda8722864..24743a80280d 100644 --- a/mypy/typeshed/stdlib/@python2/Queue.pyi +++ b/mypy/typeshed/stdlib/@python2/Queue.pyi @@ -1,5 +1,4 @@ -from collections import deque -from typing import Any, Deque, Generic, Optional, TypeVar +from typing import Any, Deque, Generic, TypeVar _T = TypeVar("_T") @@ -20,9 +19,9 @@ class Queue(Generic[_T]): def qsize(self) -> int: ... def empty(self) -> bool: ... def full(self) -> bool: ... - def put(self, item: _T, block: bool = ..., timeout: Optional[float] = ...) -> None: ... + def put(self, item: _T, block: bool = ..., timeout: float | None = ...) -> None: ... def put_nowait(self, item: _T) -> None: ... - def get(self, block: bool = ..., timeout: Optional[float] = ...) -> _T: ... + def get(self, block: bool = ..., timeout: float | None = ...) -> _T: ... def get_nowait(self) -> _T: ... class PriorityQueue(Queue[_T]): ... diff --git a/mypy/typeshed/stdlib/@python2/SimpleHTTPServer.pyi b/mypy/typeshed/stdlib/@python2/SimpleHTTPServer.pyi index 7e62b49e8bc6..758d5bd6d515 100644 --- a/mypy/typeshed/stdlib/@python2/SimpleHTTPServer.pyi +++ b/mypy/typeshed/stdlib/@python2/SimpleHTTPServer.pyi @@ -1,14 +1,14 @@ import BaseHTTPServer from StringIO import StringIO -from typing import IO, Any, AnyStr, Mapping, Optional, Union +from typing import IO, Any, AnyStr, Mapping class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): server_version: str def do_GET(self) -> None: ... def do_HEAD(self) -> None: ... - def send_head(self) -> Optional[IO[str]]: ... - def list_directory(self, path: Union[str, unicode]) -> Optional[StringIO[Any]]: ... + def send_head(self) -> IO[str] | None: ... + def list_directory(self, path: str | unicode) -> StringIO[Any] | None: ... def translate_path(self, path: AnyStr) -> AnyStr: ... def copyfile(self, source: IO[AnyStr], outputfile: IO[AnyStr]): ... - def guess_type(self, path: Union[str, unicode]) -> str: ... + def guess_type(self, path: str | unicode) -> str: ... extensions_map: Mapping[str, str] diff --git a/mypy/typeshed/stdlib/@python2/SocketServer.pyi b/mypy/typeshed/stdlib/@python2/SocketServer.pyi index b8a2c14ee5e2..e5a19ffd5e68 100644 --- a/mypy/typeshed/stdlib/@python2/SocketServer.pyi +++ b/mypy/typeshed/stdlib/@python2/SocketServer.pyi @@ -1,7 +1,6 @@ import sys -import types from socket import SocketType -from typing import Any, BinaryIO, Callable, ClassVar, List, Optional, Text, Tuple, Type, Union +from typing import Any, BinaryIO, Callable, ClassVar, List, Text, Tuple, Union class BaseServer: address_family: int @@ -11,7 +10,7 @@ class BaseServer: allow_reuse_address: bool request_queue_size: int socket_type: int - timeout: Optional[float] + timeout: float | None def __init__(self, server_address: Any, RequestHandlerClass: Callable[..., BaseRequestHandler]) -> None: ... def fileno(self) -> int: ... def handle_request(self) -> None: ... @@ -47,22 +46,22 @@ if sys.platform != "win32": class UnixStreamServer(BaseServer): def __init__( self, - server_address: Union[Text, bytes], + server_address: Text | bytes, RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... class UnixDatagramServer(BaseServer): def __init__( self, - server_address: Union[Text, bytes], + server_address: Text | bytes, RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... if sys.platform != "win32": class ForkingMixIn: - timeout: Optional[float] # undocumented - active_children: Optional[List[int]] # undocumented + timeout: float | None # undocumented + active_children: List[int] | None # undocumented max_children: int # undocumented def collect_children(self) -> None: ... # undocumented def handle_timeout(self) -> None: ... # undocumented @@ -100,16 +99,16 @@ class BaseRequestHandler: def finish(self) -> None: ... class StreamRequestHandler(BaseRequestHandler): - rbufsize: ClassVar[int] # Undocumented - wbufsize: ClassVar[int] # Undocumented - timeout: ClassVar[Optional[float]] # Undocumented - disable_nagle_algorithm: ClassVar[bool] # Undocumented - connection: SocketType # Undocumented + rbufsize: ClassVar[int] # undocumented + wbufsize: ClassVar[int] # undocumented + timeout: ClassVar[float | None] # undocumented + disable_nagle_algorithm: ClassVar[bool] # undocumented + connection: SocketType # undocumented rfile: BinaryIO wfile: BinaryIO class DatagramRequestHandler(BaseRequestHandler): - packet: SocketType # Undocumented - socket: SocketType # Undocumented + packet: SocketType # undocumented + socket: SocketType # undocumented rfile: BinaryIO wfile: BinaryIO diff --git a/mypy/typeshed/stdlib/@python2/StringIO.pyi b/mypy/typeshed/stdlib/@python2/StringIO.pyi index 4470b4fc1ad0..efa90f8e0330 100644 --- a/mypy/typeshed/stdlib/@python2/StringIO.pyi +++ b/mypy/typeshed/stdlib/@python2/StringIO.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, List, Optional +from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, List class StringIO(IO[AnyStr], Generic[AnyStr]): closed: bool @@ -15,7 +15,7 @@ class StringIO(IO[AnyStr], Generic[AnyStr]): def read(self, n: int = ...) -> AnyStr: ... def readline(self, length: int = ...) -> AnyStr: ... def readlines(self, sizehint: int = ...) -> List[AnyStr]: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def write(self, s: AnyStr) -> int: ... def writelines(self, iterable: Iterable[AnyStr]) -> None: ... def flush(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/UserDict.pyi b/mypy/typeshed/stdlib/@python2/UserDict.pyi index afa07d861a9e..dce7bebafd66 100644 --- a/mypy/typeshed/stdlib/@python2/UserDict.pyi +++ b/mypy/typeshed/stdlib/@python2/UserDict.pyi @@ -1,19 +1,4 @@ -from typing import ( - Any, - Container, - Dict, - Generic, - Iterable, - Iterator, - List, - Mapping, - Optional, - Sized, - Tuple, - TypeVar, - Union, - overload, -) +from typing import Any, Container, Dict, Generic, Iterable, Iterator, List, Mapping, Sized, Tuple, TypeVar, overload _KT = TypeVar("_KT") _VT = TypeVar("_VT") @@ -33,9 +18,9 @@ class DictMixin(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT]): # From typing.Mapping[_KT, _VT] # (can't inherit because of keys()) @overload - def get(self, k: _KT) -> Optional[_VT]: ... + def get(self, k: _KT) -> _VT | None: ... @overload - def get(self, k: _KT, default: Union[_VT, _T]) -> Union[_VT, _T]: ... + def get(self, k: _KT, default: _VT | _T) -> _VT | _T: ... def values(self) -> List[_VT]: ... def items(self) -> List[Tuple[_KT, _VT]]: ... def iterkeys(self) -> Iterator[_KT]: ... diff --git a/mypy/typeshed/stdlib/@python2/UserList.pyi b/mypy/typeshed/stdlib/@python2/UserList.pyi index 0fc2a31b8651..be4ebce5a815 100644 --- a/mypy/typeshed/stdlib/@python2/UserList.pyi +++ b/mypy/typeshed/stdlib/@python2/UserList.pyi @@ -1,4 +1,4 @@ -from typing import Iterable, List, MutableSequence, TypeVar, Union, overload +from typing import Iterable, List, MutableSequence, TypeVar, overload _T = TypeVar("_T") _S = TypeVar("_S") @@ -10,7 +10,7 @@ class UserList(MutableSequence[_T]): def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __len__(self) -> int: ... @overload def __getitem__(self, i: int) -> _T: ... diff --git a/mypy/typeshed/stdlib/@python2/UserString.pyi b/mypy/typeshed/stdlib/@python2/UserString.pyi index 33de4873992b..f60dbe18f9b1 100644 --- a/mypy/typeshed/stdlib/@python2/UserString.pyi +++ b/mypy/typeshed/stdlib/@python2/UserString.pyi @@ -1,5 +1,4 @@ -import collections -from typing import Any, Iterable, List, MutableSequence, Optional, Sequence, Text, Tuple, TypeVar, Union, overload +from typing import Any, Iterable, List, MutableSequence, Sequence, Text, Tuple, TypeVar, overload _UST = TypeVar("_UST", bound=UserString) _MST = TypeVar("_MST", bound=MutableString) @@ -25,9 +24,9 @@ class UserString(Sequence[UserString]): def capitalize(self: _UST) -> _UST: ... def center(self: _UST, width: int, *args: Any) -> _UST: ... def count(self, sub: int, start: int = ..., end: int = ...) -> int: ... - def decode(self: _UST, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> _UST: ... - def encode(self: _UST, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> _UST: ... - def endswith(self, suffix: Union[Text, Tuple[Text, ...]], start: Optional[int] = ..., end: Optional[int] = ...) -> bool: ... + def decode(self: _UST, encoding: str | None = ..., errors: str | None = ...) -> _UST: ... + def encode(self: _UST, encoding: str | None = ..., errors: str | None = ...) -> _UST: ... + def endswith(self, suffix: Text | Tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... def expandtabs(self: _UST, tabsize: int = ...) -> _UST: ... def find(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def index(self, sub: Text, start: int = ..., end: int = ...) -> int: ... @@ -43,19 +42,19 @@ class UserString(Sequence[UserString]): def join(self, seq: Iterable[Text]) -> Text: ... def ljust(self: _UST, width: int, *args: Any) -> _UST: ... def lower(self: _UST) -> _UST: ... - def lstrip(self: _UST, chars: Optional[Text] = ...) -> _UST: ... + def lstrip(self: _UST, chars: Text | None = ...) -> _UST: ... def partition(self, sep: Text) -> Tuple[Text, Text, Text]: ... def replace(self: _UST, old: Text, new: Text, maxsplit: int = ...) -> _UST: ... def rfind(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def rindex(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def rjust(self: _UST, width: int, *args: Any) -> _UST: ... def rpartition(self, sep: Text) -> Tuple[Text, Text, Text]: ... - def rstrip(self: _UST, chars: Optional[Text] = ...) -> _UST: ... - def split(self, sep: Optional[Text] = ..., maxsplit: int = ...) -> List[Text]: ... - def rsplit(self, sep: Optional[Text] = ..., maxsplit: int = ...) -> List[Text]: ... + def rstrip(self: _UST, chars: Text | None = ...) -> _UST: ... + def split(self, sep: Text | None = ..., maxsplit: int = ...) -> List[Text]: ... + def rsplit(self, sep: Text | None = ..., maxsplit: int = ...) -> List[Text]: ... def splitlines(self, keepends: int = ...) -> List[Text]: ... - def startswith(self, prefix: Union[Text, Tuple[Text, ...]], start: Optional[int] = ..., end: Optional[int] = ...) -> bool: ... - def strip(self: _UST, chars: Optional[Text] = ...) -> _UST: ... + def startswith(self, prefix: Text | Tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def strip(self: _UST, chars: Text | None = ...) -> _UST: ... def swapcase(self: _UST) -> _UST: ... def title(self: _UST) -> _UST: ... def translate(self: _UST, *args: Any) -> _UST: ... @@ -67,8 +66,8 @@ class MutableString(UserString, MutableSequence[MutableString]): def __getitem__(self: _MST, i: int) -> _MST: ... @overload def __getitem__(self: _MST, s: slice) -> _MST: ... - def __setitem__(self, index: Union[int, slice], sub: Any) -> None: ... - def __delitem__(self, index: Union[int, slice]) -> None: ... + def __setitem__(self, index: int | slice, sub: Any) -> None: ... + def __delitem__(self, index: int | slice) -> None: ... def immutable(self) -> UserString: ... def __iadd__(self: _MST, other: Any) -> _MST: ... def __imul__(self, n: int) -> _MST: ... diff --git a/mypy/typeshed/stdlib/@python2/__builtin__.pyi b/mypy/typeshed/stdlib/@python2/__builtin__.pyi index 4eb5424d8da7..fad8b2b4e7d8 100644 --- a/mypy/typeshed/stdlib/@python2/__builtin__.pyi +++ b/mypy/typeshed/stdlib/@python2/__builtin__.pyi @@ -26,7 +26,6 @@ from typing import ( MutableSequence, MutableSet, NoReturn, - Optional, Protocol, Reversible, Sequence, @@ -40,7 +39,6 @@ from typing import ( Tuple, Type, TypeVar, - Union, ValuesView, overload, ) @@ -66,9 +64,9 @@ _TT = TypeVar("_TT", bound="type") _TBE = TypeVar("_TBE", bound="BaseException") class object: - __doc__: Optional[str] + __doc__: str | None __dict__: Dict[str, Any] - __slots__: Union[Text, Iterable[Text]] + __slots__: Text | Iterable[Text] __module__: str @property def __class__(self: _T) -> Type[_T]: ... @@ -86,20 +84,20 @@ class object: def __getattribute__(self, name: str) -> Any: ... def __delattr__(self, name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> Union[str, Tuple[Any, ...]]: ... - def __reduce_ex__(self, protocol: int) -> Union[str, Tuple[Any, ...]]: ... + def __reduce__(self) -> str | Tuple[Any, ...]: ... + def __reduce_ex__(self, protocol: int) -> str | Tuple[Any, ...]: ... class staticmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... class classmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... class type(object): __base__: type @@ -123,7 +121,7 @@ class type(object): def __new__(cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... def __subclasses__(self: _TT) -> List[_TT]: ... - # Note: the documentation doesnt specify what the return type is, the standard + # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. def mro(self) -> List[type]: ... def __instancecheck__(self, instance: Any) -> bool: ... @@ -137,9 +135,9 @@ class super(object): class int: @overload - def __new__(cls: Type[_T], x: Union[Text, bytes, SupportsInt, _SupportsIndex, _SupportsTrunc] = ...) -> _T: ... + def __new__(cls: Type[_T], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> _T: ... @overload - def __new__(cls: Type[_T], x: Union[Text, bytes, bytearray], base: int) -> _T: ... + def __new__(cls: Type[_T], x: Text | bytes | bytearray, base: int) -> _T: ... @property def real(self) -> int: ... @property @@ -167,10 +165,10 @@ class int: def __rmod__(self, x: int) -> int: ... def __rdivmod__(self, x: int) -> Tuple[int, int]: ... @overload - def __pow__(self, __x: Literal[2], __modulo: Optional[int] = ...) -> int: ... + def __pow__(self, __x: Literal[2], __modulo: int | None = ...) -> int: ... @overload - def __pow__(self, __x: int, __modulo: Optional[int] = ...) -> Any: ... # Return type can be int or float, depending on x. - def __rpow__(self, x: int, mod: Optional[int] = ...) -> Any: ... + def __pow__(self, __x: int, __modulo: int | None = ...) -> Any: ... # Return type can be int or float, depending on x. + def __rpow__(self, x: int, mod: int | None = ...) -> Any: ... def __and__(self, n: int) -> int: ... def __or__(self, n: int) -> int: ... def __xor__(self, n: int) -> int: ... @@ -201,7 +199,7 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: Union[SupportsFloat, _SupportsIndex, Text, bytes, bytearray] = ...) -> _T: ... + def __new__(cls: Type[_T], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> _T: ... def as_integer_ratio(self) -> Tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @@ -253,7 +251,7 @@ class complex: @overload def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... @overload - def __new__(cls: Type[_T], real: Union[str, SupportsComplex, _SupportsIndex]) -> _T: ... + def __new__(cls: Type[_T], real: str | SupportsComplex | _SupportsIndex) -> _T: ... @property def real(self) -> float: ... @property @@ -295,9 +293,7 @@ class unicode(basestring, Sequence[unicode]): def count(self, x: unicode) -> int: ... def decode(self, encoding: unicode = ..., errors: unicode = ...) -> unicode: ... def encode(self, encoding: unicode = ..., errors: unicode = ...) -> str: ... - def endswith( - self, __suffix: Union[unicode, Tuple[unicode, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> unicode: ... def find(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> unicode: ... @@ -323,17 +319,15 @@ class unicode(basestring, Sequence[unicode]): def rindex(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rjust(self, width: int, fillchar: unicode = ...) -> unicode: ... def rpartition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... - def rsplit(self, sep: Optional[unicode] = ..., maxsplit: int = ...) -> List[unicode]: ... + def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... def rstrip(self, chars: unicode = ...) -> unicode: ... - def split(self, sep: Optional[unicode] = ..., maxsplit: int = ...) -> List[unicode]: ... + def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... def splitlines(self, keepends: bool = ...) -> List[unicode]: ... - def startswith( - self, __prefix: Union[unicode, Tuple[unicode, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def startswith(self, __prefix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, chars: unicode = ...) -> unicode: ... def swapcase(self) -> unicode: ... def title(self) -> unicode: ... - def translate(self, table: Union[Dict[int, Any], unicode]) -> unicode: ... + def translate(self, table: Dict[int, Any] | unicode) -> unicode: ... def upper(self) -> unicode: ... def zfill(self, width: int) -> unicode: ... @overload @@ -353,7 +347,7 @@ class unicode(basestring, Sequence[unicode]): def __ge__(self, x: unicode) -> bool: ... def __len__(self) -> int: ... # The argument type is incompatible with Sequence - def __contains__(self, s: Union[unicode, bytes]) -> bool: ... # type: ignore + def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore def __iter__(self) -> Iterator[unicode]: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... @@ -369,17 +363,15 @@ class str(Sequence[str], basestring): def __init__(self, o: object = ...) -> None: ... def capitalize(self) -> str: ... def center(self, __width: int, __fillchar: str = ...) -> str: ... - def count(self, x: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def count(self, x: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> unicode: ... def encode(self, encoding: Text = ..., errors: Text = ...) -> bytes: ... - def endswith( - self, __suffix: Union[Text, Tuple[Text, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> str: ... - def find(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def find(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... def format_map(self, map: _FormatMapMapping) -> str: ... - def index(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def index(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... def isdigit(self) -> bool: ... @@ -401,8 +393,8 @@ class str(Sequence[str], basestring): @overload def partition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... def replace(self, __old: AnyStr, __new: AnyStr, __count: int = ...) -> AnyStr: ... - def rfind(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... - def rindex(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def rfind(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... + def rindex(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rjust(self, __width: int, __fillchar: str = ...) -> str: ... @overload def rpartition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... @@ -411,7 +403,7 @@ class str(Sequence[str], basestring): @overload def rpartition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... @overload - def rsplit(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... @overload def rsplit(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... @overload @@ -419,28 +411,26 @@ class str(Sequence[str], basestring): @overload def rstrip(self, __chars: unicode) -> unicode: ... @overload - def split(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... + def split(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... @overload def split(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... def splitlines(self, keepends: bool = ...) -> List[str]: ... - def startswith( - self, __prefix: Union[Text, Tuple[Text, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def startswith(self, __prefix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... @overload def strip(self, __chars: str = ...) -> str: ... @overload def strip(self, chars: unicode) -> unicode: ... def swapcase(self) -> str: ... def title(self) -> str: ... - def translate(self, __table: Optional[AnyStr], deletechars: AnyStr = ...) -> AnyStr: ... + def translate(self, __table: AnyStr | None, deletechars: AnyStr = ...) -> AnyStr: ... def upper(self) -> str: ... def zfill(self, __width: int) -> str: ... def __add__(self, s: AnyStr) -> AnyStr: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[str, Text]) -> bool: ... # type: ignore + def __contains__(self, o: str | Text) -> bool: ... # type: ignore def __eq__(self, x: object) -> bool: ... def __ge__(self, x: Text) -> bool: ... - def __getitem__(self, i: Union[int, slice]) -> str: ... + def __getitem__(self, i: int | slice) -> str: ... def __gt__(self, x: Text) -> bool: ... def __hash__(self) -> int: ... def __iter__(self) -> Iterator[str]: ... @@ -475,11 +465,9 @@ class bytearray(MutableSequence[int], ByteString): def center(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def count(self, __sub: str) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> str: ... - def endswith( - self, __suffix: Union[bytes, Tuple[bytes, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> bytearray: ... - def extend(self, iterable: Union[str, Iterable[int]]) -> None: ... + def extend(self, iterable: str | Iterable[int]) -> None: ... def find(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... def index(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... def insert(self, __index: int, __item: int) -> None: ... @@ -493,21 +481,19 @@ class bytearray(MutableSequence[int], ByteString): def join(self, __iterable: Iterable[str]) -> bytearray: ... def ljust(self, __width: int, __fillchar: str = ...) -> bytearray: ... def lower(self) -> bytearray: ... - def lstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... + def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... def partition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytearray: ... def rfind(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rindex(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rjust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def rpartition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... - def rstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... - def split(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... + def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... def splitlines(self, keepends: bool = ...) -> List[bytearray]: ... - def startswith( - self, __prefix: Union[bytes, Tuple[bytes, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... - def strip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... + def startswith(self, __prefix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... def translate(self, __table: str) -> bytearray: ... @@ -529,15 +515,15 @@ class bytearray(MutableSequence[int], ByteString): @overload def __setitem__(self, i: int, x: int) -> None: ... @overload - def __setitem__(self, s: slice, x: Union[Iterable[int], bytes]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __setitem__(self, s: slice, x: Iterable[int] | bytes) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __getslice__(self, start: int, stop: int) -> bytearray: ... - def __setslice__(self, start: int, stop: int, x: Union[Sequence[int], str]) -> None: ... + def __setslice__(self, start: int, stop: int, x: Sequence[int] | str) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... def __add__(self, s: bytes) -> bytearray: ... def __mul__(self, n: int) -> bytearray: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[int, bytes]) -> bool: ... # type: ignore + def __contains__(self, o: int | bytes) -> bool: ... # type: ignore def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: bytes) -> bool: ... @@ -548,9 +534,9 @@ class bytearray(MutableSequence[int], ByteString): class memoryview(Sized, Container[str]): format: str itemsize: int - shape: Optional[Tuple[int, ...]] - strides: Optional[Tuple[int, ...]] - suboffsets: Optional[Tuple[int, ...]] + shape: Tuple[int, ...] | None + strides: Tuple[int, ...] | None + suboffsets: Tuple[int, ...] | None readonly: bool ndim: int def __init__(self, obj: ReadableBuffer) -> None: ... @@ -662,7 +648,7 @@ class list(MutableSequence[_T], Generic[_T]): def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __getslice__(self, start: int, stop: int) -> List[_T]: ... def __setslice__(self, start: int, stop: int, o: Sequence[_T]) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... @@ -743,18 +729,18 @@ class set(MutableSet[_T], Generic[_T]): def __str__(self) -> str: ... def __and__(self, s: AbstractSet[object]) -> Set[_T]: ... def __iand__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __or__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ior__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... + def __or__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __ior__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... @overload - def __sub__(self: Set[str], s: AbstractSet[Optional[Text]]) -> Set[_T]: ... + def __sub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... @overload - def __sub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... + def __sub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... @overload # type: ignore - def __isub__(self: Set[str], s: AbstractSet[Optional[Text]]) -> Set[_T]: ... + def __isub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... @overload - def __isub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... - def __xor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ixor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... + def __isub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... + def __xor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __ixor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... @@ -776,9 +762,9 @@ class frozenset(AbstractSet[_T_co], Generic[_T_co]): def __iter__(self) -> Iterator[_T_co]: ... def __str__(self) -> str: ... def __and__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __or__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... + def __or__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... def __sub__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... + def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... @@ -802,15 +788,15 @@ class xrange(Sized, Iterable[int], Reversible[int]): class property(object): def __init__( self, - fget: Optional[Callable[[Any], Any]] = ..., - fset: Optional[Callable[[Any, Any], None]] = ..., - fdel: Optional[Callable[[Any], None]] = ..., - doc: Optional[str] = ..., + fget: Callable[[Any], Any] | None = ..., + fset: Callable[[Any, Any], None] | None = ..., + fdel: Callable[[Any], None] | None = ..., + doc: str | None = ..., ) -> None: ... def getter(self, fget: Callable[[Any], Any]) -> property: ... def setter(self, fset: Callable[[Any, Any], None]) -> property: ... def deleter(self, fdel: Callable[[Any], None]) -> property: ... - def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ... + def __get__(self, obj: Any, type: type | None = ...) -> Any: ... def __set__(self, obj: Any, value: Any) -> None: ... def __delete__(self, obj: Any) -> None: ... def fget(self) -> Any: ... @@ -829,8 +815,8 @@ NotImplemented: _NotImplementedType def abs(__x: SupportsAbs[_T]) -> _T: ... def all(__iterable: Iterable[object]) -> bool: ... def any(__iterable: Iterable[object]) -> bool: ... -def apply(__func: Callable[..., _T], __args: Optional[Sequence[Any]] = ..., __kwds: Optional[Mapping[str, Any]] = ...) -> _T: ... -def bin(__number: Union[int, _SupportsIndex]) -> str: ... +def apply(__func: Callable[..., _T], __args: Sequence[Any] | None = ..., __kwds: Mapping[str, Any] | None = ...) -> _T: ... +def bin(__number: int | _SupportsIndex) -> str: ... def callable(__obj: object) -> bool: ... def chr(__i: int) -> str: ... def cmp(__x: Any, __y: Any) -> int: ... @@ -838,7 +824,7 @@ def cmp(__x: Any, __y: Any) -> int: ... _N1 = TypeVar("_N1", bool, int, float, complex) def coerce(__x: _N1, __y: _N1) -> Tuple[_N1, _N1]: ... -def compile(source: Union[Text, mod], filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... +def compile(source: Text | mod, filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... def delattr(__obj: Any, __name: Text) -> None: ... def dir(__o: object = ...) -> List[str]: ... @@ -846,37 +832,52 @@ _N2 = TypeVar("_N2", int, float) def divmod(__x: _N2, __y: _N2) -> Tuple[_N2, _N2]: ... def eval( - __source: Union[Text, bytes, CodeType], __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Mapping[str, Any]] = ... + __source: Text | bytes | CodeType, __globals: Dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... ) -> Any: ... -def execfile(__filename: str, __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Dict[str, Any]] = ...) -> None: ... +def execfile(__filename: str, __globals: Dict[str, Any] | None = ..., __locals: Dict[str, Any] | None = ...) -> None: ... def exit(code: object = ...) -> NoReturn: ... @overload def filter(__function: Callable[[AnyStr], Any], __iterable: AnyStr) -> AnyStr: ... # type: ignore @overload -def filter(__function: None, __iterable: Tuple[Optional[_T], ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: None, __iterable: Tuple[_T | None, ...]) -> Tuple[_T, ...]: ... # type: ignore @overload def filter(__function: Callable[[_T], Any], __iterable: Tuple[_T, ...]) -> Tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: None, __iterable: Iterable[Optional[_T]]) -> List[_T]: ... +def filter(__function: None, __iterable: Iterable[_T | None]) -> List[_T]: ... @overload def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T]: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode -def getattr(__o: Any, name: Text, __default: Any = ...) -> Any: ... +@overload +def getattr(__o: Any, name: Text) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None, bool +# and basic containers help mypy out in some tricky situations involving type context +# (aka bidirectional inference) +@overload +def getattr(__o: Any, name: Text, __default: None) -> Any | None: ... +@overload +def getattr(__o: Any, name: Text, __default: bool) -> Any | bool: ... +@overload +def getattr(__o: object, name: str, __default: list[Any]) -> Any | list[Any]: ... +@overload +def getattr(__o: object, name: str, __default: dict[Any, Any]) -> Any | dict[Any, Any]: ... +@overload +def getattr(__o: Any, name: Text, __default: _T) -> Any | _T: ... def globals() -> Dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... def hash(__obj: object) -> int: ... -def hex(__number: Union[int, _SupportsIndex]) -> str: ... +def hex(__number: int | _SupportsIndex) -> str: ... def id(__obj: object) -> int: ... def input(__prompt: Any = ...) -> Any: ... def intern(__string: str) -> str: ... @overload def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... @overload -def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ... +def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload def iter(__function: Callable[[], _T], __sentinel: Any) -> Iterator[_T]: ... -def isinstance(__obj: object, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... -def issubclass(__cls: type, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... +def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... +def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... def len(__obj: Sized) -> int: ... def locals() -> Dict[str, Any]: ... @overload @@ -956,15 +957,13 @@ def min(__iterable: Iterable[_T], *, key: Callable[[_T], Any] = ...) -> _T: ... @overload def next(__i: Iterator[_T]) -> _T: ... @overload -def next(__i: Iterator[_T], default: _VT) -> Union[_T, _VT]: ... -def oct(__number: Union[int, _SupportsIndex]) -> str: ... -def open(name: Union[unicode, int], mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... -def ord(__c: Union[Text, bytes]) -> int: ... +def next(__i: Iterator[_T], __default: _VT) -> _T | _VT: ... +def oct(__number: int | _SupportsIndex) -> str: ... +def open(name: unicode | int, mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... +def ord(__c: Text | bytes) -> int: ... # This is only available after from __future__ import print_function. -def print( - *values: object, sep: Optional[Text] = ..., end: Optional[Text] = ..., file: Optional[SupportsWrite[Any]] = ... -) -> None: ... +def print(*values: object, sep: Text | None = ..., end: Text | None = ..., file: SupportsWrite[Any] | None = ...) -> None: ... _E = TypeVar("_E", contravariant=True) _M = TypeVar("_M", contravariant=True) @@ -1008,12 +1007,12 @@ def round(number: SupportsFloat) -> float: ... def round(number: SupportsFloat, ndigits: int) -> float: ... def setattr(__obj: Any, __name: Text, __value: Any) -> None: ... def sorted( - __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ... + __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Callable[[_T], Any] | None = ..., reverse: bool = ... ) -> List[_T]: ... @overload -def sum(__iterable: Iterable[_T]) -> Union[_T, int]: ... +def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload -def sum(__iterable: Iterable[_T], __start: _S) -> Union[_T, _S]: ... +def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... def unichr(__i: int) -> unicode: ... def vars(__object: Any = ...) -> Dict[str, Any]: ... @overload @@ -1042,8 +1041,8 @@ def zip( ) -> List[Tuple[Any, ...]]: ... def __import__( name: Text, - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, Any] | None = ..., + locals: Mapping[str, Any] | None = ..., fromlist: Sequence[str] = ..., level: int = ..., ) -> Any: ... @@ -1061,7 +1060,7 @@ class buffer(Sized): def __init__(self, object: _AnyBuffer, offset: int = ..., size: int = ...) -> None: ... def __add__(self, other: _AnyBuffer) -> str: ... def __cmp__(self, other: _AnyBuffer) -> bool: ... - def __getitem__(self, key: Union[int, slice]) -> str: ... + def __getitem__(self, key: int | slice) -> str: ... def __getslice__(self, i: int, j: int) -> str: ... def __len__(self) -> int: ... def __mul__(self, x: int) -> str: ... @@ -1109,10 +1108,10 @@ class RuntimeError(_StandardError): ... class SyntaxError(_StandardError): msg: str - lineno: Optional[int] - offset: Optional[int] - text: Optional[str] - filename: Optional[str] + lineno: int | None + offset: int | None + text: str | None + filename: str | None class SystemError(_StandardError): ... class TypeError(_StandardError): ... @@ -1171,9 +1170,7 @@ class file(BinaryIO): def next(self) -> str: ... def read(self, n: int = ...) -> str: ... def __enter__(self) -> BinaryIO: ... - def __exit__( - self, t: Optional[type] = ..., exc: Optional[BaseException] = ..., tb: Optional[Any] = ... - ) -> Optional[bool]: ... + def __exit__(self, t: type | None = ..., exc: BaseException | None = ..., tb: Any | None = ...) -> bool | None: ... def flush(self) -> None: ... def fileno(self) -> int: ... def isatty(self) -> bool: ... @@ -1187,4 +1184,4 @@ class file(BinaryIO): def readlines(self, hint: int = ...) -> List[str]: ... def write(self, data: str) -> int: ... def writelines(self, data: Iterable[str]) -> None: ... - def truncate(self, pos: Optional[int] = ...) -> int: ... + def truncate(self, pos: int | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/__future__.pyi b/mypy/typeshed/stdlib/@python2/__future__.pyi new file mode 100644 index 000000000000..8f5ff06ac080 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/__future__.pyi @@ -0,0 +1,17 @@ +import sys +from typing import List + +class _Feature: + def __init__(self, optionalRelease: sys._version_info, mandatoryRelease: sys._version_info, compiler_flag: int) -> None: ... + def getOptionalRelease(self) -> sys._version_info: ... + def getMandatoryRelease(self) -> sys._version_info: ... + compiler_flag: int + +absolute_import: _Feature +division: _Feature +generators: _Feature +nested_scopes: _Feature +print_function: _Feature +unicode_literals: _Feature +with_statement: _Feature +all_feature_names: List[str] # undocumented diff --git a/mypy/typeshed/stdlib/@python2/__main__.pyi b/mypy/typeshed/stdlib/@python2/__main__.pyi new file mode 100644 index 000000000000..e27843e53382 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/__main__.pyi @@ -0,0 +1,3 @@ +from typing import Any + +def __getattr__(name: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/_ast.pyi b/mypy/typeshed/stdlib/@python2/_ast.pyi index 4ca7def60b04..05cbc70c41d2 100644 --- a/mypy/typeshed/stdlib/@python2/_ast.pyi +++ b/mypy/typeshed/stdlib/@python2/_ast.pyi @@ -1,5 +1,4 @@ import typing -from typing import Optional __version__: str PyCF_ONLY_AST: int @@ -41,7 +40,7 @@ class ClassDef(stmt): decorator_list: typing.List[expr] class Return(stmt): - value: Optional[expr] + value: expr | None class Delete(stmt): targets: typing.List[expr] @@ -56,7 +55,7 @@ class AugAssign(stmt): value: expr class Print(stmt): - dest: Optional[expr] + dest: expr | None values: typing.List[expr] nl: bool @@ -78,13 +77,13 @@ class If(stmt): class With(stmt): context_expr: expr - optional_vars: Optional[expr] + optional_vars: expr | None body: typing.List[stmt] class Raise(stmt): - type: Optional[expr] - inst: Optional[expr] - tback: Optional[expr] + type: expr | None + inst: expr | None + tback: expr | None class TryExcept(stmt): body: typing.List[stmt] @@ -97,20 +96,20 @@ class TryFinally(stmt): class Assert(stmt): test: expr - msg: Optional[expr] + msg: expr | None class Import(stmt): names: typing.List[alias] class ImportFrom(stmt): - module: Optional[_identifier] + module: _identifier | None names: typing.List[alias] - level: Optional[int] + level: int | None class Exec(stmt): body: expr - globals: Optional[expr] - locals: Optional[expr] + globals: expr | None + locals: expr | None class Global(stmt): names: typing.List[_identifier] @@ -126,9 +125,9 @@ class slice(AST): ... _slice = slice # this lets us type the variable named 'slice' below class Slice(slice): - lower: Optional[expr] - upper: Optional[expr] - step: Optional[expr] + lower: expr | None + upper: expr | None + step: expr | None class ExtSlice(slice): dims: typing.List[slice] @@ -189,7 +188,7 @@ class GeneratorExp(expr): generators: typing.List[comprehension] class Yield(expr): - value: Optional[expr] + value: expr | None class Compare(expr): left: expr @@ -200,8 +199,8 @@ class Call(expr): func: expr args: typing.List[expr] keywords: typing.List[keyword] - starargs: Optional[expr] - kwargs: Optional[expr] + starargs: expr | None + kwargs: expr | None class Repr(expr): value: expr @@ -282,16 +281,16 @@ class comprehension(AST): class excepthandler(AST): ... class ExceptHandler(excepthandler): - type: Optional[expr] - name: Optional[expr] + type: expr | None + name: expr | None body: typing.List[stmt] lineno: int col_offset: int class arguments(AST): args: typing.List[expr] - vararg: Optional[_identifier] - kwarg: Optional[_identifier] + vararg: _identifier | None + kwarg: _identifier | None defaults: typing.List[expr] class keyword(AST): @@ -300,4 +299,4 @@ class keyword(AST): class alias(AST): name: _identifier - asname: Optional[_identifier] + asname: _identifier | None diff --git a/mypy/typeshed/stdlib/@python2/_bisect.pyi b/mypy/typeshed/stdlib/@python2/_bisect.pyi new file mode 100644 index 000000000000..e3327a0af4e6 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_bisect.pyi @@ -0,0 +1,8 @@ +from typing import MutableSequence, Sequence, TypeVar + +_T = TypeVar("_T") + +def bisect_left(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... +def bisect_right(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... +def insort_left(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... +def insort_right(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_codecs.pyi b/mypy/typeshed/stdlib/@python2/_codecs.pyi new file mode 100644 index 000000000000..83601f6621bb --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_codecs.pyi @@ -0,0 +1,66 @@ +import codecs +import sys +from typing import Any, Callable, Dict, Text, Tuple, Union + +# For convenience: +_Handler = Callable[[Exception], Tuple[Text, int]] +_String = Union[bytes, str] +_Errors = Union[str, Text, None] +_Decodable = Union[bytes, Text] +_Encodable = Union[bytes, Text] + +# This type is not exposed; it is defined in unicodeobject.c +class _EncodingMap(object): + def size(self) -> int: ... + +_MapT = Union[Dict[int, int], _EncodingMap] + +def register(__search_function: Callable[[str], Any]) -> None: ... +def register_error(__errors: str | Text, __handler: _Handler) -> None: ... +def lookup(__encoding: str | Text) -> codecs.CodecInfo: ... +def lookup_error(__name: str | Text) -> _Handler: ... +def decode(obj: Any, encoding: str | Text = ..., errors: _Errors = ...) -> Any: ... +def encode(obj: Any, encoding: str | Text = ..., errors: _Errors = ...) -> Any: ... +def charmap_build(__map: Text) -> _MapT: ... +def ascii_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... +def ascii_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def charbuffer_encode(__data: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def charmap_decode(__data: _Decodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> Tuple[Text, int]: ... +def charmap_encode(__str: _Encodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> Tuple[bytes, int]: ... +def escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[str, int]: ... +def escape_encode(__data: bytes, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def latin_1_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... +def latin_1_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def raw_unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... +def raw_unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def readbuffer_encode(__data: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... +def unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def unicode_internal_decode(__obj: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... +def unicode_internal_encode(__obj: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_16_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_16_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_16_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_16_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... +def utf_16_ex_decode( + __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... +) -> Tuple[Text, int, int]: ... +def utf_16_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_16_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_32_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_32_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_32_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_32_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... +def utf_32_ex_decode( + __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... +) -> Tuple[Text, int, int]: ... +def utf_32_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_32_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_7_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_7_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def utf_8_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... +def utf_8_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... + +if sys.platform == "win32": + def mbcs_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... + def mbcs_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... diff --git a/mypy/typeshed/stdlib/@python2/_collections.pyi b/mypy/typeshed/stdlib/@python2/_collections.pyi index f97b6d5d6dd1..22ada07d0f24 100644 --- a/mypy/typeshed/stdlib/@python2/_collections.pyi +++ b/mypy/typeshed/stdlib/@python2/_collections.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Generic, Iterator, Optional, TypeVar, Union +from typing import Any, Callable, Dict, Generic, Iterator, TypeVar _K = TypeVar("_K") _V = TypeVar("_V") @@ -13,7 +13,7 @@ class defaultdict(Dict[_K, _V]): def copy(self: _T) -> _T: ... class deque(Generic[_T]): - maxlen: Optional[int] + maxlen: int | None def __init__(self, iterable: Iterator[_T] = ..., maxlen: int = ...) -> None: ... def append(self, x: _T) -> None: ... def appendleft(self, x: _T) -> None: ... @@ -29,7 +29,7 @@ class deque(Generic[_T]): def __contains__(self, o: Any) -> bool: ... def __copy__(self) -> deque[_T]: ... def __getitem__(self, i: int) -> _T: ... - def __iadd__(self, other: deque[_T2]) -> deque[Union[_T, _T2]]: ... + def __iadd__(self, other: deque[_T2]) -> deque[_T | _T2]: ... def __iter__(self) -> Iterator[_T]: ... def __len__(self) -> int: ... def __reversed__(self) -> Iterator[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/_csv.pyi b/mypy/typeshed/stdlib/@python2/_csv.pyi new file mode 100644 index 000000000000..ebe44bab67d9 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_csv.pyi @@ -0,0 +1,42 @@ +from typing import Any, Iterable, Iterator, List, Protocol, Sequence, Text, Type, Union + +QUOTE_ALL: int +QUOTE_MINIMAL: int +QUOTE_NONE: int +QUOTE_NONNUMERIC: int + +class Error(Exception): ... + +class Dialect: + delimiter: str + quotechar: str | None + escapechar: str | None + doublequote: bool + skipinitialspace: bool + lineterminator: str + quoting: int + strict: int + def __init__(self) -> None: ... + +_DialectLike = Union[str, Dialect, Type[Dialect]] + +class _reader(Iterator[List[str]]): + dialect: Dialect + line_num: int + def next(self) -> List[str]: ... + +class _writer: + dialect: Dialect + def writerow(self, row: Sequence[Any]) -> Any: ... + def writerows(self, rows: Iterable[Sequence[Any]]) -> None: ... + +class _Writer(Protocol): + def write(self, s: str) -> Any: ... + +def writer(csvfile: _Writer, dialect: _DialectLike = ..., **fmtparams: Any) -> _writer: ... +def reader(csvfile: Iterable[Text], dialect: _DialectLike = ..., **fmtparams: Any) -> _reader: ... +def register_dialect(name: str, dialect: Any = ..., **fmtparams: Any) -> None: ... +def unregister_dialect(name: str) -> None: ... +def get_dialect(name: str) -> Dialect: ... +def list_dialects() -> List[str]: ... +def field_size_limit(new_limit: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/_curses.pyi b/mypy/typeshed/stdlib/@python2/_curses.pyi new file mode 100644 index 000000000000..32c1f761ac9e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_curses.pyi @@ -0,0 +1,511 @@ +from typing import IO, Any, BinaryIO, Tuple, Union, overload + +_chtype = Union[str, bytes, int] + +# ACS codes are only initialized after initscr is called +ACS_BBSS: int +ACS_BLOCK: int +ACS_BOARD: int +ACS_BSBS: int +ACS_BSSB: int +ACS_BSSS: int +ACS_BTEE: int +ACS_BULLET: int +ACS_CKBOARD: int +ACS_DARROW: int +ACS_DEGREE: int +ACS_DIAMOND: int +ACS_GEQUAL: int +ACS_HLINE: int +ACS_LANTERN: int +ACS_LARROW: int +ACS_LEQUAL: int +ACS_LLCORNER: int +ACS_LRCORNER: int +ACS_LTEE: int +ACS_NEQUAL: int +ACS_PI: int +ACS_PLMINUS: int +ACS_PLUS: int +ACS_RARROW: int +ACS_RTEE: int +ACS_S1: int +ACS_S3: int +ACS_S7: int +ACS_S9: int +ACS_SBBS: int +ACS_SBSB: int +ACS_SBSS: int +ACS_SSBB: int +ACS_SSBS: int +ACS_SSSB: int +ACS_SSSS: int +ACS_STERLING: int +ACS_TTEE: int +ACS_UARROW: int +ACS_ULCORNER: int +ACS_URCORNER: int +ACS_VLINE: int +ALL_MOUSE_EVENTS: int +A_ALTCHARSET: int +A_ATTRIBUTES: int +A_BLINK: int +A_BOLD: int +A_CHARTEXT: int +A_COLOR: int +A_DIM: int +A_HORIZONTAL: int +A_INVIS: int +A_LEFT: int +A_LOW: int +A_NORMAL: int +A_PROTECT: int +A_REVERSE: int +A_RIGHT: int +A_STANDOUT: int +A_TOP: int +A_UNDERLINE: int +A_VERTICAL: int +BUTTON1_CLICKED: int +BUTTON1_DOUBLE_CLICKED: int +BUTTON1_PRESSED: int +BUTTON1_RELEASED: int +BUTTON1_TRIPLE_CLICKED: int +BUTTON2_CLICKED: int +BUTTON2_DOUBLE_CLICKED: int +BUTTON2_PRESSED: int +BUTTON2_RELEASED: int +BUTTON2_TRIPLE_CLICKED: int +BUTTON3_CLICKED: int +BUTTON3_DOUBLE_CLICKED: int +BUTTON3_PRESSED: int +BUTTON3_RELEASED: int +BUTTON3_TRIPLE_CLICKED: int +BUTTON4_CLICKED: int +BUTTON4_DOUBLE_CLICKED: int +BUTTON4_PRESSED: int +BUTTON4_RELEASED: int +BUTTON4_TRIPLE_CLICKED: int +BUTTON_ALT: int +BUTTON_CTRL: int +BUTTON_SHIFT: int +COLOR_BLACK: int +COLOR_BLUE: int +COLOR_CYAN: int +COLOR_GREEN: int +COLOR_MAGENTA: int +COLOR_RED: int +COLOR_WHITE: int +COLOR_YELLOW: int +ERR: int +KEY_A1: int +KEY_A3: int +KEY_B2: int +KEY_BACKSPACE: int +KEY_BEG: int +KEY_BREAK: int +KEY_BTAB: int +KEY_C1: int +KEY_C3: int +KEY_CANCEL: int +KEY_CATAB: int +KEY_CLEAR: int +KEY_CLOSE: int +KEY_COMMAND: int +KEY_COPY: int +KEY_CREATE: int +KEY_CTAB: int +KEY_DC: int +KEY_DL: int +KEY_DOWN: int +KEY_EIC: int +KEY_END: int +KEY_ENTER: int +KEY_EOL: int +KEY_EOS: int +KEY_EXIT: int +KEY_F0: int +KEY_F1: int +KEY_F10: int +KEY_F11: int +KEY_F12: int +KEY_F13: int +KEY_F14: int +KEY_F15: int +KEY_F16: int +KEY_F17: int +KEY_F18: int +KEY_F19: int +KEY_F2: int +KEY_F20: int +KEY_F21: int +KEY_F22: int +KEY_F23: int +KEY_F24: int +KEY_F25: int +KEY_F26: int +KEY_F27: int +KEY_F28: int +KEY_F29: int +KEY_F3: int +KEY_F30: int +KEY_F31: int +KEY_F32: int +KEY_F33: int +KEY_F34: int +KEY_F35: int +KEY_F36: int +KEY_F37: int +KEY_F38: int +KEY_F39: int +KEY_F4: int +KEY_F40: int +KEY_F41: int +KEY_F42: int +KEY_F43: int +KEY_F44: int +KEY_F45: int +KEY_F46: int +KEY_F47: int +KEY_F48: int +KEY_F49: int +KEY_F5: int +KEY_F50: int +KEY_F51: int +KEY_F52: int +KEY_F53: int +KEY_F54: int +KEY_F55: int +KEY_F56: int +KEY_F57: int +KEY_F58: int +KEY_F59: int +KEY_F6: int +KEY_F60: int +KEY_F61: int +KEY_F62: int +KEY_F63: int +KEY_F7: int +KEY_F8: int +KEY_F9: int +KEY_FIND: int +KEY_HELP: int +KEY_HOME: int +KEY_IC: int +KEY_IL: int +KEY_LEFT: int +KEY_LL: int +KEY_MARK: int +KEY_MAX: int +KEY_MESSAGE: int +KEY_MIN: int +KEY_MOUSE: int +KEY_MOVE: int +KEY_NEXT: int +KEY_NPAGE: int +KEY_OPEN: int +KEY_OPTIONS: int +KEY_PPAGE: int +KEY_PREVIOUS: int +KEY_PRINT: int +KEY_REDO: int +KEY_REFERENCE: int +KEY_REFRESH: int +KEY_REPLACE: int +KEY_RESET: int +KEY_RESIZE: int +KEY_RESTART: int +KEY_RESUME: int +KEY_RIGHT: int +KEY_SAVE: int +KEY_SBEG: int +KEY_SCANCEL: int +KEY_SCOMMAND: int +KEY_SCOPY: int +KEY_SCREATE: int +KEY_SDC: int +KEY_SDL: int +KEY_SELECT: int +KEY_SEND: int +KEY_SEOL: int +KEY_SEXIT: int +KEY_SF: int +KEY_SFIND: int +KEY_SHELP: int +KEY_SHOME: int +KEY_SIC: int +KEY_SLEFT: int +KEY_SMESSAGE: int +KEY_SMOVE: int +KEY_SNEXT: int +KEY_SOPTIONS: int +KEY_SPREVIOUS: int +KEY_SPRINT: int +KEY_SR: int +KEY_SREDO: int +KEY_SREPLACE: int +KEY_SRESET: int +KEY_SRIGHT: int +KEY_SRSUME: int +KEY_SSAVE: int +KEY_SSUSPEND: int +KEY_STAB: int +KEY_SUNDO: int +KEY_SUSPEND: int +KEY_UNDO: int +KEY_UP: int +OK: int +REPORT_MOUSE_POSITION: int +_C_API: Any +version: bytes + +def baudrate() -> int: ... +def beep() -> None: ... +def can_change_color() -> bool: ... +def cbreak(__flag: bool = ...) -> None: ... +def color_content(__color_number: int) -> Tuple[int, int, int]: ... + +# Changed in Python 3.8.8 and 3.9.2 +def color_pair(__color_number: int) -> int: ... +def curs_set(__visibility: int) -> int: ... +def def_prog_mode() -> None: ... +def def_shell_mode() -> None: ... +def delay_output(__ms: int) -> None: ... +def doupdate() -> None: ... +def echo(__flag: bool = ...) -> None: ... +def endwin() -> None: ... +def erasechar() -> bytes: ... +def filter() -> None: ... +def flash() -> None: ... +def flushinp() -> None: ... +def getmouse() -> Tuple[int, int, int, int, int]: ... +def getsyx() -> Tuple[int, int]: ... +def getwin(__file: BinaryIO) -> _CursesWindow: ... +def halfdelay(__tenths: int) -> None: ... +def has_colors() -> bool: ... +def has_ic() -> bool: ... +def has_il() -> bool: ... +def has_key(__key: int) -> bool: ... +def init_color(__color_number: int, __r: int, __g: int, __b: int) -> None: ... +def init_pair(__pair_number: int, __fg: int, __bg: int) -> None: ... +def initscr() -> _CursesWindow: ... +def intrflush(__flag: bool) -> None: ... +def is_term_resized(__nlines: int, __ncols: int) -> bool: ... +def isendwin() -> bool: ... +def keyname(__key: int) -> bytes: ... +def killchar() -> bytes: ... +def longname() -> bytes: ... +def meta(__yes: bool) -> None: ... +def mouseinterval(__interval: int) -> None: ... +def mousemask(__newmask: int) -> Tuple[int, int]: ... +def napms(__ms: int) -> int: ... +def newpad(__nlines: int, __ncols: int) -> _CursesWindow: ... +def newwin(__nlines: int, __ncols: int, __begin_y: int = ..., __begin_x: int = ...) -> _CursesWindow: ... +def nl(__flag: bool = ...) -> None: ... +def nocbreak() -> None: ... +def noecho() -> None: ... +def nonl() -> None: ... +def noqiflush() -> None: ... +def noraw() -> None: ... +def pair_content(__pair_number: int) -> Tuple[int, int]: ... +def pair_number(__attr: int) -> int: ... +def putp(__string: bytes) -> None: ... +def qiflush(__flag: bool = ...) -> None: ... +def raw(__flag: bool = ...) -> None: ... +def reset_prog_mode() -> None: ... +def reset_shell_mode() -> None: ... +def resetty() -> None: ... +def resize_term(__nlines: int, __ncols: int) -> None: ... +def resizeterm(__nlines: int, __ncols: int) -> None: ... +def savetty() -> None: ... +def setsyx(__y: int, __x: int) -> None: ... +def setupterm(term: str | None = ..., fd: int = ...) -> None: ... +def start_color() -> None: ... +def termattrs() -> int: ... +def termname() -> bytes: ... +def tigetflag(__capname: str) -> int: ... +def tigetnum(__capname: str) -> int: ... +def tigetstr(__capname: str) -> bytes: ... +def tparm( + __str: bytes, + __i1: int = ..., + __i2: int = ..., + __i3: int = ..., + __i4: int = ..., + __i5: int = ..., + __i6: int = ..., + __i7: int = ..., + __i8: int = ..., + __i9: int = ..., +) -> bytes: ... +def typeahead(__fd: int) -> None: ... +def unctrl(__ch: _chtype) -> bytes: ... +def ungetch(__ch: _chtype) -> None: ... +def ungetmouse(__id: int, __x: int, __y: int, __z: int, __bstate: int) -> None: ... +def use_default_colors() -> None: ... +def use_env(__flag: bool) -> None: ... + +class error(Exception): ... + +class _CursesWindow: + @overload + def addch(self, ch: _chtype, attr: int = ...) -> None: ... + @overload + def addch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... + @overload + def addnstr(self, str: str, n: int, attr: int = ...) -> None: ... + @overload + def addnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... + @overload + def addstr(self, str: str, attr: int = ...) -> None: ... + @overload + def addstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... + def attroff(self, __attr: int) -> None: ... + def attron(self, __attr: int) -> None: ... + def attrset(self, __attr: int) -> None: ... + def bkgd(self, __ch: _chtype, __attr: int = ...) -> None: ... + def bkgdset(self, __ch: _chtype, __attr: int = ...) -> None: ... + def border( + self, + ls: _chtype = ..., + rs: _chtype = ..., + ts: _chtype = ..., + bs: _chtype = ..., + tl: _chtype = ..., + tr: _chtype = ..., + bl: _chtype = ..., + br: _chtype = ..., + ) -> None: ... + @overload + def box(self) -> None: ... + @overload + def box(self, vertch: _chtype = ..., horch: _chtype = ...) -> None: ... + @overload + def chgat(self, attr: int) -> None: ... + @overload + def chgat(self, num: int, attr: int) -> None: ... + @overload + def chgat(self, y: int, x: int, attr: int) -> None: ... + @overload + def chgat(self, y: int, x: int, num: int, attr: int) -> None: ... + def clear(self) -> None: ... + def clearok(self, yes: int) -> None: ... + def clrtobot(self) -> None: ... + def clrtoeol(self) -> None: ... + def cursyncup(self) -> None: ... + @overload + def delch(self) -> None: ... + @overload + def delch(self, y: int, x: int) -> None: ... + def deleteln(self) -> None: ... + @overload + def derwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def derwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + def echochar(self, __ch: _chtype, __attr: int = ...) -> None: ... + def enclose(self, __y: int, __x: int) -> bool: ... + def erase(self) -> None: ... + def getbegyx(self) -> Tuple[int, int]: ... + def getbkgd(self) -> Tuple[int, int]: ... + @overload + def getch(self) -> int: ... + @overload + def getch(self, y: int, x: int) -> int: ... + @overload + def getkey(self) -> str: ... + @overload + def getkey(self, y: int, x: int) -> str: ... + def getmaxyx(self) -> Tuple[int, int]: ... + def getparyx(self) -> Tuple[int, int]: ... + @overload + def getstr(self) -> _chtype: ... + @overload + def getstr(self, n: int) -> _chtype: ... + @overload + def getstr(self, y: int, x: int) -> _chtype: ... + @overload + def getstr(self, y: int, x: int, n: int) -> _chtype: ... + def getyx(self) -> Tuple[int, int]: ... + @overload + def hline(self, ch: _chtype, n: int) -> None: ... + @overload + def hline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... + def idcok(self, flag: bool) -> None: ... + def idlok(self, yes: bool) -> None: ... + def immedok(self, flag: bool) -> None: ... + @overload + def inch(self) -> _chtype: ... + @overload + def inch(self, y: int, x: int) -> _chtype: ... + @overload + def insch(self, ch: _chtype, attr: int = ...) -> None: ... + @overload + def insch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... + def insdelln(self, nlines: int) -> None: ... + def insertln(self) -> None: ... + @overload + def insnstr(self, str: str, n: int, attr: int = ...) -> None: ... + @overload + def insnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... + @overload + def insstr(self, str: str, attr: int = ...) -> None: ... + @overload + def insstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... + @overload + def instr(self, n: int = ...) -> _chtype: ... + @overload + def instr(self, y: int, x: int, n: int = ...) -> _chtype: ... + def is_linetouched(self, __line: int) -> bool: ... + def is_wintouched(self) -> bool: ... + def keypad(self, yes: bool) -> None: ... + def leaveok(self, yes: bool) -> None: ... + def move(self, new_y: int, new_x: int) -> None: ... + def mvderwin(self, y: int, x: int) -> None: ... + def mvwin(self, new_y: int, new_x: int) -> None: ... + def nodelay(self, yes: bool) -> None: ... + def notimeout(self, yes: bool) -> None: ... + def noutrefresh(self) -> None: ... + @overload + def overlay(self, destwin: _CursesWindow) -> None: ... + @overload + def overlay( + self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int + ) -> None: ... + @overload + def overwrite(self, destwin: _CursesWindow) -> None: ... + @overload + def overwrite( + self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int + ) -> None: ... + def putwin(self, __file: IO[Any]) -> None: ... + def redrawln(self, __beg: int, __num: int) -> None: ... + def redrawwin(self) -> None: ... + @overload + def refresh(self) -> None: ... + @overload + def refresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... + def resize(self, nlines: int, ncols: int) -> None: ... + def scroll(self, lines: int = ...) -> None: ... + def scrollok(self, flag: bool) -> None: ... + def setscrreg(self, __top: int, __bottom: int) -> None: ... + def standend(self) -> None: ... + def standout(self) -> None: ... + @overload + def subpad(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subpad(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + def syncdown(self) -> None: ... + def syncok(self, flag: bool) -> None: ... + def syncup(self) -> None: ... + def timeout(self, delay: int) -> None: ... + def touchline(self, start: int, count: int, changed: bool = ...) -> None: ... + def touchwin(self) -> None: ... + def untouchwin(self) -> None: ... + @overload + def vline(self, ch: _chtype, n: int) -> None: ... + @overload + def vline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi b/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi new file mode 100644 index 000000000000..e45a1b5c4a89 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi @@ -0,0 +1,109 @@ +from types import FrameType, TracebackType +from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar + +# TODO recursive type +_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] + +_PF = Callable[[FrameType, str, Any], None] +_T = TypeVar("_T") + +__all__: List[str] + +def active_count() -> int: ... +def activeCount() -> int: ... +def current_thread() -> Thread: ... +def currentThread() -> Thread: ... +def enumerate() -> List[Thread]: ... +def settrace(func: _TF) -> None: ... +def setprofile(func: _PF | None) -> None: ... +def stack_size(size: int = ...) -> int: ... + +class ThreadError(Exception): ... + +class local(object): + def __getattribute__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + def __delattr__(self, name: str) -> None: ... + +class Thread: + name: str + ident: int | None + daemon: bool + def __init__( + self, + group: None = ..., + target: Callable[..., Any] | None = ..., + name: Text | None = ..., + args: Iterable[Any] = ..., + kwargs: Mapping[Text, Any] | None = ..., + ) -> None: ... + def start(self) -> None: ... + def run(self) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... + def getName(self) -> str: ... + def setName(self, name: Text) -> None: ... + def is_alive(self) -> bool: ... + def isAlive(self) -> bool: ... + def isDaemon(self) -> bool: ... + def setDaemon(self, daemonic: bool) -> None: ... + +class _DummyThread(Thread): ... + +class Lock: + def __init__(self) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + def locked(self) -> bool: ... + +class _RLock: + def __init__(self) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + +RLock = _RLock + +class Condition: + def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + def wait(self, timeout: float | None = ...) -> bool: ... + def notify(self, n: int = ...) -> None: ... + def notify_all(self) -> None: ... + def notifyAll(self) -> None: ... + +class Semaphore: + def __init__(self, value: int = ...) -> None: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def __enter__(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + +class BoundedSemaphore(Semaphore): ... + +class Event: + def __init__(self) -> None: ... + def is_set(self) -> bool: ... + def isSet(self) -> bool: ... + def set(self) -> None: ... + def clear(self) -> None: ... + def wait(self, timeout: float | None = ...) -> bool: ... + +class Timer(Thread): + def __init__( + self, interval: float, function: Callable[..., Any], args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ... + ) -> None: ... + def cancel(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_functools.pyi b/mypy/typeshed/stdlib/@python2/_functools.pyi index 697abb78272a..e68398238f9b 100644 --- a/mypy/typeshed/stdlib/@python2/_functools.pyi +++ b/mypy/typeshed/stdlib/@python2/_functools.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Iterable, Optional, Tuple, TypeVar, overload +from typing import Any, Callable, Dict, Iterable, Tuple, TypeVar, overload _T = TypeVar("_T") _S = TypeVar("_S") diff --git a/mypy/typeshed/stdlib/@python2/_heapq.pyi b/mypy/typeshed/stdlib/@python2/_heapq.pyi new file mode 100644 index 000000000000..08a8add08e9a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_heapq.pyi @@ -0,0 +1,11 @@ +from typing import Any, Callable, Iterable, List, TypeVar + +_T = TypeVar("_T") + +def heapify(__heap: List[Any]) -> None: ... +def heappop(__heap: List[_T]) -> _T: ... +def heappush(__heap: List[_T], __item: _T) -> None: ... +def heappushpop(__heap: List[_T], __item: _T) -> _T: ... +def heapreplace(__heap: List[_T], __item: _T) -> _T: ... +def nlargest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> List[_T]: ... +def nsmallest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> List[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/_hotshot.pyi b/mypy/typeshed/stdlib/@python2/_hotshot.pyi index 46c365f4b60b..b048f6fb83d5 100644 --- a/mypy/typeshed/stdlib/@python2/_hotshot.pyi +++ b/mypy/typeshed/stdlib/@python2/_hotshot.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Generic, List, Tuple +from typing import Any, Tuple def coverage(a: str) -> Any: ... def logreader(a: str) -> LogReaderType: ... diff --git a/mypy/typeshed/stdlib/@python2/_io.pyi b/mypy/typeshed/stdlib/@python2/_io.pyi index b88f3de0fae3..fedbbe137940 100644 --- a/mypy/typeshed/stdlib/@python2/_io.pyi +++ b/mypy/typeshed/stdlib/@python2/_io.pyi @@ -1,6 +1,6 @@ +from _typeshed import Self from mmap import mmap -from types import TracebackType -from typing import IO, Any, AnyStr, BinaryIO, Iterable, Iterator, List, Optional, Text, TextIO, Tuple, Type, TypeVar, Union +from typing import IO, Any, BinaryIO, Iterable, List, Text, TextIO, Tuple, Type, TypeVar, Union _bytearray_like = Union[bytearray, mmap] @@ -16,7 +16,7 @@ _T = TypeVar("_T") class _IOBase(BinaryIO): @property def closed(self) -> bool: ... - def _checkClosed(self, msg: Optional[str] = ...) -> None: ... # undocumented + def _checkClosed(self, msg: str | None = ...) -> None: ... # undocumented def _checkReadable(self) -> None: ... def _checkSeekable(self) -> None: ... def _checkWritable(self) -> None: ... @@ -29,12 +29,10 @@ class _IOBase(BinaryIO): def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... - def __enter__(self: _T) -> _T: ... - def __exit__( - self, t: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[Any] - ) -> Optional[bool]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: Type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... def __iter__(self: _T) -> _T: ... # The parameter type of writelines[s]() is determined by that of write(): def writelines(self, lines: Iterable[bytes]) -> None: ... @@ -57,7 +55,7 @@ class _BufferedIOBase(_IOBase): class BufferedRWPair(_BufferedIOBase): def __init__(self, reader: _RawIOBase, writer: _RawIOBase, buffer_size: int = ..., max_buffer_size: int = ...) -> None: ... def peek(self, n: int = ...) -> bytes: ... - def __enter__(self) -> BufferedRWPair: ... + def __enter__(self: Self) -> Self: ... class BufferedRandom(_BufferedIOBase): mode: str @@ -100,12 +98,12 @@ class _RawIOBase(_IOBase): class FileIO(_RawIOBase, BytesIO): mode: str closefd: bool - def __init__(self, file: Union[str, int], mode: str = ..., closefd: bool = ...) -> None: ... + def __init__(self, file: str | int, mode: str = ..., closefd: bool = ...) -> None: ... def readinto(self, buffer: _bytearray_like) -> int: ... def write(self, pbuf: str) -> int: ... class IncrementalNewlineDecoder(object): - newlines: Union[str, unicode] + newlines: str | unicode def __init__(self, decoder, translate, z=...) -> None: ... def decode(self, input, final) -> Any: ... def getstate(self) -> Tuple[Any, int]: ... @@ -114,9 +112,9 @@ class IncrementalNewlineDecoder(object): # Note: In the actual _io.py, _TextIOBase inherits from _IOBase. class _TextIOBase(TextIO): - errors: Optional[str] + errors: str | None # TODO: On _TextIOBase, this is always None. But it's unicode/bytes in subclasses. - newlines: Union[None, unicode, bytes] + newlines: None | unicode | bytes encoding: str @property def closed(self) -> bool: ... @@ -137,19 +135,17 @@ class _TextIOBase(TextIO): def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... def write(self, pbuf: unicode) -> int: ... def writelines(self, lines: Iterable[unicode]) -> None: ... - def __enter__(self: _T) -> _T: ... - def __exit__( - self, t: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[Any] - ) -> Optional[bool]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: Type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... def __iter__(self: _T) -> _T: ... class StringIO(_TextIOBase): line_buffering: bool - def __init__(self, initial_value: Optional[unicode] = ..., newline: Optional[unicode] = ...) -> None: ... + def __init__(self, initial_value: unicode | None = ..., newline: unicode | None = ...) -> None: ... def __setstate__(self, state: Tuple[Any, ...]) -> None: ... def __getstate__(self) -> Tuple[Any, ...]: ... # StringIO does not contain a "name" field. This workaround is necessary @@ -166,19 +162,19 @@ class TextIOWrapper(_TextIOBase): def __init__( self, buffer: IO[Any], - encoding: Optional[Text] = ..., - errors: Optional[Text] = ..., - newline: Optional[Text] = ..., + encoding: Text | None = ..., + errors: Text | None = ..., + newline: Text | None = ..., line_buffering: bool = ..., write_through: bool = ..., ) -> None: ... def open( - file: Union[str, unicode, int], + file: str | unicode | int, mode: Text = ..., buffering: int = ..., - encoding: Optional[Text] = ..., - errors: Optional[Text] = ..., - newline: Optional[Text] = ..., + encoding: Text | None = ..., + errors: Text | None = ..., + newline: Text | None = ..., closefd: bool = ..., ) -> IO[Any]: ... diff --git a/mypy/typeshed/stdlib/@python2/_json.pyi b/mypy/typeshed/stdlib/@python2/_json.pyi index 1c8e0409feaf..a9868b3e60fd 100644 --- a/mypy/typeshed/stdlib/@python2/_json.pyi +++ b/mypy/typeshed/stdlib/@python2/_json.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Generic, List, Tuple +from typing import Any, Tuple def encode_basestring_ascii(*args, **kwargs) -> str: ... def scanstring(a, b, *args, **kwargs) -> Tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/_markupbase.pyi b/mypy/typeshed/stdlib/@python2/_markupbase.pyi new file mode 100644 index 000000000000..d8bc79f34e8c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_markupbase.pyi @@ -0,0 +1,8 @@ +from typing import Tuple + +class ParserBase: + def __init__(self) -> None: ... + def error(self, message: str) -> None: ... + def reset(self) -> None: ... + def getpos(self) -> Tuple[int, int]: ... + def unknown_decl(self, data: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_msi.pyi b/mypy/typeshed/stdlib/@python2/_msi.pyi new file mode 100644 index 000000000000..a1030a66160f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_msi.pyi @@ -0,0 +1,49 @@ +import sys +from typing import List + +if sys.platform == "win32": + + # Actual typename View, not exposed by the implementation + class _View: + def Execute(self, params: _Record | None = ...) -> None: ... + def GetColumnInfo(self, kind: int) -> _Record: ... + def Fetch(self) -> _Record: ... + def Modify(self, mode: int, record: _Record) -> None: ... + def Close(self) -> None: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + # Actual typename Summary, not exposed by the implementation + class _Summary: + def GetProperty(self, propid: int) -> str | bytes | None: ... + def GetPropertyCount(self) -> int: ... + def SetProperty(self, propid: int, value: str | bytes) -> None: ... + def Persist(self) -> None: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + # Actual typename Database, not exposed by the implementation + class _Database: + def OpenView(self, sql: str) -> _View: ... + def Commit(self) -> None: ... + def GetSummaryInformation(self, updateCount: int) -> _Summary: ... + def Close(self) -> None: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + # Actual typename Record, not exposed by the implementation + class _Record: + def GetFieldCount(self) -> int: ... + def GetInteger(self, field: int) -> int: ... + def GetString(self, field: int) -> str: ... + def SetString(self, field: int, str: str) -> None: ... + def SetStream(self, field: int, stream: str) -> None: ... + def SetInteger(self, field: int, int: int) -> None: ... + def ClearData(self) -> None: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + def UuidCreate() -> str: ... + def FCICreate(cabname: str, files: List[str]) -> None: ... + def OpenDatabase(name: str, flags: int) -> _Database: ... + def CreateRecord(count: int) -> _Record: ... diff --git a/mypy/typeshed/stdlib/@python2/_osx_support.pyi b/mypy/typeshed/stdlib/@python2/_osx_support.pyi new file mode 100644 index 000000000000..1b890d8d8a0a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_osx_support.pyi @@ -0,0 +1,33 @@ +from typing import Dict, Iterable, List, Sequence, Tuple, TypeVar + +_T = TypeVar("_T") +_K = TypeVar("_K") +_V = TypeVar("_V") + +__all__: List[str] + +_UNIVERSAL_CONFIG_VARS: Tuple[str, ...] # undocumented +_COMPILER_CONFIG_VARS: Tuple[str, ...] # undocumented +_INITPRE: str # undocumented + +def _find_executable(executable: str, path: str | None = ...) -> str | None: ... # undocumented +def _read_output(commandstring: str) -> str | None: ... # undocumented +def _find_build_tool(toolname: str) -> str: ... # undocumented + +_SYSTEM_VERSION: str | None # undocumented + +def _get_system_version() -> str: ... # undocumented +def _remove_original_values(_config_vars: Dict[str, str]) -> None: ... # undocumented +def _save_modified_value(_config_vars: Dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented +def _supports_universal_builds() -> bool: ... # undocumented +def _find_appropriate_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented +def _remove_universal_flags(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented +def _remove_unsupported_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented +def _override_all_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented +def _check_for_unavailable_sdk(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented +def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> List[str]: ... +def customize_config_vars(_config_vars: Dict[str, str]) -> Dict[str, str]: ... +def customize_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... +def get_platform_osx( + _config_vars: Dict[str, str], osname: _T, release: _K, machine: _V +) -> Tuple[str | _T, str | _K, str | _V]: ... diff --git a/mypy/typeshed/stdlib/@python2/_random.pyi b/mypy/typeshed/stdlib/@python2/_random.pyi new file mode 100644 index 000000000000..7c2dd61af49f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_random.pyi @@ -0,0 +1,13 @@ +from typing import Tuple + +# Actually Tuple[(int,) * 625] +_State = Tuple[int, ...] + +class Random(object): + def __init__(self, seed: object = ...) -> None: ... + def seed(self, __n: object = ...) -> None: ... + def getstate(self) -> _State: ... + def setstate(self, __state: _State) -> None: ... + def random(self) -> float: ... + def getrandbits(self, __k: int) -> int: ... + def jumpahead(self, i: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_sha256.pyi b/mypy/typeshed/stdlib/@python2/_sha256.pyi index b6eb47d4bc83..746432094bf2 100644 --- a/mypy/typeshed/stdlib/@python2/_sha256.pyi +++ b/mypy/typeshed/stdlib/@python2/_sha256.pyi @@ -1,11 +1,9 @@ -from typing import Optional - class sha224(object): name: str block_size: int digest_size: int digestsize: int - def __init__(self, init: Optional[str]) -> None: ... + def __init__(self, init: str | None) -> None: ... def copy(self) -> sha224: ... def digest(self) -> str: ... def hexdigest(self) -> str: ... @@ -16,7 +14,7 @@ class sha256(object): block_size: int digest_size: int digestsize: int - def __init__(self, init: Optional[str]) -> None: ... + def __init__(self, init: str | None) -> None: ... def copy(self) -> sha256: ... def digest(self) -> str: ... def hexdigest(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/_sha512.pyi b/mypy/typeshed/stdlib/@python2/_sha512.pyi index b1ca9aee004c..90e2aee1542f 100644 --- a/mypy/typeshed/stdlib/@python2/_sha512.pyi +++ b/mypy/typeshed/stdlib/@python2/_sha512.pyi @@ -1,11 +1,9 @@ -from typing import Optional - class sha384(object): name: str block_size: int digest_size: int digestsize: int - def __init__(self, init: Optional[str]) -> None: ... + def __init__(self, init: str | None) -> None: ... def copy(self) -> sha384: ... def digest(self) -> str: ... def hexdigest(self) -> str: ... @@ -16,7 +14,7 @@ class sha512(object): block_size: int digest_size: int digestsize: int - def __init__(self, init: Optional[str]) -> None: ... + def __init__(self, init: str | None) -> None: ... def copy(self) -> sha512: ... def digest(self) -> str: ... def hexdigest(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/_socket.pyi b/mypy/typeshed/stdlib/@python2/_socket.pyi index 61c0def50587..c505384c5226 100644 --- a/mypy/typeshed/stdlib/@python2/_socket.pyi +++ b/mypy/typeshed/stdlib/@python2/_socket.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Optional, Tuple, Union, overload +from typing import IO, Any, Tuple, overload AF_APPLETALK: int AF_ASH: int @@ -276,6 +276,6 @@ class SocketType(object): @overload def sendto(self, data: str, flags: int, address: Tuple[Any, ...]) -> int: ... def setblocking(self, flag: bool) -> None: ... - def setsockopt(self, level: int, option: int, value: Union[int, str]) -> None: ... - def settimeout(self, value: Optional[float]) -> None: ... + def setsockopt(self, level: int, option: int, value: int | str) -> None: ... + def settimeout(self, value: float | None) -> None: ... def shutdown(self, flag: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_sre.pyi b/mypy/typeshed/stdlib/@python2/_sre.pyi index 263f1da05632..3bacc097451e 100644 --- a/mypy/typeshed/stdlib/@python2/_sre.pyi +++ b/mypy/typeshed/stdlib/@python2/_sre.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Union, overload +from typing import Any, Dict, Iterable, List, Mapping, Sequence, Tuple, overload CODESIZE: int MAGIC: int @@ -12,9 +12,9 @@ class SRE_Match(object): @overload def group(self) -> str: ... @overload - def group(self, group: int = ...) -> Optional[str]: ... - def groupdict(self) -> Dict[int, Optional[str]]: ... - def groups(self) -> Tuple[Optional[str], ...]: ... + def group(self, group: int = ...) -> str | None: ... + def groupdict(self) -> Dict[int, str | None]: ... + def groups(self) -> Tuple[str | None, ...]: ... def span(self) -> Tuple[int, int]: ... @property def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented @@ -30,12 +30,12 @@ class SRE_Pattern(object): groups: int groupindex: Mapping[str, int] indexgroup: Sequence[int] - def findall(self, source: str, pos: int = ..., endpos: int = ...) -> List[Union[Tuple[Any, ...], str]]: ... - def finditer(self, source: str, pos: int = ..., endpos: int = ...) -> Iterable[Union[Tuple[Any, ...], str]]: ... + def findall(self, source: str, pos: int = ..., endpos: int = ...) -> List[Tuple[Any, ...] | str]: ... + def finditer(self, source: str, pos: int = ..., endpos: int = ...) -> Iterable[Tuple[Any, ...] | str]: ... def match(self, pattern, pos: int = ..., endpos: int = ...) -> SRE_Match: ... def scanner(self, s: str, start: int = ..., end: int = ...) -> SRE_Scanner: ... def search(self, pattern, pos: int = ..., endpos: int = ...) -> SRE_Match: ... - def split(self, source: str, maxsplit: int = ...) -> List[Optional[str]]: ... + def split(self, source: str, maxsplit: int = ...) -> List[str | None]: ... def sub(self, repl: str, string: str, count: int = ...) -> Tuple[Any, ...]: ... def subn(self, repl: str, string: str, count: int = ...) -> Tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/_thread.pyi b/mypy/typeshed/stdlib/@python2/_thread.pyi new file mode 100644 index 000000000000..562ece61e042 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_thread.pyi @@ -0,0 +1,26 @@ +from types import TracebackType +from typing import Any, Callable, Dict, NoReturn, Tuple, Type + +error = RuntimeError + +def _count() -> int: ... + +_dangling: Any + +class LockType: + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... + def release(self) -> None: ... + def locked(self) -> bool: ... + def __enter__(self) -> bool: ... + def __exit__( + self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> None: ... + +def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any] = ...) -> int: ... +def interrupt_main() -> None: ... +def exit() -> NoReturn: ... +def allocate_lock() -> LockType: ... +def get_ident() -> int: ... +def stack_size(size: int = ...) -> int: ... + +TIMEOUT_MAX: float diff --git a/mypy/typeshed/stdlib/@python2/_tkinter.pyi b/mypy/typeshed/stdlib/@python2/_tkinter.pyi new file mode 100644 index 000000000000..378b04202c4f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_tkinter.pyi @@ -0,0 +1,95 @@ +from typing import Any +from typing_extensions import Literal + +# _tkinter is meant to be only used internally by tkinter, but some tkinter +# functions e.g. return _tkinter.Tcl_Obj objects. Tcl_Obj represents a Tcl +# object that hasn't been converted to a string. +# +# There are not many ways to get Tcl_Objs from tkinter, and I'm not sure if the +# only existing ways are supposed to return Tcl_Objs as opposed to returning +# strings. Here's one of these things that return Tcl_Objs: +# +# >>> import tkinter +# >>> text = tkinter.Text() +# >>> text.tag_add('foo', '1.0', 'end') +# >>> text.tag_ranges('foo') +# (, ) +class Tcl_Obj: + string: str # str(tclobj) returns this + typename: str + +class TclError(Exception): ... + +# This class allows running Tcl code. Tkinter uses it internally a lot, and +# it's often handy to drop a piece of Tcl code into a tkinter program. Example: +# +# >>> import tkinter, _tkinter +# >>> tkapp = tkinter.Tk().tk +# >>> isinstance(tkapp, _tkinter.TkappType) +# True +# >>> tkapp.call('set', 'foo', (1,2,3)) +# (1, 2, 3) +# >>> tkapp.eval('return $foo') +# '1 2 3' +# >>> +# +# call args can be pretty much anything. Also, call(some_tuple) is same as call(*some_tuple). +# +# eval always returns str because _tkinter_tkapp_eval_impl in _tkinter.c calls +# Tkapp_UnicodeResult, and it returns a string when it succeeds. +class TkappType: + # Please keep in sync with tkinter.Tk + def call(self, __command: Any, *args: Any) -> Any: ... + def eval(self, __script: str) -> str: ... + adderrorinfo: Any + createcommand: Any + createfilehandler: Any + createtimerhandler: Any + deletecommand: Any + deletefilehandler: Any + dooneevent: Any + evalfile: Any + exprboolean: Any + exprdouble: Any + exprlong: Any + exprstring: Any + getboolean: Any + getdouble: Any + getint: Any + getvar: Any + globalgetvar: Any + globalsetvar: Any + globalunsetvar: Any + interpaddr: Any + loadtk: Any + mainloop: Any + quit: Any + record: Any + setvar: Any + split: Any + splitlist: Any + unsetvar: Any + wantobjects: Any + willdispatch: Any + +# These should be kept in sync with tkinter.tix constants, except ALL_EVENTS which doesn't match TCL_ALL_EVENTS +ALL_EVENTS: Literal[-3] +FILE_EVENTS: Literal[8] +IDLE_EVENTS: Literal[32] +TIMER_EVENTS: Literal[16] +WINDOW_EVENTS: Literal[4] + +DONT_WAIT: Literal[2] +EXCEPTION: Literal[8] +READABLE: Literal[2] +WRITABLE: Literal[4] + +TCL_VERSION: str +TK_VERSION: str + +# TODO: figure out what these are (with e.g. help()) and get rid of Any +TkttType: Any +_flatten: Any +create: Any +getbusywaitinterval: Any +setbusywaitinterval: Any diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi new file mode 100644 index 000000000000..ca698e29ae8a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi @@ -0,0 +1,162 @@ +# Utility types for typeshed + +# This module contains various common types to be used by typeshed. The +# module and its types do not exist at runtime. You can use this module +# outside of typeshed, but no API stability guarantees are made. To use +# it in implementation (.py) files, the following construct must be used: +# +# from typing import TYPE_CHECKING +# if TYPE_CHECKING: +# from _typeshed import ... +# +# If on Python versions < 3.10 and "from __future__ import annotations" +# is not used, types from this module must be quoted. + +import array +import mmap +from typing import Any, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union +from typing_extensions import Literal, final + +_KT = TypeVar("_KT") +_KT_co = TypeVar("_KT_co", covariant=True) +_KT_contra = TypeVar("_KT_contra", contravariant=True) +_VT = TypeVar("_VT") +_VT_co = TypeVar("_VT_co", covariant=True) +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_T_contra = TypeVar("_T_contra", contravariant=True) + +# Use for "self" annotations: +# def __enter__(self: Self) -> Self: ... +Self = TypeVar("Self") # noqa Y001 + +class IdentityFunction(Protocol): + def __call__(self, __x: _T) -> _T: ... + +class SupportsLessThan(Protocol): + def __lt__(self, __other: Any) -> bool: ... + +SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001 + +class SupportsDivMod(Protocol[_T_contra, _T_co]): + def __divmod__(self, __other: _T_contra) -> _T_co: ... + +class SupportsRDivMod(Protocol[_T_contra, _T_co]): + def __rdivmod__(self, __other: _T_contra) -> _T_co: ... + +# Mapping-like protocols + +class SupportsItems(Protocol[_KT_co, _VT_co]): + # We want dictionaries to support this on Python 2. + def items(self) -> Iterable[Tuple[_KT_co, _VT_co]]: ... + +class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]): + def keys(self) -> Iterable[_KT]: ... + def __getitem__(self, __k: _KT) -> _VT_co: ... + +class SupportsGetItem(Container[_KT_contra], Protocol[_KT_contra, _VT_co]): + def __getitem__(self, __k: _KT_contra) -> _VT_co: ... + +class SupportsItemAccess(SupportsGetItem[_KT_contra, _VT], Protocol[_KT_contra, _VT]): + def __setitem__(self, __k: _KT_contra, __v: _VT) -> None: ... + def __delitem__(self, __v: _KT_contra) -> None: ... + +# These aliases can be used in places where a PathLike object can be used +# instead of a string in Python 3. +StrPath = Text +BytesPath = str +StrOrBytesPath = Text +AnyPath = StrOrBytesPath # obsolete, will be removed soon + +OpenTextModeUpdating = Literal[ + "r+", + "+r", + "rt+", + "r+t", + "+rt", + "tr+", + "t+r", + "+tr", + "w+", + "+w", + "wt+", + "w+t", + "+wt", + "tw+", + "t+w", + "+tw", + "a+", + "+a", + "at+", + "a+t", + "+at", + "ta+", + "t+a", + "+ta", + "x+", + "+x", + "xt+", + "x+t", + "+xt", + "tx+", + "t+x", + "+tx", +] +OpenTextModeWriting = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] +OpenTextModeReading = Literal["r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr"] +OpenTextMode = Union[OpenTextModeUpdating, OpenTextModeWriting, OpenTextModeReading] +OpenBinaryModeUpdating = Literal[ + "rb+", + "r+b", + "+rb", + "br+", + "b+r", + "+br", + "wb+", + "w+b", + "+wb", + "bw+", + "b+w", + "+bw", + "ab+", + "a+b", + "+ab", + "ba+", + "b+a", + "+ba", + "xb+", + "x+b", + "+xb", + "bx+", + "b+x", + "+bx", +] +OpenBinaryModeWriting = Literal["wb", "bw", "ab", "ba", "xb", "bx"] +OpenBinaryModeReading = Literal["rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr"] +OpenBinaryMode = Union[OpenBinaryModeUpdating, OpenBinaryModeReading, OpenBinaryModeWriting] + +class HasFileno(Protocol): + def fileno(self) -> int: ... + +FileDescriptor = int +FileDescriptorLike = Union[int, HasFileno] + +class SupportsRead(Protocol[_T_co]): + def read(self, __length: int = ...) -> _T_co: ... + +class SupportsReadline(Protocol[_T_co]): + def readline(self, __length: int = ...) -> _T_co: ... + +class SupportsNoArgReadline(Protocol[_T_co]): + def readline(self) -> _T_co: ... + +class SupportsWrite(Protocol[_T_contra]): + def write(self, __s: _T_contra) -> Any: ... + +ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap, buffer] +WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap, buffer] + +# Used by type checkers for checks involving None (does not exist at runtime) +@final +class NoneType: + def __bool__(self) -> Literal[False]: ... diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi new file mode 100644 index 000000000000..a1f10443a6f0 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi @@ -0,0 +1,35 @@ +# Types to support PEP 3333 (WSGI) +# +# This module doesn't exist at runtime and neither do the types defined in this +# file. They are provided for type checking purposes. + +from sys import _OptExcInfo +from typing import Any, Callable, Dict, Iterable, List, Optional, Protocol, Text, Tuple + +class StartResponse(Protocol): + def __call__( + self, status: str, headers: List[Tuple[str, str]], exc_info: _OptExcInfo | None = ... + ) -> Callable[[bytes], Any]: ... + +WSGIEnvironment = Dict[Text, Any] +WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] + +# WSGI input streams per PEP 3333 +class InputStream(Protocol): + def read(self, size: int = ...) -> bytes: ... + def readline(self, size: int = ...) -> bytes: ... + def readlines(self, hint: int = ...) -> List[bytes]: ... + def __iter__(self) -> Iterable[bytes]: ... + +# WSGI error streams per PEP 3333 +class ErrorStream(Protocol): + def flush(self) -> None: ... + def write(self, s: str) -> None: ... + def writelines(self, seq: List[str]) -> None: ... + +class _Readable(Protocol): + def read(self, size: int = ...) -> bytes: ... + +# Optional file wrapper in wsgi.file_wrapper +class FileWrapper(Protocol): + def __call__(self, file: _Readable, block_size: int = ...) -> Iterable[bytes]: ... diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi new file mode 100644 index 000000000000..6a5d2531ca72 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi @@ -0,0 +1,10 @@ +# Stub-only types. This module does not exist at runtime. + +from typing import Any +from typing_extensions import Protocol + +# As defined https://docs.python.org/3/library/xml.dom.html#domimplementation-objects +class DOMImplementation(Protocol): + def hasFeature(self, feature: str, version: str | None) -> bool: ... + def createDocument(self, namespaceUri: str, qualifiedName: str, doctype: Any | None) -> Any: ... + def createDocumentType(self, qualifiedName: str, publicId: str, systemId: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/_warnings.pyi b/mypy/typeshed/stdlib/@python2/_warnings.pyi new file mode 100644 index 000000000000..ccc51fecb8da --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_warnings.pyi @@ -0,0 +1,31 @@ +from typing import Any, Dict, List, Tuple, Type, overload + +default_action: str +once_registry: Dict[Any, Any] + +filters: List[Tuple[Any, ...]] + +@overload +def warn(message: str, category: Type[Warning] | None = ..., stacklevel: int = ...) -> None: ... +@overload +def warn(message: Warning, category: Any = ..., stacklevel: int = ...) -> None: ... +@overload +def warn_explicit( + message: str, + category: Type[Warning], + filename: str, + lineno: int, + module: str | None = ..., + registry: Dict[str | Tuple[str, Type[Warning], int], int] | None = ..., + module_globals: Dict[str, Any] | None = ..., +) -> None: ... +@overload +def warn_explicit( + message: Warning, + category: Any, + filename: str, + lineno: int, + module: str | None = ..., + registry: Dict[str | Tuple[str, Type[Warning], int], int] | None = ..., + module_globals: Dict[str, Any] | None = ..., +) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_weakref.pyi b/mypy/typeshed/stdlib/@python2/_weakref.pyi new file mode 100644 index 000000000000..a283d4cb60d3 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_weakref.pyi @@ -0,0 +1,26 @@ +from typing import Any, Callable, Generic, List, TypeVar, overload + +_C = TypeVar("_C", bound=Callable[..., Any]) +_T = TypeVar("_T") + +class CallableProxyType(Generic[_C]): # "weakcallableproxy" + def __getattr__(self, attr: str) -> Any: ... + +class ProxyType(Generic[_T]): # "weakproxy" + def __getattr__(self, attr: str) -> Any: ... + +class ReferenceType(Generic[_T]): + def __init__(self, o: _T, callback: Callable[[ReferenceType[_T]], Any] | None = ...) -> None: ... + def __call__(self) -> _T | None: ... + def __hash__(self) -> int: ... + +ref = ReferenceType + +def getweakrefcount(__object: Any) -> int: ... +def getweakrefs(object: Any) -> List[Any]: ... +@overload +def proxy(object: _C, callback: Callable[[_C], Any] | None = ...) -> CallableProxyType[_C]: ... + +# Return CallableProxyType if object is callable, ProxyType otherwise +@overload +def proxy(object: _T, callback: Callable[[_T], Any] | None = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/_weakrefset.pyi b/mypy/typeshed/stdlib/@python2/_weakrefset.pyi new file mode 100644 index 000000000000..f2cde7d67e52 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/_weakrefset.pyi @@ -0,0 +1,41 @@ +from typing import Any, Generic, Iterable, Iterator, MutableSet, TypeVar + +_S = TypeVar("_S") +_T = TypeVar("_T") +_SelfT = TypeVar("_SelfT", bound=WeakSet[Any]) + +class WeakSet(MutableSet[_T], Generic[_T]): + def __init__(self, data: Iterable[_T] | None = ...) -> None: ... + def add(self, item: _T) -> None: ... + def clear(self) -> None: ... + def discard(self, item: _T) -> None: ... + def copy(self: _SelfT) -> _SelfT: ... + def pop(self) -> _T: ... + def remove(self, item: _T) -> None: ... + def update(self, other: Iterable[_T]) -> None: ... + def __contains__(self, item: object) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_T]: ... + def __ior__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def difference(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def __sub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def difference_update(self, other: Iterable[_T]) -> None: ... + def __isub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def intersection(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def __and__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def intersection_update(self, other: Iterable[_T]) -> None: ... + def __iand__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def issubset(self, other: Iterable[_T]) -> bool: ... + def __le__(self, other: Iterable[_T]) -> bool: ... + def __lt__(self, other: Iterable[_T]) -> bool: ... + def issuperset(self, other: Iterable[_T]) -> bool: ... + def __ge__(self, other: Iterable[_T]) -> bool: ... + def __gt__(self, other: Iterable[_T]) -> bool: ... + def __eq__(self, other: object) -> bool: ... + def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def __xor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def symmetric_difference_update(self, other: Iterable[Any]) -> None: ... + def __ixor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def union(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def __or__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def isdisjoint(self, other: Iterable[_T]) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/_winreg.pyi b/mypy/typeshed/stdlib/@python2/_winreg.pyi index f12186cb3d9a..7297626ac8b3 100644 --- a/mypy/typeshed/stdlib/@python2/_winreg.pyi +++ b/mypy/typeshed/stdlib/@python2/_winreg.pyi @@ -1,13 +1,12 @@ -import sys from types import TracebackType -from typing import Any, Optional, Tuple, Type, Union +from typing import Any, Tuple, Type, Union _KeyType = Union[HKEYType, int] def CloseKey(__hkey: _KeyType) -> None: ... -def ConnectRegistry(__computer_name: Optional[str], __key: _KeyType) -> HKEYType: ... -def CreateKey(__key: _KeyType, __sub_key: Optional[str]) -> HKEYType: ... -def CreateKeyEx(key: _KeyType, sub_key: Optional[str], reserved: int = ..., access: int = ...) -> HKEYType: ... +def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... +def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... +def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... def DeleteValue(__key: _KeyType, __value: str) -> None: ... @@ -19,12 +18,12 @@ def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... def QueryInfoKey(__key: _KeyType) -> Tuple[int, int, int]: ... -def QueryValue(__key: _KeyType, __sub_key: Optional[str]) -> str: ... +def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... def QueryValueEx(__key: _KeyType, __name: str) -> Tuple[Any, int]: ... def SaveKey(__key: _KeyType, __file_name: str) -> None: ... def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... def SetValueEx( - __key: _KeyType, __value_name: Optional[str], __reserved: Any, __type: int, __value: Union[str, int] + __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int ) -> None: ... # reserved is ignored def DisableReflectionKey(__key: _KeyType) -> None: ... def EnableReflectionKey(__key: _KeyType) -> None: ... @@ -91,7 +90,7 @@ class HKEYType: def __int__(self) -> int: ... def __enter__(self) -> HKEYType: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... def Close(self) -> None: ... def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/abc.pyi b/mypy/typeshed/stdlib/@python2/abc.pyi index 0bf046a4d877..ac14246d44a5 100644 --- a/mypy/typeshed/stdlib/@python2/abc.pyi +++ b/mypy/typeshed/stdlib/@python2/abc.pyi @@ -1,4 +1,5 @@ import _weakrefset +from _typeshed import SupportsWrite from typing import Any, Callable, Dict, Set, Tuple, Type, TypeVar _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) @@ -8,17 +9,16 @@ _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) def abstractmethod(funcobj: _FuncT) -> _FuncT: ... class ABCMeta(type): - # TODO: FrozenSet - __abstractmethods__: Set[Any] + __abstractmethods__: frozenset[str] _abc_cache: _weakrefset.WeakSet[Any] _abc_invalidation_counter: int _abc_negative_cache: _weakrefset.WeakSet[Any] _abc_negative_cache_version: int _abc_registry: _weakrefset.WeakSet[Any] - def __init__(self, name: str, bases: Tuple[type, ...], namespace: Dict[Any, Any]) -> None: ... + def __init__(self, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> None: ... def __instancecheck__(cls: ABCMeta, instance: Any) -> Any: ... def __subclasscheck__(cls: ABCMeta, subclass: Any) -> Any: ... - def _dump_registry(cls: ABCMeta, *args: Any, **kwargs: Any) -> None: ... + def _dump_registry(cls: ABCMeta, file: SupportsWrite[Any] | None = ...) -> None: ... def register(cls: ABCMeta, subclass: Type[Any]) -> None: ... # TODO: The real abc.abstractproperty inherits from "property". diff --git a/mypy/typeshed/stdlib/@python2/aifc.pyi b/mypy/typeshed/stdlib/@python2/aifc.pyi new file mode 100644 index 000000000000..42f20b7466a1 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/aifc.pyi @@ -0,0 +1,74 @@ +from typing import IO, Any, List, NamedTuple, Text, Tuple, Union, overload +from typing_extensions import Literal + +class Error(Exception): ... + +class _aifc_params(NamedTuple): + nchannels: int + sampwidth: int + framerate: int + nframes: int + comptype: bytes + compname: bytes + +_File = Union[Text, IO[bytes]] +_Marker = Tuple[int, int, bytes] + +class Aifc_read: + def __init__(self, f: _File) -> None: ... + def initfp(self, file: IO[bytes]) -> None: ... + def getfp(self) -> IO[bytes]: ... + def rewind(self) -> None: ... + def close(self) -> None: ... + def tell(self) -> int: ... + def getnchannels(self) -> int: ... + def getnframes(self) -> int: ... + def getsampwidth(self) -> int: ... + def getframerate(self) -> int: ... + def getcomptype(self) -> bytes: ... + def getcompname(self) -> bytes: ... + def getparams(self) -> _aifc_params: ... + def getmarkers(self) -> List[_Marker] | None: ... + def getmark(self, id: int) -> _Marker: ... + def setpos(self, pos: int) -> None: ... + def readframes(self, nframes: int) -> bytes: ... + +class Aifc_write: + def __init__(self, f: _File) -> None: ... + def __del__(self) -> None: ... + def initfp(self, file: IO[bytes]) -> None: ... + def aiff(self) -> None: ... + def aifc(self) -> None: ... + def setnchannels(self, nchannels: int) -> None: ... + def getnchannels(self) -> int: ... + def setsampwidth(self, sampwidth: int) -> None: ... + def getsampwidth(self) -> int: ... + def setframerate(self, framerate: int) -> None: ... + def getframerate(self) -> int: ... + def setnframes(self, nframes: int) -> None: ... + def getnframes(self) -> int: ... + def setcomptype(self, comptype: bytes, compname: bytes) -> None: ... + def getcomptype(self) -> bytes: ... + def getcompname(self) -> bytes: ... + def setparams(self, params: Tuple[int, int, int, int, bytes, bytes]) -> None: ... + def getparams(self) -> _aifc_params: ... + def setmark(self, id: int, pos: int, name: bytes) -> None: ... + def getmark(self, id: int) -> _Marker: ... + def getmarkers(self) -> List[_Marker] | None: ... + def tell(self) -> int: ... + def writeframesraw(self, data: Any) -> None: ... # Actual type for data is Buffer Protocol + def writeframes(self, data: Any) -> None: ... + def close(self) -> None: ... + +@overload +def open(f: _File, mode: Literal["r", "rb"]) -> Aifc_read: ... +@overload +def open(f: _File, mode: Literal["w", "wb"]) -> Aifc_write: ... +@overload +def open(f: _File, mode: str | None = ...) -> Any: ... +@overload +def openfp(f: _File, mode: Literal["r", "rb"]) -> Aifc_read: ... +@overload +def openfp(f: _File, mode: Literal["w", "wb"]) -> Aifc_write: ... +@overload +def openfp(f: _File, mode: str | None = ...) -> Any: ... diff --git a/mypy/test/collect.py b/mypy/typeshed/stdlib/@python2/antigravity.pyi similarity index 100% rename from mypy/test/collect.py rename to mypy/typeshed/stdlib/@python2/antigravity.pyi diff --git a/mypy/typeshed/stdlib/@python2/argparse.pyi b/mypy/typeshed/stdlib/@python2/argparse.pyi new file mode 100644 index 000000000000..4d77f6582c5f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/argparse.pyi @@ -0,0 +1,371 @@ +from typing import ( + IO, + Any, + Callable, + Dict, + Generator, + Iterable, + List, + NoReturn, + Pattern, + Protocol, + Sequence, + Text, + Tuple, + Type, + TypeVar, + Union, + overload, +) + +_T = TypeVar("_T") +_ActionT = TypeVar("_ActionT", bound=Action) +_N = TypeVar("_N") + +_Text = Union[str, unicode] + +ONE_OR_MORE: str +OPTIONAL: str +PARSER: str +REMAINDER: str +SUPPRESS: str +ZERO_OR_MORE: str +_UNRECOGNIZED_ARGS_ATTR: str # undocumented + +class ArgumentError(Exception): + argument_name: str | None + message: str + def __init__(self, argument: Action | None, message: str) -> None: ... + +# undocumented +class _AttributeHolder: + def _get_kwargs(self) -> List[Tuple[str, Any]]: ... + def _get_args(self) -> List[Any]: ... + +# undocumented +class _ActionsContainer: + description: _Text | None + prefix_chars: _Text + argument_default: Any + conflict_handler: _Text + + _registries: Dict[_Text, Dict[Any, Any]] + _actions: List[Action] + _option_string_actions: Dict[_Text, Action] + _action_groups: List[_ArgumentGroup] + _mutually_exclusive_groups: List[_MutuallyExclusiveGroup] + _defaults: Dict[str, Any] + _negative_number_matcher: Pattern[str] + _has_negative_number_optionals: List[bool] + def __init__(self, description: Text | None, prefix_chars: Text, argument_default: Any, conflict_handler: Text) -> None: ... + def register(self, registry_name: Text, value: Any, object: Any) -> None: ... + def _registry_get(self, registry_name: Text, value: Any, default: Any = ...) -> Any: ... + def set_defaults(self, **kwargs: Any) -> None: ... + def get_default(self, dest: Text) -> Any: ... + def add_argument( + self, + *name_or_flags: Text, + action: Text | Type[Action] = ..., + nargs: int | Text = ..., + const: Any = ..., + default: Any = ..., + type: Callable[[Text], _T] | Callable[[str], _T] | FileType = ..., + choices: Iterable[_T] = ..., + required: bool = ..., + help: Text | None = ..., + metavar: Text | Tuple[Text, ...] | None = ..., + dest: Text | None = ..., + version: Text = ..., + **kwargs: Any, + ) -> Action: ... + def add_argument_group(self, *args: Any, **kwargs: Any) -> _ArgumentGroup: ... + def add_mutually_exclusive_group(self, **kwargs: Any) -> _MutuallyExclusiveGroup: ... + def _add_action(self, action: _ActionT) -> _ActionT: ... + def _remove_action(self, action: Action) -> None: ... + def _add_container_actions(self, container: _ActionsContainer) -> None: ... + def _get_positional_kwargs(self, dest: Text, **kwargs: Any) -> Dict[str, Any]: ... + def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ... + def _pop_action_class(self, kwargs: Any, default: Type[Action] | None = ...) -> Type[Action]: ... + def _get_handler(self) -> Callable[[Action, Iterable[Tuple[Text, Action]]], Any]: ... + def _check_conflict(self, action: Action) -> None: ... + def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> NoReturn: ... + def _handle_conflict_resolve(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> None: ... + +class _FormatterClass(Protocol): + def __call__(self, prog: str) -> HelpFormatter: ... + +class ArgumentParser(_AttributeHolder, _ActionsContainer): + prog: _Text + usage: _Text | None + epilog: _Text | None + formatter_class: _FormatterClass + fromfile_prefix_chars: _Text | None + add_help: bool + + # undocumented + _positionals: _ArgumentGroup + _optionals: _ArgumentGroup + _subparsers: _ArgumentGroup | None + def __init__( + self, + prog: Text | None = ..., + usage: Text | None = ..., + description: Text | None = ..., + epilog: Text | None = ..., + parents: Sequence[ArgumentParser] = ..., + formatter_class: _FormatterClass = ..., + prefix_chars: Text = ..., + fromfile_prefix_chars: Text | None = ..., + argument_default: Any = ..., + conflict_handler: Text = ..., + add_help: bool = ..., + ) -> None: ... + # The type-ignores in these overloads should be temporary. See: + # https://github.com/python/typeshed/pull/2643#issuecomment-442280277 + @overload + def parse_args(self, args: Sequence[Text] | None = ...) -> Namespace: ... + @overload + def parse_args(self, args: Sequence[Text] | None, namespace: None) -> Namespace: ... # type: ignore + @overload + def parse_args(self, args: Sequence[Text] | None, namespace: _N) -> _N: ... + @overload + def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore + @overload + def parse_args(self, *, namespace: _N) -> _N: ... + def add_subparsers( + self, + *, + title: Text = ..., + description: Text | None = ..., + prog: Text = ..., + parser_class: Type[ArgumentParser] = ..., + action: Type[Action] = ..., + option_string: Text = ..., + dest: Text | None = ..., + help: Text | None = ..., + metavar: Text | None = ..., + ) -> _SubParsersAction: ... + def print_usage(self, file: IO[str] | None = ...) -> None: ... + def print_help(self, file: IO[str] | None = ...) -> None: ... + def format_usage(self) -> str: ... + def format_help(self) -> str: ... + def parse_known_args( + self, args: Sequence[Text] | None = ..., namespace: Namespace | None = ... + ) -> Tuple[Namespace, List[str]]: ... + def convert_arg_line_to_args(self, arg_line: Text) -> List[str]: ... + def exit(self, status: int = ..., message: Text | None = ...) -> NoReturn: ... + def error(self, message: Text) -> NoReturn: ... + # undocumented + def _get_optional_actions(self) -> List[Action]: ... + def _get_positional_actions(self) -> List[Action]: ... + def _parse_known_args(self, arg_strings: List[Text], namespace: Namespace) -> Tuple[Namespace, List[str]]: ... + def _read_args_from_files(self, arg_strings: List[Text]) -> List[Text]: ... + def _match_argument(self, action: Action, arg_strings_pattern: Text) -> int: ... + def _match_arguments_partial(self, actions: Sequence[Action], arg_strings_pattern: Text) -> List[int]: ... + def _parse_optional(self, arg_string: Text) -> Tuple[Action | None, Text, Text | None] | None: ... + def _get_option_tuples(self, option_string: Text) -> List[Tuple[Action, Text, Text | None]]: ... + def _get_nargs_pattern(self, action: Action) -> _Text: ... + def _get_values(self, action: Action, arg_strings: List[Text]) -> Any: ... + def _get_value(self, action: Action, arg_string: Text) -> Any: ... + def _check_value(self, action: Action, value: Any) -> None: ... + def _get_formatter(self) -> HelpFormatter: ... + def _print_message(self, message: str, file: IO[str] | None = ...) -> None: ... + +class HelpFormatter: + # undocumented + _prog: _Text + _indent_increment: int + _max_help_position: int + _width: int + _current_indent: int + _level: int + _action_max_length: int + _root_section: Any + _current_section: Any + _whitespace_matcher: Pattern[str] + _long_break_matcher: Pattern[str] + _Section: Type[Any] # Nested class + def __init__( + self, prog: Text, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ... + ) -> None: ... + def _indent(self) -> None: ... + def _dedent(self) -> None: ... + def _add_item(self, func: Callable[..., _Text], args: Iterable[Any]) -> None: ... + def start_section(self, heading: Text | None) -> None: ... + def end_section(self) -> None: ... + def add_text(self, text: Text | None) -> None: ... + def add_usage( + self, usage: Text | None, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: Text | None = ... + ) -> None: ... + def add_argument(self, action: Action) -> None: ... + def add_arguments(self, actions: Iterable[Action]) -> None: ... + def format_help(self) -> _Text: ... + def _join_parts(self, part_strings: Iterable[Text]) -> _Text: ... + def _format_usage( + self, usage: Text, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: Text | None + ) -> _Text: ... + def _format_actions_usage(self, actions: Iterable[Action], groups: Iterable[_ArgumentGroup]) -> _Text: ... + def _format_text(self, text: Text) -> _Text: ... + def _format_action(self, action: Action) -> _Text: ... + def _format_action_invocation(self, action: Action) -> _Text: ... + def _metavar_formatter(self, action: Action, default_metavar: Text) -> Callable[[int], Tuple[_Text, ...]]: ... + def _format_args(self, action: Action, default_metavar: Text) -> _Text: ... + def _expand_help(self, action: Action) -> _Text: ... + def _iter_indented_subactions(self, action: Action) -> Generator[Action, None, None]: ... + def _split_lines(self, text: Text, width: int) -> List[_Text]: ... + def _fill_text(self, text: Text, width: int, indent: Text) -> _Text: ... + def _get_help_string(self, action: Action) -> _Text | None: ... + def _get_default_metavar_for_optional(self, action: Action) -> _Text: ... + def _get_default_metavar_for_positional(self, action: Action) -> _Text: ... + +class RawDescriptionHelpFormatter(HelpFormatter): ... +class RawTextHelpFormatter(RawDescriptionHelpFormatter): ... +class ArgumentDefaultsHelpFormatter(HelpFormatter): ... + +class Action(_AttributeHolder): + option_strings: Sequence[_Text] + dest: _Text + nargs: int | _Text | None + const: Any + default: Any + type: Callable[[str], Any] | FileType | None + choices: Iterable[Any] | None + required: bool + help: _Text | None + metavar: _Text | Tuple[_Text, ...] | None + def __init__( + self, + option_strings: Sequence[Text], + dest: Text, + nargs: int | Text | None = ..., + const: _T | None = ..., + default: _T | str | None = ..., + type: Callable[[Text], _T] | Callable[[str], _T] | FileType | None = ..., + choices: Iterable[_T] | None = ..., + required: bool = ..., + help: Text | None = ..., + metavar: Text | Tuple[Text, ...] | None = ..., + ) -> None: ... + def __call__( + self, parser: ArgumentParser, namespace: Namespace, values: Text | Sequence[Any] | None, option_string: Text | None = ... + ) -> None: ... + +class Namespace(_AttributeHolder): + def __init__(self, **kwargs: Any) -> None: ... + def __getattr__(self, name: Text) -> Any: ... + def __setattr__(self, name: Text, value: Any) -> None: ... + def __contains__(self, key: str) -> bool: ... + +class FileType: + # undocumented + _mode: _Text + _bufsize: int + def __init__(self, mode: Text = ..., bufsize: int | None = ...) -> None: ... + def __call__(self, string: Text) -> IO[Any]: ... + +# undocumented +class _ArgumentGroup(_ActionsContainer): + title: _Text | None + _group_actions: List[Action] + def __init__( + self, container: _ActionsContainer, title: Text | None = ..., description: Text | None = ..., **kwargs: Any + ) -> None: ... + +# undocumented +class _MutuallyExclusiveGroup(_ArgumentGroup): + required: bool + _container: _ActionsContainer + def __init__(self, container: _ActionsContainer, required: bool = ...) -> None: ... + +# undocumented +class _StoreAction(Action): ... + +# undocumented +class _StoreConstAction(Action): + def __init__( + self, + option_strings: Sequence[Text], + dest: Text, + const: Any, + default: Any = ..., + required: bool = ..., + help: Text | None = ..., + metavar: Text | Tuple[Text, ...] | None = ..., + ) -> None: ... + +# undocumented +class _StoreTrueAction(_StoreConstAction): + def __init__( + self, option_strings: Sequence[Text], dest: Text, default: bool = ..., required: bool = ..., help: Text | None = ... + ) -> None: ... + +# undocumented +class _StoreFalseAction(_StoreConstAction): + def __init__( + self, option_strings: Sequence[Text], dest: Text, default: bool = ..., required: bool = ..., help: Text | None = ... + ) -> None: ... + +# undocumented +class _AppendAction(Action): ... + +# undocumented +class _AppendConstAction(Action): + def __init__( + self, + option_strings: Sequence[Text], + dest: Text, + const: Any, + default: Any = ..., + required: bool = ..., + help: Text | None = ..., + metavar: Text | Tuple[Text, ...] | None = ..., + ) -> None: ... + +# undocumented +class _CountAction(Action): + def __init__( + self, option_strings: Sequence[Text], dest: Text, default: Any = ..., required: bool = ..., help: Text | None = ... + ) -> None: ... + +# undocumented +class _HelpAction(Action): + def __init__( + self, option_strings: Sequence[Text], dest: Text = ..., default: Text = ..., help: Text | None = ... + ) -> None: ... + +# undocumented +class _VersionAction(Action): + version: _Text | None + def __init__( + self, option_strings: Sequence[Text], version: Text | None = ..., dest: Text = ..., default: Text = ..., help: Text = ... + ) -> None: ... + +# undocumented +class _SubParsersAction(Action): + _ChoicesPseudoAction: Type[Any] # nested class + _prog_prefix: _Text + _parser_class: Type[ArgumentParser] + _name_parser_map: Dict[_Text, ArgumentParser] + choices: Dict[_Text, ArgumentParser] + _choices_actions: List[Action] + def __init__( + self, + option_strings: Sequence[Text], + prog: Text, + parser_class: Type[ArgumentParser], + dest: Text = ..., + help: Text | None = ..., + metavar: Text | Tuple[Text, ...] | None = ..., + ) -> None: ... + # TODO: Type keyword args properly. + def add_parser(self, name: Text, **kwargs: Any) -> ArgumentParser: ... + def _get_subactions(self) -> List[Action]: ... + +# undocumented +class ArgumentTypeError(Exception): ... + +# undocumented +def _ensure_value(namespace: Namespace, name: Text, value: Any) -> Any: ... + +# undocumented +def _get_action_name(argument: Action | None) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/array.pyi b/mypy/typeshed/stdlib/@python2/array.pyi new file mode 100644 index 000000000000..39670fe734fc --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/array.pyi @@ -0,0 +1,65 @@ +from typing import Any, BinaryIO, Generic, Iterable, List, MutableSequence, Text, Tuple, TypeVar, Union, overload +from typing_extensions import Literal + +_IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] +_FloatTypeCode = Literal["f", "d"] +_UnicodeTypeCode = Literal["u"] +_TypeCode = Union[_IntTypeCode, _FloatTypeCode, _UnicodeTypeCode] + +_T = TypeVar("_T", int, float, Text) + +class array(MutableSequence[_T], Generic[_T]): + typecode: _TypeCode + itemsize: int + @overload + def __init__(self: array[int], typecode: _IntTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + @overload + def __init__(self: array[float], typecode: _FloatTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + @overload + def __init__(self: array[Text], typecode: _UnicodeTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + @overload + def __init__(self, typecode: str, __initializer: bytes | Iterable[_T] = ...) -> None: ... + def append(self, __v: _T) -> None: ... + def buffer_info(self) -> Tuple[int, int]: ... + def byteswap(self) -> None: ... + def count(self, __v: Any) -> int: ... + def extend(self, __bb: Iterable[_T]) -> None: ... + def fromfile(self, __f: BinaryIO, __n: int) -> None: ... + def fromlist(self, __list: List[_T]) -> None: ... + def fromunicode(self, __ustr: str) -> None: ... + def index(self, __v: _T) -> int: ... # type: ignore # Overrides Sequence + def insert(self, __i: int, __v: _T) -> None: ... + def pop(self, __i: int = ...) -> _T: ... + def read(self, f: BinaryIO, n: int) -> None: ... + def remove(self, __v: Any) -> None: ... + def reverse(self) -> None: ... + def tofile(self, __f: BinaryIO) -> None: ... + def tolist(self) -> List[_T]: ... + def tounicode(self) -> str: ... + def write(self, f: BinaryIO) -> None: ... + def fromstring(self, __buffer: bytes) -> None: ... + def tostring(self) -> bytes: ... + def __len__(self) -> int: ... + @overload + def __getitem__(self, i: int) -> _T: ... + @overload + def __getitem__(self, s: slice) -> array[_T]: ... + @overload # type: ignore # Overrides MutableSequence + def __setitem__(self, i: int, o: _T) -> None: ... + @overload + def __setitem__(self, s: slice, o: array[_T]) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... + def __add__(self, x: array[_T]) -> array[_T]: ... + def __ge__(self, other: array[_T]) -> bool: ... + def __gt__(self, other: array[_T]) -> bool: ... + def __iadd__(self, x: array[_T]) -> array[_T]: ... # type: ignore # Overrides MutableSequence + def __imul__(self, n: int) -> array[_T]: ... + def __le__(self, other: array[_T]) -> bool: ... + def __lt__(self, other: array[_T]) -> bool: ... + def __mul__(self, n: int) -> array[_T]: ... + def __rmul__(self, n: int) -> array[_T]: ... + def __delslice__(self, i: int, j: int) -> None: ... + def __getslice__(self, i: int, j: int) -> array[_T]: ... + def __setslice__(self, i: int, j: int, y: array[_T]) -> None: ... + +ArrayType = array diff --git a/mypy/typeshed/stdlib/@python2/ast.pyi b/mypy/typeshed/stdlib/@python2/ast.pyi index a8432dd85978..b86e38dce4c5 100644 --- a/mypy/typeshed/stdlib/@python2/ast.pyi +++ b/mypy/typeshed/stdlib/@python2/ast.pyi @@ -4,12 +4,11 @@ # from _ast below when loaded in an unorthodox way by the Dropbox # internal Bazel integration. import typing as _typing -from typing import Any, Iterator, Optional, Union - from _ast import * from _ast import AST, Module +from typing import Any, Iterator -def parse(source: Union[str, unicode], filename: Union[str, unicode] = ..., mode: Union[str, unicode] = ...) -> Module: ... +def parse(source: str | unicode, filename: str | unicode = ..., mode: str | unicode = ...) -> Module: ... def copy_location(new_node: AST, old_node: AST) -> AST: ... def dump(node: AST, annotate_fields: bool = ..., include_attributes: bool = ...) -> str: ... def fix_missing_locations(node: AST) -> AST: ... @@ -17,7 +16,7 @@ def get_docstring(node: AST, clean: bool = ...) -> str: ... def increment_lineno(node: AST, n: int = ...) -> AST: ... def iter_child_nodes(node: AST) -> Iterator[AST]: ... def iter_fields(node: AST) -> Iterator[_typing.Tuple[str, Any]]: ... -def literal_eval(node_or_string: Union[str, unicode, AST]) -> Any: ... +def literal_eval(node_or_string: str | unicode | AST) -> Any: ... def walk(node: AST) -> Iterator[AST]: ... class NodeVisitor: @@ -25,4 +24,4 @@ class NodeVisitor: def generic_visit(self, node: AST) -> Any: ... class NodeTransformer(NodeVisitor): - def generic_visit(self, node: AST) -> Optional[AST]: ... + def generic_visit(self, node: AST) -> AST | None: ... diff --git a/mypy/typeshed/stdlib/@python2/asynchat.pyi b/mypy/typeshed/stdlib/@python2/asynchat.pyi new file mode 100644 index 000000000000..0f5526d71b1d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/asynchat.pyi @@ -0,0 +1,37 @@ +import asyncore +import socket +from abc import abstractmethod +from typing import Sequence, Tuple + +class simple_producer: + def __init__(self, data: bytes, buffer_size: int = ...) -> None: ... + def more(self) -> bytes: ... + +class async_chat(asyncore.dispatcher): + ac_in_buffer_size: int + ac_out_buffer_size: int + def __init__(self, sock: socket.socket | None = ..., map: asyncore._maptype | None = ...) -> None: ... + @abstractmethod + def collect_incoming_data(self, data: bytes) -> None: ... + @abstractmethod + def found_terminator(self) -> None: ... + def set_terminator(self, term: bytes | int | None) -> None: ... + def get_terminator(self) -> bytes | int | None: ... + def handle_read(self) -> None: ... + def handle_write(self) -> None: ... + def handle_close(self) -> None: ... + def push(self, data: bytes) -> None: ... + def push_with_producer(self, producer: simple_producer) -> None: ... + def readable(self) -> bool: ... + def writable(self) -> bool: ... + def close_when_done(self) -> None: ... + def initiate_send(self) -> None: ... + def discard_buffers(self) -> None: ... + +class fifo: + def __init__(self, list: Sequence[bytes | simple_producer] = ...) -> None: ... + def __len__(self) -> int: ... + def is_empty(self) -> bool: ... + def first(self) -> bytes: ... + def push(self, data: bytes | simple_producer) -> None: ... + def pop(self) -> Tuple[int, bytes]: ... diff --git a/mypy/typeshed/stdlib/@python2/asyncore.pyi b/mypy/typeshed/stdlib/@python2/asyncore.pyi new file mode 100644 index 000000000000..95acf9b706d3 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/asyncore.pyi @@ -0,0 +1,118 @@ +import sys +from _typeshed import FileDescriptorLike +from socket import SocketType +from typing import Any, Dict, Optional, Tuple, overload + +# cyclic dependence with asynchat +_maptype = Dict[int, Any] + +socket_map: _maptype = ... # undocumented + +class ExitNow(Exception): ... + +def read(obj: Any) -> None: ... +def write(obj: Any) -> None: ... +def readwrite(obj: Any, flags: int) -> None: ... +def poll(timeout: float = ..., map: _maptype | None = ...) -> None: ... +def poll2(timeout: float = ..., map: _maptype | None = ...) -> None: ... + +poll3 = poll2 + +def loop(timeout: float = ..., use_poll: bool = ..., map: _maptype | None = ..., count: int | None = ...) -> None: ... + +# Not really subclass of socket.socket; it's only delegation. +# It is not covariant to it. +class dispatcher: + + debug: bool + connected: bool + accepting: bool + connecting: bool + closing: bool + ignore_log_types: frozenset[str] + socket: SocketType | None + def __init__(self, sock: SocketType | None = ..., map: _maptype | None = ...) -> None: ... + def add_channel(self, map: _maptype | None = ...) -> None: ... + def del_channel(self, map: _maptype | None = ...) -> None: ... + def create_socket(self, family: int = ..., type: int = ...) -> None: ... + def set_socket(self, sock: SocketType, map: _maptype | None = ...) -> None: ... + def set_reuse_addr(self) -> None: ... + def readable(self) -> bool: ... + def writable(self) -> bool: ... + def listen(self, num: int) -> None: ... + def bind(self, addr: Tuple[Any, ...] | str) -> None: ... + def connect(self, address: Tuple[Any, ...] | str) -> None: ... + def accept(self) -> Tuple[SocketType, Any] | None: ... + def send(self, data: bytes) -> int: ... + def recv(self, buffer_size: int) -> bytes: ... + def close(self) -> None: ... + def log(self, message: Any) -> None: ... + def log_info(self, message: Any, type: str = ...) -> None: ... + def handle_read_event(self) -> None: ... + def handle_connect_event(self) -> None: ... + def handle_write_event(self) -> None: ... + def handle_expt_event(self) -> None: ... + def handle_error(self) -> None: ... + def handle_expt(self) -> None: ... + def handle_read(self) -> None: ... + def handle_write(self) -> None: ... + def handle_connect(self) -> None: ... + def handle_accept(self) -> None: ... + def handle_close(self) -> None: ... + # Historically, some methods were "imported" from `self.socket` by + # means of `__getattr__`. This was long deprecated, and as of Python + # 3.5 has been removed; simply call the relevant methods directly on + # self.socket if necessary. + def detach(self) -> int: ... + def fileno(self) -> int: ... + # return value is an address + def getpeername(self) -> Any: ... + def getsockname(self) -> Any: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: None = ...) -> int: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... + def gettimeout(self) -> float: ... + def ioctl(self, control: object, option: Tuple[int, int, int]) -> None: ... + # TODO the return value may be BinaryIO or TextIO, depending on mode + def makefile( + self, mode: str = ..., buffering: int = ..., encoding: str = ..., errors: str = ..., newline: str = ... + ) -> Any: ... + # return type is an address + def recvfrom(self, bufsize: int, flags: int = ...) -> Any: ... + def recvfrom_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... + def recv_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... + def sendall(self, data: bytes, flags: int = ...) -> None: ... + def sendto(self, data: bytes, address: Tuple[str, int] | str, flags: int = ...) -> int: ... + def setblocking(self, flag: bool) -> None: ... + def settimeout(self, value: float | None) -> None: ... + def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... + def shutdown(self, how: int) -> None: ... + +class dispatcher_with_send(dispatcher): + def __init__(self, sock: SocketType = ..., map: _maptype | None = ...) -> None: ... + def initiate_send(self) -> None: ... + def handle_write(self) -> None: ... + # incompatible signature: + # def send(self, data: bytes) -> Optional[int]: ... + +def compact_traceback() -> Tuple[Tuple[str, str, str], type, type, str]: ... +def close_all(map: _maptype | None = ..., ignore_all: bool = ...) -> None: ... + +if sys.platform != "win32": + class file_wrapper: + fd: int + def __init__(self, fd: int) -> None: ... + def recv(self, bufsize: int, flags: int = ...) -> bytes: ... + def send(self, data: bytes, flags: int = ...) -> int: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: None = ...) -> int: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... + def read(self, bufsize: int, flags: int = ...) -> bytes: ... + def write(self, data: bytes, flags: int = ...) -> int: ... + def close(self) -> None: ... + def fileno(self) -> int: ... + class file_dispatcher(dispatcher): + def __init__(self, fd: FileDescriptorLike, map: _maptype | None = ...) -> None: ... + def set_file(self, fd: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/audioop.pyi b/mypy/typeshed/stdlib/@python2/audioop.pyi new file mode 100644 index 000000000000..71671afe487e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/audioop.pyi @@ -0,0 +1,42 @@ +from typing import Tuple + +AdpcmState = Tuple[int, int] +RatecvState = Tuple[int, Tuple[Tuple[int, int], ...]] + +class error(Exception): ... + +def add(__fragment1: bytes, __fragment2: bytes, __width: int) -> bytes: ... +def adpcm2lin(__fragment: bytes, __width: int, __state: AdpcmState | None) -> Tuple[bytes, AdpcmState]: ... +def alaw2lin(__fragment: bytes, __width: int) -> bytes: ... +def avg(__fragment: bytes, __width: int) -> int: ... +def avgpp(__fragment: bytes, __width: int) -> int: ... +def bias(__fragment: bytes, __width: int, __bias: int) -> bytes: ... +def byteswap(__fragment: bytes, __width: int) -> bytes: ... +def cross(__fragment: bytes, __width: int) -> int: ... +def findfactor(__fragment: bytes, __reference: bytes) -> float: ... +def findfit(__fragment: bytes, __reference: bytes) -> Tuple[int, float]: ... +def findmax(__fragment: bytes, __length: int) -> int: ... +def getsample(__fragment: bytes, __width: int, __index: int) -> int: ... +def lin2adpcm(__fragment: bytes, __width: int, __state: AdpcmState | None) -> Tuple[bytes, AdpcmState]: ... +def lin2alaw(__fragment: bytes, __width: int) -> bytes: ... +def lin2lin(__fragment: bytes, __width: int, __newwidth: int) -> bytes: ... +def lin2ulaw(__fragment: bytes, __width: int) -> bytes: ... +def max(__fragment: bytes, __width: int) -> int: ... +def maxpp(__fragment: bytes, __width: int) -> int: ... +def minmax(__fragment: bytes, __width: int) -> Tuple[int, int]: ... +def mul(__fragment: bytes, __width: int, __factor: float) -> bytes: ... +def ratecv( + __fragment: bytes, + __width: int, + __nchannels: int, + __inrate: int, + __outrate: int, + __state: RatecvState | None, + __weightA: int = ..., + __weightB: int = ..., +) -> Tuple[bytes, RatecvState]: ... +def reverse(__fragment: bytes, __width: int) -> bytes: ... +def rms(__fragment: bytes, __width: int) -> int: ... +def tomono(__fragment: bytes, __width: int, __lfactor: float, __rfactor: float) -> bytes: ... +def tostereo(__fragment: bytes, __width: int, __lfactor: float, __rfactor: float) -> bytes: ... +def ulaw2lin(__fragment: bytes, __width: int) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/base64.pyi b/mypy/typeshed/stdlib/@python2/base64.pyi new file mode 100644 index 000000000000..00856aafddbe --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/base64.pyi @@ -0,0 +1,19 @@ +from typing import IO, Union + +_encodable = Union[bytes, unicode] +_decodable = Union[bytes, unicode] + +def b64encode(s: _encodable, altchars: bytes | None = ...) -> bytes: ... +def b64decode(s: _decodable, altchars: bytes | None = ..., validate: bool = ...) -> bytes: ... +def standard_b64encode(s: _encodable) -> bytes: ... +def standard_b64decode(s: _decodable) -> bytes: ... +def urlsafe_b64encode(s: _encodable) -> bytes: ... +def urlsafe_b64decode(s: _decodable) -> bytes: ... +def b32encode(s: _encodable) -> bytes: ... +def b32decode(s: _decodable, casefold: bool = ..., map01: bytes | None = ...) -> bytes: ... +def b16encode(s: _encodable) -> bytes: ... +def b16decode(s: _decodable, casefold: bool = ...) -> bytes: ... +def decode(input: IO[bytes], output: IO[bytes]) -> None: ... +def encode(input: IO[bytes], output: IO[bytes]) -> None: ... +def encodestring(s: bytes) -> bytes: ... +def decodestring(s: bytes) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/bdb.pyi b/mypy/typeshed/stdlib/@python2/bdb.pyi new file mode 100644 index 000000000000..5bee9dadb928 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/bdb.pyi @@ -0,0 +1,94 @@ +from types import CodeType, FrameType, TracebackType +from typing import IO, Any, Callable, Dict, Iterable, List, Mapping, Set, SupportsInt, Tuple, Type, TypeVar + +_T = TypeVar("_T") +_TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type +_ExcInfo = Tuple[Type[BaseException], BaseException, FrameType] + +GENERATOR_AND_COROUTINE_FLAGS: int = ... + +class BdbQuit(Exception): ... + +class Bdb: + + skip: Set[str] | None + breaks: Dict[str, List[int]] + fncache: Dict[str, str] + frame_returning: FrameType | None + botframe: FrameType | None + quitting: bool + stopframe: FrameType | None + returnframe: FrameType | None + stoplineno: int + def __init__(self, skip: Iterable[str] | None = ...) -> None: ... + def canonic(self, filename: str) -> str: ... + def reset(self) -> None: ... + def trace_dispatch(self, frame: FrameType, event: str, arg: Any) -> _TraceDispatch: ... + def dispatch_line(self, frame: FrameType) -> _TraceDispatch: ... + def dispatch_call(self, frame: FrameType, arg: None) -> _TraceDispatch: ... + def dispatch_return(self, frame: FrameType, arg: Any) -> _TraceDispatch: ... + def dispatch_exception(self, frame: FrameType, arg: _ExcInfo) -> _TraceDispatch: ... + def is_skipped_module(self, module_name: str) -> bool: ... + def stop_here(self, frame: FrameType) -> bool: ... + def break_here(self, frame: FrameType) -> bool: ... + def do_clear(self, arg: Any) -> bool | None: ... + def break_anywhere(self, frame: FrameType) -> bool: ... + def user_call(self, frame: FrameType, argument_list: None) -> None: ... + def user_line(self, frame: FrameType) -> None: ... + def user_return(self, frame: FrameType, return_value: Any) -> None: ... + def user_exception(self, frame: FrameType, exc_info: _ExcInfo) -> None: ... + def set_until(self, frame: FrameType, lineno: int | None = ...) -> None: ... + def set_step(self) -> None: ... + def set_next(self, frame: FrameType) -> None: ... + def set_return(self, frame: FrameType) -> None: ... + def set_trace(self, frame: FrameType | None = ...) -> None: ... + def set_continue(self) -> None: ... + def set_quit(self) -> None: ... + def set_break( + self, filename: str, lineno: int, temporary: bool = ..., cond: str | None = ..., funcname: str | None = ... + ) -> None: ... + def clear_break(self, filename: str, lineno: int) -> None: ... + def clear_bpbynumber(self, arg: SupportsInt) -> None: ... + def clear_all_file_breaks(self, filename: str) -> None: ... + def clear_all_breaks(self) -> None: ... + def get_bpbynumber(self, arg: SupportsInt) -> Breakpoint: ... + def get_break(self, filename: str, lineno: int) -> bool: ... + def get_breaks(self, filename: str, lineno: int) -> List[Breakpoint]: ... + def get_file_breaks(self, filename: str) -> List[Breakpoint]: ... + def get_all_breaks(self) -> List[Breakpoint]: ... + def get_stack(self, f: FrameType | None, t: TracebackType | None) -> Tuple[List[Tuple[FrameType, int]], int]: ... + def format_stack_entry(self, frame_lineno: int, lprefix: str = ...) -> str: ... + def run(self, cmd: str | CodeType, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runeval(self, expr: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runctx(self, cmd: str | CodeType, globals: Dict[str, Any] | None, locals: Mapping[str, Any] | None) -> None: ... + def runcall(self, __func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... + +class Breakpoint: + + next: int = ... + bplist: Dict[Tuple[str, int], List[Breakpoint]] = ... + bpbynumber: List[Breakpoint | None] = ... + + funcname: str | None + func_first_executable_line: int | None + file: str + line: int + temporary: bool + cond: str | None + enabled: bool + ignore: int + hits: int + number: int + def __init__( + self, file: str, line: int, temporary: bool = ..., cond: str | None = ..., funcname: str | None = ... + ) -> None: ... + def deleteMe(self) -> None: ... + def enable(self) -> None: ... + def disable(self) -> None: ... + def bpprint(self, out: IO[str] | None = ...) -> None: ... + def bpformat(self) -> str: ... + def __str__(self) -> str: ... + +def checkfuncname(b: Breakpoint, frame: FrameType) -> bool: ... +def effective(file: str, line: int, frame: FrameType) -> Tuple[Breakpoint, bool] | Tuple[None, None]: ... +def set_trace() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/binascii.pyi b/mypy/typeshed/stdlib/@python2/binascii.pyi new file mode 100644 index 000000000000..b8da269c95a8 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/binascii.pyi @@ -0,0 +1,25 @@ +from typing import Text + +# Python 2 accepts unicode ascii pretty much everywhere. +_Bytes = Text +_Ascii = Text + +def a2b_uu(__data: _Ascii) -> bytes: ... +def b2a_uu(__data: _Bytes) -> bytes: ... +def a2b_base64(__data: _Ascii) -> bytes: ... +def b2a_base64(__data: _Bytes) -> bytes: ... +def a2b_qp(data: _Ascii, header: bool = ...) -> bytes: ... +def b2a_qp(data: _Bytes, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... +def a2b_hqx(__data: _Ascii) -> bytes: ... +def rledecode_hqx(__data: _Bytes) -> bytes: ... +def rlecode_hqx(__data: _Bytes) -> bytes: ... +def b2a_hqx(__data: _Bytes) -> bytes: ... +def crc_hqx(__data: _Bytes, __crc: int) -> int: ... +def crc32(__data: _Bytes, __crc: int = ...) -> int: ... +def b2a_hex(__data: _Bytes) -> bytes: ... +def hexlify(__data: _Bytes) -> bytes: ... +def a2b_hex(__hexstr: _Ascii) -> bytes: ... +def unhexlify(__hexstr: _Ascii) -> bytes: ... + +class Error(ValueError): ... +class Incomplete(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/binhex.pyi b/mypy/typeshed/stdlib/@python2/binhex.pyi new file mode 100644 index 000000000000..02d094faf923 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/binhex.pyi @@ -0,0 +1,42 @@ +from typing import IO, Any, Tuple, Union + +class Error(Exception): ... + +REASONABLY_LARGE: int +LINELEN: int +RUNCHAR: bytes + +class FInfo: + def __init__(self) -> None: ... + Type: str + Creator: str + Flags: int + +_FileInfoTuple = Tuple[str, FInfo, int, int] +_FileHandleUnion = Union[str, IO[bytes]] + +def getfileinfo(name: str) -> _FileInfoTuple: ... + +class openrsrc: + def __init__(self, *args: Any) -> None: ... + def read(self, *args: Any) -> bytes: ... + def write(self, *args: Any) -> None: ... + def close(self) -> None: ... + +class BinHex: + def __init__(self, name_finfo_dlen_rlen: _FileInfoTuple, ofp: _FileHandleUnion) -> None: ... + def write(self, data: bytes) -> None: ... + def close_data(self) -> None: ... + def write_rsrc(self, data: bytes) -> None: ... + def close(self) -> None: ... + +def binhex(inp: str, out: str) -> None: ... + +class HexBin: + def __init__(self, ifp: _FileHandleUnion) -> None: ... + def read(self, *n: int) -> bytes: ... + def close_data(self) -> None: ... + def read_rsrc(self, *n: int) -> bytes: ... + def close(self) -> None: ... + +def hexbin(inp: str, out: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/bisect.pyi b/mypy/typeshed/stdlib/@python2/bisect.pyi new file mode 100644 index 000000000000..60dfc48d69bd --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/bisect.pyi @@ -0,0 +1,4 @@ +from _bisect import * + +bisect = bisect_right +insort = insort_right diff --git a/mypy/typeshed/stdlib/@python2/builtins.pyi b/mypy/typeshed/stdlib/@python2/builtins.pyi index 4eb5424d8da7..fad8b2b4e7d8 100644 --- a/mypy/typeshed/stdlib/@python2/builtins.pyi +++ b/mypy/typeshed/stdlib/@python2/builtins.pyi @@ -26,7 +26,6 @@ from typing import ( MutableSequence, MutableSet, NoReturn, - Optional, Protocol, Reversible, Sequence, @@ -40,7 +39,6 @@ from typing import ( Tuple, Type, TypeVar, - Union, ValuesView, overload, ) @@ -66,9 +64,9 @@ _TT = TypeVar("_TT", bound="type") _TBE = TypeVar("_TBE", bound="BaseException") class object: - __doc__: Optional[str] + __doc__: str | None __dict__: Dict[str, Any] - __slots__: Union[Text, Iterable[Text]] + __slots__: Text | Iterable[Text] __module__: str @property def __class__(self: _T) -> Type[_T]: ... @@ -86,20 +84,20 @@ class object: def __getattribute__(self, name: str) -> Any: ... def __delattr__(self, name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> Union[str, Tuple[Any, ...]]: ... - def __reduce_ex__(self, protocol: int) -> Union[str, Tuple[Any, ...]]: ... + def __reduce__(self) -> str | Tuple[Any, ...]: ... + def __reduce_ex__(self, protocol: int) -> str | Tuple[Any, ...]: ... class staticmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... class classmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... class type(object): __base__: type @@ -123,7 +121,7 @@ class type(object): def __new__(cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... def __subclasses__(self: _TT) -> List[_TT]: ... - # Note: the documentation doesnt specify what the return type is, the standard + # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. def mro(self) -> List[type]: ... def __instancecheck__(self, instance: Any) -> bool: ... @@ -137,9 +135,9 @@ class super(object): class int: @overload - def __new__(cls: Type[_T], x: Union[Text, bytes, SupportsInt, _SupportsIndex, _SupportsTrunc] = ...) -> _T: ... + def __new__(cls: Type[_T], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> _T: ... @overload - def __new__(cls: Type[_T], x: Union[Text, bytes, bytearray], base: int) -> _T: ... + def __new__(cls: Type[_T], x: Text | bytes | bytearray, base: int) -> _T: ... @property def real(self) -> int: ... @property @@ -167,10 +165,10 @@ class int: def __rmod__(self, x: int) -> int: ... def __rdivmod__(self, x: int) -> Tuple[int, int]: ... @overload - def __pow__(self, __x: Literal[2], __modulo: Optional[int] = ...) -> int: ... + def __pow__(self, __x: Literal[2], __modulo: int | None = ...) -> int: ... @overload - def __pow__(self, __x: int, __modulo: Optional[int] = ...) -> Any: ... # Return type can be int or float, depending on x. - def __rpow__(self, x: int, mod: Optional[int] = ...) -> Any: ... + def __pow__(self, __x: int, __modulo: int | None = ...) -> Any: ... # Return type can be int or float, depending on x. + def __rpow__(self, x: int, mod: int | None = ...) -> Any: ... def __and__(self, n: int) -> int: ... def __or__(self, n: int) -> int: ... def __xor__(self, n: int) -> int: ... @@ -201,7 +199,7 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: Union[SupportsFloat, _SupportsIndex, Text, bytes, bytearray] = ...) -> _T: ... + def __new__(cls: Type[_T], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> _T: ... def as_integer_ratio(self) -> Tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @@ -253,7 +251,7 @@ class complex: @overload def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... @overload - def __new__(cls: Type[_T], real: Union[str, SupportsComplex, _SupportsIndex]) -> _T: ... + def __new__(cls: Type[_T], real: str | SupportsComplex | _SupportsIndex) -> _T: ... @property def real(self) -> float: ... @property @@ -295,9 +293,7 @@ class unicode(basestring, Sequence[unicode]): def count(self, x: unicode) -> int: ... def decode(self, encoding: unicode = ..., errors: unicode = ...) -> unicode: ... def encode(self, encoding: unicode = ..., errors: unicode = ...) -> str: ... - def endswith( - self, __suffix: Union[unicode, Tuple[unicode, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> unicode: ... def find(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> unicode: ... @@ -323,17 +319,15 @@ class unicode(basestring, Sequence[unicode]): def rindex(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rjust(self, width: int, fillchar: unicode = ...) -> unicode: ... def rpartition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... - def rsplit(self, sep: Optional[unicode] = ..., maxsplit: int = ...) -> List[unicode]: ... + def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... def rstrip(self, chars: unicode = ...) -> unicode: ... - def split(self, sep: Optional[unicode] = ..., maxsplit: int = ...) -> List[unicode]: ... + def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... def splitlines(self, keepends: bool = ...) -> List[unicode]: ... - def startswith( - self, __prefix: Union[unicode, Tuple[unicode, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def startswith(self, __prefix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, chars: unicode = ...) -> unicode: ... def swapcase(self) -> unicode: ... def title(self) -> unicode: ... - def translate(self, table: Union[Dict[int, Any], unicode]) -> unicode: ... + def translate(self, table: Dict[int, Any] | unicode) -> unicode: ... def upper(self) -> unicode: ... def zfill(self, width: int) -> unicode: ... @overload @@ -353,7 +347,7 @@ class unicode(basestring, Sequence[unicode]): def __ge__(self, x: unicode) -> bool: ... def __len__(self) -> int: ... # The argument type is incompatible with Sequence - def __contains__(self, s: Union[unicode, bytes]) -> bool: ... # type: ignore + def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore def __iter__(self) -> Iterator[unicode]: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... @@ -369,17 +363,15 @@ class str(Sequence[str], basestring): def __init__(self, o: object = ...) -> None: ... def capitalize(self) -> str: ... def center(self, __width: int, __fillchar: str = ...) -> str: ... - def count(self, x: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def count(self, x: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> unicode: ... def encode(self, encoding: Text = ..., errors: Text = ...) -> bytes: ... - def endswith( - self, __suffix: Union[Text, Tuple[Text, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> str: ... - def find(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def find(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... def format_map(self, map: _FormatMapMapping) -> str: ... - def index(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def index(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... def isdigit(self) -> bool: ... @@ -401,8 +393,8 @@ class str(Sequence[str], basestring): @overload def partition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... def replace(self, __old: AnyStr, __new: AnyStr, __count: int = ...) -> AnyStr: ... - def rfind(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... - def rindex(self, sub: Text, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... + def rfind(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... + def rindex(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rjust(self, __width: int, __fillchar: str = ...) -> str: ... @overload def rpartition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... @@ -411,7 +403,7 @@ class str(Sequence[str], basestring): @overload def rpartition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... @overload - def rsplit(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... @overload def rsplit(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... @overload @@ -419,28 +411,26 @@ class str(Sequence[str], basestring): @overload def rstrip(self, __chars: unicode) -> unicode: ... @overload - def split(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... + def split(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... @overload def split(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... def splitlines(self, keepends: bool = ...) -> List[str]: ... - def startswith( - self, __prefix: Union[Text, Tuple[Text, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def startswith(self, __prefix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... @overload def strip(self, __chars: str = ...) -> str: ... @overload def strip(self, chars: unicode) -> unicode: ... def swapcase(self) -> str: ... def title(self) -> str: ... - def translate(self, __table: Optional[AnyStr], deletechars: AnyStr = ...) -> AnyStr: ... + def translate(self, __table: AnyStr | None, deletechars: AnyStr = ...) -> AnyStr: ... def upper(self) -> str: ... def zfill(self, __width: int) -> str: ... def __add__(self, s: AnyStr) -> AnyStr: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[str, Text]) -> bool: ... # type: ignore + def __contains__(self, o: str | Text) -> bool: ... # type: ignore def __eq__(self, x: object) -> bool: ... def __ge__(self, x: Text) -> bool: ... - def __getitem__(self, i: Union[int, slice]) -> str: ... + def __getitem__(self, i: int | slice) -> str: ... def __gt__(self, x: Text) -> bool: ... def __hash__(self) -> int: ... def __iter__(self) -> Iterator[str]: ... @@ -475,11 +465,9 @@ class bytearray(MutableSequence[int], ByteString): def center(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def count(self, __sub: str) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> str: ... - def endswith( - self, __suffix: Union[bytes, Tuple[bytes, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... + def endswith(self, __suffix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> bytearray: ... - def extend(self, iterable: Union[str, Iterable[int]]) -> None: ... + def extend(self, iterable: str | Iterable[int]) -> None: ... def find(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... def index(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... def insert(self, __index: int, __item: int) -> None: ... @@ -493,21 +481,19 @@ class bytearray(MutableSequence[int], ByteString): def join(self, __iterable: Iterable[str]) -> bytearray: ... def ljust(self, __width: int, __fillchar: str = ...) -> bytearray: ... def lower(self) -> bytearray: ... - def lstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... + def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... def partition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytearray: ... def rfind(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rindex(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rjust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def rpartition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... - def rstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... - def split(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... + def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... def splitlines(self, keepends: bool = ...) -> List[bytearray]: ... - def startswith( - self, __prefix: Union[bytes, Tuple[bytes, ...]], __start: Optional[int] = ..., __end: Optional[int] = ... - ) -> bool: ... - def strip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... + def startswith(self, __prefix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... def translate(self, __table: str) -> bytearray: ... @@ -529,15 +515,15 @@ class bytearray(MutableSequence[int], ByteString): @overload def __setitem__(self, i: int, x: int) -> None: ... @overload - def __setitem__(self, s: slice, x: Union[Iterable[int], bytes]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __setitem__(self, s: slice, x: Iterable[int] | bytes) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __getslice__(self, start: int, stop: int) -> bytearray: ... - def __setslice__(self, start: int, stop: int, x: Union[Sequence[int], str]) -> None: ... + def __setslice__(self, start: int, stop: int, x: Sequence[int] | str) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... def __add__(self, s: bytes) -> bytearray: ... def __mul__(self, n: int) -> bytearray: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[int, bytes]) -> bool: ... # type: ignore + def __contains__(self, o: int | bytes) -> bool: ... # type: ignore def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: bytes) -> bool: ... @@ -548,9 +534,9 @@ class bytearray(MutableSequence[int], ByteString): class memoryview(Sized, Container[str]): format: str itemsize: int - shape: Optional[Tuple[int, ...]] - strides: Optional[Tuple[int, ...]] - suboffsets: Optional[Tuple[int, ...]] + shape: Tuple[int, ...] | None + strides: Tuple[int, ...] | None + suboffsets: Tuple[int, ...] | None readonly: bool ndim: int def __init__(self, obj: ReadableBuffer) -> None: ... @@ -662,7 +648,7 @@ class list(MutableSequence[_T], Generic[_T]): def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __getslice__(self, start: int, stop: int) -> List[_T]: ... def __setslice__(self, start: int, stop: int, o: Sequence[_T]) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... @@ -743,18 +729,18 @@ class set(MutableSet[_T], Generic[_T]): def __str__(self) -> str: ... def __and__(self, s: AbstractSet[object]) -> Set[_T]: ... def __iand__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __or__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ior__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... + def __or__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __ior__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... @overload - def __sub__(self: Set[str], s: AbstractSet[Optional[Text]]) -> Set[_T]: ... + def __sub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... @overload - def __sub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... + def __sub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... @overload # type: ignore - def __isub__(self: Set[str], s: AbstractSet[Optional[Text]]) -> Set[_T]: ... + def __isub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... @overload - def __isub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... - def __xor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ixor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... + def __isub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... + def __xor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __ixor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... @@ -776,9 +762,9 @@ class frozenset(AbstractSet[_T_co], Generic[_T_co]): def __iter__(self) -> Iterator[_T_co]: ... def __str__(self) -> str: ... def __and__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __or__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... + def __or__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... def __sub__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... + def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... @@ -802,15 +788,15 @@ class xrange(Sized, Iterable[int], Reversible[int]): class property(object): def __init__( self, - fget: Optional[Callable[[Any], Any]] = ..., - fset: Optional[Callable[[Any, Any], None]] = ..., - fdel: Optional[Callable[[Any], None]] = ..., - doc: Optional[str] = ..., + fget: Callable[[Any], Any] | None = ..., + fset: Callable[[Any, Any], None] | None = ..., + fdel: Callable[[Any], None] | None = ..., + doc: str | None = ..., ) -> None: ... def getter(self, fget: Callable[[Any], Any]) -> property: ... def setter(self, fset: Callable[[Any, Any], None]) -> property: ... def deleter(self, fdel: Callable[[Any], None]) -> property: ... - def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ... + def __get__(self, obj: Any, type: type | None = ...) -> Any: ... def __set__(self, obj: Any, value: Any) -> None: ... def __delete__(self, obj: Any) -> None: ... def fget(self) -> Any: ... @@ -829,8 +815,8 @@ NotImplemented: _NotImplementedType def abs(__x: SupportsAbs[_T]) -> _T: ... def all(__iterable: Iterable[object]) -> bool: ... def any(__iterable: Iterable[object]) -> bool: ... -def apply(__func: Callable[..., _T], __args: Optional[Sequence[Any]] = ..., __kwds: Optional[Mapping[str, Any]] = ...) -> _T: ... -def bin(__number: Union[int, _SupportsIndex]) -> str: ... +def apply(__func: Callable[..., _T], __args: Sequence[Any] | None = ..., __kwds: Mapping[str, Any] | None = ...) -> _T: ... +def bin(__number: int | _SupportsIndex) -> str: ... def callable(__obj: object) -> bool: ... def chr(__i: int) -> str: ... def cmp(__x: Any, __y: Any) -> int: ... @@ -838,7 +824,7 @@ def cmp(__x: Any, __y: Any) -> int: ... _N1 = TypeVar("_N1", bool, int, float, complex) def coerce(__x: _N1, __y: _N1) -> Tuple[_N1, _N1]: ... -def compile(source: Union[Text, mod], filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... +def compile(source: Text | mod, filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... def delattr(__obj: Any, __name: Text) -> None: ... def dir(__o: object = ...) -> List[str]: ... @@ -846,37 +832,52 @@ _N2 = TypeVar("_N2", int, float) def divmod(__x: _N2, __y: _N2) -> Tuple[_N2, _N2]: ... def eval( - __source: Union[Text, bytes, CodeType], __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Mapping[str, Any]] = ... + __source: Text | bytes | CodeType, __globals: Dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... ) -> Any: ... -def execfile(__filename: str, __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Dict[str, Any]] = ...) -> None: ... +def execfile(__filename: str, __globals: Dict[str, Any] | None = ..., __locals: Dict[str, Any] | None = ...) -> None: ... def exit(code: object = ...) -> NoReturn: ... @overload def filter(__function: Callable[[AnyStr], Any], __iterable: AnyStr) -> AnyStr: ... # type: ignore @overload -def filter(__function: None, __iterable: Tuple[Optional[_T], ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: None, __iterable: Tuple[_T | None, ...]) -> Tuple[_T, ...]: ... # type: ignore @overload def filter(__function: Callable[[_T], Any], __iterable: Tuple[_T, ...]) -> Tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: None, __iterable: Iterable[Optional[_T]]) -> List[_T]: ... +def filter(__function: None, __iterable: Iterable[_T | None]) -> List[_T]: ... @overload def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T]: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode -def getattr(__o: Any, name: Text, __default: Any = ...) -> Any: ... +@overload +def getattr(__o: Any, name: Text) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None, bool +# and basic containers help mypy out in some tricky situations involving type context +# (aka bidirectional inference) +@overload +def getattr(__o: Any, name: Text, __default: None) -> Any | None: ... +@overload +def getattr(__o: Any, name: Text, __default: bool) -> Any | bool: ... +@overload +def getattr(__o: object, name: str, __default: list[Any]) -> Any | list[Any]: ... +@overload +def getattr(__o: object, name: str, __default: dict[Any, Any]) -> Any | dict[Any, Any]: ... +@overload +def getattr(__o: Any, name: Text, __default: _T) -> Any | _T: ... def globals() -> Dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... def hash(__obj: object) -> int: ... -def hex(__number: Union[int, _SupportsIndex]) -> str: ... +def hex(__number: int | _SupportsIndex) -> str: ... def id(__obj: object) -> int: ... def input(__prompt: Any = ...) -> Any: ... def intern(__string: str) -> str: ... @overload def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... @overload -def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ... +def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload def iter(__function: Callable[[], _T], __sentinel: Any) -> Iterator[_T]: ... -def isinstance(__obj: object, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... -def issubclass(__cls: type, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... +def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... +def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... def len(__obj: Sized) -> int: ... def locals() -> Dict[str, Any]: ... @overload @@ -956,15 +957,13 @@ def min(__iterable: Iterable[_T], *, key: Callable[[_T], Any] = ...) -> _T: ... @overload def next(__i: Iterator[_T]) -> _T: ... @overload -def next(__i: Iterator[_T], default: _VT) -> Union[_T, _VT]: ... -def oct(__number: Union[int, _SupportsIndex]) -> str: ... -def open(name: Union[unicode, int], mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... -def ord(__c: Union[Text, bytes]) -> int: ... +def next(__i: Iterator[_T], __default: _VT) -> _T | _VT: ... +def oct(__number: int | _SupportsIndex) -> str: ... +def open(name: unicode | int, mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... +def ord(__c: Text | bytes) -> int: ... # This is only available after from __future__ import print_function. -def print( - *values: object, sep: Optional[Text] = ..., end: Optional[Text] = ..., file: Optional[SupportsWrite[Any]] = ... -) -> None: ... +def print(*values: object, sep: Text | None = ..., end: Text | None = ..., file: SupportsWrite[Any] | None = ...) -> None: ... _E = TypeVar("_E", contravariant=True) _M = TypeVar("_M", contravariant=True) @@ -1008,12 +1007,12 @@ def round(number: SupportsFloat) -> float: ... def round(number: SupportsFloat, ndigits: int) -> float: ... def setattr(__obj: Any, __name: Text, __value: Any) -> None: ... def sorted( - __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ... + __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Callable[[_T], Any] | None = ..., reverse: bool = ... ) -> List[_T]: ... @overload -def sum(__iterable: Iterable[_T]) -> Union[_T, int]: ... +def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload -def sum(__iterable: Iterable[_T], __start: _S) -> Union[_T, _S]: ... +def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... def unichr(__i: int) -> unicode: ... def vars(__object: Any = ...) -> Dict[str, Any]: ... @overload @@ -1042,8 +1041,8 @@ def zip( ) -> List[Tuple[Any, ...]]: ... def __import__( name: Text, - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, Any] | None = ..., + locals: Mapping[str, Any] | None = ..., fromlist: Sequence[str] = ..., level: int = ..., ) -> Any: ... @@ -1061,7 +1060,7 @@ class buffer(Sized): def __init__(self, object: _AnyBuffer, offset: int = ..., size: int = ...) -> None: ... def __add__(self, other: _AnyBuffer) -> str: ... def __cmp__(self, other: _AnyBuffer) -> bool: ... - def __getitem__(self, key: Union[int, slice]) -> str: ... + def __getitem__(self, key: int | slice) -> str: ... def __getslice__(self, i: int, j: int) -> str: ... def __len__(self) -> int: ... def __mul__(self, x: int) -> str: ... @@ -1109,10 +1108,10 @@ class RuntimeError(_StandardError): ... class SyntaxError(_StandardError): msg: str - lineno: Optional[int] - offset: Optional[int] - text: Optional[str] - filename: Optional[str] + lineno: int | None + offset: int | None + text: str | None + filename: str | None class SystemError(_StandardError): ... class TypeError(_StandardError): ... @@ -1171,9 +1170,7 @@ class file(BinaryIO): def next(self) -> str: ... def read(self, n: int = ...) -> str: ... def __enter__(self) -> BinaryIO: ... - def __exit__( - self, t: Optional[type] = ..., exc: Optional[BaseException] = ..., tb: Optional[Any] = ... - ) -> Optional[bool]: ... + def __exit__(self, t: type | None = ..., exc: BaseException | None = ..., tb: Any | None = ...) -> bool | None: ... def flush(self) -> None: ... def fileno(self) -> int: ... def isatty(self) -> bool: ... @@ -1187,4 +1184,4 @@ class file(BinaryIO): def readlines(self, hint: int = ...) -> List[str]: ... def write(self, data: str) -> int: ... def writelines(self, data: Iterable[str]) -> None: ... - def truncate(self, pos: Optional[int] = ...) -> int: ... + def truncate(self, pos: int | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/bz2.pyi b/mypy/typeshed/stdlib/@python2/bz2.pyi new file mode 100644 index 000000000000..81ee6f6ce26a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/bz2.pyi @@ -0,0 +1,32 @@ +import io +from _typeshed import ReadableBuffer, WriteableBuffer +from typing import IO, Any, Iterable, List, Text, TypeVar, Union +from typing_extensions import SupportsIndex + +_PathOrFile = Union[Text, IO[bytes]] +_T = TypeVar("_T") + +def compress(data: bytes, compresslevel: int = ...) -> bytes: ... +def decompress(data: bytes) -> bytes: ... + +class BZ2File(io.BufferedIOBase, IO[bytes]): + def __enter__(self: _T) -> _T: ... + def __init__(self, filename: _PathOrFile, mode: str = ..., buffering: Any | None = ..., compresslevel: int = ...) -> None: ... + def read(self, size: int | None = ...) -> bytes: ... + def read1(self, size: int = ...) -> bytes: ... + def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore + def readinto(self, b: WriteableBuffer) -> int: ... + def readlines(self, size: SupportsIndex = ...) -> List[bytes]: ... + def seek(self, offset: int, whence: int = ...) -> int: ... + def write(self, data: ReadableBuffer) -> int: ... + def writelines(self, seq: Iterable[ReadableBuffer]) -> None: ... + +class BZ2Compressor(object): + def __init__(self, compresslevel: int = ...) -> None: ... + def compress(self, __data: bytes) -> bytes: ... + def flush(self) -> bytes: ... + +class BZ2Decompressor(object): + def decompress(self, data: bytes) -> bytes: ... + @property + def unused_data(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/cProfile.pyi b/mypy/typeshed/stdlib/@python2/cProfile.pyi new file mode 100644 index 000000000000..1257b0cc92eb --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/cProfile.pyi @@ -0,0 +1,28 @@ +from types import CodeType +from typing import Any, Callable, Dict, Text, Tuple, TypeVar + +def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... +def runctx( + statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: str | None = ..., sort: str | int = ... +) -> None: ... + +_SelfT = TypeVar("_SelfT", bound=Profile) +_T = TypeVar("_T") +_Label = Tuple[str, int, str] + +class Profile: + stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented + def __init__( + self, timer: Callable[[], float] = ..., timeunit: float = ..., subcalls: bool = ..., builtins: bool = ... + ) -> None: ... + def enable(self) -> None: ... + def disable(self) -> None: ... + def print_stats(self, sort: str | int = ...) -> None: ... + def dump_stats(self, file: Text) -> None: ... + def create_stats(self) -> None: ... + def snapshot_stats(self) -> None: ... + def run(self: _SelfT, cmd: str) -> _SelfT: ... + def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... + def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + +def label(code: str | CodeType) -> _Label: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/cStringIO.pyi b/mypy/typeshed/stdlib/@python2/cStringIO.pyi index 603ce3f2403f..7703e030c332 100644 --- a/mypy/typeshed/stdlib/@python2/cStringIO.pyi +++ b/mypy/typeshed/stdlib/@python2/cStringIO.pyi @@ -1,6 +1,5 @@ from abc import ABCMeta -from types import TracebackType -from typing import IO, Iterable, Iterator, List, Optional, Union, overload +from typing import IO, Iterable, Iterator, List, overload # This class isn't actually abstract, but you can't instantiate it # directly, so we might as well treat it as abstract in the stub. @@ -16,7 +15,7 @@ class InputType(IO[str], Iterator[str], metaclass=ABCMeta): def readlines(self, hint: int = ...) -> List[str]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def __iter__(self) -> InputType: ... def next(self) -> str: ... def reset(self) -> None: ... @@ -35,12 +34,12 @@ class OutputType(IO[str], Iterator[str], metaclass=ABCMeta): def readlines(self, hint: int = ...) -> List[str]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def __iter__(self) -> OutputType: ... def next(self) -> str: ... def reset(self) -> None: ... - def write(self, b: Union[str, unicode]) -> int: ... - def writelines(self, lines: Iterable[Union[str, unicode]]) -> None: ... + def write(self, b: str | unicode) -> int: ... + def writelines(self, lines: Iterable[str | unicode]) -> None: ... @overload def StringIO() -> OutputType: ... diff --git a/mypy/typeshed/stdlib/@python2/calendar.pyi b/mypy/typeshed/stdlib/@python2/calendar.pyi new file mode 100644 index 000000000000..ce765210dc1e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/calendar.pyi @@ -0,0 +1,105 @@ +import datetime +from time import struct_time +from typing import Any, Iterable, List, Optional, Sequence, Tuple + +_LocaleType = Tuple[Optional[str], Optional[str]] + +class IllegalMonthError(ValueError): + def __init__(self, month: int) -> None: ... + def __str__(self) -> str: ... + +class IllegalWeekdayError(ValueError): + def __init__(self, weekday: int) -> None: ... + def __str__(self) -> str: ... + +def isleap(year: int) -> bool: ... +def leapdays(y1: int, y2: int) -> int: ... +def weekday(year: int, month: int, day: int) -> int: ... +def monthrange(year: int, month: int) -> Tuple[int, int]: ... + +class Calendar: + firstweekday: int + def __init__(self, firstweekday: int = ...) -> None: ... + def getfirstweekday(self) -> int: ... + def setfirstweekday(self, firstweekday: int) -> None: ... + def iterweekdays(self) -> Iterable[int]: ... + def itermonthdates(self, year: int, month: int) -> Iterable[datetime.date]: ... + def itermonthdays2(self, year: int, month: int) -> Iterable[Tuple[int, int]]: ... + def itermonthdays(self, year: int, month: int) -> Iterable[int]: ... + def monthdatescalendar(self, year: int, month: int) -> List[List[datetime.date]]: ... + def monthdays2calendar(self, year: int, month: int) -> List[List[Tuple[int, int]]]: ... + def monthdayscalendar(self, year: int, month: int) -> List[List[int]]: ... + def yeardatescalendar(self, year: int, width: int = ...) -> List[List[int]]: ... + def yeardays2calendar(self, year: int, width: int = ...) -> List[List[Tuple[int, int]]]: ... + def yeardayscalendar(self, year: int, width: int = ...) -> List[List[int]]: ... + +class TextCalendar(Calendar): + def prweek(self, theweek: int, width: int) -> None: ... + def formatday(self, day: int, weekday: int, width: int) -> str: ... + def formatweek(self, theweek: int, width: int) -> str: ... + def formatweekday(self, day: int, width: int) -> str: ... + def formatweekheader(self, width: int) -> str: ... + def formatmonthname(self, theyear: int, themonth: int, width: int, withyear: bool = ...) -> str: ... + def prmonth(self, theyear: int, themonth: int, w: int = ..., l: int = ...) -> None: ... + def formatmonth(self, theyear: int, themonth: int, w: int = ..., l: int = ...) -> str: ... + def formatyear(self, theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> str: ... + def pryear(self, theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> None: ... + +def firstweekday() -> int: ... +def monthcalendar(year: int, month: int) -> List[List[int]]: ... +def prweek(theweek: int, width: int) -> None: ... +def week(theweek: int, width: int) -> str: ... +def weekheader(width: int) -> str: ... +def prmonth(theyear: int, themonth: int, w: int = ..., l: int = ...) -> None: ... +def month(theyear: int, themonth: int, w: int = ..., l: int = ...) -> str: ... +def calendar(theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> str: ... +def prcal(theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> None: ... + +class HTMLCalendar(Calendar): + def formatday(self, day: int, weekday: int) -> str: ... + def formatweek(self, theweek: int) -> str: ... + def formatweekday(self, day: int) -> str: ... + def formatweekheader(self) -> str: ... + def formatmonthname(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... + def formatmonth(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... + def formatyear(self, theyear: int, width: int = ...) -> str: ... + def formatyearpage(self, theyear: int, width: int = ..., css: str | None = ..., encoding: str | None = ...) -> str: ... + +class TimeEncoding: + def __init__(self, locale: _LocaleType) -> None: ... + def __enter__(self) -> _LocaleType: ... + def __exit__(self, *args: Any) -> None: ... + +class LocaleTextCalendar(TextCalendar): + def __init__(self, firstweekday: int = ..., locale: _LocaleType | None = ...) -> None: ... + def formatweekday(self, day: int, width: int) -> str: ... + def formatmonthname(self, theyear: int, themonth: int, width: int, withyear: bool = ...) -> str: ... + +class LocaleHTMLCalendar(HTMLCalendar): + def __init__(self, firstweekday: int = ..., locale: _LocaleType | None = ...) -> None: ... + def formatweekday(self, day: int) -> str: ... + def formatmonthname(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... + +c: TextCalendar + +def setfirstweekday(firstweekday: int) -> None: ... +def format(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... +def formatstring(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... +def timegm(tuple: Tuple[int, ...] | struct_time) -> int: ... + +# Data attributes +day_name: Sequence[str] +day_abbr: Sequence[str] +month_name: Sequence[str] +month_abbr: Sequence[str] + +# Below constants are not in docs or __all__, but enough people have used them +# they are now effectively public. + +MONDAY: int +TUESDAY: int +WEDNESDAY: int +THURSDAY: int +FRIDAY: int +SATURDAY: int +SUNDAY: int diff --git a/mypy/typeshed/stdlib/@python2/cgi.pyi b/mypy/typeshed/stdlib/@python2/cgi.pyi index c3519bba9b20..674748242ebb 100644 --- a/mypy/typeshed/stdlib/@python2/cgi.pyi +++ b/mypy/typeshed/stdlib/@python2/cgi.pyi @@ -1,12 +1,12 @@ from _typeshed import SupportsGetItem, SupportsItemAccess from builtins import type as _type -from typing import IO, Any, AnyStr, Iterable, Iterator, List, Mapping, Optional, Protocol, TypeVar, Union +from typing import IO, Any, AnyStr, Iterable, Iterator, List, Mapping, Protocol, TypeVar from UserDict import UserDict _T = TypeVar("_T", bound=FieldStorage) def parse( - fp: Optional[IO[Any]] = ..., + fp: IO[Any] | None = ..., environ: SupportsItemAccess[str, str] = ..., keep_blank_values: bool = ..., strict_parsing: bool = ..., @@ -32,7 +32,7 @@ class MiniFieldStorage: filename: Any list: Any type: Any - file: Optional[IO[bytes]] + file: IO[bytes] | None type_options: dict[Any, Any] disposition: Any disposition_options: dict[Any, Any] @@ -43,28 +43,28 @@ class MiniFieldStorage: def __repr__(self) -> str: ... class FieldStorage(object): - FieldStorageClass: Optional[_type] + FieldStorageClass: _type | None keep_blank_values: int strict_parsing: int - qs_on_post: Optional[str] + qs_on_post: str | None headers: Mapping[str, str] fp: IO[bytes] encoding: str errors: str outerboundary: bytes bytes_read: int - limit: Optional[int] + limit: int | None disposition: str disposition_options: dict[str, str] - filename: Optional[str] - file: Optional[IO[bytes]] + filename: str | None + file: IO[bytes] | None type: str type_options: dict[str, str] innerboundary: bytes length: int done: int - list: Optional[List[Any]] - value: Union[None, bytes, List[Any]] + list: List[Any] | None + value: None | bytes | List[Any] def __init__( self, fp: IO[Any] = ..., diff --git a/mypy/typeshed/stdlib/@python2/cgitb.pyi b/mypy/typeshed/stdlib/@python2/cgitb.pyi new file mode 100644 index 000000000000..daa0233ee69a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/cgitb.pyi @@ -0,0 +1,25 @@ +from types import FrameType, TracebackType +from typing import IO, Any, Callable, Dict, List, Optional, Text, Tuple, Type + +_ExcInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] + +def reset() -> str: ... # undocumented +def small(text: str) -> str: ... # undocumented +def strong(text: str) -> str: ... # undocumented +def grey(text: str) -> str: ... # undocumented +def lookup(name: str, frame: FrameType, locals: Dict[str, Any]) -> Tuple[str | None, Any]: ... # undocumented +def scanvars( + reader: Callable[[], bytes], frame: FrameType, locals: Dict[str, Any] +) -> List[Tuple[str, str | None, Any]]: ... # undocumented +def html(einfo: _ExcInfo, context: int = ...) -> str: ... +def text(einfo: _ExcInfo, context: int = ...) -> str: ... + +class Hook: # undocumented + def __init__( + self, display: int = ..., logdir: Text | None = ..., context: int = ..., file: IO[str] | None = ..., format: str = ... + ) -> None: ... + def __call__(self, etype: Type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... + def handle(self, info: _ExcInfo | None = ...) -> None: ... + +def handler(info: _ExcInfo | None = ...) -> None: ... +def enable(display: int = ..., logdir: Text | None = ..., context: int = ..., format: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/chunk.pyi b/mypy/typeshed/stdlib/@python2/chunk.pyi new file mode 100644 index 000000000000..50ff267c5436 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/chunk.pyi @@ -0,0 +1,20 @@ +from typing import IO + +class Chunk: + closed: bool + align: bool + file: IO[bytes] + chunkname: bytes + chunksize: int + size_read: int + offset: int + seekable: bool + def __init__(self, file: IO[bytes], align: bool = ..., bigendian: bool = ..., inclheader: bool = ...) -> None: ... + def getname(self) -> bytes: ... + def getsize(self) -> int: ... + def close(self) -> None: ... + def isatty(self) -> bool: ... + def seek(self, pos: int, whence: int = ...) -> None: ... + def tell(self) -> int: ... + def read(self, size: int = ...) -> bytes: ... + def skip(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/cmath.pyi b/mypy/typeshed/stdlib/@python2/cmath.pyi new file mode 100644 index 000000000000..1e19687b4885 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/cmath.pyi @@ -0,0 +1,27 @@ +from typing import SupportsComplex, SupportsFloat, Tuple, Union + +e: float +pi: float +_C = Union[SupportsFloat, SupportsComplex, complex] + +def acos(__z: _C) -> complex: ... +def acosh(__z: _C) -> complex: ... +def asin(__z: _C) -> complex: ... +def asinh(__z: _C) -> complex: ... +def atan(__z: _C) -> complex: ... +def atanh(__z: _C) -> complex: ... +def cos(__z: _C) -> complex: ... +def cosh(__z: _C) -> complex: ... +def exp(__z: _C) -> complex: ... +def isinf(__z: _C) -> bool: ... +def isnan(__z: _C) -> bool: ... +def log(__x: _C, __y_obj: _C = ...) -> complex: ... +def log10(__z: _C) -> complex: ... +def phase(__z: _C) -> float: ... +def polar(__z: _C) -> Tuple[float, float]: ... +def rect(__r: float, __phi: float) -> complex: ... +def sin(__z: _C) -> complex: ... +def sinh(__z: _C) -> complex: ... +def sqrt(__z: _C) -> complex: ... +def tan(__z: _C) -> complex: ... +def tanh(__z: _C) -> complex: ... diff --git a/mypy/typeshed/stdlib/@python2/cmd.pyi b/mypy/typeshed/stdlib/@python2/cmd.pyi new file mode 100644 index 000000000000..ffccba84ec16 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/cmd.pyi @@ -0,0 +1,39 @@ +from typing import IO, Any, Callable, List, Tuple + +class Cmd: + prompt: str + identchars: str + ruler: str + lastcmd: str + intro: Any | None + doc_leader: str + doc_header: str + misc_header: str + undoc_header: str + nohelp: str + use_rawinput: bool + stdin: IO[str] + stdout: IO[str] + cmdqueue: List[str] + completekey: str + def __init__(self, completekey: str = ..., stdin: IO[str] | None = ..., stdout: IO[str] | None = ...) -> None: ... + old_completer: Callable[[str, int], str | None] | None + def cmdloop(self, intro: Any | None = ...) -> None: ... + def precmd(self, line: str) -> str: ... + def postcmd(self, stop: bool, line: str) -> bool: ... + def preloop(self) -> None: ... + def postloop(self) -> None: ... + def parseline(self, line: str) -> Tuple[str | None, str | None, str]: ... + def onecmd(self, line: str) -> bool: ... + def emptyline(self) -> bool: ... + def default(self, line: str) -> bool: ... + def completedefault(self, *ignored: Any) -> List[str]: ... + def completenames(self, text: str, *ignored: Any) -> List[str]: ... + completion_matches: List[str] | None + def complete(self, text: str, state: int) -> List[str] | None: ... + def get_names(self) -> List[str]: ... + # Only the first element of args matters. + def complete_help(self, *args: Any) -> List[str]: ... + def do_help(self, arg: str) -> bool | None: ... + def print_topics(self, header: str, cmds: List[str] | None, cmdlen: Any, maxcol: int) -> None: ... + def columnize(self, list: List[str] | None, displaywidth: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/code.pyi b/mypy/typeshed/stdlib/@python2/code.pyi new file mode 100644 index 000000000000..ae8dfc91a32b --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/code.pyi @@ -0,0 +1,22 @@ +from types import CodeType +from typing import Any, Callable, Mapping + +class InteractiveInterpreter: + def __init__(self, locals: Mapping[str, Any] | None = ...) -> None: ... + def runsource(self, source: str, filename: str = ..., symbol: str = ...) -> bool: ... + def runcode(self, code: CodeType) -> None: ... + def showsyntaxerror(self, filename: str | None = ...) -> None: ... + def showtraceback(self) -> None: ... + def write(self, data: str) -> None: ... + +class InteractiveConsole(InteractiveInterpreter): + def __init__(self, locals: Mapping[str, Any] | None = ..., filename: str = ...) -> None: ... + def interact(self, banner: str | None = ...) -> None: ... + def push(self, line: str) -> bool: ... + def resetbuffer(self) -> None: ... + def raw_input(self, prompt: str = ...) -> str: ... + +def interact( + banner: str | None = ..., readfunc: Callable[[str], str] | None = ..., local: Mapping[str, Any] | None = ... +) -> None: ... +def compile_command(source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... diff --git a/mypy/typeshed/stdlib/@python2/codecs.pyi b/mypy/typeshed/stdlib/@python2/codecs.pyi new file mode 100644 index 000000000000..a7835106336d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/codecs.pyi @@ -0,0 +1,286 @@ +import types +from abc import abstractmethod +from typing import ( + IO, + Any, + BinaryIO, + Callable, + Generator, + Iterable, + Iterator, + List, + Protocol, + Text, + TextIO, + Tuple, + Type, + TypeVar, + Union, + overload, +) +from typing_extensions import Literal + +# TODO: this only satisfies the most common interface, where +# bytes (py2 str) is the raw form and str (py2 unicode) is the cooked form. +# In the long run, both should become template parameters maybe? +# There *are* bytes->bytes and str->str encodings in the standard library. +# They are much more common in Python 2 than in Python 3. + +_Decoded = Text +_Encoded = bytes + +class _Encoder(Protocol): + def __call__(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... # signature of Codec().encode + +class _Decoder(Protocol): + def __call__(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... # signature of Codec().decode + +class _StreamReader(Protocol): + def __call__(self, stream: IO[_Encoded], errors: str = ...) -> StreamReader: ... + +class _StreamWriter(Protocol): + def __call__(self, stream: IO[_Encoded], errors: str = ...) -> StreamWriter: ... + +class _IncrementalEncoder(Protocol): + def __call__(self, errors: str = ...) -> IncrementalEncoder: ... + +class _IncrementalDecoder(Protocol): + def __call__(self, errors: str = ...) -> IncrementalDecoder: ... + +# The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300 +# mypy and pytype disagree about where the type ignore can and cannot go, so alias the long type +_BytesToBytesEncodingT = Literal[ + "base64", + "base_64", + "base64_codec", + "bz2", + "bz2_codec", + "hex", + "hex_codec", + "quopri", + "quotedprintable", + "quoted_printable", + "quopri_codec", + "uu", + "uu_codec", + "zip", + "zlib", + "zlib_codec", +] + +@overload +def encode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... +@overload +def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore +@overload +def encode(obj: _Decoded, encoding: str = ..., errors: str = ...) -> _Encoded: ... +@overload +def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore +@overload +def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> Text: ... +@overload +def decode(obj: _Encoded, encoding: str = ..., errors: str = ...) -> _Decoded: ... +def lookup(__encoding: str) -> CodecInfo: ... +def utf_16_be_decode( + __data: _Encoded, __errors: str | None = ..., __final: bool = ... +) -> Tuple[_Decoded, int]: ... # undocumented +def utf_16_be_encode(__str: _Decoded, __errors: str | None = ...) -> Tuple[_Encoded, int]: ... # undocumented + +class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): + @property + def encode(self) -> _Encoder: ... + @property + def decode(self) -> _Decoder: ... + @property + def streamreader(self) -> _StreamReader: ... + @property + def streamwriter(self) -> _StreamWriter: ... + @property + def incrementalencoder(self) -> _IncrementalEncoder: ... + @property + def incrementaldecoder(self) -> _IncrementalDecoder: ... + name: str + def __new__( + cls, + encode: _Encoder, + decode: _Decoder, + streamreader: _StreamReader | None = ..., + streamwriter: _StreamWriter | None = ..., + incrementalencoder: _IncrementalEncoder | None = ..., + incrementaldecoder: _IncrementalDecoder | None = ..., + name: str | None = ..., + *, + _is_text_encoding: bool | None = ..., + ) -> CodecInfo: ... + +def getencoder(encoding: str) -> _Encoder: ... +def getdecoder(encoding: str) -> _Decoder: ... +def getincrementalencoder(encoding: str) -> _IncrementalEncoder: ... +def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... +def getreader(encoding: str) -> _StreamReader: ... +def getwriter(encoding: str) -> _StreamWriter: ... +def register(__search_function: Callable[[str], CodecInfo | None]) -> None: ... +def open( + filename: str, mode: str = ..., encoding: str | None = ..., errors: str = ..., buffering: int = ... +) -> StreamReaderWriter: ... +def EncodedFile(file: IO[_Encoded], data_encoding: str, file_encoding: str | None = ..., errors: str = ...) -> StreamRecoder: ... +def iterencode(iterator: Iterable[_Decoded], encoding: str, errors: str = ...) -> Generator[_Encoded, None, None]: ... +def iterdecode(iterator: Iterable[_Encoded], encoding: str, errors: str = ...) -> Generator[_Decoded, None, None]: ... + +BOM: bytes +BOM_BE: bytes +BOM_LE: bytes +BOM_UTF8: bytes +BOM_UTF16: bytes +BOM_UTF16_BE: bytes +BOM_UTF16_LE: bytes +BOM_UTF32: bytes +BOM_UTF32_BE: bytes +BOM_UTF32_LE: bytes + +# It is expected that different actions be taken depending on which of the +# three subclasses of `UnicodeError` is actually ...ed. However, the Union +# is still needed for at least one of the cases. +def register_error(__errors: str, __handler: Callable[[UnicodeError], Tuple[str | bytes, int]]) -> None: ... +def lookup_error(__name: str) -> Callable[[UnicodeError], Tuple[str | bytes, int]]: ... +def strict_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... +def replace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... +def ignore_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... +def xmlcharrefreplace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... +def backslashreplace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... + +class Codec: + # These are sort of @abstractmethod but sort of not. + # The StreamReader and StreamWriter subclasses only implement one. + def encode(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... + def decode(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... + +class IncrementalEncoder: + errors: str + def __init__(self, errors: str = ...) -> None: ... + @abstractmethod + def encode(self, input: _Decoded, final: bool = ...) -> _Encoded: ... + def reset(self) -> None: ... + # documentation says int but str is needed for the subclass. + def getstate(self) -> int | _Decoded: ... + def setstate(self, state: int | _Decoded) -> None: ... + +class IncrementalDecoder: + errors: str + def __init__(self, errors: str = ...) -> None: ... + @abstractmethod + def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... + def reset(self) -> None: ... + def getstate(self) -> Tuple[_Encoded, int]: ... + def setstate(self, state: Tuple[_Encoded, int]) -> None: ... + +# These are not documented but used in encodings/*.py implementations. +class BufferedIncrementalEncoder(IncrementalEncoder): + buffer: str + def __init__(self, errors: str = ...) -> None: ... + @abstractmethod + def _buffer_encode(self, input: _Decoded, errors: str, final: bool) -> _Encoded: ... + def encode(self, input: _Decoded, final: bool = ...) -> _Encoded: ... + +class BufferedIncrementalDecoder(IncrementalDecoder): + buffer: bytes + def __init__(self, errors: str = ...) -> None: ... + @abstractmethod + def _buffer_decode(self, input: _Encoded, errors: str, final: bool) -> Tuple[_Decoded, int]: ... + def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... + +_SW = TypeVar("_SW", bound=StreamWriter) + +# TODO: it is not possible to specify the requirement that all other +# attributes and methods are passed-through from the stream. +class StreamWriter(Codec): + errors: str + def __init__(self, stream: IO[_Encoded], errors: str = ...) -> None: ... + def write(self, object: _Decoded) -> None: ... + def writelines(self, list: Iterable[_Decoded]) -> None: ... + def reset(self) -> None: ... + def __enter__(self: _SW) -> _SW: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... + +_SR = TypeVar("_SR", bound=StreamReader) + +class StreamReader(Codec): + errors: str + def __init__(self, stream: IO[_Encoded], errors: str = ...) -> None: ... + def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> _Decoded: ... + def readline(self, size: int | None = ..., keepends: bool = ...) -> _Decoded: ... + def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> List[_Decoded]: ... + def reset(self) -> None: ... + def __enter__(self: _SR) -> _SR: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __iter__(self) -> Iterator[_Decoded]: ... + def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... + +_T = TypeVar("_T", bound=StreamReaderWriter) + +# Doesn't actually inherit from TextIO, but wraps a BinaryIO to provide text reading and writing +# and delegates attributes to the underlying binary stream with __getattr__. +class StreamReaderWriter(TextIO): + def __init__(self, stream: IO[_Encoded], Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... + def read(self, size: int = ...) -> _Decoded: ... + def readline(self, size: int | None = ...) -> _Decoded: ... + def readlines(self, sizehint: int | None = ...) -> List[_Decoded]: ... + def next(self) -> Text: ... + def __iter__(self: _T) -> _T: ... + # This actually returns None, but that's incompatible with the supertype + def write(self, data: _Decoded) -> int: ... + def writelines(self, list: Iterable[_Decoded]) -> None: ... + def reset(self) -> None: ... + # Same as write() + def seek(self, offset: int, whence: int = ...) -> int: ... + def __enter__(self: _T) -> _T: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __getattr__(self, name: str) -> Any: ... + # These methods don't actually exist directly, but they are needed to satisfy the TextIO + # interface. At runtime, they are delegated through __getattr__. + def close(self) -> None: ... + def fileno(self) -> int: ... + def flush(self) -> None: ... + def isatty(self) -> bool: ... + def readable(self) -> bool: ... + def truncate(self, size: int | None = ...) -> int: ... + def seekable(self) -> bool: ... + def tell(self) -> int: ... + def writable(self) -> bool: ... + +_SRT = TypeVar("_SRT", bound=StreamRecoder) + +class StreamRecoder(BinaryIO): + def __init__( + self, + stream: IO[_Encoded], + encode: _Encoder, + decode: _Decoder, + Reader: _StreamReader, + Writer: _StreamWriter, + errors: str = ..., + ) -> None: ... + def read(self, size: int = ...) -> bytes: ... + def readline(self, size: int | None = ...) -> bytes: ... + def readlines(self, sizehint: int | None = ...) -> List[bytes]: ... + def next(self) -> bytes: ... + def __iter__(self: _SRT) -> _SRT: ... + def write(self, data: bytes) -> int: ... + def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore # it's supposed to return None + def reset(self) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def __enter__(self: _SRT) -> _SRT: ... + def __exit__(self, type: Type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... + # These methods don't actually exist directly, but they are needed to satisfy the BinaryIO + # interface. At runtime, they are delegated through __getattr__. + def seek(self, offset: int, whence: int = ...) -> int: ... + def close(self) -> None: ... + def fileno(self) -> int: ... + def flush(self) -> None: ... + def isatty(self) -> bool: ... + def readable(self) -> bool: ... + def truncate(self, size: int | None = ...) -> int: ... + def seekable(self) -> bool: ... + def tell(self) -> int: ... + def writable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/codeop.pyi b/mypy/typeshed/stdlib/@python2/codeop.pyi new file mode 100644 index 000000000000..8ed5710c9891 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/codeop.pyi @@ -0,0 +1,13 @@ +from types import CodeType + +def compile_command(source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... + +class Compile: + flags: int + def __init__(self) -> None: ... + def __call__(self, source: str, filename: str, symbol: str) -> CodeType: ... + +class CommandCompiler: + compiler: Compile + def __init__(self) -> None: ... + def __call__(self, source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... diff --git a/mypy/typeshed/stdlib/@python2/collections.pyi b/mypy/typeshed/stdlib/@python2/collections.pyi index f6f75cb076c2..5a2f73aed7ce 100644 --- a/mypy/typeshed/stdlib/@python2/collections.pyi +++ b/mypy/typeshed/stdlib/@python2/collections.pyi @@ -16,14 +16,12 @@ from typing import ( MutableMapping as MutableMapping, MutableSequence as MutableSequence, MutableSet as MutableSet, - Optional, Reversible, Sequence as Sequence, Sized as Sized, Tuple, Type, TypeVar, - Union, ValuesView as ValuesView, overload, ) @@ -37,16 +35,13 @@ _VT = TypeVar("_VT") # namedtuple is special-cased in the type checker; the initializer is ignored. def namedtuple( - typename: Union[str, unicode], - field_names: Union[str, unicode, Iterable[Union[str, unicode]]], - verbose: bool = ..., - rename: bool = ..., + typename: str | unicode, field_names: str | unicode | Iterable[str | unicode], verbose: bool = ..., rename: bool = ... ) -> Type[Tuple[Any, ...]]: ... class deque(Sized, Iterable[_T], Reversible[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ..., maxlen: int = ...) -> None: ... @property - def maxlen(self) -> Optional[int]: ... + def maxlen(self) -> int | None: ... def append(self, x: _T) -> None: ... def appendleft(self, x: _T) -> None: ... def clear(self) -> None: ... @@ -77,7 +72,7 @@ class Counter(Dict[_T, int], Generic[_T]): def __init__(self, iterable: Iterable[_T]) -> None: ... def copy(self: _S) -> _S: ... def elements(self) -> Iterator[_T]: ... - def most_common(self, n: Optional[int] = ...) -> List[Tuple[_T, int]]: ... + def most_common(self, n: int | None = ...) -> List[Tuple[_T, int]]: ... @overload def subtract(self, __mapping: Mapping[_T, int]) -> None: ... @overload @@ -90,7 +85,7 @@ class Counter(Dict[_T, int], Generic[_T]): @overload def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ... @overload - def update(self, __m: Union[Iterable[_T], Iterable[Tuple[_T, int]]], **kwargs: int) -> None: ... + def update(self, __m: Iterable[_T] | Iterable[Tuple[_T, int]], **kwargs: int) -> None: ... @overload def update(self, **kwargs: int) -> None: ... def __add__(self, other: Counter[_T]) -> Counter[_T]: ... @@ -112,18 +107,16 @@ class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self, **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]]) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], **kwargs: _VT) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], map: Mapping[_KT, _VT]) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, map: Mapping[_KT, _VT]) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], iterable: Iterable[Tuple[_KT, _VT]]) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[Tuple[_KT, _VT]]) -> None: ... @overload - def __init__( - self, default_factory: Optional[Callable[[], _VT]], iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT - ) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... def __missing__(self, key: _KT) -> _VT: ... def copy(self: _S) -> _S: ... diff --git a/mypy/typeshed/stdlib/@python2/colorsys.pyi b/mypy/typeshed/stdlib/@python2/colorsys.pyi new file mode 100644 index 000000000000..8db2e2c9ab3a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/colorsys.pyi @@ -0,0 +1,13 @@ +from typing import Tuple + +def rgb_to_yiq(r: float, g: float, b: float) -> Tuple[float, float, float]: ... +def yiq_to_rgb(y: float, i: float, q: float) -> Tuple[float, float, float]: ... +def rgb_to_hls(r: float, g: float, b: float) -> Tuple[float, float, float]: ... +def hls_to_rgb(h: float, l: float, s: float) -> Tuple[float, float, float]: ... +def rgb_to_hsv(r: float, g: float, b: float) -> Tuple[float, float, float]: ... +def hsv_to_rgb(h: float, s: float, v: float) -> Tuple[float, float, float]: ... + +# TODO undocumented +ONE_SIXTH: float +ONE_THIRD: float +TWO_THIRD: float diff --git a/mypy/typeshed/stdlib/@python2/compileall.pyi b/mypy/typeshed/stdlib/@python2/compileall.pyi index 59680fd7926d..ef22929c4c19 100644 --- a/mypy/typeshed/stdlib/@python2/compileall.pyi +++ b/mypy/typeshed/stdlib/@python2/compileall.pyi @@ -1,16 +1,10 @@ -from _typeshed import AnyPath -from typing import Any, Optional, Pattern +from typing import Any, Pattern, Text # rx can be any object with a 'search' method; once we have Protocols we can change the type def compile_dir( - dir: AnyPath, - maxlevels: int = ..., - ddir: Optional[AnyPath] = ..., - force: bool = ..., - rx: Optional[Pattern[Any]] = ..., - quiet: int = ..., + dir: Text, maxlevels: int = ..., ddir: Text | None = ..., force: bool = ..., rx: Pattern[Any] | None = ..., quiet: int = ... ) -> int: ... def compile_file( - fullname: AnyPath, ddir: Optional[AnyPath] = ..., force: bool = ..., rx: Optional[Pattern[Any]] = ..., quiet: int = ... + fullname: Text, ddir: Text | None = ..., force: bool = ..., rx: Pattern[Any] | None = ..., quiet: int = ... ) -> int: ... def compile_path(skip_curdir: bool = ..., maxlevels: int = ..., force: bool = ..., quiet: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/contextlib.pyi b/mypy/typeshed/stdlib/@python2/contextlib.pyi new file mode 100644 index 000000000000..6aabf5a16e47 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/contextlib.pyi @@ -0,0 +1,25 @@ +from types import TracebackType +from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Optional, Type, TypeVar +from typing_extensions import Protocol + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_T_io = TypeVar("_T_io", bound=Optional[IO[str]]) +_F = TypeVar("_F", bound=Callable[..., Any]) + +_ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] +_CM_EF = TypeVar("_CM_EF", ContextManager[Any], _ExitFunc) + +class GeneratorContextManager(ContextManager[_T_co]): + def __call__(self, func: _F) -> _F: ... + +def contextmanager(func: Callable[..., Iterator[_T]]) -> Callable[..., ContextManager[_T]]: ... +def nested(*mgr: ContextManager[Any]) -> ContextManager[Iterable[Any]]: ... + +class _SupportsClose(Protocol): + def close(self) -> None: ... + +_SupportsCloseT = TypeVar("_SupportsCloseT", bound=_SupportsClose) + +class closing(ContextManager[_SupportsCloseT]): + def __init__(self, thing: _SupportsCloseT) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/cookielib.pyi b/mypy/typeshed/stdlib/@python2/cookielib.pyi index 7405ba91c0ff..0f813c128cc4 100644 --- a/mypy/typeshed/stdlib/@python2/cookielib.pyi +++ b/mypy/typeshed/stdlib/@python2/cookielib.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any class Cookie: version: Any @@ -38,9 +38,9 @@ class Cookie: rfc2109: bool = ..., ): ... def has_nonstandard_attr(self, name): ... - def get_nonstandard_attr(self, name, default: Optional[Any] = ...): ... + def get_nonstandard_attr(self, name, default: Any | None = ...): ... def set_nonstandard_attr(self, name, value): ... - def is_expired(self, now: Optional[Any] = ...): ... + def is_expired(self, now: Any | None = ...): ... class CookiePolicy: def set_ok(self, cookie, request): ... @@ -66,11 +66,11 @@ class DefaultCookiePolicy(CookiePolicy): strict_ns_set_path: Any def __init__( self, - blocked_domains: Optional[Any] = ..., - allowed_domains: Optional[Any] = ..., + blocked_domains: Any | None = ..., + allowed_domains: Any | None = ..., netscape: bool = ..., rfc2965: bool = ..., - rfc2109_as_netscape: Optional[Any] = ..., + rfc2109_as_netscape: Any | None = ..., hide_cookie2: bool = ..., strict_domain: bool = ..., strict_rfc2965_unverifiable: bool = ..., @@ -111,14 +111,14 @@ class CookieJar: domain_re: Any dots_re: Any magic_re: Any - def __init__(self, policy: Optional[Any] = ...): ... + def __init__(self, policy: Any | None = ...): ... def set_policy(self, policy): ... def add_cookie_header(self, request): ... def make_cookies(self, response, request): ... def set_cookie_if_ok(self, cookie, request): ... def set_cookie(self, cookie): ... def extract_cookies(self, response, request): ... - def clear(self, domain: Optional[Any] = ..., path: Optional[Any] = ..., name: Optional[Any] = ...): ... + def clear(self, domain: Any | None = ..., path: Any | None = ..., name: Any | None = ...): ... def clear_session_cookies(self): ... def clear_expired_cookies(self): ... def __iter__(self): ... @@ -129,10 +129,10 @@ class LoadError(IOError): ... class FileCookieJar(CookieJar): filename: Any delayload: Any - def __init__(self, filename: Optional[Any] = ..., delayload: bool = ..., policy: Optional[Any] = ...): ... - def save(self, filename: Optional[Any] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... - def load(self, filename: Optional[Any] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... - def revert(self, filename: Optional[Any] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... + def __init__(self, filename: Any | None = ..., delayload: bool = ..., policy: Any | None = ...): ... + def save(self, filename: Any | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... + def load(self, filename: Any | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... + def revert(self, filename: Any | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...): ... class LWPCookieJar(FileCookieJar): def as_lwp_str(self, ignore_discard: bool = ..., ignore_expires: bool = ...) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/copy.pyi b/mypy/typeshed/stdlib/@python2/copy.pyi new file mode 100644 index 000000000000..c88f92846ddf --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/copy.pyi @@ -0,0 +1,14 @@ +from typing import Any, Dict, TypeVar + +_T = TypeVar("_T") + +# None in CPython but non-None in Jython +PyStringMap: Any + +# Note: memo and _nil are internal kwargs. +def deepcopy(x: _T, memo: Dict[int, Any] | None = ..., _nil: Any = ...) -> _T: ... +def copy(x: _T) -> _T: ... + +class Error(Exception): ... + +error = Error diff --git a/mypy/typeshed/stdlib/@python2/copy_reg.pyi b/mypy/typeshed/stdlib/@python2/copy_reg.pyi index ea07ba410b6d..91b099888bab 100644 --- a/mypy/typeshed/stdlib/@python2/copy_reg.pyi +++ b/mypy/typeshed/stdlib/@python2/copy_reg.pyi @@ -7,8 +7,8 @@ __all__: List[str] def pickle( ob_type: _TypeT, - pickle_function: Callable[[_TypeT], Union[str, _Reduce[_TypeT]]], - constructor_ob: Optional[Callable[[_Reduce[_TypeT]], _TypeT]] = ..., + pickle_function: Callable[[_TypeT], str | _Reduce[_TypeT]], + constructor_ob: Callable[[_Reduce[_TypeT]], _TypeT] | None = ..., ) -> None: ... def constructor(object: Callable[[_Reduce[_TypeT]], _TypeT]) -> None: ... def add_extension(module: Hashable, name: Hashable, code: SupportsInt) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/copyreg.pyi b/mypy/typeshed/stdlib/@python2/copyreg.pyi new file mode 100644 index 000000000000..91b099888bab --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/copyreg.pyi @@ -0,0 +1,16 @@ +from typing import Any, Callable, Hashable, List, Optional, SupportsInt, Tuple, TypeVar, Union + +_TypeT = TypeVar("_TypeT", bound=type) +_Reduce = Union[Tuple[Callable[..., _TypeT], Tuple[Any, ...]], Tuple[Callable[..., _TypeT], Tuple[Any, ...], Optional[Any]]] + +__all__: List[str] + +def pickle( + ob_type: _TypeT, + pickle_function: Callable[[_TypeT], str | _Reduce[_TypeT]], + constructor_ob: Callable[[_Reduce[_TypeT]], _TypeT] | None = ..., +) -> None: ... +def constructor(object: Callable[[_Reduce[_TypeT]], _TypeT]) -> None: ... +def add_extension(module: Hashable, name: Hashable, code: SupportsInt) -> None: ... +def remove_extension(module: Hashable, name: Hashable, code: int) -> None: ... +def clear_extension_cache() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/crypt.pyi b/mypy/typeshed/stdlib/@python2/crypt.pyi new file mode 100644 index 000000000000..c4036dbe7a5a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/crypt.pyi @@ -0,0 +1 @@ +def crypt(word: str, salt: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/csv.pyi b/mypy/typeshed/stdlib/@python2/csv.pyi new file mode 100644 index 000000000000..886de6210ca9 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/csv.pyi @@ -0,0 +1,102 @@ +from _csv import ( + QUOTE_ALL as QUOTE_ALL, + QUOTE_MINIMAL as QUOTE_MINIMAL, + QUOTE_NONE as QUOTE_NONE, + QUOTE_NONNUMERIC as QUOTE_NONNUMERIC, + Dialect as Dialect, + Error as Error, + _DialectLike, + _reader, + _writer, + field_size_limit as field_size_limit, + get_dialect as get_dialect, + list_dialects as list_dialects, + reader as reader, + register_dialect as register_dialect, + unregister_dialect as unregister_dialect, + writer as writer, +) +from typing import ( + Any, + Dict as _DictReadMapping, + Generic, + Iterable, + Iterator, + List, + Mapping, + Sequence, + Text, + Type, + TypeVar, + overload, +) + +_T = TypeVar("_T") + +class excel(Dialect): + delimiter: str + quotechar: str + doublequote: bool + skipinitialspace: bool + lineterminator: str + quoting: int + +class excel_tab(excel): + delimiter: str + +class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): + fieldnames: Sequence[_T] | None + restkey: str | None + restval: str | None + reader: _reader + dialect: _DialectLike + line_num: int + @overload + def __init__( + self, + f: Iterable[Text], + fieldnames: Sequence[_T], + restkey: str | None = ..., + restval: str | None = ..., + dialect: _DialectLike = ..., + *args: Any, + **kwds: Any, + ) -> None: ... + @overload + def __init__( + self: DictReader[str], + f: Iterable[Text], + fieldnames: Sequence[str] | None = ..., + restkey: str | None = ..., + restval: str | None = ..., + dialect: _DialectLike = ..., + *args: Any, + **kwds: Any, + ) -> None: ... + def __iter__(self) -> DictReader[_T]: ... + def next(self) -> _DictReadMapping[_T, str]: ... + +class DictWriter(Generic[_T]): + fieldnames: Sequence[_T] + restval: Any | None + extrasaction: str + writer: _writer + def __init__( + self, + f: Any, + fieldnames: Sequence[_T], + restval: Any | None = ..., + extrasaction: str = ..., + dialect: _DialectLike = ..., + *args: Any, + **kwds: Any, + ) -> None: ... + def writeheader(self) -> None: ... + def writerow(self, rowdict: Mapping[_T, Any]) -> Any: ... + def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... + +class Sniffer(object): + preferred: List[str] + def __init__(self) -> None: ... + def sniff(self, sample: str, delimiters: str | None = ...) -> Type[Dialect]: ... + def has_header(self, sample: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi new file mode 100644 index 000000000000..33184cc2ff88 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi @@ -0,0 +1,293 @@ +import sys +from array import array +from typing import ( + Any, + Callable, + ClassVar, + Generic, + Iterable, + Iterator, + List, + Mapping, + Optional, + Sequence, + Text, + Tuple, + Type, + TypeVar, + Union as _UnionT, + overload, +) + +_T = TypeVar("_T") +_DLLT = TypeVar("_DLLT", bound=CDLL) +_CT = TypeVar("_CT", bound=_CData) + +RTLD_GLOBAL: int = ... +RTLD_LOCAL: int = ... +DEFAULT_MODE: int = ... + +class CDLL(object): + _func_flags_: ClassVar[int] = ... + _func_restype_: ClassVar[_CData] = ... + _name: str = ... + _handle: int = ... + _FuncPtr: Type[_FuncPointer] = ... + def __init__( + self, name: str | None, mode: int = ..., handle: int | None = ..., use_errno: bool = ..., use_last_error: bool = ... + ) -> None: ... + def __getattr__(self, name: str) -> _NamedFuncPointer: ... + def __getitem__(self, name: str) -> _NamedFuncPointer: ... + +if sys.platform == "win32": + class OleDLL(CDLL): ... + class WinDLL(CDLL): ... + +class PyDLL(CDLL): ... + +class LibraryLoader(Generic[_DLLT]): + def __init__(self, dlltype: Type[_DLLT]) -> None: ... + def __getattr__(self, name: str) -> _DLLT: ... + def __getitem__(self, name: str) -> _DLLT: ... + def LoadLibrary(self, name: str) -> _DLLT: ... + +cdll: LibraryLoader[CDLL] = ... +if sys.platform == "win32": + windll: LibraryLoader[WinDLL] = ... + oledll: LibraryLoader[OleDLL] = ... +pydll: LibraryLoader[PyDLL] = ... +pythonapi: PyDLL = ... + +# Anything that implements the read-write buffer interface. +# The buffer interface is defined purely on the C level, so we cannot define a normal Protocol +# for it. Instead we have to list the most common stdlib buffer classes in a Union. +_WritableBuffer = _UnionT[bytearray, memoryview, array[Any], _CData] +# Same as _WritableBuffer, but also includes read-only buffer types (like bytes). +_ReadOnlyBuffer = _UnionT[_WritableBuffer, bytes] + +class _CDataMeta(type): + # By default mypy complains about the following two methods, because strictly speaking cls + # might not be a Type[_CT]. However this can never actually happen, because the only class that + # uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here. + def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore + def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore + +class _CData(metaclass=_CDataMeta): + _b_base: int = ... + _b_needsfree_: bool = ... + _objects: Mapping[Any, int] | None = ... + @classmethod + def from_buffer(cls: Type[_CT], source: _WritableBuffer, offset: int = ...) -> _CT: ... + @classmethod + def from_buffer_copy(cls: Type[_CT], source: _ReadOnlyBuffer, offset: int = ...) -> _CT: ... + @classmethod + def from_address(cls: Type[_CT], address: int) -> _CT: ... + @classmethod + def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _CArgObject]: ... + @classmethod + def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... + +class _CanCastTo(_CData): ... +class _PointerLike(_CanCastTo): ... + +_ECT = Callable[[Optional[Type[_CData]], _FuncPointer, Tuple[_CData, ...]], _CData] +_PF = _UnionT[Tuple[int], Tuple[int, str], Tuple[int, str, Any]] + +class _FuncPointer(_PointerLike, _CData): + restype: _UnionT[Type[_CData], Callable[[int], Any], None] = ... + argtypes: Sequence[Type[_CData]] = ... + errcheck: _ECT = ... + @overload + def __init__(self, address: int) -> None: ... + @overload + def __init__(self, callable: Callable[..., Any]) -> None: ... + @overload + def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... + @overload + def __init__(self, vtlb_index: int, name: str, paramflags: Tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + +class _NamedFuncPointer(_FuncPointer): + __name__: str + +class ArgumentError(Exception): ... + +def CFUNCTYPE( + restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... +) -> Type[_FuncPointer]: ... + +if sys.platform == "win32": + def WINFUNCTYPE( + restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... + ) -> Type[_FuncPointer]: ... + +def PYFUNCTYPE(restype: Type[_CData] | None, *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... + +class _CArgObject: ... + +# Any type that can be implicitly converted to c_void_p when passed as a C function argument. +# (bytes is not included here, see below.) +_CVoidPLike = _UnionT[_PointerLike, Array[Any], _CArgObject, int] +# Same as above, but including types known to be read-only (i. e. bytes). +# This distinction is not strictly necessary (ctypes doesn't differentiate between const +# and non-const pointers), but it catches errors like memmove(b'foo', buf, 4) +# when memmove(buf, b'foo', 4) was intended. +_CVoidConstPLike = _UnionT[_CVoidPLike, bytes] + +def addressof(obj: _CData) -> int: ... +def alignment(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def byref(obj: _CData, offset: int = ...) -> _CArgObject: ... + +_CastT = TypeVar("_CastT", bound=_CanCastTo) + +def cast(obj: _UnionT[_CData, _CArgObject, int], typ: Type[_CastT]) -> _CastT: ... +def create_string_buffer(init: _UnionT[int, bytes], size: int | None = ...) -> Array[c_char]: ... + +c_buffer = create_string_buffer + +def create_unicode_buffer(init: _UnionT[int, Text], size: int | None = ...) -> Array[c_wchar]: ... + +if sys.platform == "win32": + def DllCanUnloadNow() -> int: ... + def DllGetClassObject(rclsid: Any, riid: Any, ppv: Any) -> int: ... # TODO not documented + def FormatError(code: int) -> str: ... + def GetLastError() -> int: ... + +def get_errno() -> int: ... + +if sys.platform == "win32": + def get_last_error() -> int: ... + +def memmove(dst: _CVoidPLike, src: _CVoidConstPLike, count: int) -> None: ... +def memset(dst: _CVoidPLike, c: int, count: int) -> None: ... +def POINTER(type: Type[_CT]) -> Type[pointer[_CT]]: ... + +# The real ctypes.pointer is a function, not a class. The stub version of pointer behaves like +# ctypes._Pointer in that it is the base class for all pointer types. Unlike the real _Pointer, +# it can be instantiated directly (to mimic the behavior of the real pointer function). +class pointer(Generic[_CT], _PointerLike, _CData): + _type_: Type[_CT] = ... + contents: _CT = ... + def __init__(self, arg: _CT = ...) -> None: ... + @overload + def __getitem__(self, i: int) -> _CT: ... + @overload + def __getitem__(self, s: slice) -> List[_CT]: ... + @overload + def __setitem__(self, i: int, o: _CT) -> None: ... + @overload + def __setitem__(self, s: slice, o: Iterable[_CT]) -> None: ... + +def resize(obj: _CData, size: int) -> None: ... +def set_conversion_mode(encoding: str, errors: str) -> Tuple[str, str]: ... +def set_errno(value: int) -> int: ... + +if sys.platform == "win32": + def set_last_error(value: int) -> int: ... + +def sizeof(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def string_at(address: _CVoidConstPLike, size: int = ...) -> bytes: ... + +if sys.platform == "win32": + def WinError(code: int | None = ..., descr: str | None = ...) -> OSError: ... + +def wstring_at(address: _CVoidConstPLike, size: int = ...) -> str: ... + +class _SimpleCData(Generic[_T], _CData): + value: _T = ... + def __init__(self, value: _T = ...) -> None: ... + +class c_byte(_SimpleCData[int]): ... + +class c_char(_SimpleCData[bytes]): + def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ... + +class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): + def __init__(self, value: _UnionT[int, bytes] | None = ...) -> None: ... + +class c_double(_SimpleCData[float]): ... +class c_longdouble(_SimpleCData[float]): ... +class c_float(_SimpleCData[float]): ... +class c_int(_SimpleCData[int]): ... +class c_int8(_SimpleCData[int]): ... +class c_int16(_SimpleCData[int]): ... +class c_int32(_SimpleCData[int]): ... +class c_int64(_SimpleCData[int]): ... +class c_long(_SimpleCData[int]): ... +class c_longlong(_SimpleCData[int]): ... +class c_short(_SimpleCData[int]): ... +class c_size_t(_SimpleCData[int]): ... +class c_ssize_t(_SimpleCData[int]): ... +class c_ubyte(_SimpleCData[int]): ... +class c_uint(_SimpleCData[int]): ... +class c_uint8(_SimpleCData[int]): ... +class c_uint16(_SimpleCData[int]): ... +class c_uint32(_SimpleCData[int]): ... +class c_uint64(_SimpleCData[int]): ... +class c_ulong(_SimpleCData[int]): ... +class c_ulonglong(_SimpleCData[int]): ... +class c_ushort(_SimpleCData[int]): ... +class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... +class c_wchar(_SimpleCData[Text]): ... + +class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]): + def __init__(self, value: _UnionT[int, Text] | None = ...) -> None: ... + +class c_bool(_SimpleCData[bool]): + def __init__(self, value: bool = ...) -> None: ... + +if sys.platform == "win32": + class HRESULT(_SimpleCData[int]): ... # TODO undocumented + +class py_object(_CanCastTo, _SimpleCData[_T]): ... + +class _CField: + offset: int = ... + size: int = ... + +class _StructUnionMeta(_CDataMeta): + _fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... + _pack_: int = ... + _anonymous_: Sequence[str] = ... + def __getattr__(self, name: str) -> _CField: ... + +class _StructUnionBase(_CData, metaclass=_StructUnionMeta): + def __init__(self, *args: Any, **kw: Any) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + +class Union(_StructUnionBase): ... +class Structure(_StructUnionBase): ... +class BigEndianStructure(Structure): ... +class LittleEndianStructure(Structure): ... + +class Array(Generic[_CT], _CData): + _length_: int = ... + _type_: Type[_CT] = ... + raw: bytes = ... # Note: only available if _CT == c_char + value: Any = ... # Note: bytes if _CT == c_char, Text if _CT == c_wchar, unavailable otherwise + # TODO These methods cannot be annotated correctly at the moment. + # All of these "Any"s stand for the array's element type, but it's not possible to use _CT + # here, because of a special feature of ctypes. + # By default, when accessing an element of an Array[_CT], the returned object has type _CT. + # However, when _CT is a "simple type" like c_int, ctypes automatically "unboxes" the object + # and converts it to the corresponding Python primitive. For example, when accessing an element + # of an Array[c_int], a Python int object is returned, not a c_int. + # This behavior does *not* apply to subclasses of "simple types". + # If MyInt is a subclass of c_int, then accessing an element of an Array[MyInt] returns + # a MyInt, not an int. + # This special behavior is not easy to model in a stub, so for now all places where + # the array element type would belong are annotated with Any instead. + def __init__(self, *args: Any) -> None: ... + @overload + def __getitem__(self, i: int) -> Any: ... + @overload + def __getitem__(self, s: slice) -> List[Any]: ... + @overload + def __setitem__(self, i: int, o: Any) -> None: ... + @overload + def __setitem__(self, s: slice, o: Iterable[Any]) -> None: ... + def __iter__(self) -> Iterator[Any]: ... + # Can't inherit from Sized because the metaclass conflict between + # Sized and _CData prevents using _CDataMeta. + def __len__(self) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/ctypes/util.pyi b/mypy/typeshed/stdlib/@python2/ctypes/util.pyi new file mode 100644 index 000000000000..c0274f5e539b --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ctypes/util.pyi @@ -0,0 +1,6 @@ +import sys + +def find_library(name: str) -> str | None: ... + +if sys.platform == "win32": + def find_msvcrt() -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/ctypes/wintypes.pyi b/mypy/typeshed/stdlib/@python2/ctypes/wintypes.pyi new file mode 100644 index 000000000000..c178a9bdf936 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ctypes/wintypes.pyi @@ -0,0 +1,234 @@ +from ctypes import ( + Array, + Structure, + _SimpleCData, + c_byte, + c_char, + c_char_p, + c_double, + c_float, + c_int, + c_long, + c_longlong, + c_short, + c_uint, + c_ulong, + c_ulonglong, + c_ushort, + c_void_p, + c_wchar, + c_wchar_p, + pointer, +) + +BYTE = c_byte +WORD = c_ushort +DWORD = c_ulong +CHAR = c_char +WCHAR = c_wchar +UINT = c_uint +INT = c_int +DOUBLE = c_double +FLOAT = c_float +BOOLEAN = BYTE +BOOL = c_long + +class VARIANT_BOOL(_SimpleCData[bool]): ... + +ULONG = c_ulong +LONG = c_long +USHORT = c_ushort +SHORT = c_short +LARGE_INTEGER = c_longlong +_LARGE_INTEGER = c_longlong +ULARGE_INTEGER = c_ulonglong +_ULARGE_INTEGER = c_ulonglong + +OLESTR = c_wchar_p +LPOLESTR = c_wchar_p +LPCOLESTR = c_wchar_p +LPWSTR = c_wchar_p +LPCWSTR = c_wchar_p +LPSTR = c_char_p +LPCSTR = c_char_p +LPVOID = c_void_p +LPCVOID = c_void_p + +# These two types are pointer-sized unsigned and signed ints, respectively. +# At runtime, they are either c_[u]long or c_[u]longlong, depending on the host's pointer size +# (they are not really separate classes). +class WPARAM(_SimpleCData[int]): ... +class LPARAM(_SimpleCData[int]): ... + +ATOM = WORD +LANGID = WORD +COLORREF = DWORD +LGRPID = DWORD +LCTYPE = DWORD +LCID = DWORD + +HANDLE = c_void_p +HACCEL = HANDLE +HBITMAP = HANDLE +HBRUSH = HANDLE +HCOLORSPACE = HANDLE +HDC = HANDLE +HDESK = HANDLE +HDWP = HANDLE +HENHMETAFILE = HANDLE +HFONT = HANDLE +HGDIOBJ = HANDLE +HGLOBAL = HANDLE +HHOOK = HANDLE +HICON = HANDLE +HINSTANCE = HANDLE +HKEY = HANDLE +HKL = HANDLE +HLOCAL = HANDLE +HMENU = HANDLE +HMETAFILE = HANDLE +HMODULE = HANDLE +HMONITOR = HANDLE +HPALETTE = HANDLE +HPEN = HANDLE +HRGN = HANDLE +HRSRC = HANDLE +HSTR = HANDLE +HTASK = HANDLE +HWINSTA = HANDLE +HWND = HANDLE +SC_HANDLE = HANDLE +SERVICE_STATUS_HANDLE = HANDLE + +class RECT(Structure): + left: LONG + top: LONG + right: LONG + bottom: LONG + +RECTL = RECT +_RECTL = RECT +tagRECT = RECT + +class _SMALL_RECT(Structure): + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT + +SMALL_RECT = _SMALL_RECT + +class _COORD(Structure): + X: SHORT + Y: SHORT + +class POINT(Structure): + x: LONG + y: LONG + +POINTL = POINT +_POINTL = POINT +tagPOINT = POINT + +class SIZE(Structure): + cx: LONG + cy: LONG + +SIZEL = SIZE +tagSIZE = SIZE + +def RGB(red: int, green: int, blue: int) -> int: ... + +class FILETIME(Structure): + dwLowDateTime: DWORD + dwHighDateTime: DWORD + +_FILETIME = FILETIME + +class MSG(Structure): + hWnd: HWND + message: UINT + wParam: WPARAM + lParam: LPARAM + time: DWORD + pt: POINT + +tagMSG = MSG +MAX_PATH: int + +class WIN32_FIND_DATAA(Structure): + dwFileAttributes: DWORD + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: DWORD + nFileSizeLow: DWORD + dwReserved0: DWORD + dwReserved1: DWORD + cFileName: Array[CHAR] + cAlternateFileName: Array[CHAR] + +class WIN32_FIND_DATAW(Structure): + dwFileAttributes: DWORD + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: DWORD + nFileSizeLow: DWORD + dwReserved0: DWORD + dwReserved1: DWORD + cFileName: Array[WCHAR] + cAlternateFileName: Array[WCHAR] + +# These pointer type definitions use pointer[...] instead of POINTER(...), to allow them +# to be used in type annotations. +PBOOL = pointer[BOOL] +LPBOOL = pointer[BOOL] +PBOOLEAN = pointer[BOOLEAN] +PBYTE = pointer[BYTE] +LPBYTE = pointer[BYTE] +PCHAR = pointer[CHAR] +LPCOLORREF = pointer[COLORREF] +PDWORD = pointer[DWORD] +LPDWORD = pointer[DWORD] +PFILETIME = pointer[FILETIME] +LPFILETIME = pointer[FILETIME] +PFLOAT = pointer[FLOAT] +PHANDLE = pointer[HANDLE] +LPHANDLE = pointer[HANDLE] +PHKEY = pointer[HKEY] +LPHKL = pointer[HKL] +PINT = pointer[INT] +LPINT = pointer[INT] +PLARGE_INTEGER = pointer[LARGE_INTEGER] +PLCID = pointer[LCID] +PLONG = pointer[LONG] +LPLONG = pointer[LONG] +PMSG = pointer[MSG] +LPMSG = pointer[MSG] +PPOINT = pointer[POINT] +LPPOINT = pointer[POINT] +PPOINTL = pointer[POINTL] +PRECT = pointer[RECT] +LPRECT = pointer[RECT] +PRECTL = pointer[RECTL] +LPRECTL = pointer[RECTL] +LPSC_HANDLE = pointer[SC_HANDLE] +PSHORT = pointer[SHORT] +PSIZE = pointer[SIZE] +LPSIZE = pointer[SIZE] +PSIZEL = pointer[SIZEL] +LPSIZEL = pointer[SIZEL] +PSMALL_RECT = pointer[SMALL_RECT] +PUINT = pointer[UINT] +LPUINT = pointer[UINT] +PULARGE_INTEGER = pointer[ULARGE_INTEGER] +PULONG = pointer[ULONG] +PUSHORT = pointer[USHORT] +PWCHAR = pointer[WCHAR] +PWIN32_FIND_DATAA = pointer[WIN32_FIND_DATAA] +LPWIN32_FIND_DATAA = pointer[WIN32_FIND_DATAA] +PWIN32_FIND_DATAW = pointer[WIN32_FIND_DATAW] +LPWIN32_FIND_DATAW = pointer[WIN32_FIND_DATAW] +PWORD = pointer[WORD] +LPWORD = pointer[WORD] diff --git a/mypy/typeshed/stdlib/@python2/curses/__init__.pyi b/mypy/typeshed/stdlib/@python2/curses/__init__.pyi new file mode 100644 index 000000000000..73e84fba3763 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/curses/__init__.pyi @@ -0,0 +1,15 @@ +from _curses import * # noqa: F403 +from _curses import _CursesWindow as _CursesWindow +from typing import Any, Callable, TypeVar + +_T = TypeVar("_T") + +# available after calling `curses.initscr()` +LINES: int +COLS: int + +# available after calling `curses.start_color()` +COLORS: int +COLOR_PAIRS: int + +def wrapper(__func: Callable[..., _T], *arg: Any, **kwds: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/@python2/curses/ascii.pyi b/mypy/typeshed/stdlib/@python2/curses/ascii.pyi new file mode 100644 index 000000000000..05efb326687a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/curses/ascii.pyi @@ -0,0 +1,62 @@ +from typing import List, TypeVar + +_CharT = TypeVar("_CharT", str, int) + +NUL: int +SOH: int +STX: int +ETX: int +EOT: int +ENQ: int +ACK: int +BEL: int +BS: int +TAB: int +HT: int +LF: int +NL: int +VT: int +FF: int +CR: int +SO: int +SI: int +DLE: int +DC1: int +DC2: int +DC3: int +DC4: int +NAK: int +SYN: int +ETB: int +CAN: int +EM: int +SUB: int +ESC: int +FS: int +GS: int +RS: int +US: int +SP: int +DEL: int + +controlnames: List[int] + +def isalnum(c: str | int) -> bool: ... +def isalpha(c: str | int) -> bool: ... +def isascii(c: str | int) -> bool: ... +def isblank(c: str | int) -> bool: ... +def iscntrl(c: str | int) -> bool: ... +def isdigit(c: str | int) -> bool: ... +def isgraph(c: str | int) -> bool: ... +def islower(c: str | int) -> bool: ... +def isprint(c: str | int) -> bool: ... +def ispunct(c: str | int) -> bool: ... +def isspace(c: str | int) -> bool: ... +def isupper(c: str | int) -> bool: ... +def isxdigit(c: str | int) -> bool: ... +def isctrl(c: str | int) -> bool: ... +def ismeta(c: str | int) -> bool: ... +def ascii(c: _CharT) -> _CharT: ... +def ctrl(c: _CharT) -> _CharT: ... +def alt(c: _CharT) -> _CharT: ... +def unctrl(c: str | int) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/curses/panel.pyi b/mypy/typeshed/stdlib/@python2/curses/panel.pyi new file mode 100644 index 000000000000..138e4a9f727e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/curses/panel.pyi @@ -0,0 +1,20 @@ +from _curses import _CursesWindow + +class _Curses_Panel: # type is (note the space in the class name) + def above(self) -> _Curses_Panel: ... + def below(self) -> _Curses_Panel: ... + def bottom(self) -> None: ... + def hidden(self) -> bool: ... + def hide(self) -> None: ... + def move(self, y: int, x: int) -> None: ... + def replace(self, win: _CursesWindow) -> None: ... + def set_userptr(self, obj: object) -> None: ... + def show(self) -> None: ... + def top(self) -> None: ... + def userptr(self) -> object: ... + def window(self) -> _CursesWindow: ... + +def bottom_panel() -> _Curses_Panel: ... +def new_panel(__win: _CursesWindow) -> _Curses_Panel: ... +def top_panel() -> _Curses_Panel: ... +def update_panels() -> _Curses_Panel: ... diff --git a/mypy/typeshed/stdlib/@python2/curses/textpad.pyi b/mypy/typeshed/stdlib/@python2/curses/textpad.pyi new file mode 100644 index 000000000000..578a579fda38 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/curses/textpad.pyi @@ -0,0 +1,11 @@ +from _curses import _CursesWindow +from typing import Callable + +def rectangle(win: _CursesWindow, uly: int, ulx: int, lry: int, lrx: int) -> None: ... + +class Textbox: + stripspaces: bool + def __init__(self, win: _CursesWindow, insert_mode: bool = ...) -> None: ... + def edit(self, validate: Callable[[int], int] | None = ...) -> str: ... + def do_command(self, ch: str | int) -> None: ... + def gather(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/datetime.pyi b/mypy/typeshed/stdlib/@python2/datetime.pyi new file mode 100644 index 000000000000..8b19a3d316f2 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/datetime.pyi @@ -0,0 +1,226 @@ +from time import struct_time +from typing import AnyStr, ClassVar, SupportsAbs, Tuple, Type, TypeVar, Union, overload + +_S = TypeVar("_S") + +_Text = Union[str, unicode] + +MINYEAR: int +MAXYEAR: int + +class tzinfo: + def tzname(self, dt: datetime | None) -> str | None: ... + def utcoffset(self, dt: datetime | None) -> timedelta | None: ... + def dst(self, dt: datetime | None) -> timedelta | None: ... + def fromutc(self, dt: datetime) -> datetime: ... + +_tzinfo = tzinfo + +class date: + min: ClassVar[date] + max: ClassVar[date] + resolution: ClassVar[timedelta] + def __new__(cls: Type[_S], year: int, month: int, day: int) -> _S: ... + @classmethod + def fromtimestamp(cls: Type[_S], __timestamp: float) -> _S: ... + @classmethod + def today(cls: Type[_S]) -> _S: ... + @classmethod + def fromordinal(cls: Type[_S], n: int) -> _S: ... + @property + def year(self) -> int: ... + @property + def month(self) -> int: ... + @property + def day(self) -> int: ... + def ctime(self) -> str: ... + def strftime(self, fmt: _Text) -> str: ... + def __format__(self, fmt: AnyStr) -> AnyStr: ... + def isoformat(self) -> str: ... + def timetuple(self) -> struct_time: ... + def toordinal(self) -> int: ... + def replace(self, year: int = ..., month: int = ..., day: int = ...) -> date: ... + def __le__(self, other: date) -> bool: ... + def __lt__(self, other: date) -> bool: ... + def __ge__(self, other: date) -> bool: ... + def __gt__(self, other: date) -> bool: ... + def __add__(self, other: timedelta) -> date: ... + def __radd__(self, other: timedelta) -> date: ... + @overload + def __sub__(self, other: timedelta) -> date: ... + @overload + def __sub__(self, other: date) -> timedelta: ... + def __hash__(self) -> int: ... + def weekday(self) -> int: ... + def isoweekday(self) -> int: ... + def isocalendar(self) -> Tuple[int, int, int]: ... + +class time: + min: ClassVar[time] + max: ClassVar[time] + resolution: ClassVar[timedelta] + def __new__( + cls: Type[_S], hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: _tzinfo | None = ... + ) -> _S: ... + @property + def hour(self) -> int: ... + @property + def minute(self) -> int: ... + @property + def second(self) -> int: ... + @property + def microsecond(self) -> int: ... + @property + def tzinfo(self) -> _tzinfo | None: ... + def __le__(self, other: time) -> bool: ... + def __lt__(self, other: time) -> bool: ... + def __ge__(self, other: time) -> bool: ... + def __gt__(self, other: time) -> bool: ... + def __hash__(self) -> int: ... + def isoformat(self) -> str: ... + def strftime(self, fmt: _Text) -> str: ... + def __format__(self, fmt: AnyStr) -> AnyStr: ... + def utcoffset(self) -> timedelta | None: ... + def tzname(self) -> str | None: ... + def dst(self) -> timedelta | None: ... + def replace( + self, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: _tzinfo | None = ... + ) -> time: ... + +_date = date +_time = time + +class timedelta(SupportsAbs[timedelta]): + min: ClassVar[timedelta] + max: ClassVar[timedelta] + resolution: ClassVar[timedelta] + def __new__( + cls: Type[_S], + days: float = ..., + seconds: float = ..., + microseconds: float = ..., + milliseconds: float = ..., + minutes: float = ..., + hours: float = ..., + weeks: float = ..., + ) -> _S: ... + @property + def days(self) -> int: ... + @property + def seconds(self) -> int: ... + @property + def microseconds(self) -> int: ... + def total_seconds(self) -> float: ... + def __add__(self, other: timedelta) -> timedelta: ... + def __radd__(self, other: timedelta) -> timedelta: ... + def __sub__(self, other: timedelta) -> timedelta: ... + def __rsub__(self, other: timedelta) -> timedelta: ... + def __neg__(self) -> timedelta: ... + def __pos__(self) -> timedelta: ... + def __abs__(self) -> timedelta: ... + def __mul__(self, other: float) -> timedelta: ... + def __rmul__(self, other: float) -> timedelta: ... + @overload + def __floordiv__(self, other: timedelta) -> int: ... + @overload + def __floordiv__(self, other: int) -> timedelta: ... + @overload + def __div__(self, other: timedelta) -> float: ... + @overload + def __div__(self, other: float) -> timedelta: ... + def __le__(self, other: timedelta) -> bool: ... + def __lt__(self, other: timedelta) -> bool: ... + def __ge__(self, other: timedelta) -> bool: ... + def __gt__(self, other: timedelta) -> bool: ... + def __hash__(self) -> int: ... + +class datetime(date): + min: ClassVar[datetime] + max: ClassVar[datetime] + resolution: ClassVar[timedelta] + def __new__( + cls: Type[_S], + year: int, + month: int, + day: int, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + ) -> _S: ... + @property + def year(self) -> int: ... + @property + def month(self) -> int: ... + @property + def day(self) -> int: ... + @property + def hour(self) -> int: ... + @property + def minute(self) -> int: ... + @property + def second(self) -> int: ... + @property + def microsecond(self) -> int: ... + @property + def tzinfo(self) -> _tzinfo | None: ... + @classmethod + def fromtimestamp(cls: Type[_S], t: float, tz: _tzinfo | None = ...) -> _S: ... + @classmethod + def utcfromtimestamp(cls: Type[_S], t: float) -> _S: ... + @classmethod + def today(cls: Type[_S]) -> _S: ... + @classmethod + def fromordinal(cls: Type[_S], n: int) -> _S: ... + @overload + @classmethod + def now(cls: Type[_S], tz: None = ...) -> _S: ... + @overload + @classmethod + def now(cls, tz: _tzinfo) -> datetime: ... + @classmethod + def utcnow(cls: Type[_S]) -> _S: ... + @classmethod + def combine(cls, date: _date, time: _time) -> datetime: ... + def strftime(self, fmt: _Text) -> str: ... + def __format__(self, fmt: AnyStr) -> AnyStr: ... + def toordinal(self) -> int: ... + def timetuple(self) -> struct_time: ... + def utctimetuple(self) -> struct_time: ... + def date(self) -> _date: ... + def time(self) -> _time: ... + def timetz(self) -> _time: ... + def replace( + self, + year: int = ..., + month: int = ..., + day: int = ..., + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + ) -> datetime: ... + def astimezone(self, tz: _tzinfo) -> datetime: ... + def ctime(self) -> str: ... + def isoformat(self, sep: str = ...) -> str: ... + @classmethod + def strptime(cls, date_string: _Text, format: _Text) -> datetime: ... + def utcoffset(self) -> timedelta | None: ... + def tzname(self) -> str | None: ... + def dst(self) -> timedelta | None: ... + def __le__(self, other: datetime) -> bool: ... # type: ignore + def __lt__(self, other: datetime) -> bool: ... # type: ignore + def __ge__(self, other: datetime) -> bool: ... # type: ignore + def __gt__(self, other: datetime) -> bool: ... # type: ignore + def __add__(self, other: timedelta) -> datetime: ... + def __radd__(self, other: timedelta) -> datetime: ... + @overload # type: ignore + def __sub__(self, other: datetime) -> timedelta: ... + @overload + def __sub__(self, other: timedelta) -> datetime: ... + def __hash__(self) -> int: ... + def weekday(self) -> int: ... + def isoweekday(self) -> int: ... + def isocalendar(self) -> Tuple[int, int, int]: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi b/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi new file mode 100644 index 000000000000..95f6d9cf0363 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi @@ -0,0 +1,26 @@ +from types import TracebackType +from typing import Iterator, MutableMapping, Tuple, Type, Union +from typing_extensions import Literal + +_KeyType = Union[str, bytes] +_ValueType = Union[str, bytes] + +class _Database(MutableMapping[_KeyType, bytes]): + def close(self) -> None: ... + def __getitem__(self, key: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __iter__(self) -> Iterator[bytes]: ... + def __len__(self) -> int: ... + def __del__(self) -> None: ... + def __enter__(self) -> _Database: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + +class _error(Exception): ... + +error = Tuple[Type[_error], Type[OSError]] + +def whichdb(filename: str) -> str: ... +def open(file: str, flag: Literal["r", "w", "c", "n"] = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi b/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi new file mode 100644 index 000000000000..fb5e2da5fa2c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi @@ -0,0 +1,25 @@ +from types import TracebackType +from typing import Iterator, MutableMapping, Type, Union + +_KeyType = Union[str, bytes] +_ValueType = Union[str, bytes] + +error = OSError + +class _Database(MutableMapping[_KeyType, bytes]): + def __init__(self, filebasename: str, mode: str, flag: str = ...) -> None: ... + def sync(self) -> None: ... + def iterkeys(self) -> Iterator[bytes]: ... # undocumented + def close(self) -> None: ... + def __getitem__(self, key: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __iter__(self) -> Iterator[bytes]: ... + def __len__(self) -> int: ... + def __del__(self) -> None: ... + def __enter__(self) -> _Database: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + +def open(file: str, flag: str = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi b/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi new file mode 100644 index 000000000000..0e9339bf81f9 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi @@ -0,0 +1,35 @@ +from types import TracebackType +from typing import List, Type, TypeVar, Union, overload + +_T = TypeVar("_T") +_KeyType = Union[str, bytes] +_ValueType = Union[str, bytes] + +class error(OSError): ... + +# Actual typename gdbm, not exposed by the implementation +class _gdbm: + def firstkey(self) -> bytes | None: ... + def nextkey(self, key: _KeyType) -> bytes | None: ... + def reorganize(self) -> None: ... + def sync(self) -> None: ... + def close(self) -> None: ... + def __getitem__(self, item: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __len__(self) -> int: ... + def __enter__(self) -> _gdbm: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + @overload + def get(self, k: _KeyType) -> bytes | None: ... + @overload + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> List[bytes]: ... + def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + +def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _gdbm: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi b/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi new file mode 100644 index 000000000000..28f4dd8e4e59 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi @@ -0,0 +1,34 @@ +from types import TracebackType +from typing import List, Type, TypeVar, Union, overload + +_T = TypeVar("_T") +_KeyType = Union[str, bytes] +_ValueType = Union[str, bytes] + +class error(OSError): ... + +library: str = ... + +# Actual typename dbm, not exposed by the implementation +class _dbm: + def close(self) -> None: ... + def __getitem__(self, item: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __len__(self) -> int: ... + def __del__(self) -> None: ... + def __enter__(self) -> _dbm: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + @overload + def get(self, k: _KeyType) -> bytes | None: ... + @overload + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> List[bytes]: ... + def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... + # Don't exist at runtime + __new__: None # type: ignore + __init__: None # type: ignore + +def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _dbm: ... diff --git a/mypy/typeshed/stdlib/@python2/decimal.pyi b/mypy/typeshed/stdlib/@python2/decimal.pyi new file mode 100644 index 000000000000..915bddadb584 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/decimal.pyi @@ -0,0 +1,246 @@ +from types import TracebackType +from typing import Any, Container, Dict, List, NamedTuple, Sequence, Text, Tuple, Type, TypeVar, Union + +_Decimal = Union[Decimal, int] +_DecimalNew = Union[Decimal, float, Text, Tuple[int, Sequence[int], int]] +_ComparableNum = Union[Decimal, float] +_DecimalT = TypeVar("_DecimalT", bound=Decimal) + +class DecimalTuple(NamedTuple): + sign: int + digits: Tuple[int, ...] + exponent: int + +ROUND_DOWN: str +ROUND_HALF_UP: str +ROUND_HALF_EVEN: str +ROUND_CEILING: str +ROUND_FLOOR: str +ROUND_UP: str +ROUND_HALF_DOWN: str +ROUND_05UP: str + +class DecimalException(ArithmeticError): + def handle(self, context: Context, *args: Any) -> Decimal | None: ... + +class Clamped(DecimalException): ... +class InvalidOperation(DecimalException): ... +class ConversionSyntax(InvalidOperation): ... +class DivisionByZero(DecimalException, ZeroDivisionError): ... +class DivisionImpossible(InvalidOperation): ... +class DivisionUndefined(InvalidOperation, ZeroDivisionError): ... +class Inexact(DecimalException): ... +class InvalidContext(InvalidOperation): ... +class Rounded(DecimalException): ... +class Subnormal(DecimalException): ... +class Overflow(Inexact, Rounded): ... +class Underflow(Inexact, Rounded, Subnormal): ... + +def setcontext(__context: Context) -> None: ... +def getcontext() -> Context: ... +def localcontext(ctx: Context | None = ...) -> _ContextManager: ... + +class Decimal(object): + def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Context | None = ...) -> _DecimalT: ... + @classmethod + def from_float(cls, __f: float) -> Decimal: ... + def __nonzero__(self) -> bool: ... + def __div__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rdiv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __ne__(self, other: object, context: Context | None = ...) -> bool: ... + def compare(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __hash__(self) -> int: ... + def as_tuple(self) -> DecimalTuple: ... + def to_eng_string(self, context: Context | None = ...) -> str: ... + def __abs__(self, round: bool = ..., context: Context | None = ...) -> Decimal: ... + def __add__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __divmod__(self, other: _Decimal, context: Context | None = ...) -> Tuple[Decimal, Decimal]: ... + def __eq__(self, other: object, context: Context | None = ...) -> bool: ... + def __floordiv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __ge__(self, other: _ComparableNum, context: Context | None = ...) -> bool: ... + def __gt__(self, other: _ComparableNum, context: Context | None = ...) -> bool: ... + def __le__(self, other: _ComparableNum, context: Context | None = ...) -> bool: ... + def __lt__(self, other: _ComparableNum, context: Context | None = ...) -> bool: ... + def __mod__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __mul__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __neg__(self, context: Context | None = ...) -> Decimal: ... + def __pos__(self, context: Context | None = ...) -> Decimal: ... + def __pow__(self, other: _Decimal, modulo: _Decimal | None = ..., context: Context | None = ...) -> Decimal: ... + def __radd__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rdivmod__(self, other: _Decimal, context: Context | None = ...) -> Tuple[Decimal, Decimal]: ... + def __rfloordiv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rmod__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rmul__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rsub__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rtruediv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __str__(self, eng: bool = ..., context: Context | None = ...) -> str: ... + def __sub__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __truediv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def remainder_near(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __float__(self) -> float: ... + def __int__(self) -> int: ... + def __trunc__(self) -> int: ... + @property + def real(self) -> Decimal: ... + @property + def imag(self) -> Decimal: ... + def conjugate(self) -> Decimal: ... + def __complex__(self) -> complex: ... + def __long__(self) -> long: ... + def fma(self, other: _Decimal, third: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rpow__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def normalize(self, context: Context | None = ...) -> Decimal: ... + def quantize( + self, exp: _Decimal, rounding: str | None = ..., context: Context | None = ..., watchexp: bool = ... + ) -> Decimal: ... + def same_quantum(self, other: _Decimal) -> bool: ... + def to_integral_exact(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral_value(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def sqrt(self, context: Context | None = ...) -> Decimal: ... + def max(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def adjusted(self) -> int: ... + def canonical(self, context: Context | None = ...) -> Decimal: ... + def compare_signal(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def compare_total(self, other: _Decimal) -> Decimal: ... + def compare_total_mag(self, other: _Decimal) -> Decimal: ... + def copy_abs(self) -> Decimal: ... + def copy_negate(self) -> Decimal: ... + def copy_sign(self, other: _Decimal) -> Decimal: ... + def exp(self, context: Context | None = ...) -> Decimal: ... + def is_canonical(self) -> bool: ... + def is_finite(self) -> bool: ... + def is_infinite(self) -> bool: ... + def is_nan(self) -> bool: ... + def is_normal(self, context: Context | None = ...) -> bool: ... + def is_qnan(self) -> bool: ... + def is_signed(self) -> bool: ... + def is_snan(self) -> bool: ... + def is_subnormal(self, context: Context | None = ...) -> bool: ... + def is_zero(self) -> bool: ... + def ln(self, context: Context | None = ...) -> Decimal: ... + def log10(self, context: Context | None = ...) -> Decimal: ... + def logb(self, context: Context | None = ...) -> Decimal: ... + def logical_and(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_invert(self, context: Context | None = ...) -> Decimal: ... + def logical_or(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_xor(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def max_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def next_minus(self, context: Context | None = ...) -> Decimal: ... + def next_plus(self, context: Context | None = ...) -> Decimal: ... + def next_toward(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def number_class(self, context: Context | None = ...) -> str: ... + def radix(self) -> Decimal: ... + def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __reduce__(self) -> Tuple[Type[Decimal], Tuple[str]]: ... + def __copy__(self) -> Decimal: ... + def __deepcopy__(self, memo: Any) -> Decimal: ... + def __format__(self, specifier: str, context: Context | None = ...) -> str: ... + +class _ContextManager(object): + new_context: Context + saved_context: Context + def __init__(self, new_context: Context) -> None: ... + def __enter__(self) -> Context: ... + def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + +_TrapType = Type[DecimalException] + +class Context(object): + prec: int + rounding: str + Emin: int + Emax: int + capitals: int + _clamp: int + traps: Dict[_TrapType, bool] + flags: Dict[_TrapType, bool] + def __init__( + self, + prec: int | None = ..., + rounding: str | None = ..., + traps: None | Dict[_TrapType, bool] | Container[_TrapType] = ..., + flags: None | Dict[_TrapType, bool] | Container[_TrapType] = ..., + Emin: int | None = ..., + Emax: int | None = ..., + capitals: int | None = ..., + _clamp: int | None = ..., + _ignored_flags: List[_TrapType] | None = ..., + ) -> None: ... + def clear_flags(self) -> None: ... + def copy(self) -> Context: ... + def __copy__(self) -> Context: ... + __hash__: Any = ... + def Etiny(self) -> int: ... + def Etop(self) -> int: ... + def create_decimal(self, __num: _DecimalNew = ...) -> Decimal: ... + def create_decimal_from_float(self, __f: float) -> Decimal: ... + def abs(self, __x: _Decimal) -> Decimal: ... + def add(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def canonical(self, __x: Decimal) -> Decimal: ... + def compare(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_signal(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_total(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_total_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def copy_abs(self, __x: _Decimal) -> Decimal: ... + def copy_decimal(self, __x: _Decimal) -> Decimal: ... + def copy_negate(self, __x: _Decimal) -> Decimal: ... + def copy_sign(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divide(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divide_int(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divmod(self, __x: _Decimal, __y: _Decimal) -> Tuple[Decimal, Decimal]: ... + def exp(self, __x: _Decimal) -> Decimal: ... + def fma(self, __x: _Decimal, __y: _Decimal, __z: _Decimal) -> Decimal: ... + def is_canonical(self, __x: _Decimal) -> bool: ... + def is_finite(self, __x: _Decimal) -> bool: ... + def is_infinite(self, __x: _Decimal) -> bool: ... + def is_nan(self, __x: _Decimal) -> bool: ... + def is_normal(self, __x: _Decimal) -> bool: ... + def is_qnan(self, __x: _Decimal) -> bool: ... + def is_signed(self, __x: _Decimal) -> bool: ... + def is_snan(self, __x: _Decimal) -> bool: ... + def is_subnormal(self, __x: _Decimal) -> bool: ... + def is_zero(self, __x: _Decimal) -> bool: ... + def ln(self, __x: _Decimal) -> Decimal: ... + def log10(self, __x: _Decimal) -> Decimal: ... + def logb(self, __x: _Decimal) -> Decimal: ... + def logical_and(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def logical_invert(self, __x: _Decimal) -> Decimal: ... + def logical_or(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def logical_xor(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def max(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def max_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def min(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def min_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def minus(self, __x: _Decimal) -> Decimal: ... + def multiply(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def next_minus(self, __x: _Decimal) -> Decimal: ... + def next_plus(self, __x: _Decimal) -> Decimal: ... + def next_toward(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def normalize(self, __x: _Decimal) -> Decimal: ... + def number_class(self, __x: _Decimal) -> str: ... + def plus(self, __x: _Decimal) -> Decimal: ... + def power(self, a: _Decimal, b: _Decimal, modulo: _Decimal | None = ...) -> Decimal: ... + def quantize(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def radix(self) -> Decimal: ... + def remainder(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def remainder_near(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def rotate(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def same_quantum(self, __x: _Decimal, __y: _Decimal) -> bool: ... + def scaleb(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def shift(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def sqrt(self, __x: _Decimal) -> Decimal: ... + def subtract(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def to_eng_string(self, __x: _Decimal) -> str: ... + def to_sci_string(self, __x: _Decimal) -> str: ... + def to_integral_exact(self, __x: _Decimal) -> Decimal: ... + def to_integral_value(self, __x: _Decimal) -> Decimal: ... + def to_integral(self, __x: _Decimal) -> Decimal: ... + +DefaultContext: Context +BasicContext: Context +ExtendedContext: Context diff --git a/mypy/typeshed/stdlib/@python2/difflib.pyi b/mypy/typeshed/stdlib/@python2/difflib.pyi new file mode 100644 index 000000000000..41ffc6a286d1 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/difflib.pyi @@ -0,0 +1,112 @@ +from typing import ( + Any, + AnyStr, + Callable, + Generic, + Iterable, + Iterator, + List, + NamedTuple, + Sequence, + Text, + Tuple, + TypeVar, + Union, + overload, +) + +_T = TypeVar("_T") + +# Aliases can't point to type vars, so we need to redeclare AnyStr +_StrType = TypeVar("_StrType", Text, bytes) + +_JunkCallback = Union[Callable[[Text], bool], Callable[[str], bool]] + +class Match(NamedTuple): + a: int + b: int + size: int + +class SequenceMatcher(Generic[_T]): + def __init__( + self, isjunk: Callable[[_T], bool] | None = ..., a: Sequence[_T] = ..., b: Sequence[_T] = ..., autojunk: bool = ... + ) -> None: ... + def set_seqs(self, a: Sequence[_T], b: Sequence[_T]) -> None: ... + def set_seq1(self, a: Sequence[_T]) -> None: ... + def set_seq2(self, b: Sequence[_T]) -> None: ... + def find_longest_match(self, alo: int, ahi: int, blo: int, bhi: int) -> Match: ... + def get_matching_blocks(self) -> List[Match]: ... + def get_opcodes(self) -> List[Tuple[str, int, int, int, int]]: ... + def get_grouped_opcodes(self, n: int = ...) -> Iterable[List[Tuple[str, int, int, int, int]]]: ... + def ratio(self) -> float: ... + def quick_ratio(self) -> float: ... + def real_quick_ratio(self) -> float: ... + +# mypy thinks the signatures of the overloads overlap, but the types still work fine +@overload +def get_close_matches( # type: ignore + word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ... +) -> List[AnyStr]: ... +@overload +def get_close_matches( + word: Sequence[_T], possibilities: Iterable[Sequence[_T]], n: int = ..., cutoff: float = ... +) -> List[Sequence[_T]]: ... + +class Differ: + def __init__(self, linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ...) -> None: ... + def compare(self, a: Sequence[_StrType], b: Sequence[_StrType]) -> Iterator[_StrType]: ... + +def IS_LINE_JUNK(line: _StrType, pat: Any = ...) -> bool: ... # pat is undocumented +def IS_CHARACTER_JUNK(ch: _StrType, ws: _StrType = ...) -> bool: ... # ws is undocumented +def unified_diff( + a: Sequence[_StrType], + b: Sequence[_StrType], + fromfile: _StrType = ..., + tofile: _StrType = ..., + fromfiledate: _StrType = ..., + tofiledate: _StrType = ..., + n: int = ..., + lineterm: _StrType = ..., +) -> Iterator[_StrType]: ... +def context_diff( + a: Sequence[_StrType], + b: Sequence[_StrType], + fromfile: _StrType = ..., + tofile: _StrType = ..., + fromfiledate: _StrType = ..., + tofiledate: _StrType = ..., + n: int = ..., + lineterm: _StrType = ..., +) -> Iterator[_StrType]: ... +def ndiff( + a: Sequence[_StrType], b: Sequence[_StrType], linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ... +) -> Iterator[_StrType]: ... + +class HtmlDiff(object): + def __init__( + self, + tabsize: int = ..., + wrapcolumn: int | None = ..., + linejunk: _JunkCallback | None = ..., + charjunk: _JunkCallback | None = ..., + ) -> None: ... + def make_file( + self, + fromlines: Sequence[_StrType], + tolines: Sequence[_StrType], + fromdesc: _StrType = ..., + todesc: _StrType = ..., + context: bool = ..., + numlines: int = ..., + ) -> _StrType: ... + def make_table( + self, + fromlines: Sequence[_StrType], + tolines: Sequence[_StrType], + fromdesc: _StrType = ..., + todesc: _StrType = ..., + context: bool = ..., + numlines: int = ..., + ) -> _StrType: ... + +def restore(delta: Iterable[_StrType], which: int) -> Iterator[_StrType]: ... diff --git a/mypy/typeshed/stdlib/@python2/dircache.pyi b/mypy/typeshed/stdlib/@python2/dircache.pyi index fd906f6f2ae1..366909d87133 100644 --- a/mypy/typeshed/stdlib/@python2/dircache.pyi +++ b/mypy/typeshed/stdlib/@python2/dircache.pyi @@ -1,8 +1,8 @@ -from typing import List, MutableSequence, Text, Union +from typing import List, MutableSequence, Text def reset() -> None: ... def listdir(path: Text) -> List[str]: ... opendir = listdir -def annotate(head: Text, list: Union[MutableSequence[str], MutableSequence[Text], MutableSequence[Union[str, Text]]]) -> None: ... +def annotate(head: Text, list: MutableSequence[str] | MutableSequence[Text] | MutableSequence[str | Text]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/dis.pyi b/mypy/typeshed/stdlib/@python2/dis.pyi new file mode 100644 index 000000000000..1d6537667a60 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dis.pyi @@ -0,0 +1,30 @@ +import types +from opcode import ( + EXTENDED_ARG as EXTENDED_ARG, + HAVE_ARGUMENT as HAVE_ARGUMENT, + cmp_op as cmp_op, + hascompare as hascompare, + hasconst as hasconst, + hasfree as hasfree, + hasjabs as hasjabs, + hasjrel as hasjrel, + haslocal as haslocal, + hasname as hasname, + opmap as opmap, + opname as opname, +) +from typing import Any, Callable, Dict, Iterator, List, Tuple, Union + +# Strictly this should not have to include Callable, but mypy doesn't use FunctionType +# for functions (python/mypy#3171) +_have_code = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] +_have_code_or_string = Union[_have_code, str, bytes] + +COMPILER_FLAG_NAMES: Dict[int, str] + +def findlabels(code: _have_code) -> List[int]: ... +def findlinestarts(code: _have_code) -> Iterator[Tuple[int, int]]: ... +def dis(x: _have_code_or_string = ...) -> None: ... +def distb(tb: types.TracebackType = ...) -> None: ... +def disassemble(co: _have_code, lasti: int = ...) -> None: ... +def disco(co: _have_code, lasti: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/archive_util.pyi b/mypy/typeshed/stdlib/@python2/distutils/archive_util.pyi index 0e94d3818ae4..dd2cbda73fc6 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/archive_util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/archive_util.pyi @@ -1,12 +1,5 @@ -from typing import Optional - def make_archive( - base_name: str, - format: str, - root_dir: Optional[str] = ..., - base_dir: Optional[str] = ..., - verbose: int = ..., - dry_run: int = ..., + base_name: str, format: str, root_dir: str | None = ..., base_dir: str | None = ..., verbose: int = ..., dry_run: int = ... ) -> str: ... -def make_tarball(base_name: str, base_dir: str, compress: Optional[str] = ..., verbose: int = ..., dry_run: int = ...) -> str: ... +def make_tarball(base_name: str, base_dir: str, compress: str | None = ..., verbose: int = ..., dry_run: int = ...) -> str: ... def make_zipfile(base_name: str, base_dir: str, verbose: int = ..., dry_run: int = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi index 831311d2cb52..b0539bf9e5dc 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi @@ -6,9 +6,9 @@ def gen_lib_options( compiler: CCompiler, library_dirs: List[str], runtime_library_dirs: List[str], libraries: List[str] ) -> List[str]: ... def gen_preprocess_options(macros: List[_Macro], include_dirs: List[str]) -> List[str]: ... -def get_default_compiler(osname: Optional[str] = ..., platform: Optional[str] = ...) -> str: ... +def get_default_compiler(osname: str | None = ..., platform: str | None = ...) -> str: ... def new_compiler( - plat: Optional[str] = ..., compiler: Optional[str] = ..., verbose: int = ..., dry_run: int = ..., force: int = ... + plat: str | None = ..., compiler: str | None = ..., verbose: int = ..., dry_run: int = ..., force: int = ... ) -> CCompiler: ... def show_compilers() -> None: ... @@ -16,7 +16,7 @@ class CCompiler: dry_run: bool force: bool verbose: bool - output_dir: Optional[str] + output_dir: str | None macros: List[_Macro] include_dirs: List[str] libraries: List[str] @@ -32,19 +32,19 @@ class CCompiler: def set_library_dirs(self, dirs: List[str]) -> None: ... def add_runtime_library_dir(self, dir: str) -> None: ... def set_runtime_library_dirs(self, dirs: List[str]) -> None: ... - def define_macro(self, name: str, value: Optional[str] = ...) -> None: ... + def define_macro(self, name: str, value: str | None = ...) -> None: ... def undefine_macro(self, name: str) -> None: ... def add_link_object(self, object: str) -> None: ... def set_link_objects(self, objects: List[str]) -> None: ... - def detect_language(self, sources: Union[str, List[str]]) -> Optional[str]: ... - def find_library_file(self, dirs: List[str], lib: str, debug: bool = ...) -> Optional[str]: ... + def detect_language(self, sources: str | List[str]) -> str | None: ... + def find_library_file(self, dirs: List[str], lib: str, debug: bool = ...) -> str | None: ... def has_function( self, funcname: str, - includes: Optional[List[str]] = ..., - include_dirs: Optional[List[str]] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., + includes: List[str] | None = ..., + include_dirs: List[str] | None = ..., + libraries: List[str] | None = ..., + library_dirs: List[str] | None = ..., ) -> bool: ... def library_dir_option(self, dir: str) -> str: ... def library_option(self, lib: str) -> str: ... @@ -53,95 +53,95 @@ class CCompiler: def compile( self, sources: List[str], - output_dir: Optional[str] = ..., - macros: Optional[_Macro] = ..., - include_dirs: Optional[List[str]] = ..., + output_dir: str | None = ..., + macros: _Macro | None = ..., + include_dirs: List[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - depends: Optional[List[str]] = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., + depends: List[str] | None = ..., ) -> List[str]: ... def create_static_lib( self, objects: List[str], output_libname: str, - output_dir: Optional[str] = ..., + output_dir: str | None = ..., debug: bool = ..., - target_lang: Optional[str] = ..., + target_lang: str | None = ..., ) -> None: ... def link( self, target_desc: str, objects: List[str], output_filename: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: List[str] | None = ..., + library_dirs: List[str] | None = ..., + runtime_library_dirs: List[str] | None = ..., + export_symbols: List[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_executable( self, objects: List[str], output_progname: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: List[str] | None = ..., + library_dirs: List[str] | None = ..., + runtime_library_dirs: List[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - target_lang: Optional[str] = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_shared_lib( self, objects: List[str], output_libname: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: List[str] | None = ..., + library_dirs: List[str] | None = ..., + runtime_library_dirs: List[str] | None = ..., + export_symbols: List[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_shared_object( self, objects: List[str], output_filename: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: List[str] | None = ..., + library_dirs: List[str] | None = ..., + runtime_library_dirs: List[str] | None = ..., + export_symbols: List[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def preprocess( self, source: str, - output_file: Optional[str] = ..., - macros: Optional[List[_Macro]] = ..., - include_dirs: Optional[List[str]] = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., + output_file: str | None = ..., + macros: List[_Macro] | None = ..., + include_dirs: List[str] | None = ..., + extra_preargs: List[str] | None = ..., + extra_postargs: List[str] | None = ..., ) -> None: ... def executable_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... def library_filename(self, libname: str, lib_type: str = ..., strip_dir: int = ..., output_dir: str = ...) -> str: ... def object_filenames(self, source_filenames: List[str], strip_dir: int = ..., output_dir: str = ...) -> List[str]: ... def shared_object_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... - def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: Optional[str] = ..., level: int = ...) -> None: ... + def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... def spawn(self, cmd: List[str]) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def move_file(self, src: str, dst: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi b/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi index b888c189f932..d4e90bf69970 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi @@ -1,9 +1,9 @@ from abc import abstractmethod from distutils.dist import Distribution -from typing import Any, Callable, Iterable, List, Optional, Text, Tuple, Union +from typing import Any, Callable, Iterable, List, Text, Tuple class Command: - sub_commands: List[Tuple[str, Optional[Callable[[Command], bool]]]] + sub_commands: List[Tuple[str, Callable[[Command], bool] | None]] def __init__(self, dist: Distribution) -> None: ... @abstractmethod def initialize_options(self) -> None: ... @@ -13,18 +13,18 @@ class Command: def run(self) -> None: ... def announce(self, msg: Text, level: int = ...) -> None: ... def debug_print(self, msg: Text) -> None: ... - def ensure_string(self, option: str, default: Optional[str] = ...) -> None: ... - def ensure_string_list(self, option: Union[str, List[str]]) -> None: ... + def ensure_string(self, option: str, default: str | None = ...) -> None: ... + def ensure_string_list(self, option: str | List[str]) -> None: ... def ensure_filename(self, option: str) -> None: ... def ensure_dirname(self, option: str) -> None: ... def get_command_name(self) -> str: ... def set_undefined_options(self, src_cmd: Text, *option_pairs: Tuple[str, str]) -> None: ... def get_finalized_command(self, command: Text, create: int = ...) -> Command: ... - def reinitialize_command(self, command: Union[Command, Text], reinit_subcommands: int = ...) -> Command: ... + def reinitialize_command(self, command: Command | Text, reinit_subcommands: int = ...) -> Command: ... def run_command(self, command: Text) -> None: ... def get_sub_commands(self) -> List[str]: ... def warn(self, msg: Text) -> None: ... - def execute(self, func: Callable[..., Any], args: Iterable[Any], msg: Optional[Text] = ..., level: int = ...) -> None: ... + def execute(self, func: Callable[..., Any], args: Iterable[Any], msg: Text | None = ..., level: int = ...) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def copy_file( self, @@ -32,7 +32,7 @@ class Command: outfile: str, preserve_mode: int = ..., preserve_times: int = ..., - link: Optional[str] = ..., + link: str | None = ..., level: Any = ..., ) -> Tuple[str, bool]: ... # level is not used def copy_tree( @@ -50,18 +50,18 @@ class Command: self, base_name: str, format: str, - root_dir: Optional[str] = ..., - base_dir: Optional[str] = ..., - owner: Optional[str] = ..., - group: Optional[str] = ..., + root_dir: str | None = ..., + base_dir: str | None = ..., + owner: str | None = ..., + group: str | None = ..., ) -> str: ... def make_file( self, - infiles: Union[str, List[str], Tuple[str]], + infiles: str | List[str] | Tuple[str], outfile: str, func: Callable[..., Any], args: List[Any], - exec_msg: Optional[str] = ..., - skip_msg: Optional[str] = ..., + exec_msg: str | None = ..., + skip_msg: str | None = ..., level: Any = ..., ) -> None: ... # level is not used diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi index 6b57a64b48b1..d0fd762e83b2 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi @@ -3,19 +3,19 @@ from distutils.ccompiler import CCompiler from distutils.core import Command as Command from distutils.errors import DistutilsExecError as DistutilsExecError from distutils.sysconfig import customize_compiler as customize_compiler -from typing import Dict, List, Optional, Pattern, Sequence, Tuple, Union +from typing import Dict, List, Pattern, Sequence, Tuple LANG_EXT: Dict[str, str] class config(Command): description: str = ... # Tuple is full name, short name, description - user_options: Sequence[Tuple[str, Optional[str], str]] = ... - compiler: Optional[Union[str, CCompiler]] = ... - cc: Optional[str] = ... - include_dirs: Optional[Sequence[str]] = ... - libraries: Optional[Sequence[str]] = ... - library_dirs: Optional[Sequence[str]] = ... + user_options: Sequence[Tuple[str, str | None, str]] = ... + compiler: str | CCompiler | None = ... + cc: str | None = ... + include_dirs: Sequence[str] | None = ... + libraries: Sequence[str] | None = ... + library_dirs: Sequence[str] | None = ... noisy: int = ... dump_source: int = ... temp_files: Sequence[str] = ... @@ -24,64 +24,60 @@ class config(Command): def run(self) -> None: ... def try_cpp( self, - body: Optional[str] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., + body: str | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def search_cpp( self, - pattern: Union[Pattern[str], str], - body: Optional[str] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., + pattern: Pattern[str] | str, + body: str | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def try_compile( - self, body: str, headers: Optional[Sequence[str]] = ..., include_dirs: Optional[Sequence[str]] = ..., lang: str = ... + self, body: str, headers: Sequence[str] | None = ..., include_dirs: Sequence[str] | None = ..., lang: str = ... ) -> bool: ... def try_link( self, body: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def try_run( self, body: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def check_func( self, func: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., decl: int = ..., call: int = ..., ) -> bool: ... def check_lib( self, library: str, - library_dirs: Optional[Sequence[str]] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., + library_dirs: Sequence[str] | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., other_libraries: List[str] = ..., ) -> bool: ... def check_header( - self, - header: str, - include_dirs: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., - lang: str = ..., + self, header: str, include_dirs: Sequence[str] | None = ..., library_dirs: Sequence[str] | None = ..., lang: str = ... ) -> bool: ... -def dump_file(filename: str, head: Optional[str] = ...) -> None: ... +def dump_file(filename: str, head: str | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/install.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/install.pyi index dc6d96b82a62..2824236735f0 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/install.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/install.pyi @@ -1,12 +1,12 @@ from distutils.cmd import Command -from typing import Optional, Text +from typing import Text class install(Command): user: bool - prefix: Optional[Text] - home: Optional[Text] - root: Optional[Text] - install_lib: Optional[Text] + prefix: Text | None + home: Text | None + root: Text | None + install_lib: Text | None def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi index 80ffb19bda74..bf3d0737f244 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi @@ -1,9 +1,9 @@ from distutils.cmd import Command -from typing import ClassVar, List, Optional, Tuple +from typing import ClassVar, List, Tuple class install_egg_info(Command): description: ClassVar[str] - user_options: ClassVar[List[Tuple[str, Optional[str], str]]] + user_options: ClassVar[List[Tuple[str, str | None, str]]] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi index c49a4e5b4937..3835d9fd6ec6 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi @@ -1,5 +1,5 @@ from distutils.config import PyPIRCCommand -from typing import ClassVar, List, Optional, Tuple +from typing import ClassVar, List, Tuple class upload(PyPIRCCommand): description: ClassVar[str] diff --git a/mypy/typeshed/stdlib/@python2/distutils/config.pyi b/mypy/typeshed/stdlib/@python2/distutils/config.pyi index e60507e0b65a..bcd626c81d48 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/config.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/config.pyi @@ -1,6 +1,6 @@ from abc import abstractmethod from distutils.cmd import Command -from typing import ClassVar, List, Optional, Tuple +from typing import ClassVar, List, Tuple DEFAULT_PYPIRC: str @@ -9,7 +9,7 @@ class PyPIRCCommand(Command): DEFAULT_REALM: ClassVar[str] repository: None realm: None - user_options: ClassVar[List[Tuple[str, Optional[str], str]]] + user_options: ClassVar[List[Tuple[str, str | None, str]]] boolean_options: ClassVar[List[str]] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/core.pyi b/mypy/typeshed/stdlib/@python2/distutils/core.pyi index 9a3fa70fd381..48bd7b5018bc 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/core.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/core.pyi @@ -1,7 +1,7 @@ from distutils.cmd import Command as Command from distutils.dist import Distribution as Distribution from distutils.extension import Extension as Extension -from typing import Any, List, Mapping, Optional, Tuple, Type, Union +from typing import Any, List, Mapping, Tuple, Type def setup( *, @@ -25,8 +25,8 @@ def setup( script_args: List[str] = ..., options: Mapping[str, Any] = ..., license: str = ..., - keywords: Union[List[str], str] = ..., - platforms: Union[List[str], str] = ..., + keywords: List[str] | str = ..., + platforms: List[str] | str = ..., cmdclass: Mapping[str, Type[Command]] = ..., data_files: List[Tuple[str, List[str]]] = ..., package_dir: Mapping[str, str] = ..., @@ -45,4 +45,4 @@ def setup( fullname: str = ..., **attrs: Any, ) -> None: ... -def run_setup(script_name: str, script_args: Optional[List[str]] = ..., stop_after: str = ...) -> Distribution: ... +def run_setup(script_name: str, script_args: List[str] | None = ..., stop_after: str = ...) -> Distribution: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/dist.pyi b/mypy/typeshed/stdlib/@python2/distutils/dist.pyi index 685423bda6da..adba8f093569 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/dist.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/dist.pyi @@ -1,9 +1,9 @@ from distutils.cmd import Command -from typing import Any, Dict, Iterable, Mapping, Optional, Text, Tuple, Type +from typing import Any, Dict, Iterable, Mapping, Text, Tuple, Type class Distribution: cmdclass: Dict[str, Type[Command]] - def __init__(self, attrs: Optional[Mapping[str, Any]] = ...) -> None: ... + def __init__(self, attrs: Mapping[str, Any] | None = ...) -> None: ... def get_option_dict(self, command: str) -> Dict[str, Tuple[str, Text]]: ... - def parse_config_files(self, filenames: Optional[Iterable[Text]] = ...) -> None: ... - def get_command_obj(self, command: str, create: bool = ...) -> Optional[Command]: ... + def parse_config_files(self, filenames: Iterable[Text] | None = ...) -> None: ... + def get_command_obj(self, command: str, create: bool = ...) -> Command | None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/extension.pyi b/mypy/typeshed/stdlib/@python2/distutils/extension.pyi index 02c1f55617b3..9335fad86418 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/extension.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/extension.pyi @@ -1,4 +1,4 @@ -from typing import List, Optional, Tuple +from typing import List, Tuple class Extension: def __init__( @@ -6,7 +6,7 @@ class Extension: name: str, sources: List[str], include_dirs: List[str] = ..., - define_macros: List[Tuple[str, Optional[str]]] = ..., + define_macros: List[Tuple[str, str | None]] = ..., undef_macros: List[str] = ..., library_dirs: List[str] = ..., libraries: List[str] = ..., @@ -15,7 +15,7 @@ class Extension: extra_compile_args: List[str] = ..., extra_link_args: List[str] = ..., export_symbols: List[str] = ..., - swig_opts: Optional[str] = ..., # undocumented + swig_opts: str | None = ..., # undocumented depends: List[str] = ..., language: str = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi index 8eb4c416fa28..d0e3309c2d77 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi @@ -1,21 +1,21 @@ -from typing import Any, List, Mapping, Optional, Tuple, Union, overload +from typing import Any, List, Mapping, Optional, Tuple, overload _Option = Tuple[str, Optional[str], str] _GR = Tuple[List[str], OptionDummy] def fancy_getopt( - options: List[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: Optional[List[str]] -) -> Union[List[str], _GR]: ... + options: List[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: List[str] | None +) -> List[str] | _GR: ... def wrap_text(text: str, width: int) -> List[str]: ... class FancyGetopt: - def __init__(self, option_table: Optional[List[_Option]] = ...) -> None: ... + def __init__(self, option_table: List[_Option] | None = ...) -> None: ... # TODO kinda wrong, `getopt(object=object())` is invalid @overload - def getopt(self, args: Optional[List[str]] = ...) -> _GR: ... + def getopt(self, args: List[str] | None = ...) -> _GR: ... @overload - def getopt(self, args: Optional[List[str]], object: Any) -> List[str]: ... + def getopt(self, args: List[str] | None, object: Any) -> List[str]: ... def get_option_order(self) -> List[Tuple[str, str]]: ... - def generate_help(self, header: Optional[str] = ...) -> List[str]: ... + def generate_help(self, header: str | None = ...) -> List[str]: ... class OptionDummy: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi b/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi index 018339733df0..cfe840e71040 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi @@ -1,4 +1,4 @@ -from typing import Optional, Sequence, Tuple +from typing import Sequence, Tuple def copy_file( src: str, @@ -6,7 +6,7 @@ def copy_file( preserve_mode: bool = ..., preserve_times: bool = ..., update: bool = ..., - link: Optional[str] = ..., + link: str | None = ..., verbose: bool = ..., dry_run: bool = ..., ) -> Tuple[str, str]: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi b/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi index e12eae99bf29..0fffc5402c62 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List def spawn(cmd: List[str], search_path: bool = ..., verbose: bool = ..., dry_run: bool = ...) -> None: ... -def find_executable(executable: str, path: Optional[str] = ...) -> Optional[str]: ... +def find_executable(executable: str, path: str | None = ...) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/sysconfig.pyi b/mypy/typeshed/stdlib/@python2/distutils/sysconfig.pyi index 9061db75ccf1..7d9fe7d34de3 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/sysconfig.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/sysconfig.pyi @@ -1,14 +1,14 @@ from distutils.ccompiler import CCompiler -from typing import Mapping, Optional, Union +from typing import Mapping PREFIX: str EXEC_PREFIX: str -def get_config_var(name: str) -> Union[int, str, None]: ... -def get_config_vars(*args: str) -> Mapping[str, Union[int, str]]: ... +def get_config_var(name: str) -> int | str | None: ... +def get_config_vars(*args: str) -> Mapping[str, int | str]: ... def get_config_h_filename() -> str: ... def get_makefile_filename() -> str: ... -def get_python_inc(plat_specific: bool = ..., prefix: Optional[str] = ...) -> str: ... -def get_python_lib(plat_specific: bool = ..., standard_lib: bool = ..., prefix: Optional[str] = ...) -> str: ... +def get_python_inc(plat_specific: bool = ..., prefix: str | None = ...) -> str: ... +def get_python_lib(plat_specific: bool = ..., standard_lib: bool = ..., prefix: str | None = ...) -> str: ... def customize_compiler(compiler: CCompiler) -> None: ... def set_python_build() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi b/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi index 9872a1f25751..26ba5a6fabb6 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi @@ -1,10 +1,10 @@ -from typing import IO, List, Optional, Tuple, Union +from typing import IO, List, Tuple class TextFile: def __init__( self, - filename: Optional[str] = ..., - file: Optional[IO[str]] = ..., + filename: str | None = ..., + file: IO[str] | None = ..., *, strip_comments: bool = ..., lstrip_ws: bool = ..., @@ -15,7 +15,7 @@ class TextFile: ) -> None: ... def open(self, filename: str) -> None: ... def close(self) -> None: ... - def warn(self, msg: str, line: Union[List[int], Tuple[int, int], int] = ...) -> None: ... - def readline(self) -> Optional[str]: ... + def warn(self, msg: str, line: List[int] | Tuple[int, int] | int = ...) -> None: ... + def readline(self) -> str | None: ... def readlines(self) -> List[str]: ... def unreadline(self, line: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/util.pyi b/mypy/typeshed/stdlib/@python2/distutils/util.pyi index 0086d726af65..c0882d1dd1cb 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/util.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, List, Mapping, Optional, Tuple +from typing import Any, Callable, List, Mapping, Tuple def get_platform() -> str: ... def convert_path(pathname: str) -> str: ... @@ -7,17 +7,17 @@ def check_environ() -> None: ... def subst_vars(s: str, local_vars: Mapping[str, str]) -> None: ... def split_quoted(s: str) -> List[str]: ... def execute( - func: Callable[..., None], args: Tuple[Any, ...], msg: Optional[str] = ..., verbose: bool = ..., dry_run: bool = ... + func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... ) -> None: ... def strtobool(val: str) -> bool: ... def byte_compile( py_files: List[str], optimize: int = ..., force: bool = ..., - prefix: Optional[str] = ..., - base_dir: Optional[str] = ..., + prefix: str | None = ..., + base_dir: str | None = ..., verbose: bool = ..., dry_run: bool = ..., - direct: Optional[bool] = ..., + direct: bool | None = ..., ) -> None: ... def rfc822_escape(header: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/version.pyi b/mypy/typeshed/stdlib/@python2/distutils/version.pyi index f55d01d1a172..dd0969b8635f 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/version.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/version.pyi @@ -1,33 +1,33 @@ from abc import abstractmethod -from typing import Optional, Pattern, Text, Tuple, TypeVar, Union +from typing import Pattern, Text, Tuple, TypeVar _T = TypeVar("_T", bound=Version) class Version: def __repr__(self) -> str: ... @abstractmethod - def __init__(self, vstring: Optional[Text] = ...) -> None: ... + def __init__(self, vstring: Text | None = ...) -> None: ... @abstractmethod def parse(self: _T, vstring: Text) -> _T: ... @abstractmethod def __str__(self) -> str: ... @abstractmethod - def __cmp__(self: _T, other: Union[_T, str]) -> bool: ... + def __cmp__(self: _T, other: _T | str) -> bool: ... class StrictVersion(Version): version_re: Pattern[str] version: Tuple[int, int, int] - prerelease: Optional[Tuple[Text, int]] - def __init__(self, vstring: Optional[Text] = ...) -> None: ... + prerelease: Tuple[Text, int] | None + def __init__(self, vstring: Text | None = ...) -> None: ... def parse(self: _T, vstring: Text) -> _T: ... def __str__(self) -> str: ... - def __cmp__(self: _T, other: Union[_T, str]) -> bool: ... + def __cmp__(self: _T, other: _T | str) -> bool: ... class LooseVersion(Version): component_re: Pattern[str] vstring: Text - version: Tuple[Union[Text, int], ...] - def __init__(self, vstring: Optional[Text] = ...) -> None: ... + version: Tuple[Text | int, ...] + def __init__(self, vstring: Text | None = ...) -> None: ... def parse(self: _T, vstring: Text) -> _T: ... def __str__(self) -> str: ... - def __cmp__(self: _T, other: Union[_T, str]) -> bool: ... + def __cmp__(self: _T, other: _T | str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/doctest.pyi b/mypy/typeshed/stdlib/@python2/doctest.pyi new file mode 100644 index 000000000000..6c3b922244f4 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/doctest.pyi @@ -0,0 +1,209 @@ +import types +import unittest +from typing import Any, Callable, Dict, List, NamedTuple, Tuple, Type + +class TestResults(NamedTuple): + failed: int + attempted: int + +OPTIONFLAGS_BY_NAME: Dict[str, int] + +def register_optionflag(name: str) -> int: ... + +DONT_ACCEPT_TRUE_FOR_1: int +DONT_ACCEPT_BLANKLINE: int +NORMALIZE_WHITESPACE: int +ELLIPSIS: int +SKIP: int +IGNORE_EXCEPTION_DETAIL: int + +COMPARISON_FLAGS: int + +REPORT_UDIFF: int +REPORT_CDIFF: int +REPORT_NDIFF: int +REPORT_ONLY_FIRST_FAILURE: int +REPORTING_FLAGS: int + +BLANKLINE_MARKER: str +ELLIPSIS_MARKER: str + +class Example: + source: str + want: str + exc_msg: str | None + lineno: int + indent: int + options: Dict[int, bool] + def __init__( + self, + source: str, + want: str, + exc_msg: str | None = ..., + lineno: int = ..., + indent: int = ..., + options: Dict[int, bool] | None = ..., + ) -> None: ... + def __hash__(self) -> int: ... + +class DocTest: + examples: List[Example] + globs: Dict[str, Any] + name: str + filename: str | None + lineno: int | None + docstring: str | None + def __init__( + self, + examples: List[Example], + globs: Dict[str, Any], + name: str, + filename: str | None, + lineno: int | None, + docstring: str | None, + ) -> None: ... + def __hash__(self) -> int: ... + def __lt__(self, other: DocTest) -> bool: ... + +class DocTestParser: + def parse(self, string: str, name: str = ...) -> List[str | Example]: ... + def get_doctest(self, string: str, globs: Dict[str, Any], name: str, filename: str | None, lineno: int | None) -> DocTest: ... + def get_examples(self, string: str, name: str = ...) -> List[Example]: ... + +class DocTestFinder: + def __init__( + self, verbose: bool = ..., parser: DocTestParser = ..., recurse: bool = ..., exclude_empty: bool = ... + ) -> None: ... + def find( + self, + obj: object, + name: str | None = ..., + module: None | bool | types.ModuleType = ..., + globs: Dict[str, Any] | None = ..., + extraglobs: Dict[str, Any] | None = ..., + ) -> List[DocTest]: ... + +_Out = Callable[[str], Any] +_ExcInfo = Tuple[Type[BaseException], BaseException, types.TracebackType] + +class DocTestRunner: + DIVIDER: str + optionflags: int + original_optionflags: int + tries: int + failures: int + test: DocTest + def __init__(self, checker: OutputChecker | None = ..., verbose: bool | None = ..., optionflags: int = ...) -> None: ... + def report_start(self, out: _Out, test: DocTest, example: Example) -> None: ... + def report_success(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... + def report_failure(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... + def report_unexpected_exception(self, out: _Out, test: DocTest, example: Example, exc_info: _ExcInfo) -> None: ... + def run( + self, test: DocTest, compileflags: int | None = ..., out: _Out | None = ..., clear_globs: bool = ... + ) -> TestResults: ... + def summarize(self, verbose: bool | None = ...) -> TestResults: ... + def merge(self, other: DocTestRunner) -> None: ... + +class OutputChecker: + def check_output(self, want: str, got: str, optionflags: int) -> bool: ... + def output_difference(self, example: Example, got: str, optionflags: int) -> str: ... + +class DocTestFailure(Exception): + test: DocTest + example: Example + got: str + def __init__(self, test: DocTest, example: Example, got: str) -> None: ... + +class UnexpectedException(Exception): + test: DocTest + example: Example + exc_info: _ExcInfo + def __init__(self, test: DocTest, example: Example, exc_info: _ExcInfo) -> None: ... + +class DebugRunner(DocTestRunner): ... + +master: DocTestRunner | None + +def testmod( + m: types.ModuleType | None = ..., + name: str | None = ..., + globs: Dict[str, Any] | None = ..., + verbose: bool | None = ..., + report: bool = ..., + optionflags: int = ..., + extraglobs: Dict[str, Any] | None = ..., + raise_on_error: bool = ..., + exclude_empty: bool = ..., +) -> TestResults: ... +def testfile( + filename: str, + module_relative: bool = ..., + name: str | None = ..., + package: None | str | types.ModuleType = ..., + globs: Dict[str, Any] | None = ..., + verbose: bool | None = ..., + report: bool = ..., + optionflags: int = ..., + extraglobs: Dict[str, Any] | None = ..., + raise_on_error: bool = ..., + parser: DocTestParser = ..., + encoding: str | None = ..., +) -> TestResults: ... +def run_docstring_examples( + f: object, globs: Dict[str, Any], verbose: bool = ..., name: str = ..., compileflags: int | None = ..., optionflags: int = ... +) -> None: ... +def set_unittest_reportflags(flags: int) -> int: ... + +class DocTestCase(unittest.TestCase): + def __init__( + self, + test: DocTest, + optionflags: int = ..., + setUp: Callable[[DocTest], Any] | None = ..., + tearDown: Callable[[DocTest], Any] | None = ..., + checker: OutputChecker | None = ..., + ) -> None: ... + def setUp(self) -> None: ... + def tearDown(self) -> None: ... + def runTest(self) -> None: ... + def format_failure(self, err: str) -> str: ... + def debug(self) -> None: ... + def id(self) -> str: ... + def __hash__(self) -> int: ... + def shortDescription(self) -> str: ... + +class SkipDocTestCase(DocTestCase): + def __init__(self, module: types.ModuleType) -> None: ... + def setUp(self) -> None: ... + def test_skip(self) -> None: ... + def shortDescription(self) -> str: ... + +_DocTestSuite = unittest.TestSuite + +def DocTestSuite( + module: None | str | types.ModuleType = ..., + globs: Dict[str, Any] | None = ..., + extraglobs: Dict[str, Any] | None = ..., + test_finder: DocTestFinder | None = ..., + **options: Any, +) -> _DocTestSuite: ... + +class DocFileCase(DocTestCase): + def id(self) -> str: ... + def format_failure(self, err: str) -> str: ... + +def DocFileTest( + path: str, + module_relative: bool = ..., + package: None | str | types.ModuleType = ..., + globs: Dict[str, Any] | None = ..., + parser: DocTestParser = ..., + encoding: str | None = ..., + **options: Any, +) -> DocFileCase: ... +def DocFileSuite(*paths: str, **kw: Any) -> _DocTestSuite: ... +def script_from_examples(s: str) -> str: ... +def testsource(module: None | str | types.ModuleType, name: str) -> str: ... +def debug_src(src: str, pm: bool = ..., globs: Dict[str, Any] | None = ...) -> None: ... +def debug_script(src: str, pm: bool = ..., globs: Dict[str, Any] | None = ...) -> None: ... +def debug(module: None | str | types.ModuleType, name: str, pm: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/dummy_thread.pyi b/mypy/typeshed/stdlib/@python2/dummy_thread.pyi index 28041002a708..0a28b3aaeeb9 100644 --- a/mypy/typeshed/stdlib/@python2/dummy_thread.pyi +++ b/mypy/typeshed/stdlib/@python2/dummy_thread.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, NoReturn, Optional, Tuple +from typing import Any, Callable, Dict, NoReturn, Tuple class error(Exception): def __init__(self, *args: Any) -> None: ... @@ -7,13 +7,13 @@ def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs def exit() -> NoReturn: ... def get_ident() -> int: ... def allocate_lock() -> LockType: ... -def stack_size(size: Optional[int] = ...) -> int: ... +def stack_size(size: int | None = ...) -> int: ... class LockType(object): locked_status: bool def __init__(self) -> None: ... - def acquire(self, waitflag: Optional[bool] = ...) -> bool: ... - def __enter__(self, waitflag: Optional[bool] = ...) -> bool: ... + def acquire(self, waitflag: bool | None = ...) -> bool: ... + def __enter__(self, waitflag: bool | None = ...) -> bool: ... def __exit__(self, typ: Any, val: Any, tb: Any) -> None: ... def release(self) -> bool: ... def locked(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/dummy_threading.pyi b/mypy/typeshed/stdlib/@python2/dummy_threading.pyi new file mode 100644 index 000000000000..757cb8d4bd4c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/dummy_threading.pyi @@ -0,0 +1,2 @@ +from _dummy_threading import * +from _dummy_threading import __all__ as __all__ diff --git a/mypy/typeshed/stdlib/@python2/email/__init__.pyi b/mypy/typeshed/stdlib/@python2/email/__init__.pyi index 384d9567f7b0..83d9895cab4d 100644 --- a/mypy/typeshed/stdlib/@python2/email/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/email/__init__.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, AnyStr +from typing import IO, AnyStr def message_from_string(s: AnyStr, *args, **kwargs): ... def message_from_bytes(s: str, *args, **kwargs): ... diff --git a/mypy/typeshed/stdlib/@python2/email/_parseaddr.pyi b/mypy/typeshed/stdlib/@python2/email/_parseaddr.pyi index 424ade705f77..74ea3a6e4a69 100644 --- a/mypy/typeshed/stdlib/@python2/email/_parseaddr.pyi +++ b/mypy/typeshed/stdlib/@python2/email/_parseaddr.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any def parsedate_tz(data): ... def parsedate(data): ... @@ -26,7 +26,7 @@ class AddrlistClass: def getquote(self): ... def getcomment(self): ... def getdomainliteral(self): ... - def getatom(self, atomends: Optional[Any] = ...): ... + def getatom(self, atomends: Any | None = ...): ... def getphraselist(self): ... class AddressList(AddrlistClass): diff --git a/mypy/typeshed/stdlib/@python2/email/utils.pyi b/mypy/typeshed/stdlib/@python2/email/utils.pyi index 257e4b1c947a..0d185134c9d7 100644 --- a/mypy/typeshed/stdlib/@python2/email/utils.pyi +++ b/mypy/typeshed/stdlib/@python2/email/utils.pyi @@ -5,17 +5,17 @@ from email._parseaddr import ( parsedate_tz as _parsedate_tz, ) from quopri import decodestring as _qdecode -from typing import Any, Optional +from typing import Any def formataddr(pair): ... def getaddresses(fieldvalues): ... -def formatdate(timeval: Optional[Any] = ..., localtime: bool = ..., usegmt: bool = ...): ... -def make_msgid(idstring: Optional[Any] = ...): ... +def formatdate(timeval: Any | None = ..., localtime: bool = ..., usegmt: bool = ...): ... +def make_msgid(idstring: Any | None = ...): ... def parsedate(data): ... def parsedate_tz(data): ... def parseaddr(addr): ... def unquote(str): ... def decode_rfc2231(s): ... -def encode_rfc2231(s, charset: Optional[Any] = ..., language: Optional[Any] = ...): ... +def encode_rfc2231(s, charset: Any | None = ..., language: Any | None = ...): ... def decode_params(params): ... def collapse_rfc2231_value(value, errors=..., fallback_charset=...): ... diff --git a/mypy/typeshed/stdlib/@python2/ensurepip/__init__.pyi b/mypy/typeshed/stdlib/@python2/ensurepip/__init__.pyi new file mode 100644 index 000000000000..60946e7cf35a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ensurepip/__init__.pyi @@ -0,0 +1,9 @@ +def version() -> str: ... +def bootstrap( + root: str | None = ..., + upgrade: bool = ..., + user: bool = ..., + altinstall: bool = ..., + default_pip: bool = ..., + verbosity: int = ..., +) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/errno.pyi b/mypy/typeshed/stdlib/@python2/errno.pyi new file mode 100644 index 000000000000..b053604fc33a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/errno.pyi @@ -0,0 +1,137 @@ +from typing import Mapping + +errorcode: Mapping[int, str] + +EPERM: int +ENOENT: int +ESRCH: int +EINTR: int +EIO: int +ENXIO: int +E2BIG: int +ENOEXEC: int +EBADF: int +ECHILD: int +EAGAIN: int +ENOMEM: int +EACCES: int +EFAULT: int +ENOTBLK: int +EBUSY: int +EEXIST: int +EXDEV: int +ENODEV: int +ENOTDIR: int +EISDIR: int +EINVAL: int +ENFILE: int +EMFILE: int +ENOTTY: int +ETXTBSY: int +EFBIG: int +ENOSPC: int +ESPIPE: int +EROFS: int +EMLINK: int +EPIPE: int +EDOM: int +ERANGE: int +EDEADLCK: int +ENAMETOOLONG: int +ENOLCK: int +ENOSYS: int +ENOTEMPTY: int +ELOOP: int +EWOULDBLOCK: int +ENOMSG: int +EIDRM: int +ECHRNG: int +EL2NSYNC: int +EL3HLT: int +EL3RST: int +ELNRNG: int +EUNATCH: int +ENOCSI: int +EL2HLT: int +EBADE: int +EBADR: int +EXFULL: int +ENOANO: int +EBADRQC: int +EBADSLT: int +EDEADLOCK: int +EBFONT: int +ENOSTR: int +ENODATA: int +ETIME: int +ENOSR: int +ENONET: int +ENOPKG: int +EREMOTE: int +ENOLINK: int +EADV: int +ESRMNT: int +ECOMM: int +EPROTO: int +EMULTIHOP: int +EDOTDOT: int +EBADMSG: int +EOVERFLOW: int +ENOTUNIQ: int +EBADFD: int +EREMCHG: int +ELIBACC: int +ELIBBAD: int +ELIBSCN: int +ELIBMAX: int +ELIBEXEC: int +EILSEQ: int +ERESTART: int +ESTRPIPE: int +EUSERS: int +ENOTSOCK: int +EDESTADDRREQ: int +EMSGSIZE: int +EPROTOTYPE: int +ENOPROTOOPT: int +EPROTONOSUPPORT: int +ESOCKTNOSUPPORT: int +ENOTSUP: int +EOPNOTSUPP: int +EPFNOSUPPORT: int +EAFNOSUPPORT: int +EADDRINUSE: int +EADDRNOTAVAIL: int +ENETDOWN: int +ENETUNREACH: int +ENETRESET: int +ECONNABORTED: int +ECONNRESET: int +ENOBUFS: int +EISCONN: int +ENOTCONN: int +ESHUTDOWN: int +ETOOMANYREFS: int +ETIMEDOUT: int +ECONNREFUSED: int +EHOSTDOWN: int +EHOSTUNREACH: int +EALREADY: int +EINPROGRESS: int +ESTALE: int +EUCLEAN: int +ENOTNAM: int +ENAVAIL: int +EISNAM: int +EREMOTEIO: int +EDQUOT: int +ECANCELED: int # undocumented +EKEYEXPIRED: int # undocumented +EKEYREJECTED: int # undocumented +EKEYREVOKED: int # undocumented +EMEDIUMTYPE: int # undocumented +ENOKEY: int # undocumented +ENOMEDIUM: int # undocumented +ENOTRECOVERABLE: int # undocumented +EOWNERDEAD: int # undocumented +ERFKILL: int # undocumented diff --git a/mypy/typeshed/stdlib/@python2/fcntl.pyi b/mypy/typeshed/stdlib/@python2/fcntl.pyi index 200e2249280c..b3730270f1cc 100644 --- a/mypy/typeshed/stdlib/@python2/fcntl.pyi +++ b/mypy/typeshed/stdlib/@python2/fcntl.pyi @@ -1,5 +1,5 @@ from _typeshed import FileDescriptorLike -from typing import Any, Union +from typing import Any FASYNC: int FD_CLOEXEC: int @@ -74,9 +74,9 @@ LOCK_WRITE: int # TODO All these return either int or bytes depending on the value of # cmd (not on the type of arg). -def fcntl(fd: FileDescriptorLike, op: int, arg: Union[int, bytes] = ...) -> Any: ... +def fcntl(fd: FileDescriptorLike, op: int, arg: int | bytes = ...) -> Any: ... # TODO: arg: int or read-only buffer interface or read-write buffer interface -def ioctl(fd: FileDescriptorLike, op: int, arg: Union[int, bytes] = ..., mutate_flag: bool = ...) -> Any: ... +def ioctl(fd: FileDescriptorLike, op: int, arg: int | bytes = ..., mutate_flag: bool = ...) -> Any: ... def flock(fd: FileDescriptorLike, op: int) -> None: ... def lockf(fd: FileDescriptorLike, op: int, length: int = ..., start: int = ..., whence: int = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/filecmp.pyi b/mypy/typeshed/stdlib/@python2/filecmp.pyi new file mode 100644 index 000000000000..0be5596c2bdb --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/filecmp.pyi @@ -0,0 +1,40 @@ +from typing import AnyStr, Callable, Dict, Generic, Iterable, List, Sequence, Text, Tuple + +DEFAULT_IGNORES: List[str] + +def cmp(f1: bytes | Text, f2: bytes | Text, shallow: int | bool = ...) -> bool: ... +def cmpfiles( + a: AnyStr, b: AnyStr, common: Iterable[AnyStr], shallow: int | bool = ... +) -> Tuple[List[AnyStr], List[AnyStr], List[AnyStr]]: ... + +class dircmp(Generic[AnyStr]): + def __init__( + self, a: AnyStr, b: AnyStr, ignore: Sequence[AnyStr] | None = ..., hide: Sequence[AnyStr] | None = ... + ) -> None: ... + left: AnyStr + right: AnyStr + hide: Sequence[AnyStr] + ignore: Sequence[AnyStr] + # These properties are created at runtime by __getattr__ + subdirs: Dict[AnyStr, dircmp[AnyStr]] + same_files: List[AnyStr] + diff_files: List[AnyStr] + funny_files: List[AnyStr] + common_dirs: List[AnyStr] + common_files: List[AnyStr] + common_funny: List[AnyStr] + common: List[AnyStr] + left_only: List[AnyStr] + right_only: List[AnyStr] + left_list: List[AnyStr] + right_list: List[AnyStr] + def report(self) -> None: ... + def report_partial_closure(self) -> None: ... + def report_full_closure(self) -> None: ... + methodmap: Dict[str, Callable[[], None]] + def phase0(self) -> None: ... + def phase1(self) -> None: ... + def phase2(self) -> None: ... + def phase3(self) -> None: ... + def phase4(self) -> None: ... + def phase4_closure(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/fileinput.pyi b/mypy/typeshed/stdlib/@python2/fileinput.pyi new file mode 100644 index 000000000000..316643fcf15f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/fileinput.pyi @@ -0,0 +1,45 @@ +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator, Text + +def input( + files: Text | Iterable[Text] | None = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + mode: str = ..., + openhook: Callable[[Text, str], IO[AnyStr]] = ..., +) -> FileInput[AnyStr]: ... +def close() -> None: ... +def nextfile() -> None: ... +def filename() -> str: ... +def lineno() -> int: ... +def filelineno() -> int: ... +def fileno() -> int: ... +def isfirstline() -> bool: ... +def isstdin() -> bool: ... + +class FileInput(Iterable[AnyStr], Generic[AnyStr]): + def __init__( + self, + files: None | Text | Iterable[Text] = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + mode: str = ..., + openhook: Callable[[Text, str], IO[AnyStr]] = ..., + ) -> None: ... + def __del__(self) -> None: ... + def close(self) -> None: ... + def __iter__(self) -> Iterator[AnyStr]: ... + def __next__(self) -> AnyStr: ... + def __getitem__(self, i: int) -> AnyStr: ... + def nextfile(self) -> None: ... + def readline(self) -> AnyStr: ... + def filename(self) -> str: ... + def lineno(self) -> int: ... + def filelineno(self) -> int: ... + def fileno(self) -> int: ... + def isfirstline(self) -> bool: ... + def isstdin(self) -> bool: ... + +def hook_compressed(filename: Text, mode: str) -> IO[Any]: ... +def hook_encoded(encoding: str) -> Callable[[Text, str], IO[Any]]: ... diff --git a/mypy/typeshed/stdlib/@python2/formatter.pyi b/mypy/typeshed/stdlib/@python2/formatter.pyi new file mode 100644 index 000000000000..da165f2d55e3 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/formatter.pyi @@ -0,0 +1,103 @@ +from typing import IO, Any, Iterable, List, Tuple + +AS_IS: None +_FontType = Tuple[str, bool, bool, bool] +_StylesType = Tuple[Any, ...] + +class NullFormatter: + writer: NullWriter | None + def __init__(self, writer: NullWriter | None = ...) -> None: ... + def end_paragraph(self, blankline: int) -> None: ... + def add_line_break(self) -> None: ... + def add_hor_rule(self, *args: Any, **kw: Any) -> None: ... + def add_label_data(self, format: str, counter: int, blankline: int | None = ...) -> None: ... + def add_flowing_data(self, data: str) -> None: ... + def add_literal_data(self, data: str) -> None: ... + def flush_softspace(self) -> None: ... + def push_alignment(self, align: str | None) -> None: ... + def pop_alignment(self) -> None: ... + def push_font(self, x: _FontType) -> None: ... + def pop_font(self) -> None: ... + def push_margin(self, margin: int) -> None: ... + def pop_margin(self) -> None: ... + def set_spacing(self, spacing: str | None) -> None: ... + def push_style(self, *styles: _StylesType) -> None: ... + def pop_style(self, n: int = ...) -> None: ... + def assert_line_data(self, flag: int = ...) -> None: ... + +class AbstractFormatter: + writer: NullWriter + align: str | None + align_stack: List[str | None] + font_stack: List[_FontType] + margin_stack: List[int] + spacing: str | None + style_stack: Any + nospace: int + softspace: int + para_end: int + parskip: int + hard_break: int + have_label: int + def __init__(self, writer: NullWriter) -> None: ... + def end_paragraph(self, blankline: int) -> None: ... + def add_line_break(self) -> None: ... + def add_hor_rule(self, *args: Any, **kw: Any) -> None: ... + def add_label_data(self, format: str, counter: int, blankline: int | None = ...) -> None: ... + def format_counter(self, format: Iterable[str], counter: int) -> str: ... + def format_letter(self, case: str, counter: int) -> str: ... + def format_roman(self, case: str, counter: int) -> str: ... + def add_flowing_data(self, data: str) -> None: ... + def add_literal_data(self, data: str) -> None: ... + def flush_softspace(self) -> None: ... + def push_alignment(self, align: str | None) -> None: ... + def pop_alignment(self) -> None: ... + def push_font(self, font: _FontType) -> None: ... + def pop_font(self) -> None: ... + def push_margin(self, margin: int) -> None: ... + def pop_margin(self) -> None: ... + def set_spacing(self, spacing: str | None) -> None: ... + def push_style(self, *styles: _StylesType) -> None: ... + def pop_style(self, n: int = ...) -> None: ... + def assert_line_data(self, flag: int = ...) -> None: ... + +class NullWriter: + def __init__(self) -> None: ... + def flush(self) -> None: ... + def new_alignment(self, align: str | None) -> None: ... + def new_font(self, font: _FontType) -> None: ... + def new_margin(self, margin: int, level: int) -> None: ... + def new_spacing(self, spacing: str | None) -> None: ... + def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def send_paragraph(self, blankline: int) -> None: ... + def send_line_break(self) -> None: ... + def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... + def send_label_data(self, data: str) -> None: ... + def send_flowing_data(self, data: str) -> None: ... + def send_literal_data(self, data: str) -> None: ... + +class AbstractWriter(NullWriter): + def new_alignment(self, align: str | None) -> None: ... + def new_font(self, font: _FontType) -> None: ... + def new_margin(self, margin: int, level: int) -> None: ... + def new_spacing(self, spacing: str | None) -> None: ... + def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def send_paragraph(self, blankline: int) -> None: ... + def send_line_break(self) -> None: ... + def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... + def send_label_data(self, data: str) -> None: ... + def send_flowing_data(self, data: str) -> None: ... + def send_literal_data(self, data: str) -> None: ... + +class DumbWriter(NullWriter): + file: IO[str] + maxcol: int + def __init__(self, file: IO[str] | None = ..., maxcol: int = ...) -> None: ... + def reset(self) -> None: ... + def send_paragraph(self, blankline: int) -> None: ... + def send_line_break(self) -> None: ... + def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... + def send_literal_data(self, data: str) -> None: ... + def send_flowing_data(self, data: str) -> None: ... + +def test(file: str | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/fractions.pyi b/mypy/typeshed/stdlib/@python2/fractions.pyi new file mode 100644 index 000000000000..872e20ede688 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/fractions.pyi @@ -0,0 +1,145 @@ +from decimal import Decimal +from numbers import Integral, Rational, Real +from typing import Tuple, Type, TypeVar, Union, overload +from typing_extensions import Literal + +_ComparableNum = Union[int, float, Decimal, Real] +_T = TypeVar("_T") + +@overload +def gcd(a: int, b: int) -> int: ... +@overload +def gcd(a: Integral, b: int) -> Integral: ... +@overload +def gcd(a: int, b: Integral) -> Integral: ... +@overload +def gcd(a: Integral, b: Integral) -> Integral: ... + +class Fraction(Rational): + @overload + def __new__( + cls: Type[_T], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... + ) -> _T: ... + @overload + def __new__(cls: Type[_T], __value: float | Decimal | str, *, _normalize: bool = ...) -> _T: ... + @classmethod + def from_float(cls, f: float) -> Fraction: ... + @classmethod + def from_decimal(cls, dec: Decimal) -> Fraction: ... + def limit_denominator(self, max_denominator: int = ...) -> Fraction: ... + @property + def numerator(self) -> int: ... + @property + def denominator(self) -> int: ... + @overload + def __add__(self, other: int | Fraction) -> Fraction: ... + @overload + def __add__(self, other: float) -> float: ... + @overload + def __add__(self, other: complex) -> complex: ... + @overload + def __radd__(self, other: int | Fraction) -> Fraction: ... + @overload + def __radd__(self, other: float) -> float: ... + @overload + def __radd__(self, other: complex) -> complex: ... + @overload + def __sub__(self, other: int | Fraction) -> Fraction: ... + @overload + def __sub__(self, other: float) -> float: ... + @overload + def __sub__(self, other: complex) -> complex: ... + @overload + def __rsub__(self, other: int | Fraction) -> Fraction: ... + @overload + def __rsub__(self, other: float) -> float: ... + @overload + def __rsub__(self, other: complex) -> complex: ... + @overload + def __mul__(self, other: int | Fraction) -> Fraction: ... + @overload + def __mul__(self, other: float) -> float: ... + @overload + def __mul__(self, other: complex) -> complex: ... + @overload + def __rmul__(self, other: int | Fraction) -> Fraction: ... + @overload + def __rmul__(self, other: float) -> float: ... + @overload + def __rmul__(self, other: complex) -> complex: ... + @overload + def __truediv__(self, other: int | Fraction) -> Fraction: ... + @overload + def __truediv__(self, other: float) -> float: ... + @overload + def __truediv__(self, other: complex) -> complex: ... + @overload + def __rtruediv__(self, other: int | Fraction) -> Fraction: ... + @overload + def __rtruediv__(self, other: float) -> float: ... + @overload + def __rtruediv__(self, other: complex) -> complex: ... + @overload + def __div__(self, other: int | Fraction) -> Fraction: ... + @overload + def __div__(self, other: float) -> float: ... + @overload + def __div__(self, other: complex) -> complex: ... + @overload + def __rdiv__(self, other: int | Fraction) -> Fraction: ... + @overload + def __rdiv__(self, other: float) -> float: ... + @overload + def __rdiv__(self, other: complex) -> complex: ... + @overload + def __floordiv__(self, other: int | Fraction) -> int: ... + @overload + def __floordiv__(self, other: float) -> float: ... + @overload + def __rfloordiv__(self, other: int | Fraction) -> int: ... + @overload + def __rfloordiv__(self, other: float) -> float: ... + @overload + def __mod__(self, other: int | Fraction) -> Fraction: ... + @overload + def __mod__(self, other: float) -> float: ... + @overload + def __rmod__(self, other: int | Fraction) -> Fraction: ... + @overload + def __rmod__(self, other: float) -> float: ... + @overload + def __divmod__(self, other: int | Fraction) -> Tuple[int, Fraction]: ... + @overload + def __divmod__(self, other: float) -> Tuple[float, Fraction]: ... + @overload + def __rdivmod__(self, other: int | Fraction) -> Tuple[int, Fraction]: ... + @overload + def __rdivmod__(self, other: float) -> Tuple[float, Fraction]: ... + @overload + def __pow__(self, other: int) -> Fraction: ... + @overload + def __pow__(self, other: float | Fraction) -> float: ... + @overload + def __pow__(self, other: complex) -> complex: ... + @overload + def __rpow__(self, other: int | float | Fraction) -> float: ... + @overload + def __rpow__(self, other: complex) -> complex: ... + def __pos__(self) -> Fraction: ... + def __neg__(self) -> Fraction: ... + def __abs__(self) -> Fraction: ... + def __trunc__(self) -> int: ... + def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self, other: _ComparableNum) -> bool: ... + def __gt__(self, other: _ComparableNum) -> bool: ... + def __le__(self, other: _ComparableNum) -> bool: ... + def __ge__(self, other: _ComparableNum) -> bool: ... + def __nonzero__(self) -> bool: ... + # Not actually defined within fractions.py, but provides more useful + # overrides + @property + def real(self) -> Fraction: ... + @property + def imag(self) -> Literal[0]: ... + def conjugate(self) -> Fraction: ... diff --git a/mypy/typeshed/stdlib/@python2/ftplib.pyi b/mypy/typeshed/stdlib/@python2/ftplib.pyi new file mode 100644 index 000000000000..0931a9d171cd --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ftplib.pyi @@ -0,0 +1,128 @@ +from _typeshed import SupportsRead, SupportsReadline +from socket import socket +from ssl import SSLContext +from typing import Any, BinaryIO, Callable, List, Text, Tuple, Type, TypeVar, Union +from typing_extensions import Literal + +_T = TypeVar("_T") +_IntOrStr = Union[int, Text] + +MSG_OOB: int +FTP_PORT: int +MAXLINE: int +CRLF: str + +class Error(Exception): ... +class error_reply(Error): ... +class error_temp(Error): ... +class error_perm(Error): ... +class error_proto(Error): ... + +all_errors: Tuple[Type[Exception], ...] + +class FTP: + debugging: int + + # Note: This is technically the type that's passed in as the host argument. But to make it easier in Python 2 we + # accept Text but return str. + host: str + + port: int + maxline: int + sock: socket | None + welcome: str | None + passiveserver: int + timeout: int + af: int + lastresp: str + + file: BinaryIO | None + def __init__( + self, host: Text = ..., user: Text = ..., passwd: Text = ..., acct: Text = ..., timeout: float = ... + ) -> None: ... + def connect(self, host: Text = ..., port: int = ..., timeout: float = ...) -> str: ... + def getwelcome(self) -> str: ... + def set_debuglevel(self, level: int) -> None: ... + def debug(self, level: int) -> None: ... + def set_pasv(self, val: bool | int) -> None: ... + def sanitize(self, s: Text) -> str: ... + def putline(self, line: Text) -> None: ... + def putcmd(self, line: Text) -> None: ... + def getline(self) -> str: ... + def getmultiline(self) -> str: ... + def getresp(self) -> str: ... + def voidresp(self) -> str: ... + def abort(self) -> str: ... + def sendcmd(self, cmd: Text) -> str: ... + def voidcmd(self, cmd: Text) -> str: ... + def sendport(self, host: Text, port: int) -> str: ... + def sendeprt(self, host: Text, port: int) -> str: ... + def makeport(self) -> socket: ... + def makepasv(self) -> Tuple[str, int]: ... + def login(self, user: Text = ..., passwd: Text = ..., acct: Text = ...) -> str: ... + # In practice, `rest` rest can actually be anything whose str() is an integer sequence, so to make it simple we allow integers. + def ntransfercmd(self, cmd: Text, rest: _IntOrStr | None = ...) -> Tuple[socket, int]: ... + def transfercmd(self, cmd: Text, rest: _IntOrStr | None = ...) -> socket: ... + def retrbinary( + self, cmd: Text, callback: Callable[[bytes], Any], blocksize: int = ..., rest: _IntOrStr | None = ... + ) -> str: ... + def storbinary( + self, + cmd: Text, + fp: SupportsRead[bytes], + blocksize: int = ..., + callback: Callable[[bytes], Any] | None = ..., + rest: _IntOrStr | None = ..., + ) -> str: ... + def retrlines(self, cmd: Text, callback: Callable[[str], Any] | None = ...) -> str: ... + def storlines(self, cmd: Text, fp: SupportsReadline[bytes], callback: Callable[[bytes], Any] | None = ...) -> str: ... + def acct(self, password: Text) -> str: ... + def nlst(self, *args: Text) -> List[str]: ... + # Technically only the last arg can be a Callable but ... + def dir(self, *args: str | Callable[[str], None]) -> None: ... + def rename(self, fromname: Text, toname: Text) -> str: ... + def delete(self, filename: Text) -> str: ... + def cwd(self, dirname: Text) -> str: ... + def size(self, filename: Text) -> int | None: ... + def mkd(self, dirname: Text) -> str: ... + def rmd(self, dirname: Text) -> str: ... + def pwd(self) -> str: ... + def quit(self) -> str: ... + def close(self) -> None: ... + +class FTP_TLS(FTP): + def __init__( + self, + host: Text = ..., + user: Text = ..., + passwd: Text = ..., + acct: Text = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + context: SSLContext | None = ..., + timeout: float = ..., + source_address: Tuple[str, int] | None = ..., + ) -> None: ... + ssl_version: int + keyfile: str | None + certfile: str | None + context: SSLContext + def login(self, user: Text = ..., passwd: Text = ..., acct: Text = ..., secure: bool = ...) -> str: ... + def auth(self) -> str: ... + def prot_p(self) -> str: ... + def prot_c(self) -> str: ... + +class Netrc: + def __init__(self, filename: Text | None = ...) -> None: ... + def get_hosts(self) -> List[str]: ... + def get_account(self, host: Text) -> Tuple[str | None, str | None, str | None]: ... + def get_macros(self) -> List[str]: ... + def get_macro(self, macro: Text) -> Tuple[str, ...]: ... + +def parse150(resp: str) -> int | None: ... # undocumented +def parse227(resp: str) -> Tuple[str, int]: ... # undocumented +def parse229(resp: str, peer: Any) -> Tuple[str, int]: ... # undocumented +def parse257(resp: str) -> str: ... # undocumented +def ftpcp( + source: FTP, sourcename: str, target: FTP, targetname: str = ..., type: Literal["A", "I"] = ... +) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/functools.pyi b/mypy/typeshed/stdlib/@python2/functools.pyi index 8b82177b6f6b..dd873708fea4 100644 --- a/mypy/typeshed/stdlib/@python2/functools.pyi +++ b/mypy/typeshed/stdlib/@python2/functools.pyi @@ -1,5 +1,4 @@ -from abc import ABCMeta, abstractmethod -from typing import Any, Callable, Dict, Generic, Iterable, Optional, Sequence, Tuple, Type, TypeVar, overload +from typing import Any, Callable, Dict, Generic, Iterable, Sequence, Tuple, Type, TypeVar, overload _AnyCallable = Callable[..., Any] diff --git a/mypy/typeshed/stdlib/@python2/genericpath.pyi b/mypy/typeshed/stdlib/@python2/genericpath.pyi new file mode 100644 index 000000000000..ba29db4692bb --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/genericpath.pyi @@ -0,0 +1,25 @@ +from _typeshed import SupportsLessThanT +from typing import List, Sequence, Text, Tuple, Union, overload +from typing_extensions import Literal + +# All overloads can return empty string. Ideally, Literal[""] would be a valid +# Iterable[T], so that Union[List[T], Literal[""]] could be used as a return +# type. But because this only works when T is str, we need Sequence[T] instead. +@overload +def commonprefix(m: Sequence[str]) -> str | Literal[""]: ... # type: ignore +@overload +def commonprefix(m: Sequence[Text]) -> Text: ... # type: ignore +@overload +def commonprefix(m: Sequence[List[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... +@overload +def commonprefix(m: Sequence[Tuple[SupportsLessThanT, ...]]) -> Sequence[SupportsLessThanT]: ... +def exists(path: Text) -> bool: ... +def getsize(filename: Text) -> int: ... +def isfile(path: Text) -> bool: ... +def isdir(s: Text) -> bool: ... + +# These return float if os.stat_float_times() == True, +# but int is a subclass of float. +def getatime(filename: Text) -> float: ... +def getmtime(filename: Text) -> float: ... +def getctime(filename: Text) -> float: ... diff --git a/mypy/typeshed/stdlib/@python2/gettext.pyi b/mypy/typeshed/stdlib/@python2/gettext.pyi index 0930fe63813e..a91234f6b2d3 100644 --- a/mypy/typeshed/stdlib/@python2/gettext.pyi +++ b/mypy/typeshed/stdlib/@python2/gettext.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Container, Dict, List, Optional, Sequence, Type, Union +from typing import IO, Any, Container, Dict, List, Sequence, Type def bindtextdomain(domain: str, localedir: str = ...) -> str: ... def bind_textdomain_codeset(domain: str, codeset: str = ...) -> str: ... @@ -18,14 +18,14 @@ class NullTranslations(object): def add_fallback(self, fallback: NullTranslations) -> None: ... def gettext(self, message: str) -> str: ... def lgettext(self, message: str) -> str: ... - def ugettext(self, message: Union[str, unicode]) -> unicode: ... + def ugettext(self, message: str | unicode) -> unicode: ... def ngettext(self, singular: str, plural: str, n: int) -> str: ... def lngettext(self, singular: str, plural: str, n: int) -> str: ... - def ungettext(self, singular: Union[str, unicode], plural: Union[str, unicode], n: int) -> unicode: ... + def ungettext(self, singular: str | unicode, plural: str | unicode, n: int) -> unicode: ... def info(self) -> Dict[str, str]: ... - def charset(self) -> Optional[str]: ... - def output_charset(self) -> Optional[str]: ... - def set_output_charset(self, charset: Optional[str]) -> None: ... + def charset(self) -> str | None: ... + def output_charset(self) -> str | None: ... + def set_output_charset(self, charset: str | None) -> None: ... def install(self, unicode: bool = ..., names: Container[str] = ...) -> None: ... class GNUTranslations(NullTranslations): @@ -33,16 +33,16 @@ class GNUTranslations(NullTranslations): BE_MAGIC: int def find( - domain: str, localedir: Optional[str] = ..., languages: Optional[Sequence[str]] = ..., all: Any = ... -) -> Optional[Union[str, List[str]]]: ... + domain: str, localedir: str | None = ..., languages: Sequence[str] | None = ..., all: Any = ... +) -> str | List[str] | None: ... def translation( domain: str, - localedir: Optional[str] = ..., - languages: Optional[Sequence[str]] = ..., - class_: Optional[Type[NullTranslations]] = ..., + localedir: str | None = ..., + languages: Sequence[str] | None = ..., + class_: Type[NullTranslations] | None = ..., fallback: bool = ..., - codeset: Optional[str] = ..., + codeset: str | None = ..., ) -> NullTranslations: ... def install( - domain: str, localedir: Optional[str] = ..., unicode: bool = ..., codeset: Optional[str] = ..., names: Container[str] = ... + domain: str, localedir: str | None = ..., unicode: bool = ..., codeset: str | None = ..., names: Container[str] = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/glob.pyi b/mypy/typeshed/stdlib/@python2/glob.pyi index 2804d74a6a3f..f5a389a0ddfa 100644 --- a/mypy/typeshed/stdlib/@python2/glob.pyi +++ b/mypy/typeshed/stdlib/@python2/glob.pyi @@ -1,7 +1,7 @@ -from typing import AnyStr, Iterator, List, Union +from typing import AnyStr, Iterator, List def glob(pathname: AnyStr) -> List[AnyStr]: ... def iglob(pathname: AnyStr) -> Iterator[AnyStr]: ... -def glob1(dirname: Union[str, unicode], pattern: AnyStr) -> List[AnyStr]: ... -def glob0(dirname: Union[str, unicode], basename: AnyStr) -> List[AnyStr]: ... -def has_magic(s: Union[str, unicode]) -> bool: ... # undocumented +def glob1(dirname: str | unicode, pattern: AnyStr) -> List[AnyStr]: ... +def glob0(dirname: str | unicode, basename: AnyStr) -> List[AnyStr]: ... +def has_magic(s: str | unicode) -> bool: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/grp.pyi b/mypy/typeshed/stdlib/@python2/grp.pyi new file mode 100644 index 000000000000..63898b26bf17 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/grp.pyi @@ -0,0 +1,11 @@ +from typing import List, NamedTuple + +class struct_group(NamedTuple): + gr_name: str + gr_passwd: str | None + gr_gid: int + gr_mem: List[str] + +def getgrall() -> List[struct_group]: ... +def getgrgid(id: int) -> struct_group: ... +def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/@python2/hashlib.pyi b/mypy/typeshed/stdlib/@python2/hashlib.pyi index 842804b4ccb2..9c53d2b6b30d 100644 --- a/mypy/typeshed/stdlib/@python2/hashlib.pyi +++ b/mypy/typeshed/stdlib/@python2/hashlib.pyi @@ -3,10 +3,14 @@ from typing import Tuple, Union _DataType = Union[str, unicode, bytearray, buffer, memoryview] class _hash(object): # This is not actually in the module namespace. - name: str - block_size: int - digest_size: int - digestsize: int + @property + def name(self) -> str: ... + @property + def block_size(self) -> int: ... + @property + def digest_size(self) -> int: ... + @property + def digestsize(self) -> int: ... def __init__(self, arg: _DataType = ...) -> None: ... def update(self, arg: _DataType) -> None: ... def digest(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/heapq.pyi b/mypy/typeshed/stdlib/@python2/heapq.pyi index d6da32d767d3..78ce6fd03928 100644 --- a/mypy/typeshed/stdlib/@python2/heapq.pyi +++ b/mypy/typeshed/stdlib/@python2/heapq.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsLessThan -from typing import Any, Callable, Iterable, List, Optional, Protocol, TypeVar +from typing import Callable, Iterable, List, TypeVar _T = TypeVar("_T") @@ -10,6 +10,6 @@ def heappushpop(heap: List[_T], item: _T) -> _T: ... def heapify(x: List[_T]) -> None: ... def heapreplace(heap: List[_T], item: _T) -> _T: ... def merge(*iterables: Iterable[_T]) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... +def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> List[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> List[_T]: ... def _heapify_max(__x: List[_T]) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/hmac.pyi b/mypy/typeshed/stdlib/@python2/hmac.pyi new file mode 100644 index 000000000000..cc39d8c65c8f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/hmac.pyi @@ -0,0 +1,23 @@ +from _typeshed import ReadableBuffer +from types import ModuleType +from typing import Any, AnyStr, Callable, Union, overload + +# TODO more precise type for object of hashlib +_Hash = Any +_DigestMod = Union[str, Callable[[], _Hash], ModuleType] + +digest_size: None + +def new(key: bytes, msg: ReadableBuffer | None = ..., digestmod: _DigestMod | None = ...) -> HMAC: ... + +class HMAC: + def __init__(self, key: bytes, msg: ReadableBuffer | None = ..., digestmod: _DigestMod = ...) -> None: ... + def update(self, msg: ReadableBuffer) -> None: ... + def digest(self) -> bytes: ... + def hexdigest(self) -> str: ... + def copy(self) -> HMAC: ... + +@overload +def compare_digest(__a: ReadableBuffer, __b: ReadableBuffer) -> bool: ... +@overload +def compare_digest(__a: AnyStr, __b: AnyStr) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/httplib.pyi b/mypy/typeshed/stdlib/@python2/httplib.pyi index 59dc658f79ef..f2163818fae4 100644 --- a/mypy/typeshed/stdlib/@python2/httplib.pyi +++ b/mypy/typeshed/stdlib/@python2/httplib.pyi @@ -1,6 +1,5 @@ import mimetools -import ssl -from typing import Any, Dict, Optional, Protocol +from typing import Any, Dict, Protocol class HTTPMessage(mimetools.Message): def addcontinue(self, key: str, more: str) -> None: ... @@ -25,14 +24,14 @@ class HTTPResponse: length: Any will_close: Any def __init__( - self, sock, debuglevel: int = ..., strict: int = ..., method: Optional[Any] = ..., buffering: bool = ... + self, sock, debuglevel: int = ..., strict: int = ..., method: Any | None = ..., buffering: bool = ... ) -> None: ... def begin(self): ... def close(self): ... def isclosed(self): ... - def read(self, amt: Optional[Any] = ...): ... + def read(self, amt: Any | None = ...): ... def fileno(self): ... - def getheader(self, name, default: Optional[Any] = ...): ... + def getheader(self, name, default: Any | None = ...): ... def getheaders(self): ... # This is an API stub only for HTTPConnection and HTTPSConnection, as used in @@ -56,23 +55,23 @@ class HTTPConnection: host: str = ... port: int = ... def __init__( - self, host, port: Optional[Any] = ..., strict: Optional[Any] = ..., timeout=..., source_address: Optional[Any] = ... + self, host, port: Any | None = ..., strict: Any | None = ..., timeout=..., source_address: Any | None = ... ) -> None: ... - def set_tunnel(self, host, port: Optional[Any] = ..., headers: Optional[Any] = ...): ... + def set_tunnel(self, host, port: Any | None = ..., headers: Any | None = ...): ... def set_debuglevel(self, level): ... def connect(self): ... def close(self): ... def send(self, data): ... def putrequest(self, method, url, skip_host: int = ..., skip_accept_encoding: int = ...): ... def putheader(self, header, *values): ... - def endheaders(self, message_body: Optional[Any] = ...): ... - def request(self, method, url, body: Optional[Any] = ..., headers=...): ... + def endheaders(self, message_body: Any | None = ...): ... + def request(self, method, url, body: Any | None = ..., headers=...): ... def getresponse(self, buffering: bool = ...): ... class HTTP: debuglevel: Any - def __init__(self, host: str = ..., port: Optional[Any] = ..., strict: Optional[Any] = ...) -> None: ... - def connect(self, host: Optional[Any] = ..., port: Optional[Any] = ...): ... + def __init__(self, host: str = ..., port: Any | None = ..., strict: Any | None = ...) -> None: ... + def connect(self, host: Any | None = ..., port: Any | None = ...): ... def getfile(self): ... file: Any headers: Any @@ -86,13 +85,13 @@ class HTTPSConnection(HTTPConnection): def __init__( self, host, - port: Optional[Any] = ..., - key_file: Optional[Any] = ..., - cert_file: Optional[Any] = ..., - strict: Optional[Any] = ..., + port: Any | None = ..., + key_file: Any | None = ..., + cert_file: Any | None = ..., + strict: Any | None = ..., timeout=..., - source_address: Optional[Any] = ..., - context: Optional[Any] = ..., + source_address: Any | None = ..., + context: Any | None = ..., ) -> None: ... sock: Any def connect(self): ... @@ -103,11 +102,11 @@ class HTTPS(HTTP): def __init__( self, host: str = ..., - port: Optional[Any] = ..., - key_file: Optional[Any] = ..., - cert_file: Optional[Any] = ..., - strict: Optional[Any] = ..., - context: Optional[Any] = ..., + port: Any | None = ..., + key_file: Any | None = ..., + cert_file: Any | None = ..., + strict: Any | None = ..., + context: Any | None = ..., ) -> None: ... class HTTPException(Exception): ... @@ -126,7 +125,7 @@ class IncompleteRead(HTTPException): args: Any partial: Any expected: Any - def __init__(self, partial, expected: Optional[Any] = ...) -> None: ... + def __init__(self, partial, expected: Any | None = ...) -> None: ... class ImproperConnectionState(HTTPException): ... class CannotSendRequest(ImproperConnectionState): ... @@ -146,9 +145,9 @@ error: Any class LineAndFileWrapper: def __init__(self, line, file) -> None: ... def __getattr__(self, attr): ... - def read(self, amt: Optional[Any] = ...): ... + def read(self, amt: Any | None = ...): ... def readline(self): ... - def readlines(self, size: Optional[Any] = ...): ... + def readlines(self, size: Any | None = ...): ... # Constants diff --git a/mypy/typeshed/stdlib/@python2/imaplib.pyi b/mypy/typeshed/stdlib/@python2/imaplib.pyi new file mode 100644 index 000000000000..c4346851bdac --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/imaplib.pyi @@ -0,0 +1,130 @@ +import subprocess +import time +from socket import socket as _socket +from ssl import SSLSocket +from typing import IO, Any, Callable, Dict, List, Pattern, Text, Tuple, Type, Union +from typing_extensions import Literal + +# TODO: Commands should use their actual return types, not this type alias. +# E.g. Tuple[Literal["OK"], List[bytes]] +_CommandResults = Tuple[str, List[Any]] + +_AnyResponseData = Union[List[None], List[Union[bytes, Tuple[bytes, bytes]]]] + +class IMAP4: + error: Type[Exception] = ... + abort: Type[Exception] = ... + readonly: Type[Exception] = ... + mustquote: Pattern[Text] = ... + debug: int = ... + state: str = ... + literal: Text | None = ... + tagged_commands: Dict[bytes, List[bytes] | None] + untagged_responses: Dict[str, List[bytes | Tuple[bytes, bytes]]] + continuation_response: str = ... + is_readonly: bool = ... + tagnum: int = ... + tagpre: str = ... + tagre: Pattern[Text] = ... + welcome: bytes = ... + capabilities: Tuple[str] = ... + PROTOCOL_VERSION: str = ... + def __init__(self, host: str = ..., port: int = ...) -> None: ... + def open(self, host: str = ..., port: int = ...) -> None: ... + def __getattr__(self, attr: str) -> Any: ... + host: str = ... + port: int = ... + sock: _socket = ... + file: IO[Text] | IO[bytes] = ... + def read(self, size: int) -> bytes: ... + def readline(self) -> bytes: ... + def send(self, data: bytes) -> None: ... + def shutdown(self) -> None: ... + def socket(self) -> _socket: ... + def recent(self) -> _CommandResults: ... + def response(self, code: str) -> _CommandResults: ... + def append(self, mailbox: str, flags: str, date_time: str, message: str) -> str: ... + def authenticate(self, mechanism: str, authobject: Callable[[bytes], bytes | None]) -> Tuple[str, str]: ... + def capability(self) -> _CommandResults: ... + def check(self) -> _CommandResults: ... + def close(self) -> _CommandResults: ... + def copy(self, message_set: str, new_mailbox: str) -> _CommandResults: ... + def create(self, mailbox: str) -> _CommandResults: ... + def delete(self, mailbox: str) -> _CommandResults: ... + def deleteacl(self, mailbox: str, who: str) -> _CommandResults: ... + def expunge(self) -> _CommandResults: ... + def fetch(self, message_set: str, message_parts: str) -> Tuple[str, _AnyResponseData]: ... + def getacl(self, mailbox: str) -> _CommandResults: ... + def getannotation(self, mailbox: str, entry: str, attribute: str) -> _CommandResults: ... + def getquota(self, root: str) -> _CommandResults: ... + def getquotaroot(self, mailbox: str) -> _CommandResults: ... + def list(self, directory: str = ..., pattern: str = ...) -> Tuple[str, _AnyResponseData]: ... + def login(self, user: str, password: str) -> Tuple[Literal["OK"], List[bytes]]: ... + def login_cram_md5(self, user: str, password: str) -> _CommandResults: ... + def logout(self) -> Tuple[str, _AnyResponseData]: ... + def lsub(self, directory: str = ..., pattern: str = ...) -> _CommandResults: ... + def myrights(self, mailbox: str) -> _CommandResults: ... + def namespace(self) -> _CommandResults: ... + def noop(self) -> Tuple[str, List[bytes]]: ... + def partial(self, message_num: str, message_part: str, start: str, length: str) -> _CommandResults: ... + def proxyauth(self, user: str) -> _CommandResults: ... + def rename(self, oldmailbox: str, newmailbox: str) -> _CommandResults: ... + def search(self, charset: str | None, *criteria: str) -> _CommandResults: ... + def select(self, mailbox: str = ..., readonly: bool = ...) -> Tuple[str, List[bytes | None]]: ... + def setacl(self, mailbox: str, who: str, what: str) -> _CommandResults: ... + def setannotation(self, *args: str) -> _CommandResults: ... + def setquota(self, root: str, limits: str) -> _CommandResults: ... + def sort(self, sort_criteria: str, charset: str, *search_criteria: str) -> _CommandResults: ... + def status(self, mailbox: str, names: str) -> _CommandResults: ... + def store(self, message_set: str, command: str, flags: str) -> _CommandResults: ... + def subscribe(self, mailbox: str) -> _CommandResults: ... + def thread(self, threading_algorithm: str, charset: str, *search_criteria: str) -> _CommandResults: ... + def uid(self, command: str, *args: str) -> _CommandResults: ... + def unsubscribe(self, mailbox: str) -> _CommandResults: ... + def xatom(self, name: str, *args: str) -> _CommandResults: ... + def print_log(self) -> None: ... + +class IMAP4_SSL(IMAP4): + keyfile: str = ... + certfile: str = ... + def __init__(self, host: str = ..., port: int = ..., keyfile: str | None = ..., certfile: str | None = ...) -> None: ... + host: str = ... + port: int = ... + sock: _socket = ... + sslobj: SSLSocket = ... + file: IO[Any] = ... + def open(self, host: str = ..., port: int | None = ...) -> None: ... + def read(self, size: int) -> bytes: ... + def readline(self) -> bytes: ... + def send(self, data: bytes) -> None: ... + def shutdown(self) -> None: ... + def socket(self) -> _socket: ... + def ssl(self) -> SSLSocket: ... + +class IMAP4_stream(IMAP4): + command: str = ... + def __init__(self, command: str) -> None: ... + host: str = ... + port: int = ... + sock: _socket = ... + file: IO[Any] = ... + process: subprocess.Popen[bytes] = ... + writefile: IO[Any] = ... + readfile: IO[Any] = ... + def open(self, host: str | None = ..., port: int | None = ...) -> None: ... + def read(self, size: int) -> bytes: ... + def readline(self) -> bytes: ... + def send(self, data: bytes) -> None: ... + def shutdown(self) -> None: ... + +class _Authenticator: + mech: Callable[[bytes], bytes] = ... + def __init__(self, mechinst: Callable[[bytes], bytes]) -> None: ... + def process(self, data: str) -> str: ... + def encode(self, inp: bytes) -> str: ... + def decode(self, inp: str) -> bytes: ... + +def Internaldate2tuple(resp: str) -> time.struct_time: ... +def Int2AP(num: int) -> str: ... +def ParseFlags(resp: str) -> Tuple[str]: ... +def Time2Internaldate(date_time: float | time.struct_time | str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/imghdr.pyi b/mypy/typeshed/stdlib/@python2/imghdr.pyi new file mode 100644 index 000000000000..d60cafa4c78f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/imghdr.pyi @@ -0,0 +1,15 @@ +from typing import Any, BinaryIO, Callable, List, Protocol, Text, Union, overload + +class _ReadableBinary(Protocol): + def tell(self) -> int: ... + def read(self, size: int) -> bytes: ... + def seek(self, offset: int) -> Any: ... + +_File = Union[Text, _ReadableBinary] + +@overload +def what(file: _File, h: None = ...) -> str | None: ... +@overload +def what(file: Any, h: bytes) -> str | None: ... + +tests: List[Callable[[bytes, BinaryIO | None], str | None]] diff --git a/mypy/typeshed/stdlib/@python2/imp.pyi b/mypy/typeshed/stdlib/@python2/imp.pyi index 3cd37648b968..128bd900e996 100644 --- a/mypy/typeshed/stdlib/@python2/imp.pyi +++ b/mypy/typeshed/stdlib/@python2/imp.pyi @@ -1,5 +1,5 @@ import types -from typing import IO, Any, Iterable, List, Optional, Tuple +from typing import IO, Any, Iterable, List, Tuple C_BUILTIN: int C_EXTENSION: int @@ -13,7 +13,7 @@ PY_SOURCE: int SEARCH_ERROR: int def acquire_lock() -> None: ... -def find_module(name: str, path: Iterable[str] = ...) -> Optional[Tuple[IO[Any], str, Tuple[str, str, int]]]: ... +def find_module(name: str, path: Iterable[str] = ...) -> Tuple[IO[Any], str, Tuple[str, str, int]] | None: ... def get_magic() -> str: ... def get_suffixes() -> List[Tuple[str, str, int]]: ... def init_builtin(name: str) -> types.ModuleType: ... diff --git a/mypy/typeshed/stdlib/@python2/importlib.pyi b/mypy/typeshed/stdlib/@python2/importlib.pyi index 8bb179a4bd9a..530cb1a3c79c 100644 --- a/mypy/typeshed/stdlib/@python2/importlib.pyi +++ b/mypy/typeshed/stdlib/@python2/importlib.pyi @@ -1,4 +1,4 @@ import types -from typing import Optional, Text +from typing import Text -def import_module(name: Text, package: Optional[Text] = ...) -> types.ModuleType: ... +def import_module(name: Text, package: Text | None = ...) -> types.ModuleType: ... diff --git a/mypy/typeshed/stdlib/@python2/inspect.pyi b/mypy/typeshed/stdlib/@python2/inspect.pyi index 8e95a92cac10..c6118ea8aebb 100644 --- a/mypy/typeshed/stdlib/@python2/inspect.pyi +++ b/mypy/typeshed/stdlib/@python2/inspect.pyi @@ -29,9 +29,9 @@ class ModuleInfo(NamedTuple): mode: str module_type: int -def getmembers(object: object, predicate: Optional[Callable[[Any], bool]] = ...) -> List[Tuple[str, Any]]: ... -def getmoduleinfo(path: Union[str, unicode]) -> Optional[ModuleInfo]: ... -def getmodulename(path: AnyStr) -> Optional[AnyStr]: ... +def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> List[Tuple[str, Any]]: ... +def getmoduleinfo(path: str | unicode) -> ModuleInfo | None: ... +def getmodulename(path: AnyStr) -> AnyStr | None: ... def ismodule(object: object) -> bool: ... def isclass(object: object) -> bool: ... def ismethod(object: object) -> bool: ... @@ -55,35 +55,35 @@ _SourceObjectType = Union[ModuleType, Type[Any], MethodType, FunctionType, Trace def findsource(object: _SourceObjectType) -> Tuple[List[str], int]: ... def getabsfile(object: _SourceObjectType) -> str: ... def getblock(lines: Sequence[AnyStr]) -> Sequence[AnyStr]: ... -def getdoc(object: object) -> Optional[str]: ... -def getcomments(object: object) -> Optional[str]: ... +def getdoc(object: object) -> str | None: ... +def getcomments(object: object) -> str | None: ... def getfile(object: _SourceObjectType) -> str: ... -def getmodule(object: object) -> Optional[ModuleType]: ... -def getsourcefile(object: _SourceObjectType) -> Optional[str]: ... +def getmodule(object: object) -> ModuleType | None: ... +def getsourcefile(object: _SourceObjectType) -> str | None: ... def getsourcelines(object: _SourceObjectType) -> Tuple[List[str], int]: ... def getsource(object: _SourceObjectType) -> str: ... def cleandoc(doc: AnyStr) -> AnyStr: ... -def indentsize(line: Union[str, unicode]) -> int: ... +def indentsize(line: str | unicode) -> int: ... # Classes and functions -def getclasstree(classes: List[type], unique: bool = ...) -> List[Union[Tuple[type, Tuple[type, ...]], List[Any]]]: ... +def getclasstree(classes: List[type], unique: bool = ...) -> List[Tuple[type, Tuple[type, ...]] | List[Any]]: ... class ArgSpec(NamedTuple): args: List[str] - varargs: Optional[str] - keywords: Optional[str] + varargs: str | None + keywords: str | None defaults: Tuple[Any, ...] class ArgInfo(NamedTuple): args: List[str] - varargs: Optional[str] - keywords: Optional[str] + varargs: str | None + keywords: str | None locals: Dict[str, Any] class Arguments(NamedTuple): - args: List[Union[str, List[Any]]] - varargs: Optional[str] - keywords: Optional[str] + args: List[str | List[Any]] + varargs: str | None + keywords: str | None def getargs(co: CodeType) -> Arguments: ... def getargspec(func: object) -> ArgSpec: ... @@ -103,13 +103,13 @@ class Traceback(NamedTuple): filename: str lineno: int function: str - code_context: Optional[List[str]] - index: Optional[int] # type: ignore + code_context: List[str] | None + index: int | None # type: ignore _FrameInfo = Tuple[FrameType, str, int, str, Optional[List[str]], Optional[int]] def getouterframes(frame: FrameType, context: int = ...) -> List[_FrameInfo]: ... -def getframeinfo(frame: Union[FrameType, TracebackType], context: int = ...) -> Traceback: ... +def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... def getinnerframes(traceback: TracebackType, context: int = ...) -> List[_FrameInfo]: ... def getlineno(frame: FrameType) -> int: ... def currentframe(depth: int = ...) -> FrameType: ... diff --git a/mypy/typeshed/stdlib/@python2/io.pyi b/mypy/typeshed/stdlib/@python2/io.pyi index 1e29cc67369f..f36138edd598 100644 --- a/mypy/typeshed/stdlib/@python2/io.pyi +++ b/mypy/typeshed/stdlib/@python2/io.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Union +from typing import IO, Any import _io from _io import ( @@ -18,7 +18,7 @@ from _io import ( ) def _OpenWrapper( - file: Union[str, unicode, int], + file: str | unicode | int, mode: unicode = ..., buffering: int = ..., encoding: unicode = ..., diff --git a/mypy/typeshed/stdlib/@python2/itertools.pyi b/mypy/typeshed/stdlib/@python2/itertools.pyi index addb4104419f..12996d44628b 100644 --- a/mypy/typeshed/stdlib/@python2/itertools.pyi +++ b/mypy/typeshed/stdlib/@python2/itertools.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Generic, Iterable, Iterator, Optional, Sequence, Tuple, TypeVar, Union, overload +from typing import Any, Callable, Generic, Iterable, Iterator, Sequence, Tuple, TypeVar, overload _T = TypeVar("_T") _S = TypeVar("_S") @@ -21,16 +21,16 @@ class chain(Iterator[_T], Generic[_T]): def compress(data: Iterable[_T], selectors: Iterable[Any]) -> Iterator[_T]: ... def dropwhile(predicate: Callable[[_T], Any], iterable: Iterable[_T]) -> Iterator[_T]: ... -def ifilter(predicate: Optional[Callable[[_T], Any]], iterable: Iterable[_T]) -> Iterator[_T]: ... -def ifilterfalse(predicate: Optional[Callable[[_T], Any]], iterable: Iterable[_T]) -> Iterator[_T]: ... +def ifilter(predicate: Callable[[_T], Any] | None, iterable: Iterable[_T]) -> Iterator[_T]: ... +def ifilterfalse(predicate: Callable[[_T], Any] | None, iterable: Iterable[_T]) -> Iterator[_T]: ... @overload def groupby(iterable: Iterable[_T], key: None = ...) -> Iterator[Tuple[_T, Iterator[_T]]]: ... @overload def groupby(iterable: Iterable[_T], key: Callable[[_T], _S]) -> Iterator[Tuple[_S, Iterator[_T]]]: ... @overload -def islice(iterable: Iterable[_T], stop: Optional[int]) -> Iterator[_T]: ... +def islice(iterable: Iterable[_T], stop: int | None) -> Iterator[_T]: ... @overload -def islice(iterable: Iterable[_T], start: Optional[int], stop: Optional[int], step: Optional[int] = ...) -> Iterator[_T]: ... +def islice(iterable: Iterable[_T], start: int | None, stop: int | None, step: int | None = ...) -> Iterator[_T]: ... _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") diff --git a/mypy/typeshed/stdlib/@python2/json.pyi b/mypy/typeshed/stdlib/@python2/json.pyi index 2d38e6b47bb8..bfbddb2a6835 100644 --- a/mypy/typeshed/stdlib/@python2/json.pyi +++ b/mypy/typeshed/stdlib/@python2/json.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable, Dict, List, Optional, Text, Tuple, Type, Union +from typing import IO, Any, Callable, Dict, List, Text, Tuple, Type def dumps( obj: Any, @@ -7,56 +7,56 @@ def dumps( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Optional[Type[JSONEncoder]] = ..., - indent: Optional[int] = ..., - separators: Optional[Tuple[str, str]] = ..., + cls: Type[JSONEncoder] | None = ..., + indent: int | None = ..., + separators: Tuple[str, str] | None = ..., encoding: str = ..., - default: Optional[Callable[[Any], Any]] = ..., + default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., **kwds: Any, ) -> str: ... def dump( obj: Any, - fp: Union[IO[str], IO[Text]], + fp: IO[str] | IO[Text], skipkeys: bool = ..., ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Optional[Type[JSONEncoder]] = ..., - indent: Optional[int] = ..., - separators: Optional[Tuple[str, str]] = ..., + cls: Type[JSONEncoder] | None = ..., + indent: int | None = ..., + separators: Tuple[str, str] | None = ..., encoding: str = ..., - default: Optional[Callable[[Any], Any]] = ..., + default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., **kwds: Any, ) -> None: ... def loads( - s: Union[Text, bytes], + s: Text | bytes, encoding: Any = ..., - cls: Optional[Type[JSONDecoder]] = ..., - object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ..., - parse_float: Optional[Callable[[str], Any]] = ..., - parse_int: Optional[Callable[[str], Any]] = ..., - parse_constant: Optional[Callable[[str], Any]] = ..., - object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ..., + cls: Type[JSONDecoder] | None = ..., + object_hook: Callable[[Dict[Any, Any]], Any] | None = ..., + parse_float: Callable[[str], Any] | None = ..., + parse_int: Callable[[str], Any] | None = ..., + parse_constant: Callable[[str], Any] | None = ..., + object_pairs_hook: Callable[[List[Tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... def load( - fp: SupportsRead[Union[Text, bytes]], - encoding: Optional[str] = ..., - cls: Optional[Type[JSONDecoder]] = ..., - object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ..., - parse_float: Optional[Callable[[str], Any]] = ..., - parse_int: Optional[Callable[[str], Any]] = ..., - parse_constant: Optional[Callable[[str], Any]] = ..., - object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ..., + fp: SupportsRead[Text | bytes], + encoding: str | None = ..., + cls: Type[JSONDecoder] | None = ..., + object_hook: Callable[[Dict[Any, Any]], Any] | None = ..., + parse_float: Callable[[str], Any] | None = ..., + parse_int: Callable[[str], Any] | None = ..., + parse_constant: Callable[[str], Any] | None = ..., + object_pairs_hook: Callable[[List[Tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... class JSONDecoder(object): def __init__( self, - encoding: Union[Text, bytes] = ..., + encoding: Text | bytes = ..., object_hook: Callable[..., Any] = ..., parse_float: Callable[[str], float] = ..., parse_int: Callable[[str], int] = ..., @@ -64,8 +64,8 @@ class JSONDecoder(object): strict: bool = ..., object_pairs_hook: Callable[..., Any] = ..., ) -> None: ... - def decode(self, s: Union[Text, bytes], _w: Any = ...) -> Any: ... - def raw_decode(self, s: Union[Text, bytes], idx: int = ...) -> Tuple[Any, Any]: ... + def decode(self, s: Text | bytes, _w: Any = ...) -> Any: ... + def raw_decode(self, s: Text | bytes, idx: int = ...) -> Tuple[Any, Any]: ... class JSONEncoder(object): item_separator: str @@ -75,7 +75,7 @@ class JSONEncoder(object): check_circular: bool allow_nan: bool sort_keys: bool - indent: Optional[int] + indent: int | None def __init__( self, skipkeys: bool = ..., @@ -83,9 +83,9 @@ class JSONEncoder(object): check_circular: bool = ..., allow_nan: bool = ..., sort_keys: bool = ..., - indent: Optional[int] = ..., - separators: Tuple[Union[Text, bytes], Union[Text, bytes]] = ..., - encoding: Union[Text, bytes] = ..., + indent: int | None = ..., + separators: Tuple[Text | bytes, Text | bytes] = ..., + encoding: Text | bytes = ..., default: Callable[..., Any] = ..., ) -> None: ... def default(self, o: Any) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/keyword.pyi b/mypy/typeshed/stdlib/@python2/keyword.pyi new file mode 100644 index 000000000000..e84ea1c919ec --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/keyword.pyi @@ -0,0 +1,5 @@ +from typing import Sequence, Text + +def iskeyword(s: Text) -> bool: ... + +kwlist: Sequence[str] diff --git a/test-data/packages/typedpkg_ns/typedpkg_ns/ns/__init__.py b/mypy/typeshed/stdlib/@python2/lib2to3/__init__.pyi similarity index 100% rename from test-data/packages/typedpkg_ns/typedpkg_ns/ns/__init__.py rename to mypy/typeshed/stdlib/@python2/lib2to3/__init__.pyi diff --git a/test-data/packages/typedpkg_ns/typedpkg_ns/ns/py.typed b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/__init__.pyi similarity index 100% rename from test-data/packages/typedpkg_ns/typedpkg_ns/ns/py.typed rename to mypy/typeshed/stdlib/@python2/lib2to3/pgen2/__init__.pyi diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/driver.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/driver.pyi new file mode 100644 index 000000000000..f36e3dd0a10c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/driver.pyi @@ -0,0 +1,20 @@ +from _typeshed import StrPath +from lib2to3.pgen2.grammar import Grammar +from lib2to3.pytree import _NL, _Convert +from logging import Logger +from typing import IO, Any, Iterable, Text + +class Driver: + grammar: Grammar + logger: Logger + convert: _Convert + def __init__(self, grammar: Grammar, convert: _Convert | None = ..., logger: Logger | None = ...) -> None: ... + def parse_tokens(self, tokens: Iterable[Any], debug: bool = ...) -> _NL: ... + def parse_stream_raw(self, stream: IO[Text], debug: bool = ...) -> _NL: ... + def parse_stream(self, stream: IO[Text], debug: bool = ...) -> _NL: ... + def parse_file(self, filename: StrPath, encoding: Text | None = ..., debug: bool = ...) -> _NL: ... + def parse_string(self, text: Text, debug: bool = ...) -> _NL: ... + +def load_grammar( + gt: Text = ..., gp: Text | None = ..., save: bool = ..., force: bool = ..., logger: Logger | None = ... +) -> Grammar: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi new file mode 100644 index 000000000000..6ec97ce849d2 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi @@ -0,0 +1,26 @@ +from _typeshed import StrPath +from typing import Dict, List, Optional, Text, Tuple, TypeVar + +_P = TypeVar("_P") +_Label = Tuple[int, Optional[Text]] +_DFA = List[List[Tuple[int, int]]] +_DFAS = Tuple[_DFA, Dict[int, int]] + +class Grammar: + symbol2number: Dict[Text, int] + number2symbol: Dict[int, Text] + states: List[_DFA] + dfas: Dict[int, _DFAS] + labels: List[_Label] + keywords: Dict[Text, int] + tokens: Dict[int, int] + symbol2label: Dict[Text, int] + start: int + def __init__(self) -> None: ... + def dump(self, filename: StrPath) -> None: ... + def load(self, filename: StrPath) -> None: ... + def copy(self: _P) -> _P: ... + def report(self) -> None: ... + +opmap_raw: Text +opmap: Dict[Text, Text] diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi new file mode 100644 index 000000000000..160d6fd76f76 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi @@ -0,0 +1,7 @@ +from typing import Dict, Match, Text + +simple_escapes: Dict[Text, Text] + +def escape(m: Match[str]) -> Text: ... +def evalString(s: Text) -> Text: ... +def test() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi new file mode 100644 index 000000000000..eed165db551c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi @@ -0,0 +1,26 @@ +from lib2to3.pgen2.grammar import _DFAS, Grammar +from lib2to3.pytree import _NL, _Convert, _RawNode +from typing import Any, List, Sequence, Set, Text, Tuple + +_Context = Sequence[Any] + +class ParseError(Exception): + msg: Text + type: int + value: Text | None + context: _Context + def __init__(self, msg: Text, type: int, value: Text | None, context: _Context) -> None: ... + +class Parser: + grammar: Grammar + convert: _Convert + stack: List[Tuple[_DFAS, int, _RawNode]] + rootnode: _NL | None + used_names: Set[Text] + def __init__(self, grammar: Grammar, convert: _Convert | None = ...) -> None: ... + def setup(self, start: int | None = ...) -> None: ... + def addtoken(self, type: int, value: Text | None, context: _Context) -> bool: ... + def classify(self, type: int, value: Text | None, context: _Context) -> int: ... + def shift(self, type: int, value: Text | None, newstate: int, context: _Context) -> None: ... + def push(self, type: int, newdfa: _DFAS, newstate: int, context: _Context) -> None: ... + def pop(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi new file mode 100644 index 000000000000..67dbbccdd4a6 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi @@ -0,0 +1,46 @@ +from _typeshed import StrPath +from lib2to3.pgen2 import grammar +from lib2to3.pgen2.tokenize import _TokenInfo +from typing import IO, Any, Dict, Iterable, Iterator, List, NoReturn, Text, Tuple + +class PgenGrammar(grammar.Grammar): ... + +class ParserGenerator: + filename: StrPath + stream: IO[Text] + generator: Iterator[_TokenInfo] + first: Dict[Text, Dict[Text, int]] + def __init__(self, filename: StrPath, stream: IO[Text] | None = ...) -> None: ... + def make_grammar(self) -> PgenGrammar: ... + def make_first(self, c: PgenGrammar, name: Text) -> Dict[int, int]: ... + def make_label(self, c: PgenGrammar, label: Text) -> int: ... + def addfirstsets(self) -> None: ... + def calcfirst(self, name: Text) -> None: ... + def parse(self) -> Tuple[Dict[Text, List[DFAState]], Text]: ... + def make_dfa(self, start: NFAState, finish: NFAState) -> List[DFAState]: ... + def dump_nfa(self, name: Text, start: NFAState, finish: NFAState) -> List[DFAState]: ... + def dump_dfa(self, name: Text, dfa: Iterable[DFAState]) -> None: ... + def simplify_dfa(self, dfa: List[DFAState]) -> None: ... + def parse_rhs(self) -> Tuple[NFAState, NFAState]: ... + def parse_alt(self) -> Tuple[NFAState, NFAState]: ... + def parse_item(self) -> Tuple[NFAState, NFAState]: ... + def parse_atom(self) -> Tuple[NFAState, NFAState]: ... + def expect(self, type: int, value: Any | None = ...) -> Text: ... + def gettoken(self) -> None: ... + def raise_error(self, msg: str, *args: Any) -> NoReturn: ... + +class NFAState: + arcs: List[Tuple[Text | None, NFAState]] + def __init__(self) -> None: ... + def addarc(self, next: NFAState, label: Text | None = ...) -> None: ... + +class DFAState: + nfaset: Dict[NFAState, Any] + isfinal: bool + arcs: Dict[Text, DFAState] + def __init__(self, nfaset: Dict[NFAState, Any], final: NFAState) -> None: ... + def addarc(self, next: DFAState, label: Text) -> None: ... + def unifystate(self, old: DFAState, new: DFAState) -> None: ... + def __eq__(self, other: Any) -> bool: ... + +def generate_grammar(filename: StrPath = ...) -> PgenGrammar: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi new file mode 100644 index 000000000000..3f4e41d49bd5 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi @@ -0,0 +1,63 @@ +from typing import Dict, Text + +ENDMARKER: int +NAME: int +NUMBER: int +STRING: int +NEWLINE: int +INDENT: int +DEDENT: int +LPAR: int +RPAR: int +LSQB: int +RSQB: int +COLON: int +COMMA: int +SEMI: int +PLUS: int +MINUS: int +STAR: int +SLASH: int +VBAR: int +AMPER: int +LESS: int +GREATER: int +EQUAL: int +DOT: int +PERCENT: int +BACKQUOTE: int +LBRACE: int +RBRACE: int +EQEQUAL: int +NOTEQUAL: int +LESSEQUAL: int +GREATEREQUAL: int +TILDE: int +CIRCUMFLEX: int +LEFTSHIFT: int +RIGHTSHIFT: int +DOUBLESTAR: int +PLUSEQUAL: int +MINEQUAL: int +STAREQUAL: int +SLASHEQUAL: int +PERCENTEQUAL: int +AMPEREQUAL: int +VBAREQUAL: int +CIRCUMFLEXEQUAL: int +LEFTSHIFTEQUAL: int +RIGHTSHIFTEQUAL: int +DOUBLESTAREQUAL: int +DOUBLESLASH: int +DOUBLESLASHEQUAL: int +OP: int +COMMENT: int +NL: int +ERRORTOKEN: int +N_TOKENS: int +NT_OFFSET: int +tok_name: Dict[int, Text] + +def ISTERMINAL(x: int) -> bool: ... +def ISNONTERMINAL(x: int) -> bool: ... +def ISEOF(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi new file mode 100644 index 000000000000..477341c1a54e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi @@ -0,0 +1,23 @@ +from lib2to3.pgen2.token import * # noqa +from typing import Callable, Iterable, Iterator, List, Text, Tuple + +_Coord = Tuple[int, int] +_TokenEater = Callable[[int, Text, _Coord, _Coord, Text], None] +_TokenInfo = Tuple[int, Text, _Coord, _Coord, Text] + +class TokenError(Exception): ... +class StopTokenizing(Exception): ... + +def tokenize(readline: Callable[[], Text], tokeneater: _TokenEater = ...) -> None: ... + +class Untokenizer: + tokens: List[Text] + prev_row: int + prev_col: int + def __init__(self) -> None: ... + def add_whitespace(self, start: _Coord) -> None: ... + def untokenize(self, iterable: Iterable[_TokenInfo]) -> Text: ... + def compat(self, token: Tuple[int, Text], iterable: Iterable[_TokenInfo]) -> None: ... + +def untokenize(iterable: Iterable[_TokenInfo]) -> Text: ... +def generate_tokens(readline: Callable[[], Text]) -> Iterator[_TokenInfo]: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pygram.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pygram.pyi new file mode 100644 index 000000000000..bf96a55c41b3 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pygram.pyi @@ -0,0 +1,113 @@ +from lib2to3.pgen2.grammar import Grammar + +class Symbols: + def __init__(self, grammar: Grammar) -> None: ... + +class python_symbols(Symbols): + and_expr: int + and_test: int + annassign: int + arglist: int + argument: int + arith_expr: int + assert_stmt: int + async_funcdef: int + async_stmt: int + atom: int + augassign: int + break_stmt: int + classdef: int + comp_for: int + comp_if: int + comp_iter: int + comp_op: int + comparison: int + compound_stmt: int + continue_stmt: int + decorated: int + decorator: int + decorators: int + del_stmt: int + dictsetmaker: int + dotted_as_name: int + dotted_as_names: int + dotted_name: int + encoding_decl: int + eval_input: int + except_clause: int + exec_stmt: int + expr: int + expr_stmt: int + exprlist: int + factor: int + file_input: int + flow_stmt: int + for_stmt: int + funcdef: int + global_stmt: int + if_stmt: int + import_as_name: int + import_as_names: int + import_from: int + import_name: int + import_stmt: int + lambdef: int + listmaker: int + not_test: int + old_lambdef: int + old_test: int + or_test: int + parameters: int + pass_stmt: int + power: int + print_stmt: int + raise_stmt: int + return_stmt: int + shift_expr: int + simple_stmt: int + single_input: int + sliceop: int + small_stmt: int + star_expr: int + stmt: int + subscript: int + subscriptlist: int + suite: int + term: int + test: int + testlist: int + testlist1: int + testlist_gexp: int + testlist_safe: int + testlist_star_expr: int + tfpdef: int + tfplist: int + tname: int + trailer: int + try_stmt: int + typedargslist: int + varargslist: int + vfpdef: int + vfplist: int + vname: int + while_stmt: int + with_item: int + with_stmt: int + with_var: int + xor_expr: int + yield_arg: int + yield_expr: int + yield_stmt: int + +class pattern_symbols(Symbols): + Alternative: int + Alternatives: int + Details: int + Matcher: int + NegatedUnit: int + Repeater: int + Unit: int + +python_grammar: Grammar +python_grammar_no_print_statement: Grammar +pattern_grammar: Grammar diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi new file mode 100644 index 000000000000..27c64853329e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi @@ -0,0 +1,90 @@ +from lib2to3.pgen2.grammar import Grammar +from typing import Any, Callable, Dict, Iterator, List, Optional, Text, Tuple, TypeVar, Union + +_P = TypeVar("_P") +_NL = Union[Node, Leaf] +_Context = Tuple[Text, int, int] +_Results = Dict[Text, _NL] +_RawNode = Tuple[int, Text, _Context, Optional[List[_NL]]] +_Convert = Callable[[Grammar, _RawNode], Any] + +HUGE: int + +def type_repr(type_num: int) -> Text: ... + +class Base: + type: int + parent: Node | None + prefix: Text + children: List[_NL] + was_changed: bool + was_checked: bool + def __eq__(self, other: Any) -> bool: ... + def _eq(self: _P, other: _P) -> bool: ... + def clone(self: _P) -> _P: ... + def post_order(self) -> Iterator[_NL]: ... + def pre_order(self) -> Iterator[_NL]: ... + def replace(self, new: _NL | List[_NL]) -> None: ... + def get_lineno(self) -> int: ... + def changed(self) -> None: ... + def remove(self) -> int | None: ... + @property + def next_sibling(self) -> _NL | None: ... + @property + def prev_sibling(self) -> _NL | None: ... + def leaves(self) -> Iterator[Leaf]: ... + def depth(self) -> int: ... + def get_suffix(self) -> Text: ... + def get_prefix(self) -> Text: ... + def set_prefix(self, prefix: Text) -> None: ... + +class Node(Base): + fixers_applied: List[Any] + def __init__( + self, + type: int, + children: List[_NL], + context: Any | None = ..., + prefix: Text | None = ..., + fixers_applied: List[Any] | None = ..., + ) -> None: ... + def set_child(self, i: int, child: _NL) -> None: ... + def insert_child(self, i: int, child: _NL) -> None: ... + def append_child(self, child: _NL) -> None: ... + +class Leaf(Base): + lineno: int + column: int + value: Text + fixers_applied: List[Any] + def __init__( + self, type: int, value: Text, context: _Context | None = ..., prefix: Text | None = ..., fixers_applied: List[Any] = ... + ) -> None: ... + +def convert(gr: Grammar, raw_node: _RawNode) -> _NL: ... + +class BasePattern: + type: int + content: Text | None + name: Text | None + def optimize(self) -> BasePattern: ... # sic, subclasses are free to optimize themselves into different patterns + def match(self, node: _NL, results: _Results | None = ...) -> bool: ... + def match_seq(self, nodes: List[_NL], results: _Results | None = ...) -> bool: ... + def generate_matches(self, nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... + +class LeafPattern(BasePattern): + def __init__(self, type: int | None = ..., content: Text | None = ..., name: Text | None = ...) -> None: ... + +class NodePattern(BasePattern): + wildcards: bool + def __init__(self, type: int | None = ..., content: Text | None = ..., name: Text | None = ...) -> None: ... + +class WildcardPattern(BasePattern): + min: int + max: int + def __init__(self, content: Text | None = ..., min: int = ..., max: int = ..., name: Text | None = ...) -> None: ... + +class NegatedPattern(BasePattern): + def __init__(self, content: Text | None = ...) -> None: ... + +def generate_matches(patterns: List[BasePattern], nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... diff --git a/mypy/typeshed/stdlib/@python2/linecache.pyi b/mypy/typeshed/stdlib/@python2/linecache.pyi new file mode 100644 index 000000000000..8628a0c58adc --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/linecache.pyi @@ -0,0 +1,9 @@ +from typing import Any, Dict, List, Text + +_ModuleGlobals = Dict[str, Any] + +def getline(filename: Text, lineno: int, module_globals: _ModuleGlobals | None = ...) -> str: ... +def clearcache() -> None: ... +def getlines(filename: Text, module_globals: _ModuleGlobals | None = ...) -> List[str]: ... +def checkcache(filename: Text | None = ...) -> None: ... +def updatecache(filename: Text, module_globals: _ModuleGlobals | None = ...) -> List[str]: ... diff --git a/mypy/typeshed/stdlib/@python2/locale.pyi b/mypy/typeshed/stdlib/@python2/locale.pyi new file mode 100644 index 000000000000..21a7da166e29 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/locale.pyi @@ -0,0 +1,96 @@ +# workaround for mypy#2010 +from __builtin__ import str as _str +from decimal import Decimal +from typing import Any, Callable, Dict, Iterable, List, Mapping, Sequence, Tuple + +CODESET: int +D_T_FMT: int +D_FMT: int +T_FMT: int +T_FMT_AMPM: int + +DAY_1: int +DAY_2: int +DAY_3: int +DAY_4: int +DAY_5: int +DAY_6: int +DAY_7: int +ABDAY_1: int +ABDAY_2: int +ABDAY_3: int +ABDAY_4: int +ABDAY_5: int +ABDAY_6: int +ABDAY_7: int + +MON_1: int +MON_2: int +MON_3: int +MON_4: int +MON_5: int +MON_6: int +MON_7: int +MON_8: int +MON_9: int +MON_10: int +MON_11: int +MON_12: int +ABMON_1: int +ABMON_2: int +ABMON_3: int +ABMON_4: int +ABMON_5: int +ABMON_6: int +ABMON_7: int +ABMON_8: int +ABMON_9: int +ABMON_10: int +ABMON_11: int +ABMON_12: int + +RADIXCHAR: int +THOUSEP: int +YESEXPR: int +NOEXPR: int +CRNCYSTR: int + +ERA: int +ERA_D_T_FMT: int +ERA_D_FMT: int +ERA_T_FMT: int + +ALT_DIGITS: int + +LC_CTYPE: int +LC_COLLATE: int +LC_TIME: int +LC_MONETARY: int +LC_MESSAGES: int +LC_NUMERIC: int +LC_ALL: int + +CHAR_MAX: int + +class Error(Exception): ... + +def setlocale(category: int, locale: _str | Iterable[_str] | None = ...) -> _str: ... +def localeconv() -> Mapping[_str, int | _str | List[int]]: ... +def nl_langinfo(__key: int) -> _str: ... +def getdefaultlocale(envvars: Tuple[_str, ...] = ...) -> Tuple[_str | None, _str | None]: ... +def getlocale(category: int = ...) -> Sequence[_str]: ... +def getpreferredencoding(do_setlocale: bool = ...) -> _str: ... +def normalize(localename: _str) -> _str: ... +def resetlocale(category: int = ...) -> None: ... +def strcoll(string1: _str, string2: _str) -> int: ... +def strxfrm(string: _str) -> _str: ... +def format(percent: _str, value: float | Decimal, grouping: bool = ..., monetary: bool = ..., *additional: Any) -> _str: ... +def format_string(f: _str, val: Any, grouping: bool = ...) -> _str: ... +def currency(val: int | float | Decimal, symbol: bool = ..., grouping: bool = ..., international: bool = ...) -> _str: ... +def atof(string: _str, func: Callable[[_str], float] = ...) -> float: ... +def atoi(string: _str) -> int: ... +def str(val: float) -> _str: ... + +locale_alias: Dict[_str, _str] # undocumented +locale_encoding_alias: Dict[_str, _str] # undocumented +windows_locale: Dict[int, _str] # undocumented diff --git a/mypy/typeshed/stdlib/@python2/logging/__init__.pyi b/mypy/typeshed/stdlib/@python2/logging/__init__.pyi index 240215528527..f981e2400624 100644 --- a/mypy/typeshed/stdlib/@python2/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/__init__.pyi @@ -1,6 +1,5 @@ import threading -from _typeshed import StrPath -from string import Template +from _typeshed import StrPath, SupportsWrite from time import struct_time from types import FrameType, TracebackType from typing import ( @@ -8,7 +7,7 @@ from typing import ( Any, Callable, Dict, - Iterable, + Generic, List, Mapping, MutableMapping, @@ -16,6 +15,7 @@ from typing import ( Sequence, Text, Tuple, + TypeVar, Union, overload, ) @@ -30,11 +30,11 @@ raiseExceptions: bool logThreads: bool logMultiprocessing: bool logProcesses: bool -_srcfile: Optional[str] +_srcfile: str | None def currentframe() -> FrameType: ... -_levelNames: Dict[Union[int, str], Union[str, int]] # Union[int:str, str:int] +_levelNames: Dict[int | str, str | int] # Union[int:str, str:int] class Filterer(object): filters: List[Filter] @@ -46,7 +46,7 @@ class Filterer(object): class Logger(Filterer): name: str level: int - parent: Union[Logger, PlaceHolder] + parent: Logger | PlaceHolder propagate: bool handlers: List[Handler] disabled: int @@ -56,30 +56,30 @@ class Logger(Filterer): def getEffectiveLevel(self) -> int: ... def getChild(self, suffix: str) -> Logger: ... def debug( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def info( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def warning( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... warn = warning def error( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def critical( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... fatal = critical def log( - self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def exception( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def _log( - self, level: int, msg: Any, args: _ArgsType, exc_info: Optional[_ExcInfoType] = ..., extra: Optional[Dict[str, Any]] = ... + self, level: int, msg: Any, args: _ArgsType, exc_info: _ExcInfoType | None = ..., extra: Dict[str, Any] | None = ... ) -> None: ... # undocumented def filter(self, record: LogRecord) -> bool: ... def addHandler(self, hdlr: Handler) -> None: ... @@ -94,9 +94,9 @@ class Logger(Filterer): lno: int, msg: Any, args: _ArgsType, - exc_info: Optional[_SysExcInfoType], - func: Optional[str] = ..., - extra: Optional[Mapping[str, Any]] = ..., + exc_info: _SysExcInfoType | None, + func: str | None = ..., + extra: Mapping[str, Any] | None = ..., ) -> LogRecord: ... CRITICAL: int @@ -110,9 +110,9 @@ NOTSET: int class Handler(Filterer): level: int # undocumented - formatter: Optional[Formatter] # undocumented - lock: Optional[threading.Lock] # undocumented - name: Optional[str] # undocumented + formatter: Formatter | None # undocumented + lock: threading.Lock | None # undocumented + name: str | None # undocumented def __init__(self, level: _Level = ...) -> None: ... def createLock(self) -> None: ... def acquire(self) -> None: ... @@ -128,12 +128,12 @@ class Handler(Filterer): def emit(self, record: LogRecord) -> None: ... class Formatter: - converter: Callable[[Optional[float]], struct_time] - _fmt: Optional[str] - datefmt: Optional[str] - def __init__(self, fmt: Optional[str] = ..., datefmt: Optional[str] = ...) -> None: ... + converter: Callable[[float | None], struct_time] + _fmt: str | None + datefmt: str | None + def __init__(self, fmt: str | None = ..., datefmt: str | None = ...) -> None: ... def format(self, record: LogRecord) -> str: ... - def formatTime(self, record: LogRecord, datefmt: Optional[str] = ...) -> str: ... + def formatTime(self, record: LogRecord, datefmt: str | None = ...) -> str: ... def formatException(self, ei: _SysExcInfoType) -> str: ... class Filter: @@ -144,8 +144,8 @@ class LogRecord: args: _ArgsType asctime: str created: int - exc_info: Optional[_SysExcInfoType] - exc_text: Optional[str] + exc_info: _SysExcInfoType | None + exc_text: str | None filename: str funcName: str levelname: str @@ -170,93 +170,96 @@ class LogRecord: lineno: int, msg: Any, args: _ArgsType, - exc_info: Optional[_SysExcInfoType], - func: Optional[str] = ..., + exc_info: _SysExcInfoType | None, + func: str | None = ..., ) -> None: ... def getMessage(self) -> str: ... -class LoggerAdapter: - logger: Logger +_L = TypeVar("_L", Logger, LoggerAdapter[Logger], LoggerAdapter[Any]) + +class LoggerAdapter(Generic[_L]): + logger: _L extra: Mapping[str, Any] - def __init__(self, logger: Logger, extra: Mapping[str, Any]) -> None: ... + def __init__(self, logger: _L, extra: Mapping[str, Any]) -> None: ... def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> Tuple[Any, MutableMapping[str, Any]]: ... def debug( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def info( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def warning( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def error( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def exception( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def critical( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def log( - self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def isEnabledFor(self, level: int) -> bool: ... @overload def getLogger() -> Logger: ... @overload -def getLogger(name: Union[Text, str]) -> Logger: ... +def getLogger(name: Text | str) -> Logger: ... def getLoggerClass() -> type: ... -def debug(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> None: ... -def info(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> None: ... -def warning(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> None: ... +def debug(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def info(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def warning(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... warn = warning -def error(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> None: ... -def critical( - msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any -) -> None: ... -def exception( - msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any -) -> None: ... +def error(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def critical(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def exception(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... def log( - level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Optional[Dict[str, Any]] = ..., **kwargs: Any + level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... fatal = critical def disable(level: int) -> None: ... def addLevelName(level: int, levelName: str) -> None: ... -def getLevelName(level: Union[int, str]) -> Any: ... +def getLevelName(level: int | str) -> Any: ... def makeLogRecord(dict: Mapping[str, Any]) -> LogRecord: ... @overload def basicConfig() -> None: ... @overload def basicConfig( *, - filename: Optional[str] = ..., + filename: str | None = ..., filemode: str = ..., format: str = ..., - datefmt: Optional[str] = ..., - level: Optional[_Level] = ..., + datefmt: str | None = ..., + level: _Level | None = ..., stream: IO[str] = ..., ) -> None: ... def shutdown(handlerList: Sequence[Any] = ...) -> None: ... # handlerList is undocumented def setLoggerClass(klass: type) -> None: ... def captureWarnings(capture: bool) -> None: ... -class StreamHandler(Handler): - stream: IO[str] # undocumented - def __init__(self, stream: Optional[IO[str]] = ...) -> None: ... +_StreamT = TypeVar("_StreamT", bound=SupportsWrite[str]) + +class StreamHandler(Handler, Generic[_StreamT]): + stream: _StreamT # undocumented + @overload + def __init__(self: StreamHandler[IO[str]], stream: None = ...) -> None: ... + @overload + def __init__(self: StreamHandler[_StreamT], stream: _StreamT) -> None: ... class FileHandler(StreamHandler): baseFilename: str # undocumented mode: str # undocumented - encoding: Optional[str] # undocumented + encoding: str | None # undocumented delay: bool # undocumented - def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ... + def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... def _open(self) -> IO[Any]: ... class NullHandler(Handler): ... diff --git a/mypy/typeshed/stdlib/@python2/logging/config.pyi b/mypy/typeshed/stdlib/@python2/logging/config.pyi index 695001221d79..03707bb98f55 100644 --- a/mypy/typeshed/stdlib/@python2/logging/config.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/config.pyi @@ -1,14 +1,10 @@ -from _typeshed import AnyPath, StrPath +from _typeshed import StrPath from threading import Thread -from typing import IO, Any, Callable, Dict, Optional, Union - -from ConfigParser import RawConfigParser +from typing import IO, Any, Dict _Path = StrPath def dictConfig(config: Dict[str, Any]) -> None: ... -def fileConfig( - fname: Union[str, IO[str]], defaults: Optional[Dict[str, str]] = ..., disable_existing_loggers: bool = ... -) -> None: ... +def fileConfig(fname: str | IO[str], defaults: Dict[str, str] | None = ..., disable_existing_loggers: bool = ...) -> None: ... def listen(port: int = ...) -> Thread: ... def stopListening() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/logging/handlers.pyi b/mypy/typeshed/stdlib/@python2/logging/handlers.pyi index 9403409fce87..d18d57e77af4 100644 --- a/mypy/typeshed/stdlib/@python2/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/handlers.pyi @@ -1,10 +1,7 @@ -import datetime -import ssl from _typeshed import StrPath from logging import FileHandler, Handler, LogRecord -from Queue import Queue from socket import SocketKind, SocketType -from typing import Any, Callable, ClassVar, Dict, List, Optional, Tuple, Union +from typing import Any, ClassVar, Dict, List, Tuple DEFAULT_TCP_LOGGING_PORT: int DEFAULT_UDP_LOGGING_PORT: int @@ -16,7 +13,7 @@ SYSLOG_TCP_PORT: int class WatchedFileHandler(FileHandler): dev: int ino: int - def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ... + def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... def _statstream(self) -> None: ... class RotatingFileHandler(Handler): @@ -26,7 +23,7 @@ class RotatingFileHandler(Handler): mode: str = ..., maxBytes: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., ) -> None: ... def doRollover(self) -> None: ... @@ -38,7 +35,7 @@ class TimedRotatingFileHandler(Handler): when: str = ..., interval: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., utc: bool = ..., ) -> None: ... @@ -87,20 +84,19 @@ class SysLogHandler(Handler): LOG_LOCAL5: int LOG_LOCAL6: int LOG_LOCAL7: int + address: Tuple[str, int] | str # undocumented unixsocket: bool # undocumented socktype: SocketKind # undocumented facility: int # undocumented priority_names: ClassVar[Dict[str, int]] # undocumented facility_names: ClassVar[Dict[str, int]] # undocumented priority_map: ClassVar[Dict[str, str]] # undocumented - def __init__( - self, address: Union[Tuple[str, int], str] = ..., facility: int = ..., socktype: Optional[SocketKind] = ... - ) -> None: ... - def encodePriority(self, facility: Union[int, str], priority: Union[int, str]) -> int: ... + def __init__(self, address: Tuple[str, int] | str = ..., facility: int = ..., socktype: SocketKind | None = ...) -> None: ... + def encodePriority(self, facility: int | str, priority: int | str) -> int: ... def mapPriority(self, levelName: str) -> str: ... class NTEventLogHandler(Handler): - def __init__(self, appname: str, dllname: Optional[str] = ..., logtype: str = ...) -> None: ... + def __init__(self, appname: str, dllname: str | None = ..., logtype: str = ...) -> None: ... def getEventCategory(self, record: LogRecord) -> int: ... # TODO correct return value? def getEventType(self, record: LogRecord) -> int: ... @@ -110,12 +106,12 @@ class SMTPHandler(Handler): # TODO `secure` can also be an empty tuple def __init__( self, - mailhost: Union[str, Tuple[str, int]], + mailhost: str | Tuple[str, int], fromaddr: str, toaddrs: List[str], subject: str, - credentials: Optional[Tuple[str, str]] = ..., - secure: Union[Tuple[str], Tuple[str, str], None] = ..., + credentials: Tuple[str, str] | None = ..., + secure: Tuple[str] | Tuple[str, str] | None = ..., ) -> None: ... def getSubject(self, record: LogRecord) -> str: ... @@ -125,7 +121,7 @@ class BufferingHandler(Handler): def shouldFlush(self, record: LogRecord) -> bool: ... class MemoryHandler(BufferingHandler): - def __init__(self, capacity: int, flushLevel: int = ..., target: Optional[Handler] = ...) -> None: ... + def __init__(self, capacity: int, flushLevel: int = ..., target: Handler | None = ...) -> None: ... def setTarget(self, target: Handler) -> None: ... class HTTPHandler(Handler): diff --git a/mypy/typeshed/stdlib/@python2/macpath.pyi b/mypy/typeshed/stdlib/@python2/macpath.pyi new file mode 100644 index 000000000000..bcb882e23eef --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/macpath.pyi @@ -0,0 +1,55 @@ +from genericpath import ( + commonprefix as commonprefix, + exists as exists, + getatime as getatime, + getctime as getctime, + getmtime as getmtime, + getsize as getsize, + isdir as isdir, + isfile as isfile, +) + +# Re-export common definitions from posixpath to reduce duplication +from posixpath import ( + abspath as abspath, + curdir as curdir, + defpath as defpath, + devnull as devnull, + expanduser as expanduser, + expandvars as expandvars, + extsep as extsep, + isabs as isabs, + lexists as lexists, + pardir as pardir, + pathsep as pathsep, + sep as sep, + splitdrive as splitdrive, + splitext as splitext, + supports_unicode_filenames as supports_unicode_filenames, +) +from typing import AnyStr, Text, Tuple, overload + +altsep: str | None + +def basename(s: AnyStr) -> AnyStr: ... +def dirname(s: AnyStr) -> AnyStr: ... +def normcase(path: AnyStr) -> AnyStr: ... +def normpath(s: AnyStr) -> AnyStr: ... +def realpath(path: AnyStr) -> AnyStr: ... +def islink(s: Text) -> bool: ... + +# Make sure signatures are disjunct, and allow combinations of bytes and unicode. +# (Since Python 2 allows that, too) +# Note that e.g. os.path.join("a", "b", "c", "d", u"e") will still result in +# a type error. +@overload +def join(__p1: bytes, *p: bytes) -> bytes: ... +@overload +def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: Text) -> Text: ... +@overload +def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... +@overload +def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... +@overload +def join(__p1: Text, *p: Text) -> Text: ... +def split(s: AnyStr) -> Tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/macurl2path.pyi b/mypy/typeshed/stdlib/@python2/macurl2path.pyi new file mode 100644 index 000000000000..6aac6dfeace5 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/macurl2path.pyi @@ -0,0 +1,3 @@ +def url2pathname(pathname: str) -> str: ... +def pathname2url(pathname: str) -> str: ... +def _pncomp2url(component: str | bytes) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/mailbox.pyi b/mypy/typeshed/stdlib/@python2/mailbox.pyi new file mode 100644 index 000000000000..18a66fa964c4 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/mailbox.pyi @@ -0,0 +1,187 @@ +import email.message +from types import TracebackType +from typing import ( + IO, + Any, + AnyStr, + Callable, + Dict, + Generic, + Iterable, + Iterator, + List, + Mapping, + Protocol, + Sequence, + Text, + Tuple, + Type, + TypeVar, + Union, + overload, +) +from typing_extensions import Literal + +_T = TypeVar("_T") +_MessageT = TypeVar("_MessageT", bound=Message) +_MessageData = Union[email.message.Message, bytes, str, IO[str], IO[bytes]] + +class _HasIteritems(Protocol): + def iteritems(self) -> Iterator[Tuple[str, _MessageData]]: ... + +class _HasItems(Protocol): + def items(self) -> Iterator[Tuple[str, _MessageData]]: ... + +linesep: bytes + +class Mailbox(Generic[_MessageT]): + + _path: bytes | str # undocumented + _factory: Callable[[IO[Any]], _MessageT] | None # undocumented + def __init__(self, path: Text, factory: Callable[[IO[Any]], _MessageT] | None = ..., create: bool = ...) -> None: ... + def add(self, message: _MessageData) -> str: ... + def remove(self, key: str) -> None: ... + def __delitem__(self, key: str) -> None: ... + def discard(self, key: str) -> None: ... + def __setitem__(self, key: str, message: _MessageData) -> None: ... + @overload + def get(self, key: str, default: None = ...) -> _MessageT | None: ... + @overload + def get(self, key: str, default: _T) -> _MessageT | _T: ... + def __getitem__(self, key: str) -> _MessageT: ... + def get_message(self, key: str) -> _MessageT: ... + def get_string(self, key: str) -> str: ... + def get_bytes(self, key: str) -> bytes: ... + # As '_ProxyFile' doesn't implement the full IO spec, and BytesIO is incompatible with it, get_file return is Any here + def get_file(self, key: str) -> Any: ... + def iterkeys(self) -> Iterator[str]: ... + def keys(self) -> List[str]: ... + def itervalues(self) -> Iterator[_MessageT]: ... + def __iter__(self) -> Iterator[_MessageT]: ... + def values(self) -> List[_MessageT]: ... + def iteritems(self) -> Iterator[Tuple[str, _MessageT]]: ... + def items(self) -> List[Tuple[str, _MessageT]]: ... + def __contains__(self, key: str) -> bool: ... + def __len__(self) -> int: ... + def clear(self) -> None: ... + @overload + def pop(self, key: str, default: None = ...) -> _MessageT | None: ... + @overload + def pop(self, key: str, default: _T = ...) -> _MessageT | _T: ... + def popitem(self) -> Tuple[str, _MessageT]: ... + def update(self, arg: _HasIteritems | _HasItems | Iterable[Tuple[str, _MessageData]] | None = ...) -> None: ... + def flush(self) -> None: ... + def lock(self) -> None: ... + def unlock(self) -> None: ... + def close(self) -> None: ... + +class Maildir(Mailbox[MaildirMessage]): + + colon: str + def __init__(self, dirname: Text, factory: Callable[[IO[Any]], MaildirMessage] | None = ..., create: bool = ...) -> None: ... + def get_file(self, key: str) -> _ProxyFile[bytes]: ... + def list_folders(self) -> List[str]: ... + def get_folder(self, folder: Text) -> Maildir: ... + def add_folder(self, folder: Text) -> Maildir: ... + def remove_folder(self, folder: Text) -> None: ... + def clean(self) -> None: ... + def next(self) -> str | None: ... + +class _singlefileMailbox(Mailbox[_MessageT]): ... + +class _mboxMMDF(_singlefileMailbox[_MessageT]): + def get_file(self, key: str, from_: bool = ...) -> _PartialFile[bytes]: ... + def get_bytes(self, key: str, from_: bool = ...) -> bytes: ... + def get_string(self, key: str, from_: bool = ...) -> str: ... + +class mbox(_mboxMMDF[mboxMessage]): + def __init__(self, path: Text, factory: Callable[[IO[Any]], mboxMessage] | None = ..., create: bool = ...) -> None: ... + +class MMDF(_mboxMMDF[MMDFMessage]): + def __init__(self, path: Text, factory: Callable[[IO[Any]], MMDFMessage] | None = ..., create: bool = ...) -> None: ... + +class MH(Mailbox[MHMessage]): + def __init__(self, path: Text, factory: Callable[[IO[Any]], MHMessage] | None = ..., create: bool = ...) -> None: ... + def get_file(self, key: str) -> _ProxyFile[bytes]: ... + def list_folders(self) -> List[str]: ... + def get_folder(self, folder: Text) -> MH: ... + def add_folder(self, folder: Text) -> MH: ... + def remove_folder(self, folder: Text) -> None: ... + def get_sequences(self) -> Dict[str, List[int]]: ... + def set_sequences(self, sequences: Mapping[str, Sequence[int]]) -> None: ... + def pack(self) -> None: ... + +class Babyl(_singlefileMailbox[BabylMessage]): + def __init__(self, path: Text, factory: Callable[[IO[Any]], BabylMessage] | None = ..., create: bool = ...) -> None: ... + def get_file(self, key: str) -> IO[bytes]: ... + def get_labels(self) -> List[str]: ... + +class Message(email.message.Message): + def __init__(self, message: _MessageData | None = ...) -> None: ... + +class MaildirMessage(Message): + def get_subdir(self) -> str: ... + def set_subdir(self, subdir: Literal["new", "cur"]) -> None: ... + def get_flags(self) -> str: ... + def set_flags(self, flags: Iterable[str]) -> None: ... + def add_flag(self, flag: str) -> None: ... + def remove_flag(self, flag: str) -> None: ... + def get_date(self) -> int: ... + def set_date(self, date: float) -> None: ... + def get_info(self) -> str: ... + def set_info(self, info: str) -> None: ... + +class _mboxMMDFMessage(Message): + def get_from(self) -> str: ... + def set_from(self, from_: str, time_: bool | Tuple[int, int, int, int, int, int, int, int, int] | None = ...) -> None: ... + def get_flags(self) -> str: ... + def set_flags(self, flags: Iterable[str]) -> None: ... + def add_flag(self, flag: str) -> None: ... + def remove_flag(self, flag: str) -> None: ... + +class mboxMessage(_mboxMMDFMessage): ... + +class MHMessage(Message): + def get_sequences(self) -> List[str]: ... + def set_sequences(self, sequences: Iterable[str]) -> None: ... + def add_sequence(self, sequence: str) -> None: ... + def remove_sequence(self, sequence: str) -> None: ... + +class BabylMessage(Message): + def get_labels(self) -> List[str]: ... + def set_labels(self, labels: Iterable[str]) -> None: ... + def add_label(self, label: str) -> None: ... + def remove_label(self, label: str) -> None: ... + def get_visible(self) -> Message: ... + def set_visible(self, visible: _MessageData) -> None: ... + def update_visible(self) -> None: ... + +class MMDFMessage(_mboxMMDFMessage): ... + +class _ProxyFile(Generic[AnyStr]): + def __init__(self, f: IO[AnyStr], pos: int | None = ...) -> None: ... + def read(self, size: int | None = ...) -> AnyStr: ... + def read1(self, size: int | None = ...) -> AnyStr: ... + def readline(self, size: int | None = ...) -> AnyStr: ... + def readlines(self, sizehint: int | None = ...) -> List[AnyStr]: ... + def __iter__(self) -> Iterator[AnyStr]: ... + def tell(self) -> int: ... + def seek(self, offset: int, whence: int = ...) -> None: ... + def close(self) -> None: ... + def __enter__(self) -> _ProxyFile[AnyStr]: ... + def __exit__(self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... + def readable(self) -> bool: ... + def writable(self) -> bool: ... + def seekable(self) -> bool: ... + def flush(self) -> None: ... + @property + def closed(self) -> bool: ... + +class _PartialFile(_ProxyFile[AnyStr]): + def __init__(self, f: IO[AnyStr], start: int | None = ..., stop: int | None = ...) -> None: ... + +class Error(Exception): ... +class NoSuchMailboxError(Error): ... +class NotEmptyError(Error): ... +class ExternalClashError(Error): ... +class FormatError(Error): ... diff --git a/mypy/typeshed/stdlib/@python2/mailcap.pyi b/mypy/typeshed/stdlib/@python2/mailcap.pyi new file mode 100644 index 000000000000..b29854f3c744 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/mailcap.pyi @@ -0,0 +1,8 @@ +from typing import Dict, List, Mapping, Sequence, Tuple, Union + +_Cap = Dict[str, Union[str, int]] + +def findmatch( + caps: Mapping[str, List[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... +) -> Tuple[str | None, _Cap | None]: ... +def getcaps() -> Dict[str, List[_Cap]]: ... diff --git a/mypy/typeshed/stdlib/@python2/marshal.pyi b/mypy/typeshed/stdlib/@python2/marshal.pyi new file mode 100644 index 000000000000..b2fde674a647 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/marshal.pyi @@ -0,0 +1,8 @@ +from typing import IO, Any + +version: int + +def dump(__value: Any, __file: IO[Any], __version: int = ...) -> None: ... +def load(__file: IO[Any]) -> Any: ... +def dumps(__value: Any, __version: int = ...) -> bytes: ... +def loads(__bytes: bytes) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/math.pyi b/mypy/typeshed/stdlib/@python2/math.pyi new file mode 100644 index 000000000000..caddcedd864b --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/math.pyi @@ -0,0 +1,45 @@ +from typing import Iterable, SupportsFloat, SupportsInt, Tuple + +e: float +pi: float + +def acos(__x: SupportsFloat) -> float: ... +def acosh(__x: SupportsFloat) -> float: ... +def asin(__x: SupportsFloat) -> float: ... +def asinh(__x: SupportsFloat) -> float: ... +def atan(__x: SupportsFloat) -> float: ... +def atan2(__y: SupportsFloat, __x: SupportsFloat) -> float: ... +def atanh(__x: SupportsFloat) -> float: ... +def ceil(__x: SupportsFloat) -> float: ... +def copysign(__x: SupportsFloat, __y: SupportsFloat) -> float: ... +def cos(__x: SupportsFloat) -> float: ... +def cosh(__x: SupportsFloat) -> float: ... +def degrees(__x: SupportsFloat) -> float: ... +def erf(__x: SupportsFloat) -> float: ... +def erfc(__x: SupportsFloat) -> float: ... +def exp(__x: SupportsFloat) -> float: ... +def expm1(__x: SupportsFloat) -> float: ... +def fabs(__x: SupportsFloat) -> float: ... +def factorial(__x: SupportsInt) -> int: ... +def floor(__x: SupportsFloat) -> float: ... +def fmod(__x: SupportsFloat, __y: SupportsFloat) -> float: ... +def frexp(__x: SupportsFloat) -> Tuple[float, int]: ... +def fsum(__seq: Iterable[float]) -> float: ... +def gamma(__x: SupportsFloat) -> float: ... +def hypot(__x: SupportsFloat, __y: SupportsFloat) -> float: ... +def isinf(__x: SupportsFloat) -> bool: ... +def isnan(__x: SupportsFloat) -> bool: ... +def ldexp(__x: SupportsFloat, __i: int) -> float: ... +def lgamma(__x: SupportsFloat) -> float: ... +def log(x: SupportsFloat, base: SupportsFloat = ...) -> float: ... +def log10(__x: SupportsFloat) -> float: ... +def log1p(__x: SupportsFloat) -> float: ... +def modf(__x: SupportsFloat) -> Tuple[float, float]: ... +def pow(__x: SupportsFloat, __y: SupportsFloat) -> float: ... +def radians(__x: SupportsFloat) -> float: ... +def sin(__x: SupportsFloat) -> float: ... +def sinh(__x: SupportsFloat) -> float: ... +def sqrt(__x: SupportsFloat) -> float: ... +def tan(__x: SupportsFloat) -> float: ... +def tanh(__x: SupportsFloat) -> float: ... +def trunc(__x: SupportsFloat) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/mimetypes.pyi b/mypy/typeshed/stdlib/@python2/mimetypes.pyi new file mode 100644 index 000000000000..a9661dab56ad --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/mimetypes.pyi @@ -0,0 +1,30 @@ +import sys +from typing import IO, Dict, List, Sequence, Text, Tuple + +def guess_type(url: Text, strict: bool = ...) -> Tuple[str | None, str | None]: ... +def guess_all_extensions(type: str, strict: bool = ...) -> List[str]: ... +def guess_extension(type: str, strict: bool = ...) -> str | None: ... +def init(files: Sequence[str] | None = ...) -> None: ... +def read_mime_types(file: str) -> Dict[str, str] | None: ... +def add_type(type: str, ext: str, strict: bool = ...) -> None: ... + +inited: bool +knownfiles: List[str] +suffix_map: Dict[str, str] +encodings_map: Dict[str, str] +types_map: Dict[str, str] +common_types: Dict[str, str] + +class MimeTypes: + suffix_map: Dict[str, str] + encodings_map: Dict[str, str] + types_map: Tuple[Dict[str, str], Dict[str, str]] + types_map_inv: Tuple[Dict[str, str], Dict[str, str]] + def __init__(self, filenames: Tuple[str, ...] = ..., strict: bool = ...) -> None: ... + def guess_extension(self, type: str, strict: bool = ...) -> str | None: ... + def guess_type(self, url: str, strict: bool = ...) -> Tuple[str | None, str | None]: ... + def guess_all_extensions(self, type: str, strict: bool = ...) -> List[str]: ... + def read(self, filename: str, strict: bool = ...) -> None: ... + def readfp(self, fp: IO[str], strict: bool = ...) -> None: ... + if sys.platform == "win32": + def read_windows_registry(self, strict: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/mmap.pyi b/mypy/typeshed/stdlib/@python2/mmap.pyi new file mode 100644 index 000000000000..44369e6c051d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/mmap.pyi @@ -0,0 +1,51 @@ +import sys +from typing import NoReturn, Sequence + +ACCESS_DEFAULT: int +ACCESS_READ: int +ACCESS_WRITE: int +ACCESS_COPY: int + +ALLOCATIONGRANULARITY: int + +if sys.platform == "linux": + MAP_DENYWRITE: int + MAP_EXECUTABLE: int + +if sys.platform != "win32": + MAP_ANON: int + MAP_ANONYMOUS: int + MAP_PRIVATE: int + MAP_SHARED: int + PROT_EXEC: int + PROT_READ: int + PROT_WRITE: int + + PAGESIZE: int + +class mmap(Sequence[bytes]): + if sys.platform == "win32": + def __init__(self, fileno: int, length: int, tagname: str | None = ..., access: int = ..., offset: int = ...) -> None: ... + else: + def __init__( + self, fileno: int, length: int, flags: int = ..., prot: int = ..., access: int = ..., offset: int = ... + ) -> None: ... + def close(self) -> None: ... + def flush(self, offset: int = ..., size: int = ...) -> int: ... + def move(self, dest: int, src: int, count: int) -> None: ... + def read_byte(self) -> bytes: ... + def readline(self) -> bytes: ... + def resize(self, newsize: int) -> None: ... + def seek(self, pos: int, whence: int = ...) -> None: ... + def size(self) -> int: ... + def tell(self) -> int: ... + def write_byte(self, byte: bytes) -> None: ... + def __len__(self) -> int: ... + def find(self, string: bytes, start: int = ..., end: int = ...) -> int: ... + def rfind(self, string: bytes, start: int = ..., stop: int = ...) -> int: ... + def read(self, num: int) -> bytes: ... + def write(self, string: bytes) -> None: ... + def __getitem__(self, index: int | slice) -> bytes: ... + def __getslice__(self, i: int | None, j: int | None) -> bytes: ... + def __delitem__(self, index: int | slice) -> NoReturn: ... + def __setitem__(self, index: int | slice, object: bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/modulefinder.pyi b/mypy/typeshed/stdlib/@python2/modulefinder.pyi new file mode 100644 index 000000000000..76fd014daf6e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/modulefinder.pyi @@ -0,0 +1,63 @@ +from types import CodeType +from typing import IO, Any, Container, Dict, Iterable, List, Sequence, Tuple + +LOAD_CONST: int # undocumented +IMPORT_NAME: int # undocumented +STORE_NAME: int # undocumented +STORE_GLOBAL: int # undocumented +STORE_OPS: Tuple[int, int] # undocumented +EXTENDED_ARG: int # undocumented + +packagePathMap: Dict[str, List[str]] # undocumented + +def AddPackagePath(packagename: str, path: str) -> None: ... + +replacePackageMap: Dict[str, str] # undocumented + +def ReplacePackage(oldname: str, newname: str) -> None: ... + +class Module: # undocumented + def __init__(self, name: str, file: str | None = ..., path: str | None = ...) -> None: ... + def __repr__(self) -> str: ... + +class ModuleFinder: + + modules: Dict[str, Module] + path: List[str] # undocumented + badmodules: Dict[str, Dict[str, int]] # undocumented + debug: int # undocumented + indent: int # undocumented + excludes: Container[str] # undocumented + replace_paths: Sequence[Tuple[str, str]] # undocumented + def __init__( + self, + path: List[str] | None = ..., + debug: int = ..., + excludes: Container[str] = ..., + replace_paths: Sequence[Tuple[str, str]] = ..., + ) -> None: ... + def msg(self, level: int, str: str, *args: Any) -> None: ... # undocumented + def msgin(self, *args: Any) -> None: ... # undocumented + def msgout(self, *args: Any) -> None: ... # undocumented + def run_script(self, pathname: str) -> None: ... + def load_file(self, pathname: str) -> None: ... # undocumented + def import_hook( + self, name: str, caller: Module | None = ..., fromlist: List[str] | None = ..., level: int = ... + ) -> Module | None: ... # undocumented + def determine_parent(self, caller: Module | None, level: int = ...) -> Module | None: ... # undocumented + def find_head_package(self, parent: Module, name: str) -> Tuple[Module, str]: ... # undocumented + def load_tail(self, q: Module, tail: str) -> Module: ... # undocumented + def ensure_fromlist(self, m: Module, fromlist: Iterable[str], recursive: int = ...) -> None: ... # undocumented + def find_all_submodules(self, m: Module) -> Iterable[str]: ... # undocumented + def import_module(self, partname: str, fqname: str, parent: Module) -> Module | None: ... # undocumented + def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: Tuple[str, str, str]) -> Module: ... # undocumented + def scan_code(self, co: CodeType, m: Module) -> None: ... # undocumented + def load_package(self, fqname: str, pathname: str) -> Module: ... # undocumented + def add_module(self, fqname: str) -> Module: ... # undocumented + def find_module( + self, name: str, path: str | None, parent: Module | None = ... + ) -> Tuple[IO[Any] | None, str | None, Tuple[str, str, int]]: ... # undocumented + def report(self) -> None: ... + def any_missing(self) -> List[str]: ... # undocumented + def any_missing_maybe(self) -> Tuple[List[str], List[str]]: ... # undocumented + def replace_paths_in_code(self, co: CodeType) -> CodeType: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi b/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi new file mode 100644 index 000000000000..fa6757696845 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi @@ -0,0 +1,175 @@ +import sys +from types import ModuleType +from typing import Any, Container, Dict, Iterable, List, Sequence, Set, Tuple, Type +from typing_extensions import Literal + +if sys.platform == "win32": + from _msi import _Database + + AMD64: bool + Itanium: bool + Win64: bool + + datasizemask: Literal[0x00FF] + type_valid: Literal[0x0100] + type_localizable: Literal[0x0200] + typemask: Literal[0x0C00] + type_long: Literal[0x0000] + type_short: Literal[0x0400] + type_string: Literal[0x0C00] + type_binary: Literal[0x0800] + type_nullable: Literal[0x1000] + type_key: Literal[0x2000] + knownbits: Literal[0x3FFF] + class Table: + + name: str + fields: List[Tuple[int, str, int]] + def __init__(self, name: str) -> None: ... + def add_field(self, index: int, name: str, type: int) -> None: ... + def sql(self) -> str: ... + def create(self, db: _Database) -> None: ... + class _Unspecified: ... + def change_sequence( + seq: Sequence[Tuple[str, str | None, int]], + action: str, + seqno: int | Type[_Unspecified] = ..., + cond: str | Type[_Unspecified] = ..., + ) -> None: ... + def add_data(db: _Database, table: str, values: Iterable[Tuple[Any, ...]]) -> None: ... + def add_stream(db: _Database, name: str, path: str) -> None: ... + def init_database( + name: str, schema: ModuleType, ProductName: str, ProductCode: str, ProductVersion: str, Manufacturer: str + ) -> _Database: ... + def add_tables(db: _Database, module: ModuleType) -> None: ... + def make_id(str: str) -> str: ... + def gen_uuid() -> str: ... + class CAB: + + name: str + files: List[Tuple[str, str]] + filenames: Set[str] + index: int + def __init__(self, name: str) -> None: ... + def gen_id(self, file: str) -> str: ... + def append(self, full: str, file: str, logical: str) -> Tuple[int, str]: ... + def commit(self, db: _Database) -> None: ... + _directories: Set[str] + class Directory: + + db: _Database + cab: CAB + basedir: str + physical: str + logical: str + component: str | None + short_names: Set[str] + ids: Set[str] + keyfiles: Dict[str, str] + componentflags: int | None + absolute: str + def __init__( + self, + db: _Database, + cab: CAB, + basedir: str, + physical: str, + _logical: str, + default: str, + componentflags: int | None = ..., + ) -> None: ... + def start_component( + self, + component: str | None = ..., + feature: Feature | None = ..., + flags: int | None = ..., + keyfile: str | None = ..., + uuid: str | None = ..., + ) -> None: ... + def make_short(self, file: str) -> str: ... + def add_file(self, file: str, src: str | None = ..., version: str | None = ..., language: str | None = ...) -> str: ... + def glob(self, pattern: str, exclude: Container[str] | None = ...) -> List[str]: ... + def remove_pyc(self) -> None: ... + class Binary: + + name: str + def __init__(self, fname: str) -> None: ... + def __repr__(self) -> str: ... + class Feature: + + id: str + def __init__( + self, + db: _Database, + id: str, + title: str, + desc: str, + display: int, + level: int = ..., + parent: Feature | None = ..., + directory: str | None = ..., + attributes: int = ..., + ) -> None: ... + def set_current(self) -> None: ... + class Control: + + dlg: Dialog + name: str + def __init__(self, dlg: Dialog, name: str) -> None: ... + def event(self, event: str, argument: str, condition: str = ..., ordering: int | None = ...) -> None: ... + def mapping(self, event: str, attribute: str) -> None: ... + def condition(self, action: str, condition: str) -> None: ... + class RadioButtonGroup(Control): + + property: str + index: int + def __init__(self, dlg: Dialog, name: str, property: str) -> None: ... + def add(self, name: str, x: int, y: int, w: int, h: int, text: str, value: str | None = ...) -> None: ... + class Dialog: + + db: _Database + name: str + x: int + y: int + w: int + h: int + def __init__( + self, + db: _Database, + name: str, + x: int, + y: int, + w: int, + h: int, + attr: int, + title: str, + first: str, + default: str, + cancel: str, + ) -> None: ... + def control( + self, + name: str, + type: str, + x: int, + y: int, + w: int, + h: int, + attr: int, + prop: str | None, + text: str | None, + next: str | None, + help: str | None, + ) -> Control: ... + def text(self, name: str, x: int, y: int, w: int, h: int, attr: int, text: str | None) -> Control: ... + def bitmap(self, name: str, x: int, y: int, w: int, h: int, text: str | None) -> Control: ... + def line(self, name: str, x: int, y: int, w: int, h: int) -> Control: ... + def pushbutton( + self, name: str, x: int, y: int, w: int, h: int, attr: int, text: str | None, next: str | None + ) -> Control: ... + def radiogroup( + self, name: str, x: int, y: int, w: int, h: int, attr: int, prop: str | None, text: str | None, next: str | None + ) -> RadioButtonGroup: ... + def checkbox( + self, name: str, x: int, y: int, w: int, h: int, attr: int, prop: str | None, text: str | None, next: str | None + ) -> Control: ... diff --git a/mypy/typeshed/stdlib/@python2/msilib/schema.pyi b/mypy/typeshed/stdlib/@python2/msilib/schema.pyi new file mode 100644 index 000000000000..d59e9767c3de --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/msilib/schema.pyi @@ -0,0 +1,95 @@ +import sys +from typing import List, Tuple + +if sys.platform == "win32": + from . import Table + + _Validation: Table + ActionText: Table + AdminExecuteSequence: Table + Condition: Table + AdminUISequence: Table + AdvtExecuteSequence: Table + AdvtUISequence: Table + AppId: Table + AppSearch: Table + Property: Table + BBControl: Table + Billboard: Table + Feature: Table + Binary: Table + BindImage: Table + File: Table + CCPSearch: Table + CheckBox: Table + Class: Table + Component: Table + Icon: Table + ProgId: Table + ComboBox: Table + CompLocator: Table + Complus: Table + Directory: Table + Control: Table + Dialog: Table + ControlCondition: Table + ControlEvent: Table + CreateFolder: Table + CustomAction: Table + DrLocator: Table + DuplicateFile: Table + Environment: Table + Error: Table + EventMapping: Table + Extension: Table + MIME: Table + FeatureComponents: Table + FileSFPCatalog: Table + SFPCatalog: Table + Font: Table + IniFile: Table + IniLocator: Table + InstallExecuteSequence: Table + InstallUISequence: Table + IsolatedComponent: Table + LaunchCondition: Table + ListBox: Table + ListView: Table + LockPermissions: Table + Media: Table + MoveFile: Table + MsiAssembly: Table + MsiAssemblyName: Table + MsiDigitalCertificate: Table + MsiDigitalSignature: Table + MsiFileHash: Table + MsiPatchHeaders: Table + ODBCAttribute: Table + ODBCDriver: Table + ODBCDataSource: Table + ODBCSourceAttribute: Table + ODBCTranslator: Table + Patch: Table + PatchPackage: Table + PublishComponent: Table + RadioButton: Table + Registry: Table + RegLocator: Table + RemoveFile: Table + RemoveIniFile: Table + RemoveRegistry: Table + ReserveCost: Table + SelfReg: Table + ServiceControl: Table + ServiceInstall: Table + Shortcut: Table + Signature: Table + TextStyle: Table + TypeLib: Table + UIText: Table + Upgrade: Table + Verb: Table + + tables: List[Table] + + _Validation_records: List[Tuple[str, str, str, int | None, int | None, str | None, int | None, str | None, str | None, str]] diff --git a/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi b/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi new file mode 100644 index 000000000000..e4f400d33233 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi @@ -0,0 +1,14 @@ +import sys +from typing import List, Optional, Tuple + +if sys.platform == "win32": + + _SequenceType = List[Tuple[str, Optional[str], int]] + + AdminExecuteSequence: _SequenceType + AdminUISequence: _SequenceType + AdvtExecuteSequence: _SequenceType + InstallExecuteSequence: _SequenceType + InstallUISequence: _SequenceType + + tables: List[str] diff --git a/mypy/typeshed/stdlib/@python2/msilib/text.pyi b/mypy/typeshed/stdlib/@python2/msilib/text.pyi new file mode 100644 index 000000000000..4ae8ee68184b --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/msilib/text.pyi @@ -0,0 +1,9 @@ +import sys +from typing import List, Tuple + +if sys.platform == "win32": + + ActionText: List[Tuple[str, str, str | None]] + UIText: List[Tuple[str, str | None]] + + tables: List[str] diff --git a/mypy/typeshed/stdlib/@python2/msvcrt.pyi b/mypy/typeshed/stdlib/@python2/msvcrt.pyi new file mode 100644 index 000000000000..ede80c9fbb66 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/msvcrt.pyi @@ -0,0 +1,24 @@ +import sys +from typing import Text + +# This module is only available on Windows +if sys.platform == "win32": + LK_LOCK: int + LK_NBLCK: int + LK_NBRLCK: int + LK_RLCK: int + LK_UNLCK: int + def locking(__fd: int, __mode: int, __nbytes: int) -> None: ... + def setmode(__fd: int, __mode: int) -> int: ... + def open_osfhandle(__handle: int, __flags: int) -> int: ... + def get_osfhandle(__fd: int) -> int: ... + def kbhit() -> bool: ... + def getch() -> bytes: ... + def getwch() -> Text: ... + def getche() -> bytes: ... + def getwche() -> Text: ... + def putch(__char: bytes) -> None: ... + def putwch(__unicode_char: Text) -> None: ... + def ungetch(__char: bytes) -> None: ... + def ungetwch(__unicode_char: Text) -> None: ... + def heapmin() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/__init__.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/__init__.pyi index b4f58920f574..e22e09000de1 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/__init__.pyi @@ -2,7 +2,7 @@ from multiprocessing import pool from multiprocessing.process import Process as Process, active_children as active_children, current_process as current_process from multiprocessing.util import SUBDEBUG as SUBDEBUG, SUBWARNING as SUBWARNING from Queue import Queue as _BaseQueue -from typing import Any, Callable, Iterable, Optional, TypeVar +from typing import Any, Callable, Iterable, TypeVar class ProcessError(Exception): ... class BufferTooShort(ProcessError): ... @@ -13,8 +13,8 @@ _T = TypeVar("_T") class Queue(_BaseQueue[_T]): def __init__(self, maxsize: int = ...) -> None: ... - def get(self, block: bool = ..., timeout: Optional[float] = ...) -> _T: ... - def put(self, item: _T, block: bool = ..., timeout: Optional[float] = ...) -> None: ... + def get(self, block: bool = ..., timeout: float | None = ...) -> _T: ... + def put(self, item: _T, block: bool = ..., timeout: float | None = ...) -> None: ... def qsize(self) -> int: ... def empty(self) -> bool: ... def full(self) -> bool: ... @@ -29,11 +29,11 @@ def Pipe(duplex: bool = ...): ... def cpu_count() -> int: ... def freeze_support(): ... def get_logger(): ... -def log_to_stderr(level: Optional[Any] = ...): ... +def log_to_stderr(level: Any | None = ...): ... def allow_connection_pickling(): ... def Lock(): ... def RLock(): ... -def Condition(lock: Optional[Any] = ...): ... +def Condition(lock: Any | None = ...): ... def Semaphore(value: int = ...): ... def BoundedSemaphore(value: int = ...): ... def Event(): ... @@ -43,8 +43,8 @@ def RawArray(typecode_or_type, size_or_initializer): ... def Value(typecode_or_type, *args, **kwds): ... def Array(typecode_or_type, size_or_initializer, **kwds): ... def Pool( - processes: Optional[int] = ..., - initializer: Optional[Callable[..., Any]] = ..., + processes: int | None = ..., + initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ..., - maxtasksperchild: Optional[int] = ..., + maxtasksperchild: int | None = ..., ) -> pool.Pool: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi index 8f6b2124094d..80a1456d1be8 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi @@ -1,13 +1,8 @@ import array -import itertools -import sys import threading import weakref -from multiprocessing import TimeoutError, cpu_count -from multiprocessing.dummy.connection import Pipe from Queue import Queue -from threading import BoundedSemaphore, Event, Lock, RLock, Semaphore -from typing import Any, List, Optional, Type +from typing import Any, List class DummyProcess(threading.Thread): _children: weakref.WeakKeyDictionary[Any, Any] @@ -16,7 +11,7 @@ class DummyProcess(threading.Thread): _start_called: bool def __init__(self, group=..., target=..., name=..., args=..., kwargs=...) -> None: ... @property - def exitcode(self) -> Optional[int]: ... + def exitcode(self) -> int | None: ... Process = DummyProcess diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi index 60e456e3918d..ae5e05e9ccdd 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi @@ -1,5 +1,5 @@ from Queue import Queue -from typing import Any, List, Optional, Tuple, Type +from typing import Any, List, Tuple families: List[None] @@ -15,7 +15,7 @@ class Connection(object): def poll(self, timeout=...) -> Any: ... class Listener(object): - _backlog_queue: Optional[Queue[Any]] + _backlog_queue: Queue[Any] | None address: Any def __init__(self, address=..., family=..., backlog=...) -> None: ... def accept(self) -> Connection: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi index b20618ca0291..be9747e89c2f 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi @@ -1,26 +1,26 @@ -from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, TypeVar +from typing import Any, Callable, Dict, Iterable, Iterator, List, TypeVar _T = TypeVar("_T", bound=Pool) class AsyncResult: - def get(self, timeout: Optional[float] = ...) -> Any: ... - def wait(self, timeout: Optional[float] = ...) -> None: ... + def get(self, timeout: float | None = ...) -> Any: ... + def wait(self, timeout: float | None = ...) -> None: ... def ready(self) -> bool: ... def successful(self) -> bool: ... class IMapIterator(Iterator[Any]): def __iter__(self) -> Iterator[Any]: ... - def next(self, timeout: Optional[float] = ...) -> Any: ... + def next(self, timeout: float | None = ...) -> Any: ... class IMapUnorderedIterator(IMapIterator): ... class Pool(object): def __init__( self, - processes: Optional[int] = ..., - initializer: Optional[Callable[..., None]] = ..., + processes: int | None = ..., + initializer: Callable[..., None] | None = ..., initargs: Iterable[Any] = ..., - maxtasksperchild: Optional[int] = ..., + maxtasksperchild: int | None = ..., ) -> None: ... def apply(self, func: Callable[..., Any], args: Iterable[Any] = ..., kwds: Dict[str, Any] = ...) -> Any: ... def apply_async( @@ -28,19 +28,19 @@ class Pool(object): func: Callable[..., Any], args: Iterable[Any] = ..., kwds: Dict[str, Any] = ..., - callback: Optional[Callable[..., None]] = ..., + callback: Callable[..., None] | None = ..., ) -> AsyncResult: ... - def map(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: Optional[int] = ...) -> List[Any]: ... + def map(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: int | None = ...) -> List[Any]: ... def map_async( self, func: Callable[..., Any], iterable: Iterable[Any] = ..., - chunksize: Optional[int] = ..., - callback: Optional[Callable[..., None]] = ..., + chunksize: int | None = ..., + callback: Callable[..., None] | None = ..., ) -> AsyncResult: ... - def imap(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: Optional[int] = ...) -> IMapIterator: ... + def imap(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: int | None = ...) -> IMapIterator: ... def imap_unordered( - self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: Optional[int] = ... + self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: int | None = ... ) -> IMapIterator: ... def close(self) -> None: ... def terminate(self) -> None: ... @@ -48,5 +48,5 @@ class Pool(object): class ThreadPool(Pool): def __init__( - self, processes: Optional[int] = ..., initializer: Optional[Callable[..., Any]] = ..., initargs: Iterable[Any] = ... + self, processes: int | None = ..., initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/process.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/process.pyi index 9ab9628e0e32..2cb691342580 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/process.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/process.pyi @@ -1,16 +1,14 @@ -from typing import Any, Optional +from typing import Any def current_process(): ... def active_children(): ... class Process: - def __init__( - self, group: Optional[Any] = ..., target: Optional[Any] = ..., name: Optional[Any] = ..., args=..., kwargs=... - ): ... + def __init__(self, group: Any | None = ..., target: Any | None = ..., name: Any | None = ..., args=..., kwargs=...): ... def run(self): ... def start(self): ... def terminate(self): ... - def join(self, timeout: Optional[Any] = ...): ... + def join(self, timeout: Any | None = ...): ... def is_alive(self): ... @property def name(self): ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/util.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/util.pyi index 9520022e2962..6976bc3e6cf4 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/util.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/util.pyi @@ -1,5 +1,5 @@ import threading -from typing import Any, Optional +from typing import Any SUBDEBUG: Any SUBWARNING: Any @@ -9,13 +9,13 @@ def debug(msg, *args): ... def info(msg, *args): ... def sub_warning(msg, *args): ... def get_logger(): ... -def log_to_stderr(level: Optional[Any] = ...): ... +def log_to_stderr(level: Any | None = ...): ... def get_temp_dir(): ... def register_after_fork(obj, func): ... class Finalize: - def __init__(self, obj, callback, args=..., kwargs: Optional[Any] = ..., exitpriority: Optional[Any] = ...): ... - def __call__(self, wr: Optional[Any] = ...): ... + def __init__(self, obj, callback, args=..., kwargs: Any | None = ..., exitpriority: Any | None = ...): ... + def __call__(self, wr: Any | None = ...): ... def cancel(self): ... def still_active(self): ... diff --git a/mypy/typeshed/stdlib/@python2/netrc.pyi b/mypy/typeshed/stdlib/@python2/netrc.pyi new file mode 100644 index 000000000000..3033c2f78955 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/netrc.pyi @@ -0,0 +1,16 @@ +from typing import Dict, List, Optional, Text, Tuple + +class NetrcParseError(Exception): + filename: str | None + lineno: int | None + msg: str + def __init__(self, msg: str, filename: Text | None = ..., lineno: int | None = ...) -> None: ... + +# (login, account, password) tuple +_NetrcTuple = Tuple[str, Optional[str], Optional[str]] + +class netrc: + hosts: Dict[str, _NetrcTuple] + macros: Dict[str, List[str]] + def __init__(self, file: Text | None = ...) -> None: ... + def authenticators(self, host: str) -> _NetrcTuple | None: ... diff --git a/mypy/typeshed/stdlib/@python2/nis.pyi b/mypy/typeshed/stdlib/@python2/nis.pyi new file mode 100644 index 000000000000..bc6c2bc07256 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/nis.pyi @@ -0,0 +1,9 @@ +import sys +from typing import Dict, List + +if sys.platform != "win32": + def cat(map: str, domain: str = ...) -> Dict[str, str]: ... + def get_default_domain() -> str: ... + def maps(domain: str = ...) -> List[str]: ... + def match(key: str, map: str, domain: str = ...) -> str: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/nntplib.pyi b/mypy/typeshed/stdlib/@python2/nntplib.pyi new file mode 100644 index 000000000000..56545d3b88b4 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/nntplib.pyi @@ -0,0 +1,109 @@ +import datetime +import socket +import ssl +from typing import IO, Any, Dict, Iterable, List, NamedTuple, Tuple, TypeVar, Union + +_SelfT = TypeVar("_SelfT", bound=_NNTPBase) +_File = Union[IO[bytes], bytes, str, None] + +class NNTPError(Exception): + response: str + +class NNTPReplyError(NNTPError): ... +class NNTPTemporaryError(NNTPError): ... +class NNTPPermanentError(NNTPError): ... +class NNTPProtocolError(NNTPError): ... +class NNTPDataError(NNTPError): ... + +NNTP_PORT: int +NNTP_SSL_PORT: int + +class GroupInfo(NamedTuple): + group: str + last: str + first: str + flag: str + +class ArticleInfo(NamedTuple): + number: int + message_id: str + lines: List[bytes] + +def decode_header(header_str: str) -> str: ... + +class _NNTPBase: + encoding: str + errors: str + + host: str + file: IO[bytes] + debugging: int + welcome: str + readermode_afterauth: bool + tls_on: bool + authenticated: bool + nntp_implementation: str + nntp_version: int + def __init__(self, file: IO[bytes], host: str, readermode: bool | None = ..., timeout: float = ...) -> None: ... + def __enter__(self: _SelfT) -> _SelfT: ... + def __exit__(self, *args: Any) -> None: ... + def getwelcome(self) -> str: ... + def getcapabilities(self) -> Dict[str, List[str]]: ... + def set_debuglevel(self, level: int) -> None: ... + def debug(self, level: int) -> None: ... + def capabilities(self) -> Tuple[str, Dict[str, List[str]]]: ... + def newgroups(self, date: datetime.date | datetime.datetime, *, file: _File = ...) -> Tuple[str, List[str]]: ... + def newnews(self, group: str, date: datetime.date | datetime.datetime, *, file: _File = ...) -> Tuple[str, List[str]]: ... + def list(self, group_pattern: str | None = ..., *, file: _File = ...) -> Tuple[str, List[str]]: ... + def description(self, group: str) -> str: ... + def descriptions(self, group_pattern: str) -> Tuple[str, Dict[str, str]]: ... + def group(self, name: str) -> Tuple[str, int, int, int, str]: ... + def help(self, *, file: _File = ...) -> Tuple[str, List[str]]: ... + def stat(self, message_spec: Any = ...) -> Tuple[str, int, str]: ... + def next(self) -> Tuple[str, int, str]: ... + def last(self) -> Tuple[str, int, str]: ... + def head(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... + def body(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... + def article(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... + def slave(self) -> str: ... + def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> Tuple[str, List[str]]: ... + def xover(self, start: int, end: int, *, file: _File = ...) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... + def over( + self, message_spec: None | str | List[Any] | Tuple[Any, ...], *, file: _File = ... + ) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... + def xgtitle(self, group: str, *, file: _File = ...) -> Tuple[str, List[Tuple[str, str]]]: ... + def xpath(self, id: Any) -> Tuple[str, str]: ... + def date(self) -> Tuple[str, datetime.datetime]: ... + def post(self, data: bytes | Iterable[bytes]) -> str: ... + def ihave(self, message_id: Any, data: bytes | Iterable[bytes]) -> str: ... + def quit(self) -> str: ... + def login(self, user: str | None = ..., password: str | None = ..., usenetrc: bool = ...) -> None: ... + def starttls(self, context: ssl.SSLContext | None = ...) -> None: ... + +class NNTP(_NNTPBase): + port: int + sock: socket.socket + def __init__( + self, + host: str, + port: int = ..., + user: str | None = ..., + password: str | None = ..., + readermode: bool | None = ..., + usenetrc: bool = ..., + timeout: float = ..., + ) -> None: ... + +class NNTP_SSL(_NNTPBase): + sock: socket.socket + def __init__( + self, + host: str, + port: int = ..., + user: str | None = ..., + password: str | None = ..., + ssl_context: ssl.SSLContext | None = ..., + readermode: bool | None = ..., + usenetrc: bool = ..., + timeout: float = ..., + ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/ntpath.pyi b/mypy/typeshed/stdlib/@python2/ntpath.pyi index f096428602d4..514db760886f 100644 --- a/mypy/typeshed/stdlib/@python2/ntpath.pyi +++ b/mypy/typeshed/stdlib/@python2/ntpath.pyi @@ -1,8 +1,7 @@ import os import sys -from _typeshed import AnyPath, BytesPath, StrPath from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Optional, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload _T = TypeVar("_T") @@ -15,7 +14,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -39,20 +38,20 @@ else: # NOTE: Empty lists results in '' (str) regardless of contained type. # Also, in Python 2 mixed sequences of Text and bytes results in either Text or bytes # So, fall back to Any -def commonprefix(m: Sequence[AnyPath]) -> Any: ... -def lexists(path: AnyPath) -> bool: ... +def commonprefix(m: Sequence[Text]) -> Any: ... +def lexists(path: Text) -> bool: ... # These return float if os.stat_float_times() == True, # but int is a subclass of float. -def getatime(filename: AnyPath) -> float: ... -def getmtime(filename: AnyPath) -> float: ... -def getctime(filename: AnyPath) -> float: ... -def getsize(filename: AnyPath) -> int: ... -def isabs(s: AnyPath) -> bool: ... -def isfile(path: AnyPath) -> bool: ... -def isdir(s: AnyPath) -> bool: ... -def islink(path: AnyPath) -> bool: ... -def ismount(path: AnyPath) -> bool: ... +def getatime(filename: Text) -> float: ... +def getmtime(filename: Text) -> float: ... +def getctime(filename: Text) -> float: ... +def getsize(filename: Text) -> int: ... +def isabs(s: Text) -> bool: ... +def isfile(path: Text) -> bool: ... +def isdir(s: Text) -> bool: ... +def islink(path: Text) -> bool: ... +def ismount(path: Text) -> bool: ... # Make sure signatures are disjunct, and allow combinations of bytes and unicode. # (Since Python 2 allows that, too) @@ -61,18 +60,18 @@ def ismount(path: AnyPath) -> bool: ... @overload def join(__p1: bytes, *p: bytes) -> bytes: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... @overload -def join(__p1: Text, *p: AnyPath) -> Text: ... +def join(__p1: Text, *p: Text) -> Text: ... @overload -def relpath(path: BytesPath, start: Optional[BytesPath] = ...) -> bytes: ... +def relpath(path: str, start: str | None = ...) -> str: ... @overload -def relpath(path: StrPath, start: Optional[StrPath] = ...) -> Text: ... -def samefile(f1: AnyPath, f2: AnyPath) -> bool: ... +def relpath(path: Text, start: Text | None = ...) -> Text: ... +def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/numbers.pyi b/mypy/typeshed/stdlib/@python2/numbers.pyi new file mode 100644 index 000000000000..fb88e076d446 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/numbers.pyi @@ -0,0 +1,119 @@ +# Note: these stubs are incomplete. The more complex type +# signatures are currently omitted. + +from abc import ABCMeta, abstractmethod +from typing import Any, SupportsFloat + +class Number(metaclass=ABCMeta): + @abstractmethod + def __hash__(self) -> int: ... + +class Complex(Number): + @abstractmethod + def __complex__(self) -> complex: ... + def __nonzero__(self) -> bool: ... + @property + @abstractmethod + def real(self) -> Any: ... + @property + @abstractmethod + def imag(self) -> Any: ... + @abstractmethod + def __add__(self, other: Any) -> Any: ... + @abstractmethod + def __radd__(self, other: Any) -> Any: ... + @abstractmethod + def __neg__(self) -> Any: ... + @abstractmethod + def __pos__(self) -> Any: ... + def __sub__(self, other: Any) -> Any: ... + def __rsub__(self, other: Any) -> Any: ... + @abstractmethod + def __mul__(self, other: Any) -> Any: ... + @abstractmethod + def __rmul__(self, other: Any) -> Any: ... + @abstractmethod + def __div__(self, other): ... + @abstractmethod + def __rdiv__(self, other): ... + @abstractmethod + def __truediv__(self, other: Any) -> Any: ... + @abstractmethod + def __rtruediv__(self, other: Any) -> Any: ... + @abstractmethod + def __pow__(self, exponent: Any) -> Any: ... + @abstractmethod + def __rpow__(self, base: Any) -> Any: ... + def __abs__(self) -> Real: ... + def conjugate(self) -> Any: ... + def __eq__(self, other: Any) -> bool: ... + def __ne__(self, other: Any) -> bool: ... + +class Real(Complex, SupportsFloat): + @abstractmethod + def __float__(self) -> float: ... + @abstractmethod + def __trunc__(self) -> int: ... + def __divmod__(self, other: Any) -> Any: ... + def __rdivmod__(self, other: Any) -> Any: ... + @abstractmethod + def __floordiv__(self, other: Any) -> int: ... + @abstractmethod + def __rfloordiv__(self, other: Any) -> int: ... + @abstractmethod + def __mod__(self, other: Any) -> Any: ... + @abstractmethod + def __rmod__(self, other: Any) -> Any: ... + @abstractmethod + def __lt__(self, other: Any) -> bool: ... + @abstractmethod + def __le__(self, other: Any) -> bool: ... + def __complex__(self) -> complex: ... + @property + def real(self) -> Any: ... + @property + def imag(self) -> Any: ... + def conjugate(self) -> Any: ... + +class Rational(Real): + @property + @abstractmethod + def numerator(self) -> int: ... + @property + @abstractmethod + def denominator(self) -> int: ... + def __float__(self) -> float: ... + +class Integral(Rational): + @abstractmethod + def __long__(self) -> long: ... + def __index__(self) -> int: ... + @abstractmethod + def __pow__(self, exponent: Any, modulus: Any | None = ...) -> Any: ... + @abstractmethod + def __lshift__(self, other: Any) -> Any: ... + @abstractmethod + def __rlshift__(self, other: Any) -> Any: ... + @abstractmethod + def __rshift__(self, other: Any) -> Any: ... + @abstractmethod + def __rrshift__(self, other: Any) -> Any: ... + @abstractmethod + def __and__(self, other: Any) -> Any: ... + @abstractmethod + def __rand__(self, other: Any) -> Any: ... + @abstractmethod + def __xor__(self, other: Any) -> Any: ... + @abstractmethod + def __rxor__(self, other: Any) -> Any: ... + @abstractmethod + def __or__(self, other: Any) -> Any: ... + @abstractmethod + def __ror__(self, other: Any) -> Any: ... + @abstractmethod + def __invert__(self) -> Any: ... + def __float__(self) -> float: ... + @property + def numerator(self) -> int: ... + @property + def denominator(self) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/opcode.pyi b/mypy/typeshed/stdlib/@python2/opcode.pyi new file mode 100644 index 000000000000..893dd7c7df9c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/opcode.pyi @@ -0,0 +1,15 @@ +from typing import Dict, List, Sequence + +cmp_op: Sequence[str] +hasconst: List[int] +hasname: List[int] +hasjrel: List[int] +hasjabs: List[int] +haslocal: List[int] +hascompare: List[int] +hasfree: List[int] +opname: List[str] + +opmap: Dict[str, int] +HAVE_ARGUMENT: int +EXTENDED_ARG: int diff --git a/mypy/typeshed/stdlib/@python2/operator.pyi b/mypy/typeshed/stdlib/@python2/operator.pyi new file mode 100644 index 000000000000..76a8a9b6bee4 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/operator.pyi @@ -0,0 +1,190 @@ +from typing import ( + Any, + Container, + Generic, + Mapping, + MutableMapping, + MutableSequence, + Sequence, + SupportsAbs, + Tuple, + TypeVar, + overload, +) + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_K = TypeVar("_K") +_V = TypeVar("_V") + +def lt(__a: Any, __b: Any) -> Any: ... +def le(__a: Any, __b: Any) -> Any: ... +def eq(__a: Any, __b: Any) -> Any: ... +def ne(__a: Any, __b: Any) -> Any: ... +def ge(__a: Any, __b: Any) -> Any: ... +def gt(__a: Any, __b: Any) -> Any: ... +def __lt__(a: Any, b: Any) -> Any: ... +def __le__(a: Any, b: Any) -> Any: ... +def __eq__(a: Any, b: Any) -> Any: ... +def __ne__(a: Any, b: Any) -> Any: ... +def __ge__(a: Any, b: Any) -> Any: ... +def __gt__(a: Any, b: Any) -> Any: ... +def not_(__a: Any) -> bool: ... +def __not__(a: Any) -> bool: ... +def truth(__a: Any) -> bool: ... +def is_(__a: Any, __b: Any) -> bool: ... +def is_not(__a: Any, __b: Any) -> bool: ... +def abs(__a: SupportsAbs[_T]) -> _T: ... +def __abs__(a: SupportsAbs[_T]) -> _T: ... +def add(__a: Any, __b: Any) -> Any: ... +def __add__(a: Any, b: Any) -> Any: ... +def and_(__a: Any, __b: Any) -> Any: ... +def __and__(a: Any, b: Any) -> Any: ... +def div(a: Any, b: Any) -> Any: ... +def __div__(a: Any, b: Any) -> Any: ... +def floordiv(__a: Any, __b: Any) -> Any: ... +def __floordiv__(a: Any, b: Any) -> Any: ... +def index(__a: Any) -> int: ... +def __index__(a: Any) -> int: ... +def inv(__a: Any) -> Any: ... +def invert(__a: Any) -> Any: ... +def __inv__(a: Any) -> Any: ... +def __invert__(a: Any) -> Any: ... +def lshift(__a: Any, __b: Any) -> Any: ... +def __lshift__(a: Any, b: Any) -> Any: ... +def mod(__a: Any, __b: Any) -> Any: ... +def __mod__(a: Any, b: Any) -> Any: ... +def mul(__a: Any, __b: Any) -> Any: ... +def __mul__(a: Any, b: Any) -> Any: ... +def neg(__a: Any) -> Any: ... +def __neg__(a: Any) -> Any: ... +def or_(__a: Any, __b: Any) -> Any: ... +def __or__(a: Any, b: Any) -> Any: ... +def pos(__a: Any) -> Any: ... +def __pos__(a: Any) -> Any: ... +def pow(__a: Any, __b: Any) -> Any: ... +def __pow__(a: Any, b: Any) -> Any: ... +def rshift(__a: Any, __b: Any) -> Any: ... +def __rshift__(a: Any, b: Any) -> Any: ... +def sub(__a: Any, __b: Any) -> Any: ... +def __sub__(a: Any, b: Any) -> Any: ... +def truediv(__a: Any, __b: Any) -> Any: ... +def __truediv__(a: Any, b: Any) -> Any: ... +def xor(__a: Any, __b: Any) -> Any: ... +def __xor__(a: Any, b: Any) -> Any: ... +def concat(__a: Sequence[_T], __b: Sequence[_T]) -> Sequence[_T]: ... +def __concat__(a: Sequence[_T], b: Sequence[_T]) -> Sequence[_T]: ... +def contains(__a: Container[Any], __b: Any) -> bool: ... +def __contains__(a: Container[Any], b: Any) -> bool: ... +def countOf(__a: Container[Any], __b: Any) -> int: ... +@overload +def delitem(__a: MutableSequence[Any], __b: int) -> None: ... +@overload +def delitem(__a: MutableSequence[Any], __b: slice) -> None: ... +@overload +def delitem(__a: MutableMapping[_K, Any], __b: _K) -> None: ... +@overload +def __delitem__(a: MutableSequence[Any], b: int) -> None: ... +@overload +def __delitem__(a: MutableSequence[Any], b: slice) -> None: ... +@overload +def __delitem__(a: MutableMapping[_K, Any], b: _K) -> None: ... +def delslice(a: MutableSequence[Any], b: int, c: int) -> None: ... +def __delslice__(a: MutableSequence[Any], b: int, c: int) -> None: ... +@overload +def getitem(__a: Sequence[_T], __b: int) -> _T: ... +@overload +def getitem(__a: Sequence[_T], __b: slice) -> Sequence[_T]: ... +@overload +def getitem(__a: Mapping[_K, _V], __b: _K) -> _V: ... +@overload +def __getitem__(a: Sequence[_T], b: int) -> _T: ... +@overload +def __getitem__(a: Sequence[_T], b: slice) -> Sequence[_T]: ... +@overload +def __getitem__(a: Mapping[_K, _V], b: _K) -> _V: ... +def getslice(a: Sequence[_T], b: int, c: int) -> Sequence[_T]: ... +def __getslice__(a: Sequence[_T], b: int, c: int) -> Sequence[_T]: ... +def indexOf(__a: Sequence[_T], __b: _T) -> int: ... +def repeat(a: Any, b: int) -> Any: ... +def __repeat__(a: Any, b: int) -> Any: ... +def sequenceIncludes(a: Container[Any], b: Any) -> bool: ... +@overload +def setitem(__a: MutableSequence[_T], __b: int, __c: _T) -> None: ... +@overload +def setitem(__a: MutableSequence[_T], __b: slice, __c: Sequence[_T]) -> None: ... +@overload +def setitem(__a: MutableMapping[_K, _V], __b: _K, __c: _V) -> None: ... +@overload +def __setitem__(a: MutableSequence[_T], b: int, c: _T) -> None: ... +@overload +def __setitem__(a: MutableSequence[_T], b: slice, c: Sequence[_T]) -> None: ... +@overload +def __setitem__(a: MutableMapping[_K, _V], b: _K, c: _V) -> None: ... +def setslice(a: MutableSequence[_T], b: int, c: int, v: Sequence[_T]) -> None: ... +def __setslice__(a: MutableSequence[_T], b: int, c: int, v: Sequence[_T]) -> None: ... + +class attrgetter(Generic[_T_co]): + @overload + def __new__(cls, attr: str) -> attrgetter[Any]: ... + @overload + def __new__(cls, attr: str, __attr2: str) -> attrgetter[Tuple[Any, Any]]: ... + @overload + def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[Tuple[Any, Any, Any]]: ... + @overload + def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[Tuple[Any, Any, Any, Any]]: ... + @overload + def __new__(cls, attr: str, *attrs: str) -> attrgetter[Tuple[Any, ...]]: ... + def __call__(self, obj: Any) -> _T_co: ... + +class itemgetter(Generic[_T_co]): + @overload + def __new__(cls, item: Any) -> itemgetter[Any]: ... + @overload + def __new__(cls, item: Any, __item2: Any) -> itemgetter[Tuple[Any, Any]]: ... + @overload + def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[Tuple[Any, Any, Any]]: ... + @overload + def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[Tuple[Any, Any, Any, Any]]: ... + @overload + def __new__(cls, item: Any, *items: Any) -> itemgetter[Tuple[Any, ...]]: ... + def __call__(self, obj: Any) -> _T_co: ... + +class methodcaller: + def __init__(self, __name: str, *args: Any, **kwargs: Any) -> None: ... + def __call__(self, obj: Any) -> Any: ... + +def iadd(__a: Any, __b: Any) -> Any: ... +def __iadd__(a: Any, b: Any) -> Any: ... +def iand(__a: Any, __b: Any) -> Any: ... +def __iand__(a: Any, b: Any) -> Any: ... +def iconcat(__a: Any, __b: Any) -> Any: ... +def __iconcat__(a: Any, b: Any) -> Any: ... +def idiv(a: Any, b: Any) -> Any: ... +def __idiv__(a: Any, b: Any) -> Any: ... +def ifloordiv(__a: Any, __b: Any) -> Any: ... +def __ifloordiv__(a: Any, b: Any) -> Any: ... +def ilshift(__a: Any, __b: Any) -> Any: ... +def __ilshift__(a: Any, b: Any) -> Any: ... +def imod(__a: Any, __b: Any) -> Any: ... +def __imod__(a: Any, b: Any) -> Any: ... +def imul(__a: Any, __b: Any) -> Any: ... +def __imul__(a: Any, b: Any) -> Any: ... +def ior(__a: Any, __b: Any) -> Any: ... +def __ior__(a: Any, b: Any) -> Any: ... +def ipow(__a: Any, __b: Any) -> Any: ... +def __ipow__(a: Any, b: Any) -> Any: ... +def irepeat(a: Any, b: int) -> Any: ... +def __irepeat__(a: Any, b: int) -> Any: ... +def irshift(__a: Any, __b: Any) -> Any: ... +def __irshift__(a: Any, b: Any) -> Any: ... +def isub(__a: Any, __b: Any) -> Any: ... +def __isub__(a: Any, b: Any) -> Any: ... +def itruediv(__a: Any, __b: Any) -> Any: ... +def __itruediv__(a: Any, b: Any) -> Any: ... +def ixor(__a: Any, __b: Any) -> Any: ... +def __ixor__(a: Any, b: Any) -> Any: ... +def isCallable(x: Any) -> bool: ... +def isMappingType(x: Any) -> bool: ... +def isNumberType(x: Any) -> bool: ... +def isSequenceType(x: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/optparse.pyi b/mypy/typeshed/stdlib/@python2/optparse.pyi new file mode 100644 index 000000000000..08a926e301b3 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/optparse.pyi @@ -0,0 +1,229 @@ +from typing import IO, Any, AnyStr, Callable, Dict, Iterable, List, Mapping, Sequence, Tuple, Type, Union, overload + +# See https://groups.google.com/forum/#!topic/python-ideas/gA1gdj3RZ5g +_Text = Union[str, unicode] + +NO_DEFAULT: Tuple[_Text, ...] +SUPPRESS_HELP: _Text +SUPPRESS_USAGE: _Text + +def check_builtin(option: Option, opt: Any, value: _Text) -> Any: ... +def check_choice(option: Option, opt: Any, value: _Text) -> Any: ... +def isbasestring(x: Any) -> bool: ... + +class OptParseError(Exception): + msg: _Text + def __init__(self, msg: _Text) -> None: ... + +class BadOptionError(OptParseError): + opt_str: _Text + def __init__(self, opt_str: _Text) -> None: ... + +class AmbiguousOptionError(BadOptionError): + possibilities: Iterable[_Text] + def __init__(self, opt_str: _Text, possibilities: Sequence[_Text]) -> None: ... + +class OptionError(OptParseError): + msg: _Text + option_id: _Text + def __init__(self, msg: _Text, option: Option) -> None: ... + +class OptionConflictError(OptionError): ... +class OptionValueError(OptParseError): ... + +class HelpFormatter: + NO_DEFAULT_VALUE: _Text + _long_opt_fmt: _Text + _short_opt_fmt: _Text + current_indent: int + default_tag: _Text + help_position: Any + help_width: Any + indent_increment: int + level: int + max_help_position: int + option_strings: Dict[Option, _Text] + parser: OptionParser + short_first: Any + width: int + def __init__(self, indent_increment: int, max_help_position: int, width: int | None, short_first: int) -> None: ... + def dedent(self) -> None: ... + def expand_default(self, option: Option) -> _Text: ... + def format_description(self, description: _Text) -> _Text: ... + def format_epilog(self, epilog: _Text) -> _Text: ... + def format_heading(self, heading: Any) -> _Text: ... + def format_option(self, option: Option) -> _Text: ... + def format_option_strings(self, option: Option) -> _Text: ... + def format_usage(self, usage: Any) -> _Text: ... + def indent(self) -> None: ... + def set_long_opt_delimiter(self, delim: _Text) -> None: ... + def set_parser(self, parser: OptionParser) -> None: ... + def set_short_opt_delimiter(self, delim: _Text) -> None: ... + def store_option_strings(self, parser: OptionParser) -> None: ... + +class IndentedHelpFormatter(HelpFormatter): + def __init__( + self, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ..., short_first: int = ... + ) -> None: ... + def format_heading(self, heading: _Text) -> _Text: ... + def format_usage(self, usage: _Text) -> _Text: ... + +class TitledHelpFormatter(HelpFormatter): + def __init__( + self, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ..., short_first: int = ... + ) -> None: ... + def format_heading(self, heading: _Text) -> _Text: ... + def format_usage(self, usage: _Text) -> _Text: ... + +class Option: + ACTIONS: Tuple[_Text, ...] + ALWAYS_TYPED_ACTIONS: Tuple[_Text, ...] + ATTRS: List[_Text] + CHECK_METHODS: List[Callable[..., Any]] | None + CONST_ACTIONS: Tuple[_Text, ...] + STORE_ACTIONS: Tuple[_Text, ...] + TYPED_ACTIONS: Tuple[_Text, ...] + TYPES: Tuple[_Text, ...] + TYPE_CHECKER: Dict[_Text, Callable[..., Any]] + _long_opts: List[_Text] + _short_opts: List[_Text] + action: _Text + dest: _Text | None + default: Any + nargs: int + type: Any + callback: Callable[..., Any] | None + callback_args: Tuple[Any, ...] | None + callback_kwargs: Dict[_Text, Any] | None + help: _Text | None + metavar: _Text | None + def __init__(self, *opts: _Text | None, **attrs: Any) -> None: ... + def _check_action(self) -> None: ... + def _check_callback(self) -> None: ... + def _check_choice(self) -> None: ... + def _check_const(self) -> None: ... + def _check_dest(self) -> None: ... + def _check_nargs(self) -> None: ... + def _check_opt_strings(self, opts: Iterable[_Text | None]) -> List[_Text]: ... + def _check_type(self) -> None: ... + def _set_attrs(self, attrs: Dict[_Text, Any]) -> None: ... + def _set_opt_strings(self, opts: Iterable[_Text]) -> None: ... + def check_value(self, opt: _Text, value: Any) -> Any: ... + def convert_value(self, opt: _Text, value: Any) -> Any: ... + def get_opt_string(self) -> _Text: ... + def process(self, opt: Any, value: Any, values: Any, parser: OptionParser) -> int: ... + def take_action(self, action: _Text, dest: _Text, opt: Any, value: Any, values: Any, parser: OptionParser) -> int: ... + def takes_value(self) -> bool: ... + +make_option = Option + +class OptionContainer: + _long_opt: Dict[_Text, Option] + _short_opt: Dict[_Text, Option] + conflict_handler: _Text + defaults: Dict[_Text, Any] + description: Any + option_class: Type[Option] + def __init__(self, option_class: Type[Option], conflict_handler: Any, description: Any) -> None: ... + def _check_conflict(self, option: Any) -> None: ... + def _create_option_mappings(self) -> None: ... + def _share_option_mappings(self, parser: OptionParser) -> None: ... + @overload + def add_option(self, opt: Option) -> Option: ... + @overload + def add_option(self, *args: _Text | None, **kwargs: Any) -> Any: ... + def add_options(self, option_list: Iterable[Option]) -> None: ... + def destroy(self) -> None: ... + def format_description(self, formatter: HelpFormatter | None) -> Any: ... + def format_help(self, formatter: HelpFormatter | None) -> _Text: ... + def format_option_help(self, formatter: HelpFormatter | None) -> _Text: ... + def get_description(self) -> Any: ... + def get_option(self, opt_str: _Text) -> Option | None: ... + def has_option(self, opt_str: _Text) -> bool: ... + def remove_option(self, opt_str: _Text) -> None: ... + def set_conflict_handler(self, handler: Any) -> None: ... + def set_description(self, description: Any) -> None: ... + +class OptionGroup(OptionContainer): + option_list: List[Option] + parser: OptionParser + title: _Text + def __init__(self, parser: OptionParser, title: _Text, description: _Text | None = ...) -> None: ... + def _create_option_list(self) -> None: ... + def set_title(self, title: _Text) -> None: ... + +class Values: + def __init__(self, defaults: Mapping[str, Any] | None = ...) -> None: ... + def _update(self, dict: Mapping[_Text, Any], mode: Any) -> None: ... + def _update_careful(self, dict: Mapping[_Text, Any]) -> None: ... + def _update_loose(self, dict: Mapping[_Text, Any]) -> None: ... + def ensure_value(self, attr: _Text, value: Any) -> Any: ... + def read_file(self, filename: _Text, mode: _Text = ...) -> None: ... + def read_module(self, modname: _Text, mode: _Text = ...) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + +class OptionParser(OptionContainer): + allow_interspersed_args: bool + epilog: _Text | None + formatter: HelpFormatter + largs: List[_Text] | None + option_groups: List[OptionGroup] + option_list: List[Option] + process_default_values: Any + prog: _Text | None + rargs: List[Any] | None + standard_option_list: List[Option] + usage: _Text | None + values: Values | None + version: _Text + def __init__( + self, + usage: _Text | None = ..., + option_list: Iterable[Option] | None = ..., + option_class: Type[Option] = ..., + version: _Text | None = ..., + conflict_handler: _Text = ..., + description: _Text | None = ..., + formatter: HelpFormatter | None = ..., + add_help_option: bool = ..., + prog: _Text | None = ..., + epilog: _Text | None = ..., + ) -> None: ... + def _add_help_option(self) -> None: ... + def _add_version_option(self) -> None: ... + def _create_option_list(self) -> None: ... + def _get_all_options(self) -> List[Option]: ... + def _get_args(self, args: Iterable[Any]) -> List[Any]: ... + def _init_parsing_state(self) -> None: ... + def _match_long_opt(self, opt: _Text) -> _Text: ... + def _populate_option_list(self, option_list: Iterable[Option], add_help: bool = ...) -> None: ... + def _process_args(self, largs: List[Any], rargs: List[Any], values: Values) -> None: ... + def _process_long_opt(self, rargs: List[Any], values: Any) -> None: ... + def _process_short_opts(self, rargs: List[Any], values: Any) -> None: ... + @overload + def add_option_group(self, __opt_group: OptionGroup) -> OptionGroup: ... + @overload + def add_option_group(self, *args: Any, **kwargs: Any) -> OptionGroup: ... + def check_values(self, values: Values, args: List[_Text]) -> Tuple[Values, List[_Text]]: ... + def disable_interspersed_args(self) -> None: ... + def enable_interspersed_args(self) -> None: ... + def error(self, msg: _Text) -> None: ... + def exit(self, status: int = ..., msg: str | None = ...) -> None: ... + def expand_prog_name(self, s: _Text | None) -> Any: ... + def format_epilog(self, formatter: HelpFormatter) -> Any: ... + def format_help(self, formatter: HelpFormatter | None = ...) -> _Text: ... + def format_option_help(self, formatter: HelpFormatter | None = ...) -> _Text: ... + def get_default_values(self) -> Values: ... + def get_option_group(self, opt_str: _Text) -> Any: ... + def get_prog_name(self) -> _Text: ... + def get_usage(self) -> _Text: ... + def get_version(self) -> _Text: ... + def parse_args(self, args: Sequence[AnyStr] | None = ..., values: Values | None = ...) -> Tuple[Values, List[AnyStr]]: ... + def print_usage(self, file: IO[str] | None = ...) -> None: ... + def print_help(self, file: IO[str] | None = ...) -> None: ... + def print_version(self, file: IO[str] | None = ...) -> None: ... + def set_default(self, dest: Any, value: Any) -> None: ... + def set_defaults(self, **kwargs: Any) -> None: ... + def set_process_default_values(self, process: Any) -> None: ... + def set_usage(self, usage: _Text) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/os/__init__.pyi b/mypy/typeshed/stdlib/@python2/os/__init__.pyi index 7b32f5087495..1955c07020de 100644 --- a/mypy/typeshed/stdlib/@python2/os/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/os/__init__.pyi @@ -1,7 +1,6 @@ import sys -from _typeshed import AnyPath, FileDescriptorLike +from _typeshed import FileDescriptorLike from builtins import OSError -from io import TextIOWrapper as _TextIOWrapper from posix import listdir as listdir, stat_result as stat_result # TODO: use this, see https://github.com/python/mypy/issues/3078 from typing import ( IO, @@ -16,9 +15,7 @@ from typing import ( MutableMapping, NamedTuple, NoReturn, - Optional, Sequence, - Set, Text, Tuple, TypeVar, @@ -37,15 +34,6 @@ _T = TypeVar("_T") error = OSError -if sys.version_info >= (3, 2): - supports_bytes_environ: bool - -if sys.version_info >= (3, 3): - supports_dir_fd: Set[Callable[..., Any]] - supports_fd: Set[Callable[..., Any]] - supports_effective_ids: Set[Callable[..., Any]] - supports_follow_symlinks: Set[Callable[..., Any]] - SEEK_SET: int SEEK_CUR: int SEEK_END: int @@ -88,7 +76,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -110,9 +98,6 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): def __len__(self) -> int: ... environ: _Environ[str] -if sys.version_info >= (3, 2): - environb: _Environ[bytes] - if sys.platform != "win32": # Unix only confstr_names: Dict[str, int] @@ -199,11 +184,11 @@ if sys.platform != "win32": def uname() -> Tuple[str, str, str, str, str]: ... @overload -def getenv(key: Text) -> Optional[str]: ... +def getenv(key: Text) -> str | None: ... @overload -def getenv(key: Text, default: _T) -> Union[str, _T]: ... -def putenv(key: Union[bytes, Text], value: Union[bytes, Text]) -> None: ... -def unsetenv(key: Union[bytes, Text]) -> None: ... +def getenv(key: Text, default: _T) -> str | _T: ... +def putenv(key: bytes | Text, value: bytes | Text) -> None: ... +def unsetenv(key: bytes | Text) -> None: ... def fdopen(fd: int, *args, **kwargs) -> IO[Any]: ... def close(fd: int) -> None: ... def closerange(fd_low: int, fd_high: int) -> None: ... @@ -212,44 +197,40 @@ def dup2(fd: int, fd2: int) -> None: ... def fstat(fd: int) -> Any: ... def fsync(fd: FileDescriptorLike) -> None: ... def lseek(fd: int, pos: int, how: int) -> int: ... -def open(file: AnyPath, flags: int, mode: int = ...) -> int: ... +def open(file: Text, flags: int, mode: int = ...) -> int: ... def pipe() -> Tuple[int, int]: ... def read(fd: int, n: int) -> bytes: ... -def write(fd: int, string: Union[bytes, buffer]) -> int: ... -def access(path: AnyPath, mode: int) -> bool: ... -def chdir(path: AnyPath) -> None: ... +def write(fd: int, string: bytes | buffer) -> int: ... +def access(path: Text, mode: int) -> bool: ... +def chdir(path: Text) -> None: ... def fchdir(fd: FileDescriptorLike) -> None: ... def getcwd() -> str: ... def getcwdu() -> unicode: ... -def chmod(path: AnyPath, mode: int) -> None: ... -def link(src: AnyPath, link_name: AnyPath) -> None: ... -def lstat(path: AnyPath) -> Any: ... -def mknod(filename: AnyPath, mode: int = ..., device: int = ...) -> None: ... +def chmod(path: Text, mode: int) -> None: ... +def link(src: Text, link_name: Text) -> None: ... +def lstat(path: Text) -> Any: ... +def mknod(filename: Text, mode: int = ..., device: int = ...) -> None: ... def major(device: int) -> int: ... def minor(device: int) -> int: ... def makedev(major: int, minor: int) -> int: ... -def mkdir(path: AnyPath, mode: int = ...) -> None: ... -def makedirs(path: AnyPath, mode: int = ...) -> None: ... +def mkdir(path: Text, mode: int = ...) -> None: ... +def makedirs(path: Text, mode: int = ...) -> None: ... def readlink(path: AnyStr) -> AnyStr: ... -def remove(path: AnyPath) -> None: ... -def removedirs(path: AnyPath) -> None: ... -def rename(src: AnyPath, dst: AnyPath) -> None: ... -def renames(old: AnyPath, new: AnyPath) -> None: ... -def rmdir(path: AnyPath) -> None: ... -def stat(path: AnyPath) -> Any: ... +def remove(path: Text) -> None: ... +def removedirs(path: Text) -> None: ... +def rename(src: Text, dst: Text) -> None: ... +def renames(old: Text, new: Text) -> None: ... +def rmdir(path: Text) -> None: ... +def stat(path: Text) -> Any: ... @overload def stat_float_times() -> bool: ... @overload def stat_float_times(newvalue: bool) -> None: ... -def symlink(source: AnyPath, link_name: AnyPath) -> None: ... -def unlink(path: AnyPath) -> None: ... +def symlink(source: Text, link_name: Text) -> None: ... +def unlink(path: Text) -> None: ... # TODO: add ns, dir_fd, follow_symlinks argument -if sys.version_info >= (3, 0): - def utime(path: AnyPath, times: Optional[Tuple[float, float]] = ...) -> None: ... - -else: - def utime(path: AnyPath, times: Optional[Tuple[float, float]]) -> None: ... +def utime(path: Text, times: Tuple[float, float] | None) -> None: ... if sys.platform != "win32": # Unix only @@ -257,7 +238,7 @@ if sys.platform != "win32": def fchown(fd: int, uid: int, gid: int) -> None: ... if sys.platform != "darwin": def fdatasync(fd: FileDescriptorLike) -> None: ... # Unix only, not Mac - def fpathconf(fd: int, name: Union[str, int]) -> int: ... + def fpathconf(fd: int, name: str | int) -> int: ... def fstatvfs(fd: int) -> _StatVFS: ... def ftruncate(fd: int, length: int) -> None: ... def isatty(fd: int) -> bool: ... @@ -265,47 +246,37 @@ if sys.platform != "win32": def tcgetpgrp(fd: int) -> int: ... def tcsetpgrp(fd: int, pg: int) -> None: ... def ttyname(fd: int) -> str: ... - def chflags(path: AnyPath, flags: int) -> None: ... - def chroot(path: AnyPath) -> None: ... - def chown(path: AnyPath, uid: int, gid: int) -> None: ... - def lchflags(path: AnyPath, flags: int) -> None: ... - def lchmod(path: AnyPath, mode: int) -> None: ... - def lchown(path: AnyPath, uid: int, gid: int) -> None: ... - def mkfifo(path: AnyPath, mode: int = ...) -> None: ... - def pathconf(path: AnyPath, name: Union[str, int]) -> int: ... - def statvfs(path: AnyPath) -> _StatVFS: ... - -if sys.version_info >= (3, 6): - def walk( - top: Union[AnyStr, PathLike[AnyStr]], - topdown: bool = ..., - onerror: Optional[Callable[[OSError], Any]] = ..., - followlinks: bool = ..., - ) -> Iterator[Tuple[AnyStr, List[AnyStr], List[AnyStr]]]: ... - -else: - def walk( - top: AnyStr, topdown: bool = ..., onerror: Optional[Callable[[OSError], Any]] = ..., followlinks: bool = ... - ) -> Iterator[Tuple[AnyStr, List[AnyStr], List[AnyStr]]]: ... - + def chflags(path: Text, flags: int) -> None: ... + def chroot(path: Text) -> None: ... + def chown(path: Text, uid: int, gid: int) -> None: ... + def lchflags(path: Text, flags: int) -> None: ... + def lchmod(path: Text, mode: int) -> None: ... + def lchown(path: Text, uid: int, gid: int) -> None: ... + def mkfifo(path: Text, mode: int = ...) -> None: ... + def pathconf(path: Text, name: str | int) -> int: ... + def statvfs(path: Text) -> _StatVFS: ... + +def walk( + top: AnyStr, topdown: bool = ..., onerror: Callable[[OSError], Any] | None = ..., followlinks: bool = ... +) -> Iterator[Tuple[AnyStr, List[AnyStr], List[AnyStr]]]: ... def abort() -> NoReturn: ... # These are defined as execl(file, *args) but the first *arg is mandatory. -def execl(file: AnyPath, __arg0: Union[bytes, Text], *args: Union[bytes, Text]) -> NoReturn: ... -def execlp(file: AnyPath, __arg0: Union[bytes, Text], *args: Union[bytes, Text]) -> NoReturn: ... +def execl(file: Text, __arg0: bytes | Text, *args: bytes | Text) -> NoReturn: ... +def execlp(file: Text, __arg0: bytes | Text, *args: bytes | Text) -> NoReturn: ... # These are: execle(file, *args, env) but env is pulled from the last element of the args. -def execle(file: AnyPath, __arg0: Union[bytes, Text], *args: Any) -> NoReturn: ... -def execlpe(file: AnyPath, __arg0: Union[bytes, Text], *args: Any) -> NoReturn: ... +def execle(file: Text, __arg0: bytes | Text, *args: Any) -> NoReturn: ... +def execlpe(file: Text, __arg0: bytes | Text, *args: Any) -> NoReturn: ... # The docs say `args: tuple or list of strings` # The implementation enforces tuple or list so we can't use Sequence. _ExecVArgs = Union[Tuple[Union[bytes, Text], ...], List[bytes], List[Text], List[Union[bytes, Text]]] -def execv(path: AnyPath, args: _ExecVArgs) -> NoReturn: ... -def execve(path: AnyPath, args: _ExecVArgs, env: Mapping[str, str]) -> NoReturn: ... -def execvp(file: AnyPath, args: _ExecVArgs) -> NoReturn: ... -def execvpe(file: AnyPath, args: _ExecVArgs, env: Mapping[str, str]) -> NoReturn: ... +def execv(path: Text, args: _ExecVArgs) -> NoReturn: ... +def execve(path: Text, args: _ExecVArgs, env: Mapping[str, str]) -> NoReturn: ... +def execvp(file: Text, args: _ExecVArgs) -> NoReturn: ... +def execvpe(file: Text, args: _ExecVArgs, env: Mapping[str, str]) -> NoReturn: ... def _exit(n: int) -> NoReturn: ... def kill(pid: int, sig: int) -> None: ... @@ -317,36 +288,28 @@ if sys.platform != "win32": def nice(increment: int) -> int: ... def plock(op: int) -> None: ... # ???op is int? -if sys.version_info >= (3, 0): - class popen(_TextIOWrapper): - # TODO 'b' modes or bytes command not accepted? - def __init__(self, command: str, mode: str = ..., bufsize: int = ...) -> None: ... - def close(self) -> Any: ... # may return int - -else: - def popen(command: str, *args, **kwargs) -> IO[Any]: ... - def popen2(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... - def popen3(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any], IO[Any]]: ... - def popen4(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... - -def spawnl(mode: int, path: AnyPath, arg0: Union[bytes, Text], *args: Union[bytes, Text]) -> int: ... -def spawnle(mode: int, path: AnyPath, arg0: Union[bytes, Text], *args: Any) -> int: ... # Imprecise sig -def spawnv(mode: int, path: AnyPath, args: List[Union[bytes, Text]]) -> int: ... -def spawnve(mode: int, path: AnyPath, args: List[Union[bytes, Text]], env: Mapping[str, str]) -> int: ... -def system(command: AnyPath) -> int: ... +def popen(command: str, *args, **kwargs) -> IO[Any]: ... +def popen2(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... +def popen3(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any], IO[Any]]: ... +def popen4(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... +def spawnl(mode: int, path: Text, arg0: bytes | Text, *args: bytes | Text) -> int: ... +def spawnle(mode: int, path: Text, arg0: bytes | Text, *args: Any) -> int: ... # Imprecise sig +def spawnv(mode: int, path: Text, args: List[bytes | Text]) -> int: ... +def spawnve(mode: int, path: Text, args: List[bytes | Text], env: Mapping[str, str]) -> int: ... +def system(command: Text) -> int: ... def times() -> Tuple[float, float, float, float, float]: ... def waitpid(pid: int, options: int) -> Tuple[int, int]: ... def urandom(n: int) -> bytes: ... if sys.platform == "win32": - def startfile(path: AnyPath, operation: Optional[str] = ...) -> None: ... + def startfile(path: Text, operation: str | None = ...) -> None: ... else: # Unix only - def spawnlp(mode: int, file: AnyPath, arg0: Union[bytes, Text], *args: Union[bytes, Text]) -> int: ... - def spawnlpe(mode: int, file: AnyPath, arg0: Union[bytes, Text], *args: Any) -> int: ... # Imprecise signature - def spawnvp(mode: int, file: AnyPath, args: List[Union[bytes, Text]]) -> int: ... - def spawnvpe(mode: int, file: AnyPath, args: List[Union[bytes, Text]], env: Mapping[str, str]) -> int: ... + def spawnlp(mode: int, file: Text, arg0: bytes | Text, *args: bytes | Text) -> int: ... + def spawnlpe(mode: int, file: Text, arg0: bytes | Text, *args: Any) -> int: ... # Imprecise signature + def spawnvp(mode: int, file: Text, args: List[bytes | Text]) -> int: ... + def spawnvpe(mode: int, file: Text, args: List[bytes | Text], env: Mapping[str, str]) -> int: ... def wait() -> Tuple[int, int]: ... def wait3(options: int) -> Tuple[int, int, Any]: ... def wait4(pid: int, options: int) -> Tuple[int, int, Any]: ... @@ -358,22 +321,13 @@ else: def WEXITSTATUS(status: int) -> int: ... def WSTOPSIG(status: int) -> int: ... def WTERMSIG(status: int) -> int: ... - def confstr(name: Union[str, int]) -> Optional[str]: ... + def confstr(name: str | int) -> str | None: ... def getloadavg() -> Tuple[float, float, float]: ... - def sysconf(name: Union[str, int]) -> int: ... - -if sys.version_info >= (3, 0): - def sched_getaffinity(id: int) -> Set[int]: ... - -if sys.version_info >= (3, 3): - class waitresult: - si_pid: int - def waitid(idtype: int, id: int, options: int) -> waitresult: ... + def sysconf(name: str | int) -> int: ... -if sys.version_info < (3, 0): - def tmpfile() -> IO[Any]: ... - def tmpnam() -> str: ... - def tempnam(dir: str = ..., prefix: str = ...) -> str: ... +def tmpfile() -> IO[Any]: ... +def tmpnam() -> str: ... +def tempnam(dir: str = ..., prefix: str = ...) -> str: ... P_ALL: int WEXITED: int diff --git a/mypy/typeshed/stdlib/@python2/os/path.pyi b/mypy/typeshed/stdlib/@python2/os/path.pyi index c89bc8b69e8d..2ce2f592f0e2 100644 --- a/mypy/typeshed/stdlib/@python2/os/path.pyi +++ b/mypy/typeshed/stdlib/@python2/os/path.pyi @@ -1,7 +1,6 @@ import os import sys -from _typeshed import AnyPath, BytesPath, StrPath -from typing import Any, AnyStr, Callable, List, Optional, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload _T = TypeVar("_T") @@ -14,7 +13,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -38,21 +37,21 @@ else: # NOTE: Empty lists results in '' (str) regardless of contained type. # Also, in Python 2 mixed sequences of Text and bytes results in either Text or bytes # So, fall back to Any -def commonprefix(m: Sequence[AnyPath]) -> Any: ... -def exists(path: AnyPath) -> bool: ... -def lexists(path: AnyPath) -> bool: ... +def commonprefix(m: Sequence[Text]) -> Any: ... +def exists(path: Text) -> bool: ... +def lexists(path: Text) -> bool: ... # These return float if os.stat_float_times() == True, # but int is a subclass of float. -def getatime(filename: AnyPath) -> float: ... -def getmtime(filename: AnyPath) -> float: ... -def getctime(filename: AnyPath) -> float: ... -def getsize(filename: AnyPath) -> int: ... -def isabs(s: AnyPath) -> bool: ... -def isfile(path: AnyPath) -> bool: ... -def isdir(s: AnyPath) -> bool: ... -def islink(path: AnyPath) -> bool: ... -def ismount(path: AnyPath) -> bool: ... +def getatime(filename: Text) -> float: ... +def getmtime(filename: Text) -> float: ... +def getctime(filename: Text) -> float: ... +def getsize(filename: Text) -> int: ... +def isabs(s: Text) -> bool: ... +def isfile(path: Text) -> bool: ... +def isdir(s: Text) -> bool: ... +def islink(path: Text) -> bool: ... +def ismount(path: Text) -> bool: ... # Make sure signatures are disjunct, and allow combinations of bytes and unicode. # (Since Python 2 allows that, too) @@ -61,18 +60,18 @@ def ismount(path: AnyPath) -> bool: ... @overload def join(__p1: bytes, *p: bytes) -> bytes: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... @overload -def join(__p1: Text, *p: AnyPath) -> Text: ... +def join(__p1: Text, *p: Text) -> Text: ... @overload -def relpath(path: BytesPath, start: Optional[BytesPath] = ...) -> bytes: ... +def relpath(path: str, start: str | None = ...) -> str: ... @overload -def relpath(path: StrPath, start: Optional[StrPath] = ...) -> Text: ... -def samefile(f1: AnyPath, f2: AnyPath) -> bool: ... +def relpath(path: Text, start: Text | None = ...) -> Text: ... +def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/os2emxpath.pyi b/mypy/typeshed/stdlib/@python2/os2emxpath.pyi index f096428602d4..514db760886f 100644 --- a/mypy/typeshed/stdlib/@python2/os2emxpath.pyi +++ b/mypy/typeshed/stdlib/@python2/os2emxpath.pyi @@ -1,8 +1,7 @@ import os import sys -from _typeshed import AnyPath, BytesPath, StrPath from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Optional, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload _T = TypeVar("_T") @@ -15,7 +14,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -39,20 +38,20 @@ else: # NOTE: Empty lists results in '' (str) regardless of contained type. # Also, in Python 2 mixed sequences of Text and bytes results in either Text or bytes # So, fall back to Any -def commonprefix(m: Sequence[AnyPath]) -> Any: ... -def lexists(path: AnyPath) -> bool: ... +def commonprefix(m: Sequence[Text]) -> Any: ... +def lexists(path: Text) -> bool: ... # These return float if os.stat_float_times() == True, # but int is a subclass of float. -def getatime(filename: AnyPath) -> float: ... -def getmtime(filename: AnyPath) -> float: ... -def getctime(filename: AnyPath) -> float: ... -def getsize(filename: AnyPath) -> int: ... -def isabs(s: AnyPath) -> bool: ... -def isfile(path: AnyPath) -> bool: ... -def isdir(s: AnyPath) -> bool: ... -def islink(path: AnyPath) -> bool: ... -def ismount(path: AnyPath) -> bool: ... +def getatime(filename: Text) -> float: ... +def getmtime(filename: Text) -> float: ... +def getctime(filename: Text) -> float: ... +def getsize(filename: Text) -> int: ... +def isabs(s: Text) -> bool: ... +def isfile(path: Text) -> bool: ... +def isdir(s: Text) -> bool: ... +def islink(path: Text) -> bool: ... +def ismount(path: Text) -> bool: ... # Make sure signatures are disjunct, and allow combinations of bytes and unicode. # (Since Python 2 allows that, too) @@ -61,18 +60,18 @@ def ismount(path: AnyPath) -> bool: ... @overload def join(__p1: bytes, *p: bytes) -> bytes: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... @overload -def join(__p1: Text, *p: AnyPath) -> Text: ... +def join(__p1: Text, *p: Text) -> Text: ... @overload -def relpath(path: BytesPath, start: Optional[BytesPath] = ...) -> bytes: ... +def relpath(path: str, start: str | None = ...) -> str: ... @overload -def relpath(path: StrPath, start: Optional[StrPath] = ...) -> Text: ... -def samefile(f1: AnyPath, f2: AnyPath) -> bool: ... +def relpath(path: Text, start: Text | None = ...) -> Text: ... +def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi b/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi new file mode 100644 index 000000000000..af3e2c210930 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi @@ -0,0 +1,131 @@ +from typing import Any, List, overload +from typing_extensions import Literal + +AFMT_AC3: int +AFMT_A_LAW: int +AFMT_IMA_ADPCM: int +AFMT_MPEG: int +AFMT_MU_LAW: int +AFMT_QUERY: int +AFMT_S16_BE: int +AFMT_S16_LE: int +AFMT_S16_NE: int +AFMT_S8: int +AFMT_U16_BE: int +AFMT_U16_LE: int +AFMT_U8: int +SNDCTL_COPR_HALT: int +SNDCTL_COPR_LOAD: int +SNDCTL_COPR_RCODE: int +SNDCTL_COPR_RCVMSG: int +SNDCTL_COPR_RDATA: int +SNDCTL_COPR_RESET: int +SNDCTL_COPR_RUN: int +SNDCTL_COPR_SENDMSG: int +SNDCTL_COPR_WCODE: int +SNDCTL_COPR_WDATA: int +SNDCTL_DSP_BIND_CHANNEL: int +SNDCTL_DSP_CHANNELS: int +SNDCTL_DSP_GETBLKSIZE: int +SNDCTL_DSP_GETCAPS: int +SNDCTL_DSP_GETCHANNELMASK: int +SNDCTL_DSP_GETFMTS: int +SNDCTL_DSP_GETIPTR: int +SNDCTL_DSP_GETISPACE: int +SNDCTL_DSP_GETODELAY: int +SNDCTL_DSP_GETOPTR: int +SNDCTL_DSP_GETOSPACE: int +SNDCTL_DSP_GETSPDIF: int +SNDCTL_DSP_GETTRIGGER: int +SNDCTL_DSP_MAPINBUF: int +SNDCTL_DSP_MAPOUTBUF: int +SNDCTL_DSP_NONBLOCK: int +SNDCTL_DSP_POST: int +SNDCTL_DSP_PROFILE: int +SNDCTL_DSP_RESET: int +SNDCTL_DSP_SAMPLESIZE: int +SNDCTL_DSP_SETDUPLEX: int +SNDCTL_DSP_SETFMT: int +SNDCTL_DSP_SETFRAGMENT: int +SNDCTL_DSP_SETSPDIF: int +SNDCTL_DSP_SETSYNCRO: int +SNDCTL_DSP_SETTRIGGER: int +SNDCTL_DSP_SPEED: int +SNDCTL_DSP_STEREO: int +SNDCTL_DSP_SUBDIVIDE: int +SNDCTL_DSP_SYNC: int +SNDCTL_FM_4OP_ENABLE: int +SNDCTL_FM_LOAD_INSTR: int +SNDCTL_MIDI_INFO: int +SNDCTL_MIDI_MPUCMD: int +SNDCTL_MIDI_MPUMODE: int +SNDCTL_MIDI_PRETIME: int +SNDCTL_SEQ_CTRLRATE: int +SNDCTL_SEQ_GETINCOUNT: int +SNDCTL_SEQ_GETOUTCOUNT: int +SNDCTL_SEQ_GETTIME: int +SNDCTL_SEQ_NRMIDIS: int +SNDCTL_SEQ_NRSYNTHS: int +SNDCTL_SEQ_OUTOFBAND: int +SNDCTL_SEQ_PANIC: int +SNDCTL_SEQ_PERCMODE: int +SNDCTL_SEQ_RESET: int +SNDCTL_SEQ_RESETSAMPLES: int +SNDCTL_SEQ_SYNC: int +SNDCTL_SEQ_TESTMIDI: int +SNDCTL_SEQ_THRESHOLD: int +SNDCTL_SYNTH_CONTROL: int +SNDCTL_SYNTH_ID: int +SNDCTL_SYNTH_INFO: int +SNDCTL_SYNTH_MEMAVL: int +SNDCTL_SYNTH_REMOVESAMPLE: int +SNDCTL_TMR_CONTINUE: int +SNDCTL_TMR_METRONOME: int +SNDCTL_TMR_SELECT: int +SNDCTL_TMR_SOURCE: int +SNDCTL_TMR_START: int +SNDCTL_TMR_STOP: int +SNDCTL_TMR_TEMPO: int +SNDCTL_TMR_TIMEBASE: int +SOUND_MIXER_ALTPCM: int +SOUND_MIXER_BASS: int +SOUND_MIXER_CD: int +SOUND_MIXER_DIGITAL1: int +SOUND_MIXER_DIGITAL2: int +SOUND_MIXER_DIGITAL3: int +SOUND_MIXER_IGAIN: int +SOUND_MIXER_IMIX: int +SOUND_MIXER_LINE: int +SOUND_MIXER_LINE1: int +SOUND_MIXER_LINE2: int +SOUND_MIXER_LINE3: int +SOUND_MIXER_MIC: int +SOUND_MIXER_MONITOR: int +SOUND_MIXER_NRDEVICES: int +SOUND_MIXER_OGAIN: int +SOUND_MIXER_PCM: int +SOUND_MIXER_PHONEIN: int +SOUND_MIXER_PHONEOUT: int +SOUND_MIXER_RADIO: int +SOUND_MIXER_RECLEV: int +SOUND_MIXER_SPEAKER: int +SOUND_MIXER_SYNTH: int +SOUND_MIXER_TREBLE: int +SOUND_MIXER_VIDEO: int +SOUND_MIXER_VOLUME: int + +control_labels: List[str] +control_names: List[str] + +# TODO: oss_audio_device return type +@overload +def open(mode: Literal["r", "w", "rw"]) -> Any: ... +@overload +def open(device: str, mode: Literal["r", "w", "rw"]) -> Any: ... + +# TODO: oss_mixer_device return type +def openmixer(device: str = ...) -> Any: ... + +class OSSAudioError(Exception): ... + +error = OSSAudioError diff --git a/mypy/typeshed/stdlib/@python2/parser.pyi b/mypy/typeshed/stdlib/@python2/parser.pyi new file mode 100644 index 000000000000..ff8bf039ee80 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/parser.pyi @@ -0,0 +1,21 @@ +from types import CodeType +from typing import Any, List, Sequence, Text, Tuple + +def expr(source: Text) -> STType: ... +def suite(source: Text) -> STType: ... +def sequence2st(sequence: Sequence[Any]) -> STType: ... +def tuple2st(sequence: Sequence[Any]) -> STType: ... +def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... +def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... +def compilest(st: STType, filename: Text = ...) -> CodeType: ... +def isexpr(st: STType) -> bool: ... +def issuite(st: STType) -> bool: ... + +class ParserError(Exception): ... + +class STType: + def compile(self, filename: Text = ...) -> CodeType: ... + def isexpr(self) -> bool: ... + def issuite(self) -> bool: ... + def tolist(self, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... + def totuple(self, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... diff --git a/mypy/typeshed/stdlib/@python2/pdb.pyi b/mypy/typeshed/stdlib/@python2/pdb.pyi new file mode 100644 index 000000000000..6d3a6d5c5903 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pdb.pyi @@ -0,0 +1,165 @@ +from bdb import Bdb +from cmd import Cmd +from types import FrameType, TracebackType +from typing import IO, Any, Callable, ClassVar, Dict, Iterable, List, Mapping, Tuple, TypeVar + +_T = TypeVar("_T") + +line_prefix: str # undocumented + +class Restart(Exception): ... + +def run(statement: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... +def runeval(expression: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> Any: ... +def runctx(statement: str, globals: Dict[str, Any], locals: Mapping[str, Any]) -> None: ... +def runcall(func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... +def set_trace() -> None: ... +def post_mortem(t: TracebackType | None = ...) -> None: ... +def pm() -> None: ... + +class Pdb(Bdb, Cmd): + # Everything here is undocumented, except for __init__ + + commands_resuming: ClassVar[List[str]] + + aliases: Dict[str, str] + mainpyfile: str + _wait_for_mainpyfile: bool + rcLines: List[str] + commands: Dict[int, List[str]] + commands_doprompt: Dict[int, bool] + commands_silent: Dict[int, bool] + commands_defining: bool + commands_bnum: int | None + lineno: int | None + stack: List[Tuple[FrameType, int]] + curindex: int + curframe: FrameType | None + curframe_locals: Mapping[str, Any] + def __init__( + self, completekey: str = ..., stdin: IO[str] | None = ..., stdout: IO[str] | None = ..., skip: Iterable[str] | None = ... + ) -> None: ... + def forget(self) -> None: ... + def setup(self, f: FrameType | None, tb: TracebackType | None) -> None: ... + def execRcLines(self) -> None: ... + def bp_commands(self, frame: FrameType) -> bool: ... + def interaction(self, frame: FrameType | None, traceback: TracebackType | None) -> None: ... + def displayhook(self, obj: object) -> None: ... + def handle_command_def(self, line: str) -> bool: ... + def defaultFile(self) -> str: ... + def lineinfo(self, identifier: str) -> Tuple[None, None, None] | Tuple[str, str, int]: ... + def checkline(self, filename: str, lineno: int) -> int: ... + def _getval(self, arg: str) -> object: ... + def print_stack_trace(self) -> None: ... + def print_stack_entry(self, frame_lineno: Tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... + def lookupmodule(self, filename: str) -> str | None: ... + def _runscript(self, filename: str) -> None: ... + def do_commands(self, arg: str) -> bool | None: ... + def do_break(self, arg: str, temporary: bool = ...) -> bool | None: ... + def do_tbreak(self, arg: str) -> bool | None: ... + def do_enable(self, arg: str) -> bool | None: ... + def do_disable(self, arg: str) -> bool | None: ... + def do_condition(self, arg: str) -> bool | None: ... + def do_ignore(self, arg: str) -> bool | None: ... + def do_clear(self, arg: str) -> bool | None: ... + def do_where(self, arg: str) -> bool | None: ... + def do_up(self, arg: str) -> bool | None: ... + def do_down(self, arg: str) -> bool | None: ... + def do_until(self, arg: str) -> bool | None: ... + def do_step(self, arg: str) -> bool | None: ... + def do_next(self, arg: str) -> bool | None: ... + def do_run(self, arg: str) -> bool | None: ... + def do_return(self, arg: str) -> bool | None: ... + def do_continue(self, arg: str) -> bool | None: ... + def do_jump(self, arg: str) -> bool | None: ... + def do_debug(self, arg: str) -> bool | None: ... + def do_quit(self, arg: str) -> bool | None: ... + def do_EOF(self, arg: str) -> bool | None: ... + def do_args(self, arg: str) -> bool | None: ... + def do_retval(self, arg: str) -> bool | None: ... + def do_p(self, arg: str) -> bool | None: ... + def do_pp(self, arg: str) -> bool | None: ... + def do_list(self, arg: str) -> bool | None: ... + def do_whatis(self, arg: str) -> bool | None: ... + def do_alias(self, arg: str) -> bool | None: ... + def do_unalias(self, arg: str) -> bool | None: ... + def do_help(self, arg: str) -> bool | None: ... + do_b = do_break + do_cl = do_clear + do_w = do_where + do_bt = do_where + do_u = do_up + do_d = do_down + do_unt = do_until + do_s = do_step + do_n = do_next + do_restart = do_run + do_r = do_return + do_c = do_continue + do_cont = do_continue + do_j = do_jump + do_q = do_quit + do_exit = do_quit + do_a = do_args + do_rv = do_retval + do_l = do_list + do_h = do_help + def help_exec(self) -> None: ... + def help_pdb(self) -> None: ... + def help_help(self) -> None: ... + def help_h(self) -> None: ... + def help_where(self) -> None: ... + def help_w(self) -> None: ... + def help_down(self) -> None: ... + def help_d(self) -> None: ... + def help_up(self) -> None: ... + def help_u(self) -> None: ... + def help_break(self) -> None: ... + def help_b(self) -> None: ... + def help_clear(self) -> None: ... + def help_cl(self) -> None: ... + def help_tbreak(self) -> None: ... + def help_enable(self) -> None: ... + def help_disable(self) -> None: ... + def help_ignore(self) -> None: ... + def help_condition(self) -> None: ... + def help_step(self) -> None: ... + def help_s(self) -> None: ... + def help_until(self) -> None: ... + def help_unt(self) -> None: ... + def help_next(self) -> None: ... + def help_n(self) -> None: ... + def help_return(self) -> None: ... + def help_r(self) -> None: ... + def help_continue(self) -> None: ... + def help_cont(self) -> None: ... + def help_c(self) -> None: ... + def help_jump(self) -> None: ... + def help_j(self) -> None: ... + def help_debug(self) -> None: ... + def help_list(self) -> None: ... + def help_l(self) -> None: ... + def help_args(self) -> None: ... + def help_a(self) -> None: ... + def help_p(self) -> None: ... + def help_pp(self) -> None: ... + def help_run(self) -> None: ... + def help_quit(self) -> None: ... + def help_q(self) -> None: ... + def help_whatis(self) -> None: ... + def help_EOF(self) -> None: ... + def help_alias(self) -> None: ... + def help_unalias(self) -> None: ... + def help_commands(self) -> None: ... + help_bt = help_w + help_restart = help_run + help_exit = help_q + +# undocumented + +def find_function(funcname: str, filename: str) -> Tuple[str, str, int] | None: ... +def main() -> None: ... +def help() -> None: ... + +class _rstr(str): + def __repr__(self) -> _rstr: ... diff --git a/mypy/typeshed/stdlib/@python2/pickle.pyi b/mypy/typeshed/stdlib/@python2/pickle.pyi new file mode 100644 index 000000000000..07e32e64b449 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pickle.pyi @@ -0,0 +1,95 @@ +from typing import IO, Any, Callable, Iterator, Optional, Tuple, Type, Union + +HIGHEST_PROTOCOL: int +bytes_types: Tuple[Type[Any], ...] # undocumented + +def dump(obj: Any, file: IO[bytes], protocol: int | None = ...) -> None: ... +def dumps(obj: Any, protocol: int | None = ...) -> bytes: ... +def load(file: IO[bytes]) -> Any: ... +def loads(string: bytes) -> Any: ... + +class PickleError(Exception): ... +class PicklingError(PickleError): ... +class UnpicklingError(PickleError): ... + +_reducedtype = Union[ + str, + Tuple[Callable[..., Any], Tuple[Any, ...]], + Tuple[Callable[..., Any], Tuple[Any, ...], Any], + Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]]], + Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]], Optional[Iterator[Any]]], +] + +class Pickler: + fast: bool + def __init__(self, file: IO[bytes], protocol: int | None = ...) -> None: ... + def dump(self, __obj: Any) -> None: ... + def clear_memo(self) -> None: ... + def persistent_id(self, obj: Any) -> Any: ... + +class Unpickler: + def __init__(self, file: IO[bytes]) -> None: ... + def load(self) -> Any: ... + def find_class(self, __module_name: str, __global_name: str) -> Any: ... + +MARK: bytes +STOP: bytes +POP: bytes +POP_MARK: bytes +DUP: bytes +FLOAT: bytes +INT: bytes +BININT: bytes +BININT1: bytes +LONG: bytes +BININT2: bytes +NONE: bytes +PERSID: bytes +BINPERSID: bytes +REDUCE: bytes +STRING: bytes +BINSTRING: bytes +SHORT_BINSTRING: bytes +UNICODE: bytes +BINUNICODE: bytes +APPEND: bytes +BUILD: bytes +GLOBAL: bytes +DICT: bytes +EMPTY_DICT: bytes +APPENDS: bytes +GET: bytes +BINGET: bytes +INST: bytes +LONG_BINGET: bytes +LIST: bytes +EMPTY_LIST: bytes +OBJ: bytes +PUT: bytes +BINPUT: bytes +LONG_BINPUT: bytes +SETITEM: bytes +TUPLE: bytes +EMPTY_TUPLE: bytes +SETITEMS: bytes +BINFLOAT: bytes + +TRUE: bytes +FALSE: bytes + +# protocol 2 +PROTO: bytes +NEWOBJ: bytes +EXT1: bytes +EXT2: bytes +EXT4: bytes +TUPLE1: bytes +TUPLE2: bytes +TUPLE3: bytes +NEWTRUE: bytes +NEWFALSE: bytes +LONG1: bytes +LONG4: bytes + +def encode_long(x: int) -> bytes: ... # undocumented +def decode_long(data: bytes) -> int: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/pickletools.pyi b/mypy/typeshed/stdlib/@python2/pickletools.pyi new file mode 100644 index 000000000000..14ec0fdff03a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pickletools.pyi @@ -0,0 +1,124 @@ +from typing import IO, Any, Callable, Iterator, List, MutableMapping, Text, Tuple, Type + +_Reader = Callable[[IO[bytes]], Any] + +UP_TO_NEWLINE: int +TAKEN_FROM_ARGUMENT1: int +TAKEN_FROM_ARGUMENT4: int + +class ArgumentDescriptor(object): + name: str + n: int + reader: _Reader + doc: str + def __init__(self, name: str, n: int, reader: _Reader, doc: str) -> None: ... + +def read_uint1(f: IO[bytes]) -> int: ... + +uint1: ArgumentDescriptor + +def read_uint2(f: IO[bytes]) -> int: ... + +uint2: ArgumentDescriptor + +def read_int4(f: IO[bytes]) -> int: ... + +int4: ArgumentDescriptor + +def read_stringnl(f: IO[bytes], decode: bool = ..., stripquotes: bool = ...) -> bytes | Text: ... + +stringnl: ArgumentDescriptor + +def read_stringnl_noescape(f: IO[bytes]) -> str: ... + +stringnl_noescape: ArgumentDescriptor + +def read_stringnl_noescape_pair(f: IO[bytes]) -> Text: ... + +stringnl_noescape_pair: ArgumentDescriptor + +def read_string1(f: IO[bytes]) -> str: ... + +string1: ArgumentDescriptor + +def read_string4(f: IO[bytes]) -> str: ... + +string4: ArgumentDescriptor + +def read_unicodestringnl(f: IO[bytes]) -> Text: ... + +unicodestringnl: ArgumentDescriptor + +def read_unicodestring4(f: IO[bytes]) -> Text: ... + +unicodestring4: ArgumentDescriptor + +def read_decimalnl_short(f: IO[bytes]) -> int: ... +def read_decimalnl_long(f: IO[bytes]) -> int: ... + +decimalnl_short: ArgumentDescriptor +decimalnl_long: ArgumentDescriptor + +def read_floatnl(f: IO[bytes]) -> float: ... + +floatnl: ArgumentDescriptor + +def read_float8(f: IO[bytes]) -> float: ... + +float8: ArgumentDescriptor + +def read_long1(f: IO[bytes]) -> int: ... + +long1: ArgumentDescriptor + +def read_long4(f: IO[bytes]) -> int: ... + +long4: ArgumentDescriptor + +class StackObject(object): + name: str + obtype: Type[Any] | Tuple[Type[Any], ...] + doc: str + def __init__(self, name: str, obtype: Type[Any] | Tuple[Type[Any], ...], doc: str) -> None: ... + +pyint: StackObject +pylong: StackObject +pyinteger_or_bool: StackObject +pybool: StackObject +pyfloat: StackObject +pystring: StackObject +pyunicode: StackObject +pynone: StackObject +pytuple: StackObject +pylist: StackObject +pydict: StackObject +anyobject: StackObject +markobject: StackObject +stackslice: StackObject + +class OpcodeInfo(object): + name: str + code: str + arg: ArgumentDescriptor | None + stack_before: List[StackObject] + stack_after: List[StackObject] + proto: int + doc: str + def __init__( + self, + name: str, + code: str, + arg: ArgumentDescriptor | None, + stack_before: List[StackObject], + stack_after: List[StackObject], + proto: int, + doc: str, + ) -> None: ... + +opcodes: List[OpcodeInfo] + +def genops(pickle: bytes | IO[bytes]) -> Iterator[Tuple[OpcodeInfo, Any | None, int | None]]: ... +def optimize(p: bytes | IO[bytes]) -> bytes: ... +def dis( + pickle: bytes | IO[bytes], out: IO[str] | None = ..., memo: MutableMapping[int, Any] | None = ..., indentlevel: int = ... +) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pkgutil.pyi b/mypy/typeshed/stdlib/@python2/pkgutil.pyi new file mode 100644 index 000000000000..fd42af916cfe --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pkgutil.pyi @@ -0,0 +1,27 @@ +from _typeshed import SupportsRead +from typing import IO, Any, Callable, Iterable, Iterator, List, Tuple, Union + +Loader = Any +MetaPathFinder = Any +PathEntryFinder = Any + +_ModuleInfoLike = Tuple[Union[MetaPathFinder, PathEntryFinder], str, bool] + +def extend_path(path: List[str], name: str) -> List[str]: ... + +class ImpImporter: + def __init__(self, path: str | None = ...) -> None: ... + +class ImpLoader: + def __init__(self, fullname: str, file: IO[str], filename: str, etc: Tuple[str, str, int]) -> None: ... + +def find_loader(fullname: str) -> Loader | None: ... +def get_importer(path_item: str) -> PathEntryFinder | None: ... +def get_loader(module_or_name: str) -> Loader: ... +def iter_importers(fullname: str = ...) -> Iterator[MetaPathFinder | PathEntryFinder]: ... +def iter_modules(path: Iterable[str] | None = ..., prefix: str = ...) -> Iterator[_ModuleInfoLike]: ... +def read_code(stream: SupportsRead[bytes]) -> Any: ... # undocumented +def walk_packages( + path: Iterable[str] | None = ..., prefix: str = ..., onerror: Callable[[str], None] | None = ... +) -> Iterator[_ModuleInfoLike]: ... +def get_data(package: str, resource: str) -> bytes | None: ... diff --git a/mypy/typeshed/stdlib/@python2/platform.pyi b/mypy/typeshed/stdlib/@python2/platform.pyi index 44bbe4d62aa9..b984a2b2d3d5 100644 --- a/mypy/typeshed/stdlib/@python2/platform.pyi +++ b/mypy/typeshed/stdlib/@python2/platform.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional, Tuple +from typing import Any, Tuple __copyright__: Any DEV_NULL: Any @@ -12,13 +12,13 @@ class _popen: pipe: Any bufsize: Any mode: Any - def __init__(self, cmd, mode=..., bufsize: Optional[Any] = ...): ... + def __init__(self, cmd, mode=..., bufsize: Any | None = ...): ... def read(self): ... def readlines(self): ... def close(self, remove=..., error=...): ... __del__: Any -def popen(cmd, mode=..., bufsize: Optional[Any] = ...): ... +def popen(cmd, mode=..., bufsize: Any | None = ...): ... def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> Tuple[str, str, str, str]: ... def mac_ver( release: str = ..., versioninfo: Tuple[str, str, str] = ..., machine: str = ... diff --git a/mypy/typeshed/stdlib/@python2/plistlib.pyi b/mypy/typeshed/stdlib/@python2/plistlib.pyi new file mode 100644 index 000000000000..d815e3c35404 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/plistlib.pyi @@ -0,0 +1,24 @@ +from typing import IO, Any, Dict as DictT, Mapping, Text, Union + +_Path = Union[str, Text] + +def readPlist(pathOrFile: _Path | IO[bytes]) -> Any: ... +def writePlist(value: Mapping[str, Any], pathOrFile: _Path | IO[bytes]) -> None: ... +def readPlistFromBytes(data: bytes) -> Any: ... +def writePlistToBytes(value: Mapping[str, Any]) -> bytes: ... +def readPlistFromResource(path: _Path, restype: str = ..., resid: int = ...) -> Any: ... +def writePlistToResource(rootObject: Mapping[str, Any], path: _Path, restype: str = ..., resid: int = ...) -> None: ... +def readPlistFromString(data: str) -> Any: ... +def writePlistToString(rootObject: Mapping[str, Any]) -> str: ... + +class Dict(DictT[str, Any]): + def __getattr__(self, attr: str) -> Any: ... + def __setattr__(self, attr: str, value: Any) -> None: ... + def __delattr__(self, attr: str) -> None: ... + +class Data: + data: bytes + def __init__(self, data: bytes) -> None: ... + +class InvalidFileException(ValueError): + def __init__(self, message: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/popen2.pyi b/mypy/typeshed/stdlib/@python2/popen2.pyi index 5101a6f87487..0efee4e6d271 100644 --- a/mypy/typeshed/stdlib/@python2/popen2.pyi +++ b/mypy/typeshed/stdlib/@python2/popen2.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterable, List, Optional, TextIO, Tuple, TypeVar, Union +from typing import Any, Iterable, TextIO, Tuple, TypeVar _T = TypeVar("_T") @@ -8,10 +8,10 @@ class Popen3: pid: int tochild: TextIO fromchild: TextIO - childerr: Optional[TextIO] + childerr: TextIO | None def __init__(self, cmd: Iterable[Any] = ..., capturestderr: bool = ..., bufsize: int = ...) -> None: ... def __del__(self) -> None: ... - def poll(self, _deadstate: _T = ...) -> Union[int, _T]: ... + def poll(self, _deadstate: _T = ...) -> int | _T: ... def wait(self) -> int: ... class Popen4(Popen3): diff --git a/mypy/typeshed/stdlib/@python2/poplib.pyi b/mypy/typeshed/stdlib/@python2/poplib.pyi new file mode 100644 index 000000000000..7a71f9850dfe --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/poplib.pyi @@ -0,0 +1,45 @@ +import socket +from typing import Any, BinaryIO, List, Pattern, Text, Tuple, overload + +_LongResp = Tuple[bytes, List[bytes], int] + +class error_proto(Exception): ... + +POP3_PORT: int +POP3_SSL_PORT: int +CR: bytes +LF: bytes +CRLF: bytes + +class POP3: + host: Text + port: int + sock: socket.socket + file: BinaryIO + welcome: bytes + def __init__(self, host: Text, port: int = ..., timeout: float = ...) -> None: ... + def getwelcome(self) -> bytes: ... + def set_debuglevel(self, level: int) -> None: ... + def user(self, user: Text) -> bytes: ... + def pass_(self, pswd: Text) -> bytes: ... + def stat(self) -> Tuple[int, int]: ... + def list(self, which: Any | None = ...) -> _LongResp: ... + def retr(self, which: Any) -> _LongResp: ... + def dele(self, which: Any) -> bytes: ... + def noop(self) -> bytes: ... + def rset(self) -> bytes: ... + def quit(self) -> bytes: ... + def close(self) -> None: ... + def rpop(self, user: Text) -> bytes: ... + timestamp: Pattern[Text] + def apop(self, user: Text, secret: Text) -> bytes: ... + def top(self, which: Any, howmuch: int) -> _LongResp: ... + @overload + def uidl(self) -> _LongResp: ... + @overload + def uidl(self, which: Any) -> bytes: ... + +class POP3_SSL(POP3): + def __init__( + self, host: Text, port: int = ..., keyfile: Text | None = ..., certfile: Text | None = ..., timeout: float = ... + ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/posix.pyi b/mypy/typeshed/stdlib/@python2/posix.pyi index ae79286ec50d..c39ce325289b 100644 --- a/mypy/typeshed/stdlib/@python2/posix.pyi +++ b/mypy/typeshed/stdlib/@python2/posix.pyi @@ -1,5 +1,5 @@ from _typeshed import FileDescriptorLike -from typing import IO, AnyStr, Dict, List, Mapping, NamedTuple, Optional, Sequence, Tuple, TypeVar, Union +from typing import IO, AnyStr, Dict, List, Mapping, NamedTuple, Sequence, Tuple, TypeVar error = OSError @@ -100,7 +100,7 @@ def chown(path: unicode, uid: int, gid: int) -> None: ... def chroot(path: unicode) -> None: ... def close(fd: int) -> None: ... def closerange(fd_low: int, fd_high: int) -> None: ... -def confstr(name: Union[str, int]) -> str: ... +def confstr(name: str | int) -> str: ... def ctermid() -> str: ... def dup(fd: int) -> int: ... def dup2(fd: int, fd2: int) -> None: ... @@ -178,7 +178,7 @@ def statvfs(path: unicode) -> statvfs_result: ... def stat_float_times(fd: int) -> None: ... def strerror(code: int) -> str: ... def symlink(source: unicode, link_name: unicode) -> None: ... -def sysconf(name: Union[str, int]) -> int: ... +def sysconf(name: str | int) -> int: ... def system(command: unicode) -> int: ... def tcgetpgrp(fd: int) -> int: ... def tcsetpgrp(fd: int, pg: int) -> None: ... @@ -190,7 +190,7 @@ def uname() -> Tuple[str, str, str, str, str]: ... def unlink(path: unicode) -> None: ... def unsetenv(varname: str) -> None: ... def urandom(n: int) -> str: ... -def utime(path: unicode, times: Optional[Tuple[int, int]]) -> None: ... +def utime(path: unicode, times: Tuple[int, int] | None) -> None: ... def wait() -> int: ... _r = Tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] diff --git a/mypy/typeshed/stdlib/@python2/posixpath.pyi b/mypy/typeshed/stdlib/@python2/posixpath.pyi index f096428602d4..514db760886f 100644 --- a/mypy/typeshed/stdlib/@python2/posixpath.pyi +++ b/mypy/typeshed/stdlib/@python2/posixpath.pyi @@ -1,8 +1,7 @@ import os import sys -from _typeshed import AnyPath, BytesPath, StrPath from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Optional, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload _T = TypeVar("_T") @@ -15,7 +14,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -39,20 +38,20 @@ else: # NOTE: Empty lists results in '' (str) regardless of contained type. # Also, in Python 2 mixed sequences of Text and bytes results in either Text or bytes # So, fall back to Any -def commonprefix(m: Sequence[AnyPath]) -> Any: ... -def lexists(path: AnyPath) -> bool: ... +def commonprefix(m: Sequence[Text]) -> Any: ... +def lexists(path: Text) -> bool: ... # These return float if os.stat_float_times() == True, # but int is a subclass of float. -def getatime(filename: AnyPath) -> float: ... -def getmtime(filename: AnyPath) -> float: ... -def getctime(filename: AnyPath) -> float: ... -def getsize(filename: AnyPath) -> int: ... -def isabs(s: AnyPath) -> bool: ... -def isfile(path: AnyPath) -> bool: ... -def isdir(s: AnyPath) -> bool: ... -def islink(path: AnyPath) -> bool: ... -def ismount(path: AnyPath) -> bool: ... +def getatime(filename: Text) -> float: ... +def getmtime(filename: Text) -> float: ... +def getctime(filename: Text) -> float: ... +def getsize(filename: Text) -> int: ... +def isabs(s: Text) -> bool: ... +def isfile(path: Text) -> bool: ... +def isdir(s: Text) -> bool: ... +def islink(path: Text) -> bool: ... +def ismount(path: Text) -> bool: ... # Make sure signatures are disjunct, and allow combinations of bytes and unicode. # (Since Python 2 allows that, too) @@ -61,18 +60,18 @@ def ismount(path: AnyPath) -> bool: ... @overload def join(__p1: bytes, *p: bytes) -> bytes: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: bytes, __p3: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... @overload -def join(__p1: bytes, __p2: Text, *p: AnyPath) -> Text: ... +def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... @overload -def join(__p1: Text, *p: AnyPath) -> Text: ... +def join(__p1: Text, *p: Text) -> Text: ... @overload -def relpath(path: BytesPath, start: Optional[BytesPath] = ...) -> bytes: ... +def relpath(path: str, start: str | None = ...) -> str: ... @overload -def relpath(path: StrPath, start: Optional[StrPath] = ...) -> Text: ... -def samefile(f1: AnyPath, f2: AnyPath) -> bool: ... +def relpath(path: Text, start: Text | None = ...) -> Text: ... +def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/pprint.pyi b/mypy/typeshed/stdlib/@python2/pprint.pyi new file mode 100644 index 000000000000..407a9afb8e47 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pprint.pyi @@ -0,0 +1,17 @@ +from typing import IO, Any, Dict, Tuple + +def pformat(object: object, indent: int = ..., width: int = ..., depth: int | None = ...) -> str: ... +def pprint( + object: object, stream: IO[str] | None = ..., indent: int = ..., width: int = ..., depth: int | None = ... +) -> None: ... +def isreadable(object: object) -> bool: ... +def isrecursive(object: object) -> bool: ... +def saferepr(object: object) -> str: ... + +class PrettyPrinter: + def __init__(self, indent: int = ..., width: int = ..., depth: int | None = ..., stream: IO[str] | None = ...) -> None: ... + def pformat(self, object: object) -> str: ... + def pprint(self, object: object) -> None: ... + def isreadable(self, object: object) -> bool: ... + def isrecursive(self, object: object) -> bool: ... + def format(self, object: object, context: Dict[int, Any], maxlevels: int, level: int) -> Tuple[str, bool, bool]: ... diff --git a/mypy/typeshed/stdlib/@python2/profile.pyi b/mypy/typeshed/stdlib/@python2/profile.pyi new file mode 100644 index 000000000000..08e9b906dd0d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/profile.pyi @@ -0,0 +1,26 @@ +from typing import Any, Callable, Dict, Text, Tuple, TypeVar + +def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... +def runctx( + statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: str | None = ..., sort: str | int = ... +) -> None: ... + +_SelfT = TypeVar("_SelfT", bound=Profile) +_T = TypeVar("_T") +_Label = Tuple[str, int, str] + +class Profile: + bias: int + stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented + def __init__(self, timer: Callable[[], float] | None = ..., bias: int | None = ...) -> None: ... + def set_cmd(self, cmd: str) -> None: ... + def simulate_call(self, name: str) -> None: ... + def simulate_cmd_complete(self) -> None: ... + def print_stats(self, sort: str | int = ...) -> None: ... + def dump_stats(self, file: Text) -> None: ... + def create_stats(self) -> None: ... + def snapshot_stats(self) -> None: ... + def run(self: _SelfT, cmd: str) -> _SelfT: ... + def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... + def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def calibrate(self, m: int, verbose: int = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/@python2/pstats.pyi b/mypy/typeshed/stdlib/@python2/pstats.pyi new file mode 100644 index 000000000000..cecd1e84e305 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pstats.pyi @@ -0,0 +1,37 @@ +from cProfile import Profile as _cProfile +from profile import Profile +from typing import IO, Any, Dict, Iterable, List, Text, Tuple, TypeVar, Union, overload + +_Selector = Union[str, float, int] +_T = TypeVar("_T", bound=Stats) + +class Stats: + sort_arg_dict_default: Dict[str, Tuple[Any, str]] + def __init__( + self: _T, + __arg: None | str | Text | Profile | _cProfile = ..., + *args: None | str | Text | Profile | _cProfile | _T, + stream: IO[Any] | None = ..., + ) -> None: ... + def init(self, arg: None | str | Text | Profile | _cProfile) -> None: ... + def load_stats(self, arg: None | str | Text | Profile | _cProfile) -> None: ... + def get_top_level_stats(self) -> None: ... + def add(self: _T, *arg_list: None | str | Text | Profile | _cProfile | _T) -> _T: ... + def dump_stats(self, filename: Text) -> None: ... + def get_sort_arg_defs(self) -> Dict[str, Tuple[Tuple[Tuple[int, int], ...], str]]: ... + @overload + def sort_stats(self: _T, field: int) -> _T: ... + @overload + def sort_stats(self: _T, *field: str) -> _T: ... + def reverse_order(self: _T) -> _T: ... + def strip_dirs(self: _T) -> _T: ... + def calc_callees(self) -> None: ... + def eval_print_amount(self, sel: _Selector, list: List[str], msg: str) -> Tuple[List[str], str]: ... + def get_print_list(self, sel_list: Iterable[_Selector]) -> Tuple[int, List[str]]: ... + def print_stats(self: _T, *amount: _Selector) -> _T: ... + def print_callees(self: _T, *amount: _Selector) -> _T: ... + def print_callers(self: _T, *amount: _Selector) -> _T: ... + def print_call_heading(self, name_size: int, column_title: str) -> None: ... + def print_call_line(self, name_size: int, source: str, call_dict: Dict[str, Any], arrow: str = ...) -> None: ... + def print_title(self) -> None: ... + def print_line(self, func: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pty.pyi b/mypy/typeshed/stdlib/@python2/pty.pyi new file mode 100644 index 000000000000..e8afa2df5166 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pty.pyi @@ -0,0 +1,15 @@ +from typing import Callable, Iterable, Tuple + +_Reader = Callable[[int], bytes] + +STDIN_FILENO: int +STDOUT_FILENO: int +STDERR_FILENO: int + +CHILD: int + +def openpty() -> Tuple[int, int]: ... +def master_open() -> Tuple[int, str]: ... +def slave_open(tty_name: str) -> int: ... +def fork() -> Tuple[int, int]: ... +def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pwd.pyi b/mypy/typeshed/stdlib/@python2/pwd.pyi new file mode 100644 index 000000000000..83020c1576dd --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pwd.pyi @@ -0,0 +1,14 @@ +from typing import List, Tuple + +class struct_passwd(Tuple[str, str, int, int, str, str, str]): + pw_name: str + pw_passwd: str + pw_uid: int + pw_gid: int + pw_gecos: str + pw_dir: str + pw_shell: str + +def getpwall() -> List[struct_passwd]: ... +def getpwuid(__uid: int) -> struct_passwd: ... +def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/@python2/py_compile.pyi b/mypy/typeshed/stdlib/@python2/py_compile.pyi new file mode 100644 index 000000000000..44905b43da33 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/py_compile.pyi @@ -0,0 +1,13 @@ +from typing import List, Text, Type, Union + +_EitherStr = Union[bytes, Text] + +class PyCompileError(Exception): + exc_type_name: str + exc_value: BaseException + file: str + msg: str + def __init__(self, exc_type: Type[BaseException], exc_value: BaseException, file: str, msg: str = ...) -> None: ... + +def compile(file: _EitherStr, cfile: _EitherStr | None = ..., dfile: _EitherStr | None = ..., doraise: bool = ...) -> None: ... +def main(args: List[Text] | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/pyclbr.pyi b/mypy/typeshed/stdlib/@python2/pyclbr.pyi new file mode 100644 index 000000000000..893079901665 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pyclbr.pyi @@ -0,0 +1,20 @@ +from typing import Dict, List, Sequence + +class Class: + module: str + name: str + super: List[Class | str] | None + methods: Dict[str, int] + file: int + lineno: int + def __init__(self, module: str, name: str, super: List[Class | str] | None, file: str, lineno: int) -> None: ... + +class Function: + module: str + name: str + file: int + lineno: int + def __init__(self, module: str, name: str, file: str, lineno: int) -> None: ... + +def readmodule(module: str, path: Sequence[str] | None = ...) -> Dict[str, Class]: ... +def readmodule_ex(module: str, path: Sequence[str] | None = ...) -> Dict[str, Class | Function | List[str]]: ... diff --git a/mypy/typeshed/stdlib/@python2/pydoc.pyi b/mypy/typeshed/stdlib/@python2/pydoc.pyi new file mode 100644 index 000000000000..dee0c4710b39 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pydoc.pyi @@ -0,0 +1,258 @@ +from _typeshed import SupportsWrite +from types import MethodType, ModuleType, TracebackType +from typing import ( + IO, + Any, + AnyStr, + Callable, + Container, + Dict, + List, + Mapping, + MutableMapping, + NoReturn, + Optional, + Text, + Tuple, + Type, +) + +from repr import Repr + +# the return type of sys.exc_info(), used by ErrorDuringImport.__init__ +_Exc_Info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] + +__author__: str +__date__: str +__version__: str +__credits__: str + +def pathdirs() -> List[str]: ... +def getdoc(object: object) -> Text: ... +def splitdoc(doc: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def classname(object: object, modname: str) -> str: ... +def isdata(object: object) -> bool: ... +def replace(text: AnyStr, *pairs: AnyStr) -> AnyStr: ... +def cram(text: str, maxlen: int) -> str: ... +def stripid(text: str) -> str: ... +def allmethods(cl: type) -> MutableMapping[str, MethodType]: ... +def visiblename(name: str, all: Container[str] | None = ..., obj: object | None = ...) -> bool: ... +def classify_class_attrs(object: object) -> List[Tuple[str, str, type, str]]: ... +def ispackage(path: str) -> bool: ... +def source_synopsis(file: IO[AnyStr]) -> AnyStr | None: ... +def synopsis(filename: str, cache: MutableMapping[str, Tuple[int, str]] = ...) -> str | None: ... + +class ErrorDuringImport(Exception): + filename: str + exc: Type[BaseException] | None + value: BaseException | None + tb: TracebackType | None + def __init__(self, filename: str, exc_info: _Exc_Info) -> None: ... + +def importfile(path: str) -> ModuleType: ... +def safeimport(path: str, forceload: bool = ..., cache: MutableMapping[str, ModuleType] = ...) -> ModuleType: ... + +class Doc: + PYTHONDOCS: str + def document(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def fail(self, object: object, name: str | None = ..., *args: Any) -> NoReturn: ... + def docmodule(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docclass(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docroutine(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docother(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docproperty(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docdata(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def getdocloc(self, object: object, basedir: str = ...) -> str | None: ... + +class HTMLRepr(Repr): + maxlist: int + maxtuple: int + maxdict: int + maxstring: int + maxother: int + def __init__(self) -> None: ... + def escape(self, text: str) -> str: ... + def repr(self, object: object) -> str: ... + def repr1(self, x: object, level: complex) -> str: ... + def repr_string(self, x: Text, level: complex) -> str: ... + def repr_str(self, x: Text, level: complex) -> str: ... + def repr_instance(self, x: object, level: complex) -> str: ... + def repr_unicode(self, x: AnyStr, level: complex) -> str: ... + +class HTMLDoc(Doc): + repr: Callable[[object], str] + escape: Callable[[str], str] + def page(self, title: str, contents: str) -> str: ... + def heading(self, title: str, fgcol: str, bgcol: str, extras: str = ...) -> str: ... + def section( + self, + title: str, + fgcol: str, + bgcol: str, + contents: str, + width: int = ..., + prelude: str = ..., + marginalia: str | None = ..., + gap: str = ..., + ) -> str: ... + def bigsection(self, title: str, *args: Any) -> str: ... + def preformat(self, text: str) -> str: ... + def multicolumn(self, list: List[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... + def grey(self, text: str) -> str: ... + def namelink(self, name: str, *dicts: MutableMapping[str, str]) -> str: ... + def classlink(self, object: object, modname: str) -> str: ... + def modulelink(self, object: object) -> str: ... + def modpkglink(self, modpkginfo: Tuple[str, str, bool, bool]) -> str: ... + def markup( + self, + text: str, + escape: Callable[[str], str] | None = ..., + funcs: Mapping[str, str] = ..., + classes: Mapping[str, str] = ..., + methods: Mapping[str, str] = ..., + ) -> str: ... + def formattree( + self, tree: List[Tuple[type, Tuple[type, ...]] | List[Any]], modname: str, parent: type | None = ... + ) -> str: ... + def docmodule(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... + def docclass( + self, + object: object, + name: str | None = ..., + mod: str | None = ..., + funcs: Mapping[str, str] = ..., + classes: Mapping[str, str] = ..., + *ignored: Any, + ) -> str: ... + def formatvalue(self, object: object) -> str: ... + def docroutine( + self, + object: object, + name: str | None = ..., + mod: str | None = ..., + funcs: Mapping[str, str] = ..., + classes: Mapping[str, str] = ..., + methods: Mapping[str, str] = ..., + cl: type | None = ..., + *ignored: Any, + ) -> str: ... + def docproperty( + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any + ) -> str: ... + def docother(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... + def docdata( + self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any + ) -> str: ... + def index(self, dir: str, shadowed: MutableMapping[str, bool] | None = ...) -> str: ... + def filelink(self, url: str, path: str) -> str: ... + +class TextRepr(Repr): + maxlist: int + maxtuple: int + maxdict: int + maxstring: int + maxother: int + def __init__(self) -> None: ... + def repr1(self, x: object, level: complex) -> str: ... + def repr_string(self, x: str, level: complex) -> str: ... + def repr_str(self, x: str, level: complex) -> str: ... + def repr_instance(self, x: object, level: complex) -> str: ... + +class TextDoc(Doc): + repr: Callable[[object], str] + def bold(self, text: str) -> str: ... + def indent(self, text: str, prefix: str = ...) -> str: ... + def section(self, title: str, contents: str) -> str: ... + def formattree( + self, tree: List[Tuple[type, Tuple[type, ...]] | List[Any]], modname: str, parent: type | None = ..., prefix: str = ... + ) -> str: ... + def docmodule(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... + def docclass(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... + def formatvalue(self, object: object) -> str: ... + def docroutine( + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any + ) -> str: ... + def docproperty( + self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any + ) -> str: ... + def docdata( + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any + ) -> str: ... + def docother( + self, + object: object, + name: str | None = ..., + mod: str | None = ..., + parent: str | None = ..., + maxlen: int | None = ..., + doc: Any | None = ..., + *ignored: Any, + ) -> str: ... + +def pager(text: str) -> None: ... +def getpager() -> Callable[[str], None]: ... +def plain(text: str) -> str: ... +def pipepager(text: str, cmd: str) -> None: ... +def tempfilepager(text: str, cmd: str) -> None: ... +def ttypager(text: str) -> None: ... +def plainpager(text: str) -> None: ... +def describe(thing: Any) -> str: ... +def locate(path: str, forceload: bool = ...) -> object: ... + +text: TextDoc +html: HTMLDoc + +class _OldStyleClass: ... + +def resolve(thing: str | object, forceload: bool = ...) -> Tuple[object, str] | None: ... +def render_doc(thing: str | object, title: str = ..., forceload: bool = ..., renderer: Doc | None = ...) -> str: ... +def doc(thing: str | object, title: str = ..., forceload: bool = ..., output: SupportsWrite[str] | None = ...) -> None: ... +def writedoc(thing: str | object, forceload: bool = ...) -> None: ... +def writedocs(dir: str, pkgpath: str = ..., done: Any | None = ...) -> None: ... + +class Helper: + keywords: Dict[str, str | Tuple[str, str]] + symbols: Dict[str, str] + topics: Dict[str, str | Tuple[str, ...]] + def __init__(self, input: IO[str] | None = ..., output: IO[str] | None = ...) -> None: ... + input: IO[str] + output: IO[str] + def __call__(self, request: str | Helper | object = ...) -> None: ... + def interact(self) -> None: ... + def getline(self, prompt: str) -> str: ... + def help(self, request: Any) -> None: ... + def intro(self) -> None: ... + def list(self, items: List[str], columns: int = ..., width: int = ...) -> None: ... + def listkeywords(self) -> None: ... + def listsymbols(self) -> None: ... + def listtopics(self) -> None: ... + def showtopic(self, topic: str, more_xrefs: str = ...) -> None: ... + def showsymbol(self, symbol: str) -> None: ... + def listmodules(self, key: str = ...) -> None: ... + +help: Helper + +# See Python issue #11182: "remove the unused and undocumented pydoc.Scanner class" +# class Scanner: +# roots = ... # type: Any +# state = ... # type: Any +# children = ... # type: Any +# descendp = ... # type: Any +# def __init__(self, roots, children, descendp) -> None: ... +# def next(self): ... + +class ModuleScanner: + quit: bool + def run( + self, + callback: Callable[[str | None, str, str], None], + key: Any | None = ..., + completer: Callable[[], None] | None = ..., + onerror: Callable[[str], None] | None = ..., + ) -> None: ... + +def apropos(key: str) -> None: ... +def ispath(x: Any) -> bool: ... +def cli() -> None: ... +def serve(port: int, callback: Callable[[Any], None] | None = ..., completer: Callable[[], None] | None = ...) -> None: ... +def gui() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pydoc_data/__init__.pyi b/mypy/typeshed/stdlib/@python2/pydoc_data/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi b/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi new file mode 100644 index 000000000000..1c48f4022fd6 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi @@ -0,0 +1,3 @@ +from typing import Dict + +topics: Dict[str, str] diff --git a/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi new file mode 100644 index 000000000000..bd73f850b559 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi @@ -0,0 +1,75 @@ +import pyexpat.errors as errors +import pyexpat.model as model +from _typeshed import SupportsRead +from typing import Any, Callable, Dict, List, Optional, Text, Tuple + +EXPAT_VERSION: str # undocumented +version_info: Tuple[int, int, int] # undocumented +native_encoding: str # undocumented +features: List[Tuple[str, int]] # undocumented + +class ExpatError(Exception): + code: int + lineno: int + offset: int + +error = ExpatError + +XML_PARAM_ENTITY_PARSING_NEVER: int +XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE: int +XML_PARAM_ENTITY_PARSING_ALWAYS: int + +_Model = Tuple[int, int, Optional[str], Tuple[Any, ...]] + +class XMLParserType(object): + def Parse(self, __data: Text | bytes, __isfinal: bool = ...) -> int: ... + def ParseFile(self, __file: SupportsRead[bytes]) -> int: ... + def SetBase(self, __base: Text) -> None: ... + def GetBase(self) -> str | None: ... + def GetInputContext(self) -> bytes | None: ... + def ExternalEntityParserCreate(self, __context: Text | None, __encoding: Text = ...) -> XMLParserType: ... + def SetParamEntityParsing(self, __flag: int) -> int: ... + def UseForeignDTD(self, __flag: bool = ...) -> None: ... + buffer_size: int + buffer_text: bool + buffer_used: int + namespace_prefixes: bool # undocumented + ordered_attributes: bool + specified_attributes: bool + ErrorByteIndex: int + ErrorCode: int + ErrorColumnNumber: int + ErrorLineNumber: int + CurrentByteIndex: int + CurrentColumnNumber: int + CurrentLineNumber: int + XmlDeclHandler: Callable[[str, str | None, int], Any] | None + StartDoctypeDeclHandler: Callable[[str, str | None, str | None, bool], Any] | None + EndDoctypeDeclHandler: Callable[[], Any] | None + ElementDeclHandler: Callable[[str, _Model], Any] | None + AttlistDeclHandler: Callable[[str, str, str, str | None, bool], Any] | None + StartElementHandler: Callable[[str, Dict[str, str]], Any] | Callable[[str, List[str]], Any] | Callable[ + [str, Dict[str, str], List[str]], Any + ] | None + EndElementHandler: Callable[[str], Any] | None + ProcessingInstructionHandler: Callable[[str, str], Any] | None + CharacterDataHandler: Callable[[str], Any] | None + UnparsedEntityDeclHandler: Callable[[str, str | None, str, str | None, str], Any] | None + EntityDeclHandler: Callable[[str, bool, str | None, str | None, str, str | None, str | None], Any] | None + NotationDeclHandler: Callable[[str, str | None, str, str | None], Any] | None + StartNamespaceDeclHandler: Callable[[str, str], Any] | None + EndNamespaceDeclHandler: Callable[[str], Any] | None + CommentHandler: Callable[[str], Any] | None + StartCdataSectionHandler: Callable[[], Any] | None + EndCdataSectionHandler: Callable[[], Any] | None + DefaultHandler: Callable[[str], Any] | None + DefaultHandlerExpand: Callable[[str], Any] | None + NotStandaloneHandler: Callable[[], int] | None + ExternalEntityRefHandler: Callable[[str, str | None, str | None, str | None], int] | None + +def ErrorString(__code: int) -> str: ... + +# intern is undocumented +def ParserCreate( + encoding: Text | None = ..., namespace_separator: Text | None = ..., intern: Dict[str, Any] | None = ... +) -> XMLParserType: ... diff --git a/mypy/typeshed/stdlib/@python2/pyexpat/errors.pyi b/mypy/typeshed/stdlib/@python2/pyexpat/errors.pyi new file mode 100644 index 000000000000..498030fd695f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pyexpat/errors.pyi @@ -0,0 +1,37 @@ +XML_ERROR_ABORTED: str +XML_ERROR_ASYNC_ENTITY: str +XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: str +XML_ERROR_BAD_CHAR_REF: str +XML_ERROR_BINARY_ENTITY_REF: str +XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING: str +XML_ERROR_DUPLICATE_ATTRIBUTE: str +XML_ERROR_ENTITY_DECLARED_IN_PE: str +XML_ERROR_EXTERNAL_ENTITY_HANDLING: str +XML_ERROR_FEATURE_REQUIRES_XML_DTD: str +XML_ERROR_FINISHED: str +XML_ERROR_INCOMPLETE_PE: str +XML_ERROR_INCORRECT_ENCODING: str +XML_ERROR_INVALID_TOKEN: str +XML_ERROR_JUNK_AFTER_DOC_ELEMENT: str +XML_ERROR_MISPLACED_XML_PI: str +XML_ERROR_NOT_STANDALONE: str +XML_ERROR_NOT_SUSPENDED: str +XML_ERROR_NO_ELEMENTS: str +XML_ERROR_NO_MEMORY: str +XML_ERROR_PARAM_ENTITY_REF: str +XML_ERROR_PARTIAL_CHAR: str +XML_ERROR_PUBLICID: str +XML_ERROR_RECURSIVE_ENTITY_REF: str +XML_ERROR_SUSPENDED: str +XML_ERROR_SUSPEND_PE: str +XML_ERROR_SYNTAX: str +XML_ERROR_TAG_MISMATCH: str +XML_ERROR_TEXT_DECL: str +XML_ERROR_UNBOUND_PREFIX: str +XML_ERROR_UNCLOSED_CDATA_SECTION: str +XML_ERROR_UNCLOSED_TOKEN: str +XML_ERROR_UNDECLARING_PREFIX: str +XML_ERROR_UNDEFINED_ENTITY: str +XML_ERROR_UNEXPECTED_STATE: str +XML_ERROR_UNKNOWN_ENCODING: str +XML_ERROR_XML_DECL: str diff --git a/mypy/typeshed/stdlib/@python2/pyexpat/model.pyi b/mypy/typeshed/stdlib/@python2/pyexpat/model.pyi new file mode 100644 index 000000000000..f357cf6511a2 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/pyexpat/model.pyi @@ -0,0 +1,11 @@ +XML_CTYPE_ANY: int +XML_CTYPE_CHOICE: int +XML_CTYPE_EMPTY: int +XML_CTYPE_MIXED: int +XML_CTYPE_NAME: int +XML_CTYPE_SEQ: int + +XML_CQUANT_NONE: int +XML_CQUANT_OPT: int +XML_CQUANT_PLUS: int +XML_CQUANT_REP: int diff --git a/mypy/typeshed/stdlib/@python2/quopri.pyi b/mypy/typeshed/stdlib/@python2/quopri.pyi new file mode 100644 index 000000000000..c2ffabe7d531 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/quopri.pyi @@ -0,0 +1,6 @@ +from typing import BinaryIO + +def encode(input: BinaryIO, output: BinaryIO, quotetabs: int, header: int = ...) -> None: ... +def encodestring(s: bytes, quotetabs: int = ..., header: int = ...) -> bytes: ... +def decode(input: BinaryIO, output: BinaryIO, header: int = ...) -> None: ... +def decodestring(s: bytes, header: int = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/random.pyi b/mypy/typeshed/stdlib/@python2/random.pyi index 059bd9360708..6fb5d602067c 100644 --- a/mypy/typeshed/stdlib/@python2/random.pyi +++ b/mypy/typeshed/stdlib/@python2/random.pyi @@ -1,5 +1,5 @@ import _random -from typing import AbstractSet, Any, Callable, Iterator, List, MutableSequence, Protocol, Sequence, TypeVar, Union, overload +from typing import Any, Callable, Iterator, List, MutableSequence, Protocol, Sequence, TypeVar, overload _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) diff --git a/mypy/typeshed/stdlib/@python2/re.pyi b/mypy/typeshed/stdlib/@python2/re.pyi index 11e3d02fcf5c..fbe021ce67be 100644 --- a/mypy/typeshed/stdlib/@python2/re.pyi +++ b/mypy/typeshed/stdlib/@python2/re.pyi @@ -1,19 +1,4 @@ -from typing import ( - Any, - AnyStr, - Callable, - Dict, - Generic, - Iterator, - List, - Match, - Optional, - Pattern, - Sequence, - Tuple, - Union, - overload, -) +from typing import Any, AnyStr, Callable, Iterator, List, Match, Pattern, Tuple, overload # ----- re variables and constants ----- DEBUG: int @@ -39,65 +24,59 @@ def compile(pattern: AnyStr, flags: int = ...) -> Pattern[AnyStr]: ... @overload def compile(pattern: Pattern[AnyStr], flags: int = ...) -> Pattern[AnyStr]: ... @overload -def search(pattern: Union[str, unicode], string: AnyStr, flags: int = ...) -> Optional[Match[AnyStr]]: ... +def search(pattern: str | unicode, string: AnyStr, flags: int = ...) -> Match[AnyStr] | None: ... @overload -def search(pattern: Union[Pattern[str], Pattern[unicode]], string: AnyStr, flags: int = ...) -> Optional[Match[AnyStr]]: ... +def search(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> Match[AnyStr] | None: ... @overload -def match(pattern: Union[str, unicode], string: AnyStr, flags: int = ...) -> Optional[Match[AnyStr]]: ... +def match(pattern: str | unicode, string: AnyStr, flags: int = ...) -> Match[AnyStr] | None: ... @overload -def match(pattern: Union[Pattern[str], Pattern[unicode]], string: AnyStr, flags: int = ...) -> Optional[Match[AnyStr]]: ... +def match(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> Match[AnyStr] | None: ... @overload -def split(pattern: Union[str, unicode], string: AnyStr, maxsplit: int = ..., flags: int = ...) -> List[AnyStr]: ... +def split(pattern: str | unicode, string: AnyStr, maxsplit: int = ..., flags: int = ...) -> List[AnyStr]: ... @overload -def split( - pattern: Union[Pattern[str], Pattern[unicode]], string: AnyStr, maxsplit: int = ..., flags: int = ... -) -> List[AnyStr]: ... +def split(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, maxsplit: int = ..., flags: int = ...) -> List[AnyStr]: ... @overload -def findall(pattern: Union[str, unicode], string: AnyStr, flags: int = ...) -> List[Any]: ... +def findall(pattern: str | unicode, string: AnyStr, flags: int = ...) -> List[Any]: ... @overload -def findall(pattern: Union[Pattern[str], Pattern[unicode]], string: AnyStr, flags: int = ...) -> List[Any]: ... +def findall(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> List[Any]: ... # Return an iterator yielding match objects over all non-overlapping matches # for the RE pattern in string. The string is scanned left-to-right, and # matches are returned in the order found. Empty matches are included in the # result unless they touch the beginning of another match. @overload -def finditer(pattern: Union[str, unicode], string: AnyStr, flags: int = ...) -> Iterator[Match[AnyStr]]: ... +def finditer(pattern: str | unicode, string: AnyStr, flags: int = ...) -> Iterator[Match[AnyStr]]: ... @overload -def finditer(pattern: Union[Pattern[str], Pattern[unicode]], string: AnyStr, flags: int = ...) -> Iterator[Match[AnyStr]]: ... +def finditer(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> Iterator[Match[AnyStr]]: ... @overload -def sub(pattern: Union[str, unicode], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> AnyStr: ... +def sub(pattern: str | unicode, repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> AnyStr: ... @overload def sub( - pattern: Union[str, unicode], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ... + pattern: str | unicode, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ... ) -> AnyStr: ... @overload -def sub( - pattern: Union[Pattern[str], Pattern[unicode]], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ... -) -> AnyStr: ... +def sub(pattern: Pattern[str] | Pattern[unicode], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> AnyStr: ... @overload def sub( - pattern: Union[Pattern[str], Pattern[unicode]], + pattern: Pattern[str] | Pattern[unicode], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ..., ) -> AnyStr: ... @overload -def subn( - pattern: Union[str, unicode], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ... -) -> Tuple[AnyStr, int]: ... +def subn(pattern: str | unicode, repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> Tuple[AnyStr, int]: ... @overload def subn( - pattern: Union[str, unicode], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ... + pattern: str | unicode, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ... ) -> Tuple[AnyStr, int]: ... @overload def subn( - pattern: Union[Pattern[str], Pattern[unicode]], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ... + pattern: Pattern[str] | Pattern[unicode], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ... ) -> Tuple[AnyStr, int]: ... @overload def subn( - pattern: Union[Pattern[str], Pattern[unicode]], + pattern: Pattern[str] | Pattern[unicode], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., @@ -105,4 +84,4 @@ def subn( ) -> Tuple[AnyStr, int]: ... def escape(string: AnyStr) -> AnyStr: ... def purge() -> None: ... -def template(pattern: Union[AnyStr, Pattern[AnyStr]], flags: int = ...) -> Pattern[AnyStr]: ... +def template(pattern: AnyStr | Pattern[AnyStr], flags: int = ...) -> Pattern[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/readline.pyi b/mypy/typeshed/stdlib/@python2/readline.pyi new file mode 100644 index 000000000000..fb9b12d9a8e9 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/readline.pyi @@ -0,0 +1,30 @@ +from typing import Callable, Optional, Sequence, Text + +_CompleterT = Optional[Callable[[str, int], Optional[str]]] +_CompDispT = Optional[Callable[[str, Sequence[str], int], None]] + +def parse_and_bind(__string: str) -> None: ... +def read_init_file(__filename: Text | None = ...) -> None: ... +def get_line_buffer() -> str: ... +def insert_text(__string: str) -> None: ... +def redisplay() -> None: ... +def read_history_file(__filename: Text | None = ...) -> None: ... +def write_history_file(__filename: Text | None = ...) -> None: ... +def get_history_length() -> int: ... +def set_history_length(__length: int) -> None: ... +def clear_history() -> None: ... +def get_current_history_length() -> int: ... +def get_history_item(__index: int) -> str: ... +def remove_history_item(__pos: int) -> None: ... +def replace_history_item(__pos: int, __line: str) -> None: ... +def add_history(__string: str) -> None: ... +def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... +def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... +def set_completer(__function: _CompleterT = ...) -> None: ... +def get_completer() -> _CompleterT: ... +def get_completion_type() -> int: ... +def get_begidx() -> int: ... +def get_endidx() -> int: ... +def set_completer_delims(__string: str) -> None: ... +def get_completer_delims() -> str: ... +def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/rfc822.pyi b/mypy/typeshed/stdlib/@python2/rfc822.pyi index f536568b807d..d6ae0031ffdf 100644 --- a/mypy/typeshed/stdlib/@python2/rfc822.pyi +++ b/mypy/typeshed/stdlib/@python2/rfc822.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any class Message: fp: Any @@ -18,7 +18,7 @@ class Message: def getallmatchingheaders(self, name): ... def getfirstmatchingheader(self, name): ... def getrawheader(self, name): ... - def getheader(self, name, default: Optional[Any] = ...): ... + def getheader(self, name, default: Any | None = ...): ... get: Any def getheaders(self, name): ... def getaddr(self, name): ... @@ -57,7 +57,7 @@ class AddrlistClass: def getquote(self): ... def getcomment(self): ... def getdomainliteral(self): ... - def getatom(self, atomends: Optional[Any] = ...): ... + def getatom(self, atomends: Any | None = ...): ... def getphraselist(self): ... class AddressList(AddrlistClass): diff --git a/mypy/typeshed/stdlib/@python2/rlcompleter.pyi b/mypy/typeshed/stdlib/@python2/rlcompleter.pyi new file mode 100644 index 000000000000..a61c61eb24f2 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/rlcompleter.pyi @@ -0,0 +1,7 @@ +from typing import Any, Dict, Union + +_Text = Union[str, unicode] + +class Completer: + def __init__(self, namespace: Dict[str, Any] | None = ...) -> None: ... + def complete(self, text: _Text, state: int) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/runpy.pyi b/mypy/typeshed/stdlib/@python2/runpy.pyi index 6674af077d5d..3d5f0500f2e0 100644 --- a/mypy/typeshed/stdlib/@python2/runpy.pyi +++ b/mypy/typeshed/stdlib/@python2/runpy.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any class _TempModule: mod_name: Any @@ -13,5 +13,5 @@ class _ModifiedArgv0: def __enter__(self): ... def __exit__(self, *args): ... -def run_module(mod_name, init_globals: Optional[Any] = ..., run_name: Optional[Any] = ..., alter_sys: bool = ...): ... -def run_path(path_name, init_globals: Optional[Any] = ..., run_name: Optional[Any] = ...): ... +def run_module(mod_name, init_globals: Any | None = ..., run_name: Any | None = ..., alter_sys: bool = ...): ... +def run_path(path_name, init_globals: Any | None = ..., run_name: Any | None = ...): ... diff --git a/mypy/typeshed/stdlib/@python2/sched.pyi b/mypy/typeshed/stdlib/@python2/sched.pyi new file mode 100644 index 000000000000..f718dd7a57bd --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sched.pyi @@ -0,0 +1,18 @@ +from typing import Any, Callable, Dict, List, NamedTuple, Text, Tuple + +class Event(NamedTuple): + time: float + priority: Any + action: Callable[..., Any] + argument: Tuple[Any, ...] + kwargs: Dict[Text, Any] + +class scheduler: + def __init__(self, timefunc: Callable[[], float], delayfunc: Callable[[float], None]) -> None: ... + def enterabs(self, time: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... + def enter(self, delay: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... + def run(self) -> None: ... + def cancel(self, event: Event) -> None: ... + def empty(self) -> bool: ... + @property + def queue(self) -> List[Event]: ... diff --git a/mypy/typeshed/stdlib/@python2/select.pyi b/mypy/typeshed/stdlib/@python2/select.pyi new file mode 100644 index 000000000000..b960fd4e24b5 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/select.pyi @@ -0,0 +1,124 @@ +import sys +from _typeshed import FileDescriptorLike +from typing import Any, Iterable, List, Tuple + +if sys.platform != "win32": + PIPE_BUF: int + POLLERR: int + POLLHUP: int + POLLIN: int + POLLMSG: int + POLLNVAL: int + POLLOUT: int + POLLPRI: int + POLLRDBAND: int + POLLRDNORM: int + POLLWRBAND: int + POLLWRNORM: int + +class poll: + def __init__(self) -> None: ... + def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... + def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... + def unregister(self, fd: FileDescriptorLike) -> None: ... + def poll(self, timeout: float | None = ...) -> List[Tuple[int, int]]: ... + +def select( + __rlist: Iterable[Any], __wlist: Iterable[Any], __xlist: Iterable[Any], __timeout: float | None = ... +) -> Tuple[List[Any], List[Any], List[Any]]: ... + +class error(Exception): ... + +if sys.platform != "linux" and sys.platform != "win32": + # BSD only + class kevent(object): + data: Any + fflags: int + filter: int + flags: int + ident: int + udata: Any + def __init__( + self, + ident: FileDescriptorLike, + filter: int = ..., + flags: int = ..., + fflags: int = ..., + data: Any = ..., + udata: Any = ..., + ) -> None: ... + # BSD only + class kqueue(object): + closed: bool + def __init__(self) -> None: ... + def close(self) -> None: ... + def control( + self, __changelist: Iterable[kevent] | None, __maxevents: int, __timeout: float | None = ... + ) -> List[kevent]: ... + def fileno(self) -> int: ... + @classmethod + def fromfd(cls, __fd: FileDescriptorLike) -> kqueue: ... + KQ_EV_ADD: int + KQ_EV_CLEAR: int + KQ_EV_DELETE: int + KQ_EV_DISABLE: int + KQ_EV_ENABLE: int + KQ_EV_EOF: int + KQ_EV_ERROR: int + KQ_EV_FLAG1: int + KQ_EV_ONESHOT: int + KQ_EV_SYSFLAGS: int + KQ_FILTER_AIO: int + KQ_FILTER_NETDEV: int + KQ_FILTER_PROC: int + KQ_FILTER_READ: int + KQ_FILTER_SIGNAL: int + KQ_FILTER_TIMER: int + KQ_FILTER_VNODE: int + KQ_FILTER_WRITE: int + KQ_NOTE_ATTRIB: int + KQ_NOTE_CHILD: int + KQ_NOTE_DELETE: int + KQ_NOTE_EXEC: int + KQ_NOTE_EXIT: int + KQ_NOTE_EXTEND: int + KQ_NOTE_FORK: int + KQ_NOTE_LINK: int + if sys.platform != "darwin": + KQ_NOTE_LINKDOWN: int + KQ_NOTE_LINKINV: int + KQ_NOTE_LINKUP: int + KQ_NOTE_LOWAT: int + KQ_NOTE_PCTRLMASK: int + KQ_NOTE_PDATAMASK: int + KQ_NOTE_RENAME: int + KQ_NOTE_REVOKE: int + KQ_NOTE_TRACK: int + KQ_NOTE_TRACKERR: int + KQ_NOTE_WRITE: int + +if sys.platform == "linux": + class epoll(object): + def __init__(self, sizehint: int = ...) -> None: ... + def close(self) -> None: ... + closed: bool + def fileno(self) -> int: ... + def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... + def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... + def unregister(self, fd: FileDescriptorLike) -> None: ... + def poll(self, timeout: float | None = ..., maxevents: int = ...) -> List[Tuple[int, int]]: ... + @classmethod + def fromfd(cls, __fd: FileDescriptorLike) -> epoll: ... + EPOLLERR: int + EPOLLET: int + EPOLLHUP: int + EPOLLIN: int + EPOLLMSG: int + EPOLLONESHOT: int + EPOLLOUT: int + EPOLLPRI: int + EPOLLRDBAND: int + EPOLLRDNORM: int + EPOLLWRBAND: int + EPOLLWRNORM: int + EPOLL_RDHUP: int diff --git a/mypy/typeshed/stdlib/@python2/sets.pyi b/mypy/typeshed/stdlib/@python2/sets.pyi index e0a652053cc5..d2b94ea44bbc 100644 --- a/mypy/typeshed/stdlib/@python2/sets.pyi +++ b/mypy/typeshed/stdlib/@python2/sets.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Hashable, Iterable, Iterator, MutableMapping, Optional, TypeVar, Union +from typing import Any, Hashable, Iterable, Iterator, MutableMapping, TypeVar, Union _T = TypeVar("_T") _Setlike = Union[BaseSet[_T], Iterable[_T]] @@ -33,11 +33,11 @@ class BaseSet(Iterable[_T]): def __gt__(self, other: BaseSet[_T]) -> bool: ... class ImmutableSet(BaseSet[_T], Hashable): - def __init__(self, iterable: Optional[_Setlike[_T]] = ...) -> None: ... + def __init__(self, iterable: _Setlike[_T] | None = ...) -> None: ... def __hash__(self) -> int: ... class Set(BaseSet[_T]): - def __init__(self, iterable: Optional[_Setlike[_T]] = ...) -> None: ... + def __init__(self, iterable: _Setlike[_T] | None = ...) -> None: ... def __ior__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... def union_update(self, other: _Setlike[_T]) -> None: ... def __iand__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... diff --git a/mypy/typeshed/stdlib/@python2/shelve.pyi b/mypy/typeshed/stdlib/@python2/shelve.pyi index 442c3fe3d52e..d9b1a00e58df 100644 --- a/mypy/typeshed/stdlib/@python2/shelve.pyi +++ b/mypy/typeshed/stdlib/@python2/shelve.pyi @@ -1,9 +1,9 @@ import collections -from typing import Any, Dict, Iterator, List, Optional, Tuple +from typing import Any, Dict, Iterator, List, Tuple class Shelf(collections.MutableMapping[Any, Any]): def __init__( - self, dict: Dict[Any, Any], protocol: Optional[int] = ..., writeback: bool = ..., keyencoding: str = ... + self, dict: Dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... ) -> None: ... def __iter__(self) -> Iterator[str]: ... def keys(self) -> List[Any]: ... @@ -22,7 +22,7 @@ class Shelf(collections.MutableMapping[Any, Any]): class BsdDbShelf(Shelf): def __init__( - self, dict: Dict[Any, Any], protocol: Optional[int] = ..., writeback: bool = ..., keyencoding: str = ... + self, dict: Dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... ) -> None: ... def set_location(self, key: Any) -> Tuple[str, Any]: ... def next(self) -> Tuple[str, Any]: ... @@ -31,6 +31,6 @@ class BsdDbShelf(Shelf): def last(self) -> Tuple[str, Any]: ... class DbfilenameShelf(Shelf): - def __init__(self, filename: str, flag: str = ..., protocol: Optional[int] = ..., writeback: bool = ...) -> None: ... + def __init__(self, filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> None: ... -def open(filename: str, flag: str = ..., protocol: Optional[int] = ..., writeback: bool = ...) -> DbfilenameShelf: ... +def open(filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> DbfilenameShelf: ... diff --git a/mypy/typeshed/stdlib/@python2/shlex.pyi b/mypy/typeshed/stdlib/@python2/shlex.pyi index 37c667238f09..89c28fc9be7f 100644 --- a/mypy/typeshed/stdlib/@python2/shlex.pyi +++ b/mypy/typeshed/stdlib/@python2/shlex.pyi @@ -1,14 +1,14 @@ -from typing import IO, Any, List, Optional, Text, TypeVar, Union +from typing import IO, Any, List, Text, TypeVar -def split(s: Optional[str], comments: bool = ..., posix: bool = ...) -> List[str]: ... +def split(s: str | None, comments: bool = ..., posix: bool = ...) -> List[str]: ... _SLT = TypeVar("_SLT", bound=shlex) class shlex: - def __init__(self, instream: Union[IO[Any], Text] = ..., infile: IO[Any] = ..., posix: bool = ...) -> None: ... + def __init__(self, instream: IO[Any] | Text = ..., infile: IO[Any] = ..., posix: bool = ...) -> None: ... def __iter__(self: _SLT) -> _SLT: ... def next(self) -> str: ... - def get_token(self) -> Optional[str]: ... + def get_token(self) -> str | None: ... def push_token(self, _str: str) -> None: ... def read_token(self) -> str: ... def sourcehook(self, filename: str) -> None: ... @@ -23,8 +23,8 @@ class shlex: escapedquotes: str whitespace_split: bool infile: IO[Any] - source: Optional[str] + source: str | None debug: int lineno: int token: Any - eof: Optional[str] + eof: str | None diff --git a/mypy/typeshed/stdlib/@python2/shutil.pyi b/mypy/typeshed/stdlib/@python2/shutil.pyi new file mode 100644 index 000000000000..4805c8e4cdb7 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/shutil.pyi @@ -0,0 +1,45 @@ +from _typeshed import SupportsRead, SupportsWrite +from typing import Any, AnyStr, Callable, Iterable, List, Sequence, Set, Text, Tuple, Type, TypeVar, Union + +_AnyStr = TypeVar("_AnyStr", str, unicode) +_AnyPath = TypeVar("_AnyPath", str, unicode) +_PathReturn = Type[None] + +class Error(EnvironmentError): ... +class SpecialFileError(EnvironmentError): ... +class ExecError(EnvironmentError): ... + +def copyfileobj(fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...) -> None: ... +def copyfile(src: Text, dst: Text) -> None: ... +def copymode(src: Text, dst: Text) -> None: ... +def copystat(src: Text, dst: Text) -> None: ... +def copy(src: Text, dst: Text) -> _PathReturn: ... +def copy2(src: Text, dst: Text) -> _PathReturn: ... +def ignore_patterns(*patterns: Text) -> Callable[[Any, List[_AnyStr]], Set[_AnyStr]]: ... +def copytree( + src: AnyStr, dst: AnyStr, symlinks: bool = ..., ignore: None | Callable[[AnyStr, List[AnyStr]], Iterable[AnyStr]] = ... +) -> _PathReturn: ... +def rmtree(path: _AnyPath, ignore_errors: bool = ..., onerror: Callable[[Any, _AnyPath, Any], Any] | None = ...) -> None: ... + +_CopyFn = Union[Callable[[str, str], None], Callable[[Text, Text], None]] + +def move(src: Text, dst: Text) -> _PathReturn: ... +def make_archive( + base_name: _AnyStr, + format: str, + root_dir: Text | None = ..., + base_dir: Text | None = ..., + verbose: bool = ..., + dry_run: bool = ..., + owner: str | None = ..., + group: str | None = ..., + logger: Any | None = ..., +) -> _AnyStr: ... +def get_archive_formats() -> List[Tuple[str, str]]: ... +def register_archive_format( + name: str, + function: Callable[..., Any], + extra_args: Sequence[Tuple[str, Any] | List[Any]] | None = ..., + description: str = ..., +) -> None: ... +def unregister_archive_format(name: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/signal.pyi b/mypy/typeshed/stdlib/@python2/signal.pyi index c33ff19dcf10..16a8f2d1cb8b 100644 --- a/mypy/typeshed/stdlib/@python2/signal.pyi +++ b/mypy/typeshed/stdlib/@python2/signal.pyi @@ -1,5 +1,5 @@ from types import FrameType -from typing import Any, Callable, Tuple, Union +from typing import Callable, Tuple, Union SIG_DFL: int = ... SIG_IGN: int = ... diff --git a/mypy/typeshed/stdlib/@python2/site.pyi b/mypy/typeshed/stdlib/@python2/site.pyi new file mode 100644 index 000000000000..c77c9397f612 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/site.pyi @@ -0,0 +1,12 @@ +from typing import Iterable, List + +PREFIXES: List[str] +ENABLE_USER_SITE: bool | None +USER_SITE: str | None +USER_BASE: str | None + +def main() -> None: ... +def addsitedir(sitedir: str, known_paths: Iterable[str] | None = ...) -> None: ... +def getsitepackages(prefixes: Iterable[str] | None = ...) -> List[str]: ... +def getuserbase() -> str: ... +def getusersitepackages() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/smtpd.pyi b/mypy/typeshed/stdlib/@python2/smtpd.pyi new file mode 100644 index 000000000000..1c17b82d8ab5 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/smtpd.pyi @@ -0,0 +1,45 @@ +import asynchat +import asyncore +import socket +from typing import Any, List, Text, Tuple, Type + +_Address = Tuple[str, int] # (host, port) + +class SMTPChannel(asynchat.async_chat): + COMMAND: int + DATA: int + def __init__(self, server: SMTPServer, conn: socket.socket, addr: Any, data_size_limit: int = ...) -> None: ... + # base asynchat.async_chat.push() accepts bytes + def push(self, msg: Text) -> None: ... # type: ignore + def collect_incoming_data(self, data: bytes) -> None: ... + def found_terminator(self) -> None: ... + def smtp_HELO(self, arg: str) -> None: ... + def smtp_NOOP(self, arg: str) -> None: ... + def smtp_QUIT(self, arg: str) -> None: ... + def smtp_MAIL(self, arg: str) -> None: ... + def smtp_RCPT(self, arg: str) -> None: ... + def smtp_RSET(self, arg: str) -> None: ... + def smtp_DATA(self, arg: str) -> None: ... + +class SMTPServer(asyncore.dispatcher): + channel_class: Type[SMTPChannel] + + data_size_limit: int + enable_SMTPUTF8: bool + def __init__(self, localaddr: _Address, remoteaddr: _Address, data_size_limit: int = ...) -> None: ... + def handle_accepted(self, conn: socket.socket, addr: Any) -> None: ... + def process_message( + self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str, **kwargs: Any + ) -> str | None: ... + +class DebuggingServer(SMTPServer): ... + +class PureProxy(SMTPServer): + def process_message( # type: ignore + self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str + ) -> str | None: ... + +class MailmanProxy(PureProxy): + def process_message( # type: ignore + self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str + ) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/sndhdr.pyi b/mypy/typeshed/stdlib/@python2/sndhdr.pyi new file mode 100644 index 000000000000..189529fd21d6 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sndhdr.pyi @@ -0,0 +1,6 @@ +from typing import Text, Tuple, Union + +_SndHeaders = Tuple[str, int, int, int, Union[int, str]] + +def what(filename: Text) -> _SndHeaders | None: ... +def whathdr(filename: Text) -> _SndHeaders | None: ... diff --git a/mypy/typeshed/stdlib/@python2/socket.pyi b/mypy/typeshed/stdlib/@python2/socket.pyi new file mode 100644 index 000000000000..2bf719dd9faa --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/socket.pyi @@ -0,0 +1,471 @@ +import sys +from typing import Any, BinaryIO, Iterable, List, Text, Tuple, TypeVar, Union, overload + +# ----- Constants ----- +# Some socket families are listed in the "Socket families" section of the docs, +# but not the "Constants" section. These are listed at the end of the list of +# constants. +# +# Besides those and the first few constants listed, the constants are listed in +# documentation order. + +# Constants defined by Python (i.e. not OS constants re-exported from C) +has_ipv6: bool +SocketType: Any +# Re-exported errno +EAGAIN: int +EBADF: int +EINTR: int +EWOULDBLOCK: int + +# Constants re-exported from C + +# Per socketmodule.c, only these three families are portable +AF_UNIX: AddressFamily +AF_INET: AddressFamily +AF_INET6: AddressFamily + +SOCK_STREAM: SocketKind +SOCK_DGRAM: SocketKind +SOCK_RAW: SocketKind +SOCK_RDM: SocketKind +SOCK_SEQPACKET: SocketKind + +# Address families not mentioned in the docs +AF_AAL5: AddressFamily +AF_APPLETALK: AddressFamily +AF_ASH: AddressFamily +AF_ATMPVC: AddressFamily +AF_ATMSVC: AddressFamily +AF_AX25: AddressFamily +AF_BRIDGE: AddressFamily +AF_DECnet: AddressFamily +AF_ECONET: AddressFamily +AF_IPX: AddressFamily +AF_IRDA: AddressFamily +AF_KEY: AddressFamily +AF_LLC: AddressFamily +AF_NETBEUI: AddressFamily +AF_NETROM: AddressFamily +AF_PPPOX: AddressFamily +AF_ROSE: AddressFamily +AF_ROUTE: AddressFamily +AF_SECURITY: AddressFamily +AF_SNA: AddressFamily +AF_SYSTEM: AddressFamily +AF_UNSPEC: AddressFamily +AF_WANPIPE: AddressFamily +AF_X25: AddressFamily + +# The "many constants" referenced by the docs +SOMAXCONN: int +AI_ADDRCONFIG: AddressInfo +AI_ALL: AddressInfo +AI_CANONNAME: AddressInfo +AI_DEFAULT: AddressInfo +AI_MASK: AddressInfo +AI_NUMERICHOST: AddressInfo +AI_NUMERICSERV: AddressInfo +AI_PASSIVE: AddressInfo +AI_V4MAPPED: AddressInfo +AI_V4MAPPED_CFG: AddressInfo +EAI_ADDRFAMILY: int +EAI_AGAIN: int +EAI_BADFLAGS: int +EAI_BADHINTS: int +EAI_FAIL: int +EAI_FAMILY: int +EAI_MAX: int +EAI_MEMORY: int +EAI_NODATA: int +EAI_NONAME: int +EAI_OVERFLOW: int +EAI_PROTOCOL: int +EAI_SERVICE: int +EAI_SOCKTYPE: int +EAI_SYSTEM: int +INADDR_ALLHOSTS_GROUP: int +INADDR_ANY: int +INADDR_BROADCAST: int +INADDR_LOOPBACK: int +INADDR_MAX_LOCAL_GROUP: int +INADDR_NONE: int +INADDR_UNSPEC_GROUP: int +IPPORT_RESERVED: int +IPPORT_USERRESERVED: int +IPPROTO_AH: int +IPPROTO_BIP: int +IPPROTO_DSTOPTS: int +IPPROTO_EGP: int +IPPROTO_EON: int +IPPROTO_ESP: int +IPPROTO_FRAGMENT: int +IPPROTO_GGP: int +IPPROTO_GRE: int +IPPROTO_HELLO: int +IPPROTO_HOPOPTS: int +IPPROTO_ICMP: int +IPPROTO_ICMPV6: int +IPPROTO_IDP: int +IPPROTO_IGMP: int +IPPROTO_IP: int +IPPROTO_IPCOMP: int +IPPROTO_IPIP: int +IPPROTO_IPV4: int +IPPROTO_IPV6: int +IPPROTO_MAX: int +IPPROTO_MOBILE: int +IPPROTO_ND: int +IPPROTO_NONE: int +IPPROTO_PIM: int +IPPROTO_PUP: int +IPPROTO_RAW: int +IPPROTO_ROUTING: int +IPPROTO_RSVP: int +IPPROTO_SCTP: int +IPPROTO_TCP: int +IPPROTO_TP: int +IPPROTO_UDP: int +IPPROTO_VRRP: int +IPPROTO_XTP: int +IPV6_CHECKSUM: int +IPV6_DONTFRAG: int +IPV6_DSTOPTS: int +IPV6_HOPLIMIT: int +IPV6_HOPOPTS: int +IPV6_JOIN_GROUP: int +IPV6_LEAVE_GROUP: int +IPV6_MULTICAST_HOPS: int +IPV6_MULTICAST_IF: int +IPV6_MULTICAST_LOOP: int +IPV6_NEXTHOP: int +IPV6_PATHMTU: int +IPV6_PKTINFO: int +IPV6_RECVDSTOPTS: int +IPV6_RECVHOPLIMIT: int +IPV6_RECVHOPOPTS: int +IPV6_RECVPATHMTU: int +IPV6_RECVPKTINFO: int +IPV6_RECVRTHDR: int +IPV6_RECVTCLASS: int +IPV6_RTHDR: int +IPV6_RTHDRDSTOPTS: int +IPV6_RTHDR_TYPE_0: int +IPV6_TCLASS: int +IPV6_UNICAST_HOPS: int +IPV6_USE_MIN_MTU: int +IPV6_V6ONLY: int +IPX_TYPE: int +IP_ADD_MEMBERSHIP: int +IP_DEFAULT_MULTICAST_LOOP: int +IP_DEFAULT_MULTICAST_TTL: int +IP_DROP_MEMBERSHIP: int +IP_HDRINCL: int +IP_MAX_MEMBERSHIPS: int +IP_MULTICAST_IF: int +IP_MULTICAST_LOOP: int +IP_MULTICAST_TTL: int +IP_OPTIONS: int +IP_RECVDSTADDR: int +IP_RECVOPTS: int +IP_RECVRETOPTS: int +IP_RETOPTS: int +IP_TOS: int +IP_TRANSPARENT: int +IP_TTL: int +LOCAL_PEERCRED: int +MSG_BCAST: MsgFlag +MSG_BTAG: MsgFlag +MSG_CMSG_CLOEXEC: MsgFlag +MSG_CONFIRM: MsgFlag +MSG_CTRUNC: MsgFlag +MSG_DONTROUTE: MsgFlag +MSG_DONTWAIT: MsgFlag +MSG_EOF: MsgFlag +MSG_EOR: MsgFlag +MSG_ERRQUEUE: MsgFlag +MSG_ETAG: MsgFlag +MSG_FASTOPEN: MsgFlag +MSG_MCAST: MsgFlag +MSG_MORE: MsgFlag +MSG_NOSIGNAL: MsgFlag +MSG_NOTIFICATION: MsgFlag +MSG_OOB: MsgFlag +MSG_PEEK: MsgFlag +MSG_TRUNC: MsgFlag +MSG_WAITALL: MsgFlag +NI_DGRAM: int +NI_MAXHOST: int +NI_MAXSERV: int +NI_NAMEREQD: int +NI_NOFQDN: int +NI_NUMERICHOST: int +NI_NUMERICSERV: int +SCM_CREDENTIALS: int +SCM_CREDS: int +SCM_RIGHTS: int +SHUT_RD: int +SHUT_RDWR: int +SHUT_WR: int +SOL_ATALK: int +SOL_AX25: int +SOL_HCI: int +SOL_IP: int +SOL_IPX: int +SOL_NETROM: int +SOL_ROSE: int +SOL_SOCKET: int +SOL_TCP: int +SOL_UDP: int +SO_ACCEPTCONN: int +SO_BINDTODEVICE: int +SO_BROADCAST: int +SO_DEBUG: int +SO_DONTROUTE: int +SO_ERROR: int +SO_EXCLUSIVEADDRUSE: int +SO_KEEPALIVE: int +SO_LINGER: int +SO_MARK: int +SO_OOBINLINE: int +SO_PASSCRED: int +SO_PEERCRED: int +SO_PRIORITY: int +SO_RCVBUF: int +SO_RCVLOWAT: int +SO_RCVTIMEO: int +SO_REUSEADDR: int +SO_REUSEPORT: int +SO_SETFIB: int +SO_SNDBUF: int +SO_SNDLOWAT: int +SO_SNDTIMEO: int +SO_TYPE: int +SO_USELOOPBACK: int +TCP_CORK: int +TCP_DEFER_ACCEPT: int +TCP_FASTOPEN: int +TCP_INFO: int +TCP_KEEPCNT: int +TCP_KEEPIDLE: int +TCP_KEEPINTVL: int +TCP_LINGER2: int +TCP_MAXSEG: int +TCP_NODELAY: int +TCP_QUICKACK: int +TCP_SYNCNT: int +TCP_WINDOW_CLAMP: int +# Specifically-documented constants + +if sys.platform == "linux": + AF_PACKET: AddressFamily + PF_PACKET: int + PACKET_BROADCAST: int + PACKET_FASTROUTE: int + PACKET_HOST: int + PACKET_LOOPBACK: int + PACKET_MULTICAST: int + PACKET_OTHERHOST: int + PACKET_OUTGOING: int + +if sys.platform == "win32": + SIO_RCVALL: int + SIO_KEEPALIVE_VALS: int + RCVALL_IPLEVEL: int + RCVALL_MAX: int + RCVALL_OFF: int + RCVALL_ON: int + RCVALL_SOCKETLEVELONLY: int + +if sys.platform == "linux": + AF_TIPC: AddressFamily + SOL_TIPC: int + TIPC_ADDR_ID: int + TIPC_ADDR_NAME: int + TIPC_ADDR_NAMESEQ: int + TIPC_CFG_SRV: int + TIPC_CLUSTER_SCOPE: int + TIPC_CONN_TIMEOUT: int + TIPC_CRITICAL_IMPORTANCE: int + TIPC_DEST_DROPPABLE: int + TIPC_HIGH_IMPORTANCE: int + TIPC_IMPORTANCE: int + TIPC_LOW_IMPORTANCE: int + TIPC_MEDIUM_IMPORTANCE: int + TIPC_NODE_SCOPE: int + TIPC_PUBLISHED: int + TIPC_SRC_DROPPABLE: int + TIPC_SUBSCR_TIMEOUT: int + TIPC_SUB_CANCEL: int + TIPC_SUB_PORTS: int + TIPC_SUB_SERVICE: int + TIPC_TOP_SRV: int + TIPC_WAIT_FOREVER: int + TIPC_WITHDRAWN: int + TIPC_ZONE_SCOPE: int + +AF_LINK: AddressFamily # Availability: BSD, macOS + +# Semi-documented constants +# (Listed under "Socket families" in the docs, but not "Constants") + +if sys.platform == "linux": + # Netlink is defined by Linux + AF_NETLINK: AddressFamily + NETLINK_ARPD: int + NETLINK_CRYPTO: int + NETLINK_DNRTMSG: int + NETLINK_FIREWALL: int + NETLINK_IP6_FW: int + NETLINK_NFLOG: int + NETLINK_ROUTE6: int + NETLINK_ROUTE: int + NETLINK_SKIP: int + NETLINK_TAPBASE: int + NETLINK_TCPDIAG: int + NETLINK_USERSOCK: int + NETLINK_W1: int + NETLINK_XFRM: int + +if sys.platform != "win32" and sys.platform != "darwin": + # Linux and some BSD support is explicit in the docs + # Windows and macOS do not support in practice + AF_BLUETOOTH: AddressFamily + BTPROTO_HCI: int + BTPROTO_L2CAP: int + BTPROTO_RFCOMM: int + BTPROTO_SCO: int # not in FreeBSD + + BDADDR_ANY: str + BDADDR_LOCAL: str + + HCI_FILTER: int # not in NetBSD or DragonFlyBSD + # not in FreeBSD, NetBSD, or DragonFlyBSD + HCI_TIME_STAMP: int + HCI_DATA_DIR: int + +if sys.platform == "darwin": + # PF_SYSTEM is defined by macOS + PF_SYSTEM: int + SYSPROTO_CONTROL: int + +# enum versions of above flags +AddressFamily = int +SocketKind = int + +AddressInfo = int +MsgFlag = int + +# ----- Exceptions ----- + +class error(IOError): ... + +class herror(error): + def __init__(self, herror: int = ..., string: str = ...) -> None: ... + +class gaierror(error): + def __init__(self, error: int = ..., string: str = ...) -> None: ... + +class timeout(error): + def __init__(self, error: int = ..., string: str = ...) -> None: ... + +# ----- Classes ----- + +# Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, +# AF_NETLINK, AF_TIPC) or strings (AF_UNIX). +_Address = Union[Tuple[Any, ...], str] +_RetAddress = Any +# TODO Most methods allow bytes as address objects + +_WriteBuffer = Union[bytearray, memoryview] + +_CMSG = Tuple[int, int, bytes] +_SelfT = TypeVar("_SelfT", bound=socket) + +class socket: + family: int + type: int + proto: int + def __init__(self, family: int = ..., type: int = ..., proto: int = ...) -> None: ... + # --- methods --- + def accept(self) -> Tuple[socket, _RetAddress]: ... + def bind(self, address: _Address | bytes) -> None: ... + def close(self) -> None: ... + def connect(self, address: _Address | bytes) -> None: ... + def connect_ex(self, address: _Address | bytes) -> int: ... + def detach(self) -> int: ... + def dup(self) -> socket: ... + def fileno(self) -> int: ... + def getpeername(self) -> _RetAddress: ... + def getsockname(self) -> _RetAddress: ... + @overload + def getsockopt(self, level: int, optname: int) -> int: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... + def gettimeout(self) -> float | None: ... + if sys.platform == "win32": + def ioctl(self, control: int, option: int | Tuple[int, int, int]) -> None: ... + def listen(self, __backlog: int) -> None: ... + # Note that the makefile's documented windows-specific behavior is not represented + def makefile(self, mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... + def recv(self, bufsize: int, flags: int = ...) -> bytes: ... + def recvfrom(self, bufsize: int, flags: int = ...) -> Tuple[bytes, _RetAddress]: ... + def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> Tuple[int, _RetAddress]: ... + def recv_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> int: ... + def send(self, data: bytes, flags: int = ...) -> int: ... + def sendall(self, data: bytes, flags: int = ...) -> None: ... # return type: None on success + @overload + def sendto(self, data: bytes, address: _Address) -> int: ... + @overload + def sendto(self, data: bytes, flags: int, address: _Address) -> int: ... + def setblocking(self, flag: bool) -> None: ... + def settimeout(self, value: float | None) -> None: ... + def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... + if sys.platform == "win32": + def share(self, process_id: int) -> bytes: ... + def shutdown(self, how: int) -> None: ... + +# ----- Functions ----- + +def create_connection( + address: Tuple[str | None, int], + timeout: float | None = ..., + source_address: Tuple[bytearray | bytes | Text, int] | None = ..., +) -> socket: ... +def fromfd(fd: int, family: int, type: int, proto: int = ...) -> socket: ... + +# the 5th tuple item is an address +def getaddrinfo( + host: bytearray | bytes | Text | None, + port: str | int | None, + family: int = ..., + socktype: int = ..., + proto: int = ..., + flags: int = ..., +) -> List[Tuple[AddressFamily, SocketKind, int, str, Tuple[Any, ...]]]: ... +def getfqdn(name: str = ...) -> str: ... +def gethostbyname(hostname: str) -> str: ... +def gethostbyname_ex(hostname: str) -> Tuple[str, List[str], List[str]]: ... +def gethostname() -> str: ... +def gethostbyaddr(ip_address: str) -> Tuple[str, List[str], List[str]]: ... +def getnameinfo(sockaddr: Tuple[str, int] | Tuple[str, int, int, int], flags: int) -> Tuple[str, str]: ... +def getprotobyname(protocolname: str) -> int: ... +def getservbyname(servicename: str, protocolname: str = ...) -> int: ... +def getservbyport(port: int, protocolname: str = ...) -> str: ... + +if sys.platform == "win32": + def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... + +else: + def socketpair(family: int | None = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... + +def ntohl(x: int) -> int: ... # param & ret val are 32-bit ints +def ntohs(x: int) -> int: ... # param & ret val are 16-bit ints +def htonl(x: int) -> int: ... # param & ret val are 32-bit ints +def htons(x: int) -> int: ... # param & ret val are 16-bit ints +def inet_aton(ip_string: str) -> bytes: ... # ret val 4 bytes in length +def inet_ntoa(packed_ip: bytes) -> str: ... +def inet_pton(address_family: int, ip_string: str) -> bytes: ... +def inet_ntop(address_family: int, packed_ip: bytes) -> str: ... +def getdefaulttimeout() -> float | None: ... +def setdefaulttimeout(timeout: float | None) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi b/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi new file mode 100644 index 000000000000..d5d20d67b58e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi @@ -0,0 +1 @@ +from sqlite3.dbapi2 import * # noqa: F403 diff --git a/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi new file mode 100644 index 000000000000..023a0506f4aa --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi @@ -0,0 +1,251 @@ +from datetime import date, datetime, time +from typing import Any, Callable, Generator, Iterable, Iterator, List, Protocol, Text, Tuple, Type, TypeVar + +_T = TypeVar("_T") + +paramstyle: str +threadsafety: int +apilevel: str +Date = date +Time = time +Timestamp = datetime + +def DateFromTicks(ticks: float) -> Date: ... +def TimeFromTicks(ticks: float) -> Time: ... +def TimestampFromTicks(ticks: float) -> Timestamp: ... + +version_info: Tuple[int, int, int] +sqlite_version_info: Tuple[int, int, int] +Binary = buffer + +# The remaining definitions are imported from _sqlite3. + +PARSE_COLNAMES: int +PARSE_DECLTYPES: int +SQLITE_ALTER_TABLE: int +SQLITE_ANALYZE: int +SQLITE_ATTACH: int +SQLITE_CREATE_INDEX: int +SQLITE_CREATE_TABLE: int +SQLITE_CREATE_TEMP_INDEX: int +SQLITE_CREATE_TEMP_TABLE: int +SQLITE_CREATE_TEMP_TRIGGER: int +SQLITE_CREATE_TEMP_VIEW: int +SQLITE_CREATE_TRIGGER: int +SQLITE_CREATE_VIEW: int +SQLITE_DELETE: int +SQLITE_DENY: int +SQLITE_DETACH: int +SQLITE_DROP_INDEX: int +SQLITE_DROP_TABLE: int +SQLITE_DROP_TEMP_INDEX: int +SQLITE_DROP_TEMP_TABLE: int +SQLITE_DROP_TEMP_TRIGGER: int +SQLITE_DROP_TEMP_VIEW: int +SQLITE_DROP_TRIGGER: int +SQLITE_DROP_VIEW: int +SQLITE_IGNORE: int +SQLITE_INSERT: int +SQLITE_OK: int +SQLITE_PRAGMA: int +SQLITE_READ: int +SQLITE_REINDEX: int +SQLITE_SELECT: int +SQLITE_TRANSACTION: int +SQLITE_UPDATE: int +adapters: Any +converters: Any +sqlite_version: str +version: str + +# TODO: adapt needs to get probed +def adapt(obj, protocol, alternate): ... +def complete_statement(sql: str) -> bool: ... +def connect( + database: bytes | Text, + timeout: float = ..., + detect_types: int = ..., + isolation_level: str | None = ..., + check_same_thread: bool = ..., + factory: Type[Connection] | None = ..., + cached_statements: int = ..., +) -> Connection: ... +def enable_callback_tracebacks(__enable: bool) -> None: ... +def enable_shared_cache(enable: int) -> None: ... +def register_adapter(__type: Type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... +def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... + +class Cache(object): + def __init__(self, *args, **kwargs) -> None: ... + def display(self, *args, **kwargs) -> None: ... + def get(self, *args, **kwargs) -> None: ... + +class _AggregateProtocol(Protocol): + def step(self, value: int) -> None: ... + def finalize(self) -> int: ... + +class Connection(object): + DataError: Any + DatabaseError: Any + Error: Any + IntegrityError: Any + InterfaceError: Any + InternalError: Any + NotSupportedError: Any + OperationalError: Any + ProgrammingError: Any + Warning: Any + in_transaction: Any + isolation_level: Any + row_factory: Any + text_factory: Any + total_changes: Any + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + def close(self) -> None: ... + def commit(self) -> None: ... + def create_aggregate(self, name: str, n_arg: int, aggregate_class: Callable[[], _AggregateProtocol]) -> None: ... + def create_collation(self, __name: str, __callback: Any) -> None: ... + def create_function(self, name: str, num_params: int, func: Any) -> None: ... + def cursor(self, cursorClass: type | None = ...) -> Cursor: ... + def execute(self, sql: str, parameters: Iterable[Any] = ...) -> Cursor: ... + # TODO: please check in executemany() if seq_of_parameters type is possible like this + def executemany(self, __sql: str, __parameters: Iterable[Iterable[Any]]) -> Cursor: ... + def executescript(self, __sql_script: bytes | Text) -> Cursor: ... + def interrupt(self, *args: Any, **kwargs: Any) -> None: ... + def iterdump(self, *args: Any, **kwargs: Any) -> Generator[str, None, None]: ... + def rollback(self, *args: Any, **kwargs: Any) -> None: ... + # TODO: set_authorizer(authorzer_callback) + # see https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.set_authorizer + # returns [SQLITE_OK, SQLITE_DENY, SQLITE_IGNORE] so perhaps int + def set_authorizer(self, *args: Any, **kwargs: Any) -> None: ... + # set_progress_handler(handler, n) -> see https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.set_progress_handler + def set_progress_handler(self, *args: Any, **kwargs: Any) -> None: ... + def set_trace_callback(self, *args: Any, **kwargs: Any) -> None: ... + # enable_load_extension and load_extension is not available on python distributions compiled + # without sqlite3 loadable extension support. see footnotes https://docs.python.org/3/library/sqlite3.html#f1 + def enable_load_extension(self, enabled: bool) -> None: ... + def load_extension(self, path: str) -> None: ... + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + def __enter__(self) -> Connection: ... + def __exit__(self, t: type | None, exc: BaseException | None, tb: Any | None) -> None: ... + +class Cursor(Iterator[Any]): + arraysize: Any + connection: Any + description: Any + lastrowid: Any + row_factory: Any + rowcount: int + # TODO: Cursor class accepts exactly 1 argument + # required type is sqlite3.Connection (which is imported as _Connection) + # however, the name of the __init__ variable is unknown + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + def close(self, *args: Any, **kwargs: Any) -> None: ... + def execute(self, __sql: str, __parameters: Iterable[Any] = ...) -> Cursor: ... + def executemany(self, __sql: str, __seq_of_parameters: Iterable[Iterable[Any]]) -> Cursor: ... + def executescript(self, __sql_script: bytes | Text) -> Cursor: ... + def fetchall(self) -> List[Any]: ... + def fetchmany(self, size: int | None = ...) -> List[Any]: ... + def fetchone(self) -> Any: ... + def setinputsizes(self, *args: Any, **kwargs: Any) -> None: ... + def setoutputsize(self, *args: Any, **kwargs: Any) -> None: ... + def __iter__(self) -> Cursor: ... + def next(self) -> Any: ... + +class DataError(DatabaseError): ... +class DatabaseError(Error): ... +class Error(Exception): ... +class IntegrityError(DatabaseError): ... +class InterfaceError(Error): ... +class InternalError(DatabaseError): ... +class NotSupportedError(DatabaseError): ... +class OperationalError(DatabaseError): ... + +class OptimizedUnicode(object): + maketrans: Any + def __init__(self, *args, **kwargs): ... + def capitalize(self, *args, **kwargs): ... + def casefold(self, *args, **kwargs): ... + def center(self, *args, **kwargs): ... + def count(self, *args, **kwargs): ... + def encode(self, *args, **kwargs): ... + def endswith(self, *args, **kwargs): ... + def expandtabs(self, *args, **kwargs): ... + def find(self, *args, **kwargs): ... + def format(self, *args, **kwargs): ... + def format_map(self, *args, **kwargs): ... + def index(self, *args, **kwargs): ... + def isalnum(self, *args, **kwargs): ... + def isalpha(self, *args, **kwargs): ... + def isdecimal(self, *args, **kwargs): ... + def isdigit(self, *args, **kwargs): ... + def isidentifier(self, *args, **kwargs): ... + def islower(self, *args, **kwargs): ... + def isnumeric(self, *args, **kwargs): ... + def isprintable(self, *args, **kwargs): ... + def isspace(self, *args, **kwargs): ... + def istitle(self, *args, **kwargs): ... + def isupper(self, *args, **kwargs): ... + def join(self, *args, **kwargs): ... + def ljust(self, *args, **kwargs): ... + def lower(self, *args, **kwargs): ... + def lstrip(self, *args, **kwargs): ... + def partition(self, *args, **kwargs): ... + def replace(self, *args, **kwargs): ... + def rfind(self, *args, **kwargs): ... + def rindex(self, *args, **kwargs): ... + def rjust(self, *args, **kwargs): ... + def rpartition(self, *args, **kwargs): ... + def rsplit(self, *args, **kwargs): ... + def rstrip(self, *args, **kwargs): ... + def split(self, *args, **kwargs): ... + def splitlines(self, *args, **kwargs): ... + def startswith(self, *args, **kwargs): ... + def strip(self, *args, **kwargs): ... + def swapcase(self, *args, **kwargs): ... + def title(self, *args, **kwargs): ... + def translate(self, *args, **kwargs): ... + def upper(self, *args, **kwargs): ... + def zfill(self, *args, **kwargs): ... + def __add__(self, other): ... + def __contains__(self, *args, **kwargs): ... + def __eq__(self, other): ... + def __format__(self, *args, **kwargs): ... + def __ge__(self, other): ... + def __getitem__(self, index): ... + def __getnewargs__(self, *args, **kwargs): ... + def __gt__(self, other): ... + def __hash__(self): ... + def __iter__(self): ... + def __le__(self, other): ... + def __len__(self, *args, **kwargs): ... + def __lt__(self, other): ... + def __mod__(self, other): ... + def __mul__(self, other): ... + def __ne__(self, other): ... + def __rmod__(self, other): ... + def __rmul__(self, other): ... + +class PrepareProtocol(object): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + +class ProgrammingError(DatabaseError): ... + +class Row(object): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + def keys(self, *args: Any, **kwargs: Any): ... + def __eq__(self, other): ... + def __ge__(self, other): ... + def __getitem__(self, index): ... + def __gt__(self, other): ... + def __hash__(self): ... + def __iter__(self): ... + def __le__(self, other): ... + def __len__(self): ... + def __lt__(self, other): ... + def __ne__(self, other): ... + +class Statement(object): + def __init__(self, *args, **kwargs): ... + +class Warning(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/sre_compile.pyi b/mypy/typeshed/stdlib/@python2/sre_compile.pyi new file mode 100644 index 000000000000..efc3e568a07c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sre_compile.pyi @@ -0,0 +1,22 @@ +from sre_constants import ( + SRE_FLAG_DEBUG as SRE_FLAG_DEBUG, + SRE_FLAG_DOTALL as SRE_FLAG_DOTALL, + SRE_FLAG_IGNORECASE as SRE_FLAG_IGNORECASE, + SRE_FLAG_LOCALE as SRE_FLAG_LOCALE, + SRE_FLAG_MULTILINE as SRE_FLAG_MULTILINE, + SRE_FLAG_TEMPLATE as SRE_FLAG_TEMPLATE, + SRE_FLAG_UNICODE as SRE_FLAG_UNICODE, + SRE_FLAG_VERBOSE as SRE_FLAG_VERBOSE, + SRE_INFO_CHARSET as SRE_INFO_CHARSET, + SRE_INFO_LITERAL as SRE_INFO_LITERAL, + SRE_INFO_PREFIX as SRE_INFO_PREFIX, +) +from sre_parse import SubPattern +from typing import Any, List, Pattern, Tuple, Type + +MAXCODE: int +STRING_TYPES: Tuple[Type[str], Type[unicode]] +_IsStringType = int + +def isstring(obj: Any) -> _IsStringType: ... +def compile(p: str | bytes | SubPattern, flags: int = ...) -> Pattern[Any]: ... diff --git a/mypy/typeshed/stdlib/@python2/sre_parse.pyi b/mypy/typeshed/stdlib/@python2/sre_parse.pyi index e2a0be4e3bf1..35f6d4d32ae2 100644 --- a/mypy/typeshed/stdlib/@python2/sre_parse.pyi +++ b/mypy/typeshed/stdlib/@python2/sre_parse.pyi @@ -7,7 +7,7 @@ OCTDIGITS: Set[Any] HEXDIGITS: Set[Any] WHITESPACE: Set[Any] ESCAPES: Dict[str, Tuple[str, int]] -CATEGORIES: Dict[str, Union[Tuple[str, str], Tuple[str, List[Tuple[str, str]]]]] +CATEGORIES: Dict[str, Tuple[str, str] | Tuple[str, List[Tuple[str, str]]]] FLAGS: Dict[str, int] class Pattern: @@ -31,13 +31,13 @@ _CodeType = Union[str, _AvType] class SubPattern: pattern: str data: List[_CodeType] - width: Optional[int] + width: int | None def __init__(self, pattern, data: List[_CodeType] = ...) -> None: ... def dump(self, level: int = ...) -> None: ... def __len__(self) -> int: ... - def __delitem__(self, index: Union[int, slice]) -> None: ... - def __getitem__(self, index: Union[int, slice]) -> Union[SubPattern, _CodeType]: ... - def __setitem__(self, index: Union[int, slice], code: _CodeType): ... + def __delitem__(self, index: int | slice) -> None: ... + def __getitem__(self, index: int | slice) -> SubPattern | _CodeType: ... + def __setitem__(self, index: int | slice, code: _CodeType): ... def insert(self, index, code: _CodeType) -> None: ... def append(self, code: _CodeType) -> None: ... def getwidth(self) -> int: ... @@ -47,8 +47,8 @@ class Tokenizer: index: int def __init__(self, string: str) -> None: ... def match(self, char: str, skip: int = ...) -> int: ... - def get(self) -> Optional[str]: ... - def tell(self) -> Tuple[int, Optional[str]]: ... + def get(self) -> str | None: ... + def tell(self) -> Tuple[int, str | None]: ... def seek(self, index: int) -> None: ... def isident(char: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/ssl.pyi b/mypy/typeshed/stdlib/@python2/ssl.pyi new file mode 100644 index 000000000000..aabecaaba87a --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/ssl.pyi @@ -0,0 +1,265 @@ +import socket +import sys +from _typeshed import StrPath +from typing import Any, Callable, ClassVar, Dict, Iterable, List, NamedTuple, Optional, Set, Text, Tuple, Union, overload +from typing_extensions import Literal + +_PCTRTT = Tuple[Tuple[str, str], ...] +_PCTRTTT = Tuple[_PCTRTT, ...] +_PeerCertRetDictType = Dict[str, Union[str, _PCTRTTT, _PCTRTT]] +_PeerCertRetType = Union[_PeerCertRetDictType, bytes, None] +_EnumRetType = List[Tuple[bytes, str, Union[Set[str], bool]]] +_PasswordType = Union[Callable[[], Union[str, bytes]], str, bytes] + +_SC1ArgT = SSLSocket +_SrvnmeCbType = Callable[[_SC1ArgT, Optional[str], SSLSocket], Optional[int]] + +class SSLError(OSError): + library: str + reason: str + +class SSLZeroReturnError(SSLError): ... +class SSLWantReadError(SSLError): ... +class SSLWantWriteError(SSLError): ... +class SSLSyscallError(SSLError): ... +class SSLEOFError(SSLError): ... +class CertificateError(ValueError): ... + +def wrap_socket( + sock: socket.socket, + keyfile: str | None = ..., + certfile: str | None = ..., + server_side: bool = ..., + cert_reqs: int = ..., + ssl_version: int = ..., + ca_certs: str | None = ..., + do_handshake_on_connect: bool = ..., + suppress_ragged_eofs: bool = ..., + ciphers: str | None = ..., +) -> SSLSocket: ... +def create_default_context( + purpose: Any = ..., *, cafile: str | None = ..., capath: str | None = ..., cadata: Text | bytes | None = ... +) -> SSLContext: ... +def _create_unverified_context( + protocol: int = ..., + *, + cert_reqs: int | None = ..., + check_hostname: bool = ..., + purpose: Any = ..., + certfile: str | None = ..., + keyfile: str | None = ..., + cafile: str | None = ..., + capath: str | None = ..., + cadata: Text | bytes | None = ..., +) -> SSLContext: ... + +_create_default_https_context: Callable[..., SSLContext] + +def RAND_status() -> bool: ... +def RAND_egd(path: str) -> None: ... +def RAND_add(__s: bytes, __entropy: float) -> None: ... +def match_hostname(cert: _PeerCertRetType, hostname: str) -> None: ... +def cert_time_to_seconds(cert_time: str) -> int: ... +def get_server_certificate(addr: Tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... +def DER_cert_to_PEM_cert(der_cert_bytes: bytes) -> str: ... +def PEM_cert_to_DER_cert(pem_cert_string: str) -> bytes: ... + +class DefaultVerifyPaths(NamedTuple): + cafile: str + capath: str + openssl_cafile_env: str + openssl_cafile: str + openssl_capath_env: str + openssl_capath: str + +def get_default_verify_paths() -> DefaultVerifyPaths: ... + +if sys.platform == "win32": + def enum_certificates(store_name: str) -> _EnumRetType: ... + def enum_crls(store_name: str) -> _EnumRetType: ... + +CERT_NONE: int +CERT_OPTIONAL: int +CERT_REQUIRED: int + +VERIFY_DEFAULT: int +VERIFY_CRL_CHECK_LEAF: int +VERIFY_CRL_CHECK_CHAIN: int +VERIFY_X509_STRICT: int +VERIFY_X509_TRUSTED_FIRST: int + +PROTOCOL_SSLv23: int +PROTOCOL_SSLv2: int +PROTOCOL_SSLv3: int +PROTOCOL_TLSv1: int +PROTOCOL_TLSv1_1: int +PROTOCOL_TLSv1_2: int +PROTOCOL_TLS: int +OP_ALL: int +OP_NO_SSLv2: int +OP_NO_SSLv3: int +OP_NO_TLSv1: int +OP_NO_TLSv1_1: int +OP_NO_TLSv1_2: int +OP_CIPHER_SERVER_PREFERENCE: int +OP_SINGLE_DH_USE: int +OP_SINGLE_ECDH_USE: int +OP_NO_COMPRESSION: int + +HAS_ALPN: bool +HAS_ECDH: bool +HAS_SNI: bool +HAS_NPN: bool +CHANNEL_BINDING_TYPES: List[str] + +OPENSSL_VERSION: str +OPENSSL_VERSION_INFO: Tuple[int, int, int, int, int] +OPENSSL_VERSION_NUMBER: int + +ALERT_DESCRIPTION_HANDSHAKE_FAILURE: int +ALERT_DESCRIPTION_INTERNAL_ERROR: int +ALERT_DESCRIPTION_ACCESS_DENIED: int +ALERT_DESCRIPTION_BAD_CERTIFICATE: int +ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE: int +ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE: int +ALERT_DESCRIPTION_BAD_RECORD_MAC: int +ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: int +ALERT_DESCRIPTION_CERTIFICATE_REVOKED: int +ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: int +ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE: int +ALERT_DESCRIPTION_CLOSE_NOTIFY: int +ALERT_DESCRIPTION_DECODE_ERROR: int +ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: int +ALERT_DESCRIPTION_DECRYPT_ERROR: int +ALERT_DESCRIPTION_ILLEGAL_PARAMETER: int +ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: int +ALERT_DESCRIPTION_NO_RENEGOTIATION: int +ALERT_DESCRIPTION_PROTOCOL_VERSION: int +ALERT_DESCRIPTION_RECORD_OVERFLOW: int +ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: int +ALERT_DESCRIPTION_UNKNOWN_CA: int +ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY: int +ALERT_DESCRIPTION_UNRECOGNIZED_NAME: int +ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: int +ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: int +ALERT_DESCRIPTION_USER_CANCELLED: int + +class _ASN1Object(NamedTuple): + nid: int + shortname: str + longname: str + oid: str + +class Purpose(_ASN1Object): + SERVER_AUTH: ClassVar[Purpose] + CLIENT_AUTH: ClassVar[Purpose] + +class SSLSocket(socket.socket): + context: SSLContext + server_side: bool + server_hostname: str | None + def __init__( + self, + sock: socket.socket | None = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + server_side: bool = ..., + cert_reqs: int = ..., + ssl_version: int = ..., + ca_certs: str | None = ..., + do_handshake_on_connect: bool = ..., + family: int = ..., + type: int = ..., + proto: int = ..., + fileno: int | None = ..., + suppress_ragged_eofs: bool = ..., + npn_protocols: Iterable[str] | None = ..., + ciphers: str | None = ..., + server_hostname: str | None = ..., + _context: SSLContext | None = ..., + _session: Any | None = ..., + ) -> None: ... + def connect(self, addr: socket._Address | bytes) -> None: ... + def connect_ex(self, addr: socket._Address | bytes) -> int: ... + def recv(self, buflen: int = ..., flags: int = ...) -> bytes: ... + def recv_into(self, buffer: socket._WriteBuffer, nbytes: int | None = ..., flags: int = ...) -> int: ... + def recvfrom(self, buflen: int = ..., flags: int = ...) -> tuple[bytes, socket._RetAddress]: ... + def recvfrom_into( + self, buffer: socket._WriteBuffer, nbytes: int | None = ..., flags: int = ... + ) -> tuple[int, socket._RetAddress]: ... + @overload + def sendto(self, data: bytes, flags_or_addr: socket._Address) -> int: ... + @overload + def sendto(self, data: bytes, flags_or_addr: int | socket._Address, addr: socket._Address | None = ...) -> int: ... + def read(self, len: int = ..., buffer: bytearray | None = ...) -> bytes: ... + def write(self, data: bytes) -> int: ... + def do_handshake(self, block: bool = ...) -> None: ... # block is undocumented + @overload + def getpeercert(self, binary_form: Literal[False] = ...) -> _PeerCertRetDictType | None: ... + @overload + def getpeercert(self, binary_form: Literal[True]) -> bytes | None: ... + @overload + def getpeercert(self, binary_form: bool) -> _PeerCertRetType: ... + def cipher(self) -> Tuple[str, str, int] | None: ... + def compression(self) -> str | None: ... + def get_channel_binding(self, cb_type: str = ...) -> bytes | None: ... + def selected_alpn_protocol(self) -> str | None: ... + def selected_npn_protocol(self) -> str | None: ... + def accept(self) -> Tuple[SSLSocket, socket._RetAddress]: ... + def unwrap(self) -> socket.socket: ... + def version(self) -> str | None: ... + def pending(self) -> int: ... + +class SSLContext: + check_hostname: bool + options: int + def __new__(cls, protocol: int, *args: Any, **kwargs: Any) -> SSLContext: ... + @property + def protocol(self) -> int: ... + verify_flags: int + verify_mode: int + def __init__(self, protocol: int) -> None: ... + def cert_store_stats(self) -> Dict[str, int]: ... + def load_cert_chain(self, certfile: StrPath, keyfile: StrPath | None = ..., password: _PasswordType | None = ...) -> None: ... + def load_default_certs(self, purpose: Purpose = ...) -> None: ... + def load_verify_locations( + self, cafile: StrPath | None = ..., capath: StrPath | None = ..., cadata: Text | bytes | None = ... + ) -> None: ... + def get_ca_certs(self, binary_form: bool = ...) -> List[_PeerCertRetDictType] | List[bytes]: ... + def set_default_verify_paths(self) -> None: ... + def set_ciphers(self, __cipherlist: str) -> None: ... + def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None: ... + def set_npn_protocols(self, npn_protocols: Iterable[str]) -> None: ... + def set_servername_callback(self, __method: _SrvnmeCbType | None) -> None: ... + def load_dh_params(self, __path: str) -> None: ... + def set_ecdh_curve(self, __name: str) -> None: ... + def wrap_socket( + self, + sock: socket.socket, + server_side: bool = ..., + do_handshake_on_connect: bool = ..., + suppress_ragged_eofs: bool = ..., + server_hostname: str | None = ..., + ) -> SSLSocket: ... + def session_stats(self) -> Dict[str, int]: ... + +# TODO below documented in cpython but not in docs.python.org +# taken from python 3.4 +SSL_ERROR_EOF: int +SSL_ERROR_INVALID_ERROR_CODE: int +SSL_ERROR_SSL: int +SSL_ERROR_SYSCALL: int +SSL_ERROR_WANT_CONNECT: int +SSL_ERROR_WANT_READ: int +SSL_ERROR_WANT_WRITE: int +SSL_ERROR_WANT_X509_LOOKUP: int +SSL_ERROR_ZERO_RETURN: int + +def get_protocol_name(protocol_code: int) -> str: ... + +AF_INET: int +PEM_FOOTER: str +PEM_HEADER: str +SOCK_STREAM: int +SOL_SOCKET: int +SO_TYPE: int diff --git a/mypy/typeshed/stdlib/@python2/string.pyi b/mypy/typeshed/stdlib/@python2/string.pyi index 03a6a2dfd800..fe028dab39bd 100644 --- a/mypy/typeshed/stdlib/@python2/string.pyi +++ b/mypy/typeshed/stdlib/@python2/string.pyi @@ -1,4 +1,4 @@ -from typing import Any, AnyStr, Iterable, List, Mapping, Optional, Sequence, Text, Tuple, Union, overload +from typing import Any, AnyStr, Iterable, List, Mapping, Sequence, Text, Tuple, overload ascii_letters: str ascii_lowercase: str @@ -48,13 +48,13 @@ class Template: template: Text def __init__(self, template: Text) -> None: ... @overload - def substitute(self, mapping: Union[Mapping[str, str], Mapping[unicode, str]] = ..., **kwds: str) -> str: ... + def substitute(self, mapping: Mapping[str, str] | Mapping[unicode, str] = ..., **kwds: str) -> str: ... @overload - def substitute(self, mapping: Union[Mapping[str, Text], Mapping[unicode, Text]] = ..., **kwds: Text) -> Text: ... + def substitute(self, mapping: Mapping[str, Text] | Mapping[unicode, Text] = ..., **kwds: Text) -> Text: ... @overload - def safe_substitute(self, mapping: Union[Mapping[str, str], Mapping[unicode, str]] = ..., **kwds: str) -> str: ... + def safe_substitute(self, mapping: Mapping[str, str] | Mapping[unicode, str] = ..., **kwds: str) -> str: ... @overload - def safe_substitute(self, mapping: Union[Mapping[str, Text], Mapping[unicode, Text]], **kwds: Text) -> Text: ... + def safe_substitute(self, mapping: Mapping[str, Text] | Mapping[unicode, Text], **kwds: Text) -> Text: ... # TODO(MichalPokorny): This is probably badly and/or loosely typed. class Formatter(object): @@ -62,7 +62,7 @@ class Formatter(object): def vformat(self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> str: ... def parse(self, format_string: str) -> Iterable[Tuple[str, str, str, str]]: ... def get_field(self, field_name: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... - def get_value(self, key: Union[int, str], args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... - def check_unused_args(self, used_args: Sequence[Union[int, str]], args: Sequence[Any], kwargs: Mapping[str, Any]) -> None: ... + def get_value(self, key: int | str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... + def check_unused_args(self, used_args: Sequence[int | str], args: Sequence[Any], kwargs: Mapping[str, Any]) -> None: ... def format_field(self, value: Any, format_spec: str) -> Any: ... def convert_field(self, value: Any, conversion: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/stringold.pyi b/mypy/typeshed/stdlib/@python2/stringold.pyi index ea11da72575d..d221547f1c07 100644 --- a/mypy/typeshed/stdlib/@python2/stringold.pyi +++ b/mypy/typeshed/stdlib/@python2/stringold.pyi @@ -1,4 +1,4 @@ -from typing import AnyStr, Iterable, List, Optional, Type +from typing import AnyStr, Iterable, List whitespace: str lowercase: str @@ -8,7 +8,7 @@ digits: str hexdigits: str octdigits: str _idmap: str -_idmapL: Optional[List[str]] +_idmapL: List[str] | None index_error = ValueError atoi_error = ValueError atof_error = ValueError diff --git a/mypy/typeshed/stdlib/@python2/stringprep.pyi b/mypy/typeshed/stdlib/@python2/stringprep.pyi new file mode 100644 index 000000000000..604fd2f2cae7 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/stringprep.pyi @@ -0,0 +1,21 @@ +from typing import Text + +def in_table_a1(code: Text) -> bool: ... +def in_table_b1(code: Text) -> bool: ... +def map_table_b3(code: Text) -> Text: ... +def map_table_b2(a: Text) -> Text: ... +def in_table_c11(code: Text) -> bool: ... +def in_table_c12(code: Text) -> bool: ... +def in_table_c11_c12(code: Text) -> bool: ... +def in_table_c21(code: Text) -> bool: ... +def in_table_c22(code: Text) -> bool: ... +def in_table_c21_c22(code: Text) -> bool: ... +def in_table_c3(code: Text) -> bool: ... +def in_table_c4(code: Text) -> bool: ... +def in_table_c5(code: Text) -> bool: ... +def in_table_c6(code: Text) -> bool: ... +def in_table_c7(code: Text) -> bool: ... +def in_table_c8(code: Text) -> bool: ... +def in_table_c9(code: Text) -> bool: ... +def in_table_d1(code: Text) -> bool: ... +def in_table_d2(code: Text) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/struct.pyi b/mypy/typeshed/stdlib/@python2/struct.pyi new file mode 100644 index 000000000000..bf27d12783da --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/struct.pyi @@ -0,0 +1,24 @@ +from array import array +from mmap import mmap +from typing import Any, Text, Tuple, Union + +class error(Exception): ... + +_FmtType = Union[bytes, Text] +_BufferType = Union[array[int], bytes, bytearray, buffer, memoryview, mmap] +_WriteBufferType = Union[array[Any], bytearray, buffer, memoryview, mmap] + +def pack(fmt: _FmtType, *v: Any) -> bytes: ... +def pack_into(fmt: _FmtType, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... +def unpack(__format: _FmtType, __buffer: _BufferType) -> Tuple[Any, ...]: ... +def unpack_from(__format: _FmtType, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... +def calcsize(__format: _FmtType) -> int: ... + +class Struct: + format: bytes + size: int + def __init__(self, format: _FmtType) -> None: ... + def pack(self, *v: Any) -> bytes: ... + def pack_into(self, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... + def unpack(self, __buffer: _BufferType) -> Tuple[Any, ...]: ... + def unpack_from(self, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/subprocess.pyi b/mypy/typeshed/stdlib/@python2/subprocess.pyi index b3a2e92e7fec..8c101272322a 100644 --- a/mypy/typeshed/stdlib/@python2/subprocess.pyi +++ b/mypy/typeshed/stdlib/@python2/subprocess.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Callable, Generic, List, Mapping, Optional, Sequence, Text, Tuple, TypeVar, Union +from typing import IO, Any, Callable, Generic, Mapping, Optional, Sequence, Text, Tuple, TypeVar, Union _FILE = Union[None, int, IO[Any]] _TXT = Union[bytes, Text] @@ -16,8 +16,8 @@ def call( preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[_TXT] = ..., - env: Optional[_ENV] = ..., + cwd: _TXT | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -32,8 +32,8 @@ def check_call( preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[_TXT] = ..., - env: Optional[_ENV] = ..., + cwd: _TXT | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -49,8 +49,8 @@ def check_output( preexec_fn: Callable[[], Any] = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[_TXT] = ..., - env: Optional[_ENV] = ..., + cwd: _TXT | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -65,38 +65,38 @@ class CalledProcessError(Exception): cmd: Any # morally: Optional[bytes] output: bytes - def __init__(self, returncode: int, cmd: _CMD, output: Optional[bytes] = ...) -> None: ... + def __init__(self, returncode: int, cmd: _CMD, output: bytes | None = ...) -> None: ... # We use a dummy type variable used to make Popen generic like it is in python 3 _T = TypeVar("_T", bound=bytes) class Popen(Generic[_T]): - stdin: Optional[IO[bytes]] - stdout: Optional[IO[bytes]] - stderr: Optional[IO[bytes]] + stdin: IO[bytes] | None + stdout: IO[bytes] | None + stderr: IO[bytes] | None pid: int returncode: int def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[_TXT] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: _TXT | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[_TXT] = ..., - env: Optional[_ENV] = ..., + cwd: _TXT | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., ) -> Popen[bytes]: ... - def poll(self) -> Optional[int]: ... + def poll(self) -> int | None: ... def wait(self) -> int: ... # morally: -> Tuple[Optional[bytes], Optional[bytes]] - def communicate(self, input: Optional[_TXT] = ...) -> Tuple[bytes, bytes]: ... + def communicate(self, input: _TXT | None = ...) -> Tuple[bytes, bytes]: ... def send_signal(self, signal: int) -> None: ... def terminate(self) -> None: ... def kill(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sunau.pyi b/mypy/typeshed/stdlib/@python2/sunau.pyi new file mode 100644 index 000000000000..3ee4b9651346 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sunau.pyi @@ -0,0 +1,66 @@ +from typing import IO, Any, NoReturn, Text, Tuple, Union + +_File = Union[Text, IO[bytes]] + +class Error(Exception): ... + +AUDIO_FILE_MAGIC: int +AUDIO_FILE_ENCODING_MULAW_8: int +AUDIO_FILE_ENCODING_LINEAR_8: int +AUDIO_FILE_ENCODING_LINEAR_16: int +AUDIO_FILE_ENCODING_LINEAR_24: int +AUDIO_FILE_ENCODING_LINEAR_32: int +AUDIO_FILE_ENCODING_FLOAT: int +AUDIO_FILE_ENCODING_DOUBLE: int +AUDIO_FILE_ENCODING_ADPCM_G721: int +AUDIO_FILE_ENCODING_ADPCM_G722: int +AUDIO_FILE_ENCODING_ADPCM_G723_3: int +AUDIO_FILE_ENCODING_ADPCM_G723_5: int +AUDIO_FILE_ENCODING_ALAW_8: int +AUDIO_UNKNOWN_SIZE: int + +_sunau_params = Tuple[int, int, int, int, str, str] + +class Au_read: + def __init__(self, f: _File) -> None: ... + def getfp(self) -> IO[bytes] | None: ... + def rewind(self) -> None: ... + def close(self) -> None: ... + def tell(self) -> int: ... + def getnchannels(self) -> int: ... + def getnframes(self) -> int: ... + def getsampwidth(self) -> int: ... + def getframerate(self) -> int: ... + def getcomptype(self) -> str: ... + def getcompname(self) -> str: ... + def getparams(self) -> _sunau_params: ... + def getmarkers(self) -> None: ... + def getmark(self, id: Any) -> NoReturn: ... + def setpos(self, pos: int) -> None: ... + def readframes(self, nframes: int) -> bytes | None: ... + +class Au_write: + def __init__(self, f: _File) -> None: ... + def setnchannels(self, nchannels: int) -> None: ... + def getnchannels(self) -> int: ... + def setsampwidth(self, sampwidth: int) -> None: ... + def getsampwidth(self) -> int: ... + def setframerate(self, framerate: float) -> None: ... + def getframerate(self) -> int: ... + def setnframes(self, nframes: int) -> None: ... + def getnframes(self) -> int: ... + def setcomptype(self, type: str, name: str) -> None: ... + def getcomptype(self) -> str: ... + def getcompname(self) -> str: ... + def setparams(self, params: _sunau_params) -> None: ... + def getparams(self) -> _sunau_params: ... + def tell(self) -> int: ... + # should be any bytes-like object after 3.4, but we don't have a type for that + def writeframesraw(self, data: bytes) -> None: ... + def writeframes(self, data: bytes) -> None: ... + def close(self) -> None: ... + +# Returns a Au_read if mode is rb and Au_write if mode is wb +def open(f: _File, mode: str | None = ...) -> Any: ... + +openfp = open diff --git a/mypy/typeshed/stdlib/@python2/symtable.pyi b/mypy/typeshed/stdlib/@python2/symtable.pyi new file mode 100644 index 000000000000..bd3f25c7cb63 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/symtable.pyi @@ -0,0 +1,43 @@ +from typing import Any, List, Sequence, Text, Tuple + +def symtable(code: Text, filename: Text, compile_type: Text) -> SymbolTable: ... + +class SymbolTable(object): + def __init__(self, raw_table: Any, filename: str) -> None: ... + def get_type(self) -> str: ... + def get_id(self) -> int: ... + def get_name(self) -> str: ... + def get_lineno(self) -> int: ... + def is_optimized(self) -> bool: ... + def is_nested(self) -> bool: ... + def has_children(self) -> bool: ... + def has_exec(self) -> bool: ... + def has_import_star(self) -> bool: ... + def get_identifiers(self) -> Sequence[str]: ... + def lookup(self, name: str) -> Symbol: ... + def get_symbols(self) -> List[Symbol]: ... + def get_children(self) -> List[SymbolTable]: ... + +class Function(SymbolTable): + def get_parameters(self) -> Tuple[str, ...]: ... + def get_locals(self) -> Tuple[str, ...]: ... + def get_globals(self) -> Tuple[str, ...]: ... + def get_frees(self) -> Tuple[str, ...]: ... + +class Class(SymbolTable): + def get_methods(self) -> Tuple[str, ...]: ... + +class Symbol(object): + def __init__(self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ...) -> None: ... + def get_name(self) -> str: ... + def is_referenced(self) -> bool: ... + def is_parameter(self) -> bool: ... + def is_global(self) -> bool: ... + def is_declared_global(self) -> bool: ... + def is_local(self) -> bool: ... + def is_free(self) -> bool: ... + def is_imported(self) -> bool: ... + def is_assigned(self) -> bool: ... + def is_namespace(self) -> bool: ... + def get_namespaces(self) -> Sequence[SymbolTable]: ... + def get_namespace(self) -> SymbolTable: ... diff --git a/mypy/typeshed/stdlib/@python2/sys.pyi b/mypy/typeshed/stdlib/@python2/sys.pyi index 0136f3456c58..d4858ec251fa 100644 --- a/mypy/typeshed/stdlib/@python2/sys.pyi +++ b/mypy/typeshed/stdlib/@python2/sys.pyi @@ -1,5 +1,5 @@ -from types import ClassType, FrameType, ModuleType, TracebackType -from typing import IO, Any, BinaryIO, Callable, Dict, List, NoReturn, Optional, Sequence, Text, Tuple, Type, Union, overload +from types import ClassType, FrameType, TracebackType +from typing import IO, Any, Callable, Dict, List, NoReturn, Text, Tuple, Type, Union # The following type alias are stub-only and do not exist during runtime _ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] @@ -86,8 +86,8 @@ path_hooks: List[Any] path_importer_cache: Dict[str, Any] displayhook: Callable[[object], Any] excepthook: Callable[[Type[BaseException], BaseException, TracebackType], Any] -exc_type: Optional[type] -exc_value: Union[BaseException, ClassType] +exc_type: type | None +exc_value: BaseException | ClassType exc_traceback: TracebackType class _WindowsVersionType: @@ -120,8 +120,8 @@ def getfilesystemencoding() -> str: ... # In practice, never returns None def getrefcount(arg: Any) -> int: ... def getrecursionlimit() -> int: ... def getsizeof(obj: object, default: int = ...) -> int: ... -def getprofile() -> Optional[Any]: ... -def gettrace() -> Optional[Any]: ... +def getprofile() -> Any | None: ... +def gettrace() -> Any | None: ... def setcheckinterval(interval: int) -> None: ... # deprecated def setdlopenflags(n: int) -> None: ... def setdefaultencoding(encoding: Text) -> None: ... # only exists after reload(sys) diff --git a/mypy/typeshed/stdlib/@python2/sysconfig.pyi b/mypy/typeshed/stdlib/@python2/sysconfig.pyi new file mode 100644 index 000000000000..2bef9e467bc9 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/sysconfig.pyi @@ -0,0 +1,17 @@ +from typing import IO, Any, Dict, List, Tuple, overload + +def get_config_var(name: str) -> str | None: ... +@overload +def get_config_vars() -> Dict[str, Any]: ... +@overload +def get_config_vars(arg: str, *args: str) -> List[Any]: ... +def get_scheme_names() -> Tuple[str, ...]: ... +def get_path_names() -> Tuple[str, ...]: ... +def get_path(name: str, scheme: str = ..., vars: Dict[str, Any] | None = ..., expand: bool = ...) -> str: ... +def get_paths(scheme: str = ..., vars: Dict[str, Any] | None = ..., expand: bool = ...) -> Dict[str, str]: ... +def get_python_version() -> str: ... +def get_platform() -> str: ... +def is_python_build(check_home: bool = ...) -> bool: ... +def parse_config_h(fp: IO[Any], vars: Dict[str, Any] | None = ...) -> Dict[str, Any]: ... +def get_config_h_filename() -> str: ... +def get_makefile_filename() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/syslog.pyi b/mypy/typeshed/stdlib/@python2/syslog.pyi new file mode 100644 index 000000000000..49169f40db5c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/syslog.pyi @@ -0,0 +1,43 @@ +from typing import overload + +LOG_ALERT: int +LOG_AUTH: int +LOG_CONS: int +LOG_CRIT: int +LOG_CRON: int +LOG_DAEMON: int +LOG_DEBUG: int +LOG_EMERG: int +LOG_ERR: int +LOG_INFO: int +LOG_KERN: int +LOG_LOCAL0: int +LOG_LOCAL1: int +LOG_LOCAL2: int +LOG_LOCAL3: int +LOG_LOCAL4: int +LOG_LOCAL5: int +LOG_LOCAL6: int +LOG_LOCAL7: int +LOG_LPR: int +LOG_MAIL: int +LOG_NDELAY: int +LOG_NEWS: int +LOG_NOTICE: int +LOG_NOWAIT: int +LOG_PERROR: int +LOG_PID: int +LOG_SYSLOG: int +LOG_USER: int +LOG_UUCP: int +LOG_WARNING: int + +def LOG_MASK(a: int) -> int: ... +def LOG_UPTO(a: int) -> int: ... +def closelog() -> None: ... +def openlog(ident: str = ..., logoption: int = ..., facility: int = ...) -> None: ... +def setlogmask(x: int) -> int: ... +@overload +def syslog(priority: int, message: str) -> None: ... +@overload +def syslog(message: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/tabnanny.pyi b/mypy/typeshed/stdlib/@python2/tabnanny.pyi new file mode 100644 index 000000000000..95873761ee75 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/tabnanny.pyi @@ -0,0 +1,13 @@ +from typing import Iterable, Text, Tuple + +verbose: int +filename_only: int + +class NannyNag(Exception): + def __init__(self, lineno: int, msg: str, line: str) -> None: ... + def get_lineno(self) -> int: ... + def get_msg(self) -> str: ... + def get_line(self) -> str: ... + +def check(file: Text) -> None: ... +def process_tokens(tokens: Iterable[Tuple[int, str, Tuple[int, int], Tuple[int, int], str]]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/tarfile.pyi b/mypy/typeshed/stdlib/@python2/tarfile.pyi new file mode 100644 index 000000000000..c08c96b6f0d5 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/tarfile.pyi @@ -0,0 +1,288 @@ +import io +from types import TracebackType +from typing import IO, Callable, Dict, Iterable, Iterator, List, Mapping, Text, Tuple, Type + +# tar constants +NUL: bytes +BLOCKSIZE: int +RECORDSIZE: int +GNU_MAGIC: bytes +POSIX_MAGIC: bytes + +LENGTH_NAME: int +LENGTH_LINK: int +LENGTH_PREFIX: int + +REGTYPE: bytes +AREGTYPE: bytes +LNKTYPE: bytes +SYMTYPE: bytes +CONTTYPE: bytes +BLKTYPE: bytes +DIRTYPE: bytes +FIFOTYPE: bytes +CHRTYPE: bytes + +GNUTYPE_LONGNAME: bytes +GNUTYPE_LONGLINK: bytes +GNUTYPE_SPARSE: bytes + +XHDTYPE: bytes +XGLTYPE: bytes +SOLARIS_XHDTYPE: bytes + +USTAR_FORMAT: int +GNU_FORMAT: int +PAX_FORMAT: int +DEFAULT_FORMAT: int + +# tarfile constants + +SUPPORTED_TYPES: Tuple[bytes, ...] +REGULAR_TYPES: Tuple[bytes, ...] +GNU_TYPES: Tuple[bytes, ...] +PAX_FIELDS: Tuple[str, ...] +PAX_NUMBER_FIELDS: Dict[str, type] + +ENCODING: str + +TAR_PLAIN: int +TAR_GZIPPED: int + +def open( + name: Text | None = ..., + mode: str = ..., + fileobj: IO[bytes] | None = ..., + bufsize: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + errors: str = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + compresslevel: int | None = ..., +) -> TarFile: ... + +class ExFileObject(io.BufferedReader): + def __init__(self, tarfile: TarFile, tarinfo: TarInfo) -> None: ... + +class TarFile(Iterable[TarInfo]): + OPEN_METH: Mapping[str, str] + name: Text | None + mode: str + fileobj: IO[bytes] | None + format: int | None + tarinfo: Type[TarInfo] + dereference: bool | None + ignore_zeros: bool | None + encoding: str | None + errors: str + fileobject: Type[ExFileObject] + pax_headers: Mapping[str, str] | None + debug: int | None + errorlevel: int | None + offset: int # undocumented + posix: bool + def __init__( + self, + name: Text | None = ..., + mode: str = ..., + fileobj: IO[bytes] | None = ..., + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + errors: str = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + copybufsize: int | None = ..., # undocumented + ) -> None: ... + def __enter__(self) -> TarFile: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + def __iter__(self) -> Iterator[TarInfo]: ... + @classmethod + def open( + cls, + name: Text | None = ..., + mode: str = ..., + fileobj: IO[bytes] | None = ..., + bufsize: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + errors: str = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> TarFile: ... + @classmethod + def taropen( + cls, + name: Text | None, + mode: str = ..., + fileobj: IO[bytes] | None = ..., + *, + compresslevel: int = ..., + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> TarFile: ... + @classmethod + def gzopen( + cls, + name: Text | None, + mode: str = ..., + fileobj: IO[bytes] | None = ..., + compresslevel: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> TarFile: ... + @classmethod + def bz2open( + cls, + name: Text | None, + mode: str = ..., + fileobj: IO[bytes] | None = ..., + compresslevel: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> TarFile: ... + @classmethod + def xzopen( + cls, + name: Text | None, + mode: str = ..., + fileobj: IO[bytes] | None = ..., + preset: int | None = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> TarFile: ... + def getmember(self, name: str) -> TarInfo: ... + def getmembers(self) -> List[TarInfo]: ... + def getnames(self) -> List[str]: ... + def list(self, verbose: bool = ...) -> None: ... + def next(self) -> TarInfo | None: ... + def extractall(self, path: Text = ..., members: Iterable[TarInfo] | None = ...) -> None: ... + def extract(self, member: str | TarInfo, path: Text = ...) -> None: ... + def extractfile(self, member: str | TarInfo) -> IO[bytes] | None: ... + def makedir(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def makefile(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def makeunknown(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def makefifo(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def makedev(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def makelink(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def chown(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def chmod(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def utime(self, tarinfo: TarInfo, targetpath: Text) -> None: ... # undocumented + def add( + self, + name: str, + arcname: str | None = ..., + recursive: bool = ..., + exclude: Callable[[str], bool] | None = ..., + filter: Callable[[TarInfo], TarInfo | None] | None = ..., + ) -> None: ... + def addfile(self, tarinfo: TarInfo, fileobj: IO[bytes] | None = ...) -> None: ... + def gettarinfo(self, name: str | None = ..., arcname: str | None = ..., fileobj: IO[bytes] | None = ...) -> TarInfo: ... + def close(self) -> None: ... + +def is_tarfile(name: Text) -> bool: ... +def filemode(mode: int) -> str: ... # undocumented + +class TarFileCompat: + def __init__(self, filename: str, mode: str = ..., compression: int = ...) -> None: ... + +class TarError(Exception): ... +class ReadError(TarError): ... +class CompressionError(TarError): ... +class StreamError(TarError): ... +class ExtractError(TarError): ... +class HeaderError(TarError): ... + +class TarInfo: + name: str + path: str + size: int + mtime: int + chksum: int + devmajor: int + devminor: int + offset: int + offset_data: int + sparse: bytes | None + tarfile: TarFile | None + mode: int + type: bytes + linkname: str + uid: int + gid: int + uname: str + gname: str + pax_headers: Mapping[str, str] + def __init__(self, name: str = ...) -> None: ... + @classmethod + def frombuf(cls, buf: bytes) -> TarInfo: ... + @classmethod + def fromtarfile(cls, tarfile: TarFile) -> TarInfo: ... + @property + def linkpath(self) -> str: ... + @linkpath.setter + def linkpath(self, linkname: str) -> None: ... + def get_info(self) -> Mapping[str, str | int | bytes | Mapping[str, str]]: ... + def tobuf(self, format: int | None = ..., encoding: str | None = ..., errors: str = ...) -> bytes: ... + def create_ustar_header( + self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str, errors: str + ) -> bytes: ... + def create_gnu_header( + self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str, errors: str + ) -> bytes: ... + def create_pax_header(self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str) -> bytes: ... + @classmethod + def create_pax_global_header(cls, pax_headers: Mapping[str, str]) -> bytes: ... + def isfile(self) -> bool: ... + def isreg(self) -> bool: ... + def issparse(self) -> bool: ... + def isdir(self) -> bool: ... + def issym(self) -> bool: ... + def islnk(self) -> bool: ... + def ischr(self) -> bool: ... + def isblk(self) -> bool: ... + def isfifo(self) -> bool: ... + def isdev(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/telnetlib.pyi b/mypy/typeshed/stdlib/@python2/telnetlib.pyi new file mode 100644 index 000000000000..dfb01f26398e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/telnetlib.pyi @@ -0,0 +1,111 @@ +import socket +from typing import Any, Callable, Match, Pattern, Sequence, Tuple + +DEBUGLEVEL: int +TELNET_PORT: int + +IAC: bytes +DONT: bytes +DO: bytes +WONT: bytes +WILL: bytes +theNULL: bytes + +SE: bytes +NOP: bytes +DM: bytes +BRK: bytes +IP: bytes +AO: bytes +AYT: bytes +EC: bytes +EL: bytes +GA: bytes +SB: bytes + +BINARY: bytes +ECHO: bytes +RCP: bytes +SGA: bytes +NAMS: bytes +STATUS: bytes +TM: bytes +RCTE: bytes +NAOL: bytes +NAOP: bytes +NAOCRD: bytes +NAOHTS: bytes +NAOHTD: bytes +NAOFFD: bytes +NAOVTS: bytes +NAOVTD: bytes +NAOLFD: bytes +XASCII: bytes +LOGOUT: bytes +BM: bytes +DET: bytes +SUPDUP: bytes +SUPDUPOUTPUT: bytes +SNDLOC: bytes +TTYPE: bytes +EOR: bytes +TUID: bytes +OUTMRK: bytes +TTYLOC: bytes +VT3270REGIME: bytes +X3PAD: bytes +NAWS: bytes +TSPEED: bytes +LFLOW: bytes +LINEMODE: bytes +XDISPLOC: bytes +OLD_ENVIRON: bytes +AUTHENTICATION: bytes +ENCRYPT: bytes +NEW_ENVIRON: bytes + +TN3270E: bytes +XAUTH: bytes +CHARSET: bytes +RSP: bytes +COM_PORT_OPTION: bytes +SUPPRESS_LOCAL_ECHO: bytes +TLS: bytes +KERMIT: bytes +SEND_URL: bytes +FORWARD_X: bytes +PRAGMA_LOGON: bytes +SSPI_LOGON: bytes +PRAGMA_HEARTBEAT: bytes +EXOPL: bytes +NOOPT: bytes + +class Telnet: + host: str | None # undocumented + def __init__(self, host: str | None = ..., port: int = ..., timeout: float = ...) -> None: ... + def open(self, host: str, port: int = ..., timeout: float = ...) -> None: ... + def msg(self, msg: str, *args: Any) -> None: ... + def set_debuglevel(self, debuglevel: int) -> None: ... + def close(self) -> None: ... + def get_socket(self) -> socket.socket: ... + def fileno(self) -> int: ... + def write(self, buffer: bytes) -> None: ... + def read_until(self, match: bytes, timeout: float | None = ...) -> bytes: ... + def read_all(self) -> bytes: ... + def read_some(self) -> bytes: ... + def read_very_eager(self) -> bytes: ... + def read_eager(self) -> bytes: ... + def read_lazy(self) -> bytes: ... + def read_very_lazy(self) -> bytes: ... + def read_sb_data(self) -> bytes: ... + def set_option_negotiation_callback(self, callback: Callable[[socket.socket, bytes, bytes], Any] | None) -> None: ... + def process_rawq(self) -> None: ... + def rawq_getchar(self) -> bytes: ... + def fill_rawq(self) -> None: ... + def sock_avail(self) -> bool: ... + def interact(self) -> None: ... + def mt_interact(self) -> None: ... + def listener(self) -> None: ... + def expect( + self, list: Sequence[Pattern[bytes] | bytes], timeout: float | None = ... + ) -> Tuple[int, Match[bytes] | None, bytes]: ... diff --git a/mypy/typeshed/stdlib/@python2/tempfile.pyi b/mypy/typeshed/stdlib/@python2/tempfile.pyi index 687e10784585..c5f67d243ac8 100644 --- a/mypy/typeshed/stdlib/@python2/tempfile.pyi +++ b/mypy/typeshed/stdlib/@python2/tempfile.pyi @@ -1,11 +1,11 @@ from random import Random from thread import LockType -from typing import IO, Any, AnyStr, Iterable, Iterator, List, Optional, Text, Tuple, Union, overload +from typing import IO, Any, AnyStr, Iterable, Iterator, List, Text, Tuple, overload TMP_MAX: int tempdir: str template: str -_name_sequence: Optional[_RandomNameSequence] +_name_sequence: _RandomNameSequence | None class _RandomNameSequence: characters: str = ... @@ -24,7 +24,7 @@ class _TemporaryFileWrapper(IO[str]): def __init__(self, file: IO[str], name: Any, delete: bool = ...) -> None: ... def __del__(self) -> None: ... def __enter__(self) -> _TemporaryFileWrapper: ... - def __exit__(self, exc, value, tb) -> Optional[bool]: ... + def __exit__(self, exc, value, tb) -> bool | None: ... def __getattr__(self, name: unicode) -> Any: ... def close(self) -> None: ... def unlink(self, path: unicode) -> None: ... @@ -43,7 +43,7 @@ class _TemporaryFileWrapper(IO[str]): def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... def write(self, s: Text) -> int: ... def writelines(self, lines: Iterable[str]) -> None: ... @@ -51,34 +51,32 @@ class _TemporaryFileWrapper(IO[str]): # TODO text files def TemporaryFile( - mode: Union[bytes, unicode] = ..., + mode: bytes | unicode = ..., bufsize: int = ..., - suffix: Union[bytes, unicode] = ..., - prefix: Union[bytes, unicode] = ..., - dir: Union[bytes, unicode] = ..., + suffix: bytes | unicode = ..., + prefix: bytes | unicode = ..., + dir: bytes | unicode | None = ..., ) -> _TemporaryFileWrapper: ... def NamedTemporaryFile( - mode: Union[bytes, unicode] = ..., + mode: bytes | unicode = ..., bufsize: int = ..., - suffix: Union[bytes, unicode] = ..., - prefix: Union[bytes, unicode] = ..., - dir: Union[bytes, unicode] = ..., + suffix: bytes | unicode = ..., + prefix: bytes | unicode = ..., + dir: bytes | unicode | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper: ... def SpooledTemporaryFile( max_size: int = ..., - mode: Union[bytes, unicode] = ..., + mode: bytes | unicode = ..., buffering: int = ..., - suffix: Union[bytes, unicode] = ..., - prefix: Union[bytes, unicode] = ..., - dir: Union[bytes, unicode] = ..., + suffix: bytes | unicode = ..., + prefix: bytes | unicode = ..., + dir: bytes | unicode | None = ..., ) -> _TemporaryFileWrapper: ... class TemporaryDirectory: name: Any - def __init__( - self, suffix: Union[bytes, unicode] = ..., prefix: Union[bytes, unicode] = ..., dir: Union[bytes, unicode] = ... - ) -> None: ... + def __init__(self, suffix: bytes | unicode = ..., prefix: bytes | unicode = ..., dir: bytes | unicode = ...) -> None: ... def cleanup(self) -> None: ... def __enter__(self) -> Any: ... # Can be str or unicode def __exit__(self, type, value, traceback) -> None: ... @@ -86,17 +84,17 @@ class TemporaryDirectory: @overload def mkstemp() -> Tuple[int, str]: ... @overload -def mkstemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: Optional[AnyStr] = ..., text: bool = ...) -> Tuple[int, AnyStr]: ... +def mkstemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ..., text: bool = ...) -> Tuple[int, AnyStr]: ... @overload def mkdtemp() -> str: ... @overload -def mkdtemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: Optional[AnyStr] = ...) -> AnyStr: ... +def mkdtemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ...) -> AnyStr: ... @overload def mktemp() -> str: ... @overload -def mktemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: Optional[AnyStr] = ...) -> AnyStr: ... +def mktemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ...) -> AnyStr: ... def gettempdir() -> str: ... def gettempprefix() -> str: ... def _candidate_tempdir_list() -> List[str]: ... -def _get_candidate_names() -> Optional[_RandomNameSequence]: ... +def _get_candidate_names() -> _RandomNameSequence | None: ... def _get_default_tempdir() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/termios.pyi b/mypy/typeshed/stdlib/@python2/termios.pyi new file mode 100644 index 000000000000..0c627f4b72bd --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/termios.pyi @@ -0,0 +1,246 @@ +from _typeshed import FileDescriptorLike +from typing import Any, List, Union + +_Attr = List[Union[int, List[Union[bytes, int]]]] + +# TODO constants not really documented +B0: int +B1000000: int +B110: int +B115200: int +B1152000: int +B1200: int +B134: int +B150: int +B1500000: int +B1800: int +B19200: int +B200: int +B2000000: int +B230400: int +B2400: int +B2500000: int +B300: int +B3000000: int +B3500000: int +B38400: int +B4000000: int +B460800: int +B4800: int +B50: int +B500000: int +B57600: int +B576000: int +B600: int +B75: int +B921600: int +B9600: int +BRKINT: int +BS0: int +BS1: int +BSDLY: int +CBAUD: int +CBAUDEX: int +CDSUSP: int +CEOF: int +CEOL: int +CEOT: int +CERASE: int +CFLUSH: int +CIBAUD: int +CINTR: int +CKILL: int +CLNEXT: int +CLOCAL: int +CQUIT: int +CR0: int +CR1: int +CR2: int +CR3: int +CRDLY: int +CREAD: int +CRPRNT: int +CRTSCTS: int +CS5: int +CS6: int +CS7: int +CS8: int +CSIZE: int +CSTART: int +CSTOP: int +CSTOPB: int +CSUSP: int +CWERASE: int +ECHO: int +ECHOCTL: int +ECHOE: int +ECHOK: int +ECHOKE: int +ECHONL: int +ECHOPRT: int +EXTA: int +EXTB: int +FF0: int +FF1: int +FFDLY: int +FIOASYNC: int +FIOCLEX: int +FIONBIO: int +FIONCLEX: int +FIONREAD: int +FLUSHO: int +HUPCL: int +ICANON: int +ICRNL: int +IEXTEN: int +IGNBRK: int +IGNCR: int +IGNPAR: int +IMAXBEL: int +INLCR: int +INPCK: int +IOCSIZE_MASK: int +IOCSIZE_SHIFT: int +ISIG: int +ISTRIP: int +IUCLC: int +IXANY: int +IXOFF: int +IXON: int +NCC: int +NCCS: int +NL0: int +NL1: int +NLDLY: int +NOFLSH: int +N_MOUSE: int +N_PPP: int +N_SLIP: int +N_STRIP: int +N_TTY: int +OCRNL: int +OFDEL: int +OFILL: int +OLCUC: int +ONLCR: int +ONLRET: int +ONOCR: int +OPOST: int +PARENB: int +PARMRK: int +PARODD: int +PENDIN: int +TAB0: int +TAB1: int +TAB2: int +TAB3: int +TABDLY: int +TCFLSH: int +TCGETA: int +TCGETS: int +TCIFLUSH: int +TCIOFF: int +TCIOFLUSH: int +TCION: int +TCOFLUSH: int +TCOOFF: int +TCOON: int +TCSADRAIN: int +TCSAFLUSH: int +TCSANOW: int +TCSBRK: int +TCSBRKP: int +TCSETA: int +TCSETAF: int +TCSETAW: int +TCSETS: int +TCSETSF: int +TCSETSW: int +TCXONC: int +TIOCCONS: int +TIOCEXCL: int +TIOCGETD: int +TIOCGICOUNT: int +TIOCGLCKTRMIOS: int +TIOCGPGRP: int +TIOCGSERIAL: int +TIOCGSOFTCAR: int +TIOCGWINSZ: int +TIOCINQ: int +TIOCLINUX: int +TIOCMBIC: int +TIOCMBIS: int +TIOCMGET: int +TIOCMIWAIT: int +TIOCMSET: int +TIOCM_CAR: int +TIOCM_CD: int +TIOCM_CTS: int +TIOCM_DSR: int +TIOCM_DTR: int +TIOCM_LE: int +TIOCM_RI: int +TIOCM_RNG: int +TIOCM_RTS: int +TIOCM_SR: int +TIOCM_ST: int +TIOCNOTTY: int +TIOCNXCL: int +TIOCOUTQ: int +TIOCPKT: int +TIOCPKT_DATA: int +TIOCPKT_DOSTOP: int +TIOCPKT_FLUSHREAD: int +TIOCPKT_FLUSHWRITE: int +TIOCPKT_NOSTOP: int +TIOCPKT_START: int +TIOCPKT_STOP: int +TIOCSCTTY: int +TIOCSERCONFIG: int +TIOCSERGETLSR: int +TIOCSERGETMULTI: int +TIOCSERGSTRUCT: int +TIOCSERGWILD: int +TIOCSERSETMULTI: int +TIOCSERSWILD: int +TIOCSER_TEMT: int +TIOCSETD: int +TIOCSLCKTRMIOS: int +TIOCSPGRP: int +TIOCSSERIAL: int +TIOCSSOFTCAR: int +TIOCSTI: int +TIOCSWINSZ: int +TOSTOP: int +VDISCARD: int +VEOF: int +VEOL: int +VEOL2: int +VERASE: int +VINTR: int +VKILL: int +VLNEXT: int +VMIN: int +VQUIT: int +VREPRINT: int +VSTART: int +VSTOP: int +VSUSP: int +VSWTC: int +VSWTCH: int +VT0: int +VT1: int +VTDLY: int +VTIME: int +VWERASE: int +XCASE: int +XTABS: int + +def tcgetattr(__fd: FileDescriptorLike) -> List[Any]: ... +def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... +def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... +def tcdrain(__fd: FileDescriptorLike) -> None: ... +def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... +def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + +class error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/this.pyi b/mypy/typeshed/stdlib/@python2/this.pyi new file mode 100644 index 000000000000..0687a6675cca --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/this.pyi @@ -0,0 +1,4 @@ +from typing import Dict + +s: str +d: Dict[str, str] diff --git a/mypy/typeshed/stdlib/@python2/threading.pyi b/mypy/typeshed/stdlib/@python2/threading.pyi new file mode 100644 index 000000000000..e45a1b5c4a89 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/threading.pyi @@ -0,0 +1,109 @@ +from types import FrameType, TracebackType +from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar + +# TODO recursive type +_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] + +_PF = Callable[[FrameType, str, Any], None] +_T = TypeVar("_T") + +__all__: List[str] + +def active_count() -> int: ... +def activeCount() -> int: ... +def current_thread() -> Thread: ... +def currentThread() -> Thread: ... +def enumerate() -> List[Thread]: ... +def settrace(func: _TF) -> None: ... +def setprofile(func: _PF | None) -> None: ... +def stack_size(size: int = ...) -> int: ... + +class ThreadError(Exception): ... + +class local(object): + def __getattribute__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + def __delattr__(self, name: str) -> None: ... + +class Thread: + name: str + ident: int | None + daemon: bool + def __init__( + self, + group: None = ..., + target: Callable[..., Any] | None = ..., + name: Text | None = ..., + args: Iterable[Any] = ..., + kwargs: Mapping[Text, Any] | None = ..., + ) -> None: ... + def start(self) -> None: ... + def run(self) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... + def getName(self) -> str: ... + def setName(self, name: Text) -> None: ... + def is_alive(self) -> bool: ... + def isAlive(self) -> bool: ... + def isDaemon(self) -> bool: ... + def setDaemon(self, daemonic: bool) -> None: ... + +class _DummyThread(Thread): ... + +class Lock: + def __init__(self) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + def locked(self) -> bool: ... + +class _RLock: + def __init__(self) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + +RLock = _RLock + +class Condition: + def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... + def __enter__(self) -> bool: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + def wait(self, timeout: float | None = ...) -> bool: ... + def notify(self, n: int = ...) -> None: ... + def notify_all(self) -> None: ... + def notifyAll(self) -> None: ... + +class Semaphore: + def __init__(self, value: int = ...) -> None: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ...) -> bool: ... + def __enter__(self, blocking: bool = ...) -> bool: ... + def release(self) -> None: ... + +class BoundedSemaphore(Semaphore): ... + +class Event: + def __init__(self) -> None: ... + def is_set(self) -> bool: ... + def isSet(self) -> bool: ... + def set(self) -> None: ... + def clear(self) -> None: ... + def wait(self, timeout: float | None = ...) -> bool: ... + +class Timer(Thread): + def __init__( + self, interval: float, function: Callable[..., Any], args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ... + ) -> None: ... + def cancel(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/time.pyi b/mypy/typeshed/stdlib/@python2/time.pyi new file mode 100644 index 000000000000..48ae9da9c65e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/time.pyi @@ -0,0 +1,45 @@ +import sys +from typing import Any, NamedTuple, Tuple + +_TimeTuple = Tuple[int, int, int, int, int, int, int, int, int] + +accept2dyear: bool +altzone: int +daylight: int +timezone: int +tzname: Tuple[str, str] + +class _struct_time(NamedTuple): + tm_year: int + tm_mon: int + tm_mday: int + tm_hour: int + tm_min: int + tm_sec: int + tm_wday: int + tm_yday: int + tm_isdst: int + @property + def n_fields(self) -> int: ... + @property + def n_sequence_fields(self) -> int: ... + @property + def n_unnamed_fields(self) -> int: ... + +class struct_time(_struct_time): + def __init__(self, o: _TimeTuple, _arg: Any = ...) -> None: ... + def __new__(cls, o: _TimeTuple, _arg: Any = ...) -> struct_time: ... + +def asctime(t: _TimeTuple | struct_time = ...) -> str: ... +def clock() -> float: ... +def ctime(secs: float | None = ...) -> str: ... +def gmtime(secs: float | None = ...) -> struct_time: ... +def localtime(secs: float | None = ...) -> struct_time: ... +def mktime(t: _TimeTuple | struct_time) -> float: ... +def sleep(secs: float) -> None: ... +def strftime(format: str, t: _TimeTuple | struct_time = ...) -> str: ... +def strptime(string: str, format: str = ...) -> struct_time: ... +def time() -> float: ... + +if sys.platform != "win32": + def tzset() -> None: ... # Unix only diff --git a/mypy/typeshed/stdlib/@python2/timeit.pyi b/mypy/typeshed/stdlib/@python2/timeit.pyi new file mode 100644 index 000000000000..ecb528725a9c --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/timeit.pyi @@ -0,0 +1,20 @@ +from typing import IO, Any, Callable, List, Sequence, Text, Union + +_str = Union[str, Text] +_Timer = Callable[[], float] +_stmt = Union[_str, Callable[[], Any]] + +default_timer: _Timer + +class Timer: + def __init__(self, stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ...) -> None: ... + def print_exc(self, file: IO[str] | None = ...) -> None: ... + def timeit(self, number: int = ...) -> float: ... + def repeat(self, repeat: int = ..., number: int = ...) -> List[float]: ... + +def timeit(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., number: int = ...) -> float: ... +def repeat(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., repeat: int = ..., number: int = ...) -> List[float]: ... + +_timerFunc = Callable[[], float] + +def main(args: Sequence[str] | None = ..., *, _wrap_timer: Callable[[_timerFunc], _timerFunc] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/token.pyi b/mypy/typeshed/stdlib/@python2/token.pyi new file mode 100644 index 000000000000..4ba710470624 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/token.pyi @@ -0,0 +1,62 @@ +from typing import Dict + +ENDMARKER: int +NAME: int +NUMBER: int +STRING: int +NEWLINE: int +INDENT: int +DEDENT: int +LPAR: int +RPAR: int +LSQB: int +RSQB: int +COLON: int +COMMA: int +SEMI: int +PLUS: int +MINUS: int +STAR: int +SLASH: int +VBAR: int +AMPER: int +LESS: int +GREATER: int +EQUAL: int +DOT: int +PERCENT: int +BACKQUOTE: int +LBRACE: int +RBRACE: int +EQEQUAL: int +NOTEQUAL: int +LESSEQUAL: int +GREATEREQUAL: int +TILDE: int +CIRCUMFLEX: int +LEFTSHIFT: int +RIGHTSHIFT: int +DOUBLESTAR: int +PLUSEQUAL: int +MINEQUAL: int +STAREQUAL: int +SLASHEQUAL: int +PERCENTEQUAL: int +AMPEREQUAL: int +VBAREQUAL: int +CIRCUMFLEXEQUAL: int +LEFTSHIFTEQUAL: int +RIGHTSHIFTEQUAL: int +DOUBLESTAREQUAL: int +DOUBLESLASH: int +DOUBLESLASHEQUAL: int +AT: int +OP: int +ERRORTOKEN: int +N_TOKENS: int +NT_OFFSET: int +tok_name: Dict[int, str] + +def ISTERMINAL(x: int) -> bool: ... +def ISNONTERMINAL(x: int) -> bool: ... +def ISEOF(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/tokenize.pyi b/mypy/typeshed/stdlib/@python2/tokenize.pyi index 86d5937d6bc9..98ec01a6cb75 100644 --- a/mypy/typeshed/stdlib/@python2/tokenize.pyi +++ b/mypy/typeshed/stdlib/@python2/tokenize.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Generator, Iterable, Iterator, List, Tuple, Union +from typing import Any, Callable, Dict, Generator, Iterable, Iterator, List, Tuple __author__: str __credits__: str diff --git a/mypy/typeshed/stdlib/@python2/trace.pyi b/mypy/typeshed/stdlib/@python2/trace.pyi new file mode 100644 index 000000000000..62f228673a55 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/trace.pyi @@ -0,0 +1,49 @@ +import types +from _typeshed import StrPath +from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, TypeVar + +_T = TypeVar("_T") +_localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] +_fileModuleFunction = Tuple[str, Optional[str], str] + +class CoverageResults: + def __init__( + self, + counts: Dict[Tuple[str, int], int] | None = ..., + calledfuncs: Dict[_fileModuleFunction, int] | None = ..., + infile: StrPath | None = ..., + callers: Dict[Tuple[_fileModuleFunction, _fileModuleFunction], int] | None = ..., + outfile: StrPath | None = ..., + ) -> None: ... # undocumented + def update(self, other: CoverageResults) -> None: ... + def write_results(self, show_missing: bool = ..., summary: bool = ..., coverdir: StrPath | None = ...) -> None: ... + def write_results_file( + self, path: StrPath, lines: Sequence[str], lnotab: Any, lines_hit: Mapping[int, int], encoding: str | None = ... + ) -> Tuple[int, int]: ... + +class Trace: + def __init__( + self, + count: int = ..., + trace: int = ..., + countfuncs: int = ..., + countcallers: int = ..., + ignoremods: Sequence[str] = ..., + ignoredirs: Sequence[str] = ..., + infile: StrPath | None = ..., + outfile: StrPath | None = ..., + timing: bool = ..., + ) -> None: ... + def run(self, cmd: str | types.CodeType) -> None: ... + def runctx( + self, cmd: str | types.CodeType, globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ... + ) -> None: ... + def runfunc(self, func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def file_module_function_of(self, frame: types.FrameType) -> _fileModuleFunction: ... + def globaltrace_trackcallers(self, frame: types.FrameType, why: str, arg: Any) -> None: ... + def globaltrace_countfuncs(self, frame: types.FrameType, why: str, arg: Any) -> None: ... + def globaltrace_lt(self, frame: types.FrameType, why: str, arg: Any) -> None: ... + def localtrace_trace_and_count(self, frame: types.FrameType, why: str, arg: Any) -> _localtrace: ... + def localtrace_trace(self, frame: types.FrameType, why: str, arg: Any) -> _localtrace: ... + def localtrace_count(self, frame: types.FrameType, why: str, arg: Any) -> _localtrace: ... + def results(self) -> CoverageResults: ... diff --git a/mypy/typeshed/stdlib/@python2/traceback.pyi b/mypy/typeshed/stdlib/@python2/traceback.pyi new file mode 100644 index 000000000000..2152ab255942 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/traceback.pyi @@ -0,0 +1,27 @@ +from types import FrameType, TracebackType +from typing import IO, List, Optional, Tuple, Type + +_PT = Tuple[str, int, str, Optional[str]] + +def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... +def print_exception( + etype: Type[BaseException] | None, + value: BaseException | None, + tb: TracebackType | None, + limit: int | None = ..., + file: IO[str] | None = ..., +) -> None: ... +def print_exc(limit: int | None = ..., file: IO[str] | None = ...) -> None: ... +def print_last(limit: int | None = ..., file: IO[str] | None = ...) -> None: ... +def print_stack(f: FrameType | None = ..., limit: int | None = ..., file: IO[str] | None = ...) -> None: ... +def extract_tb(tb: TracebackType | None, limit: int | None = ...) -> List[_PT]: ... +def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> List[_PT]: ... +def format_list(extracted_list: List[_PT]) -> List[str]: ... +def format_exception_only(etype: Type[BaseException] | None, value: BaseException | None) -> List[str]: ... +def format_exception( + etype: Type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ... +) -> List[str]: ... +def format_exc(limit: int | None = ...) -> str: ... +def format_tb(tb: TracebackType | None, limit: int | None = ...) -> List[str]: ... +def format_stack(f: FrameType | None = ..., limit: int | None = ...) -> List[str]: ... +def tb_lineno(tb: TracebackType) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/tty.pyi b/mypy/typeshed/stdlib/@python2/tty.pyi new file mode 100644 index 000000000000..c0dc418e9933 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/tty.pyi @@ -0,0 +1,15 @@ +from typing import IO, Union + +_FD = Union[int, IO[str]] + +# XXX: Undocumented integer constants +IFLAG: int +OFLAG: int +CFLAG: int +LFLAG: int +ISPEED: int +OSPEED: int +CC: int + +def setraw(fd: _FD, when: int = ...) -> None: ... +def setcbreak(fd: _FD, when: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/turtle.pyi b/mypy/typeshed/stdlib/@python2/turtle.pyi new file mode 100644 index 000000000000..659dfd31b161 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/turtle.pyi @@ -0,0 +1,504 @@ +from typing import Any, Callable, Dict, List, Sequence, Text, Tuple, TypeVar, Union, overload + +# TODO: Replace these aliases once we have Python 2 stubs for the Tkinter module. +Canvas = Any +PhotoImage = Any + +# Note: '_Color' is the alias we use for arguments and _AnyColor is the +# alias we use for return types. Really, these two aliases should be the +# same, but as per the "no union returns" typeshed policy, we'll return +# Any instead. +_Color = Union[Text, Tuple[float, float, float]] +_AnyColor = Any + +# TODO: Replace this with a TypedDict once it becomes standardized. +_PenState = Dict[str, Any] + +_Speed = Union[str, float] +_PolygonCoords = Sequence[Tuple[float, float]] + +# TODO: Type this more accurately +# Vec2D is actually a custom subclass of 'tuple'. +Vec2D = Tuple[float, float] + +class TurtleScreenBase(object): + cv: Canvas = ... + canvwidth: int = ... + canvheight: int = ... + xscale: float = ... + yscale: float = ... + def __init__(self, cv: Canvas) -> None: ... + +class Terminator(Exception): ... +class TurtleGraphicsError(Exception): ... + +class Shape(object): + def __init__(self, type_: str, data: _PolygonCoords | PhotoImage | None = ...) -> None: ... + def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: _Color | None = ...) -> None: ... + +class TurtleScreen(TurtleScreenBase): + def __init__(self, cv: Canvas, mode: str = ..., colormode: float = ..., delay: int = ...) -> None: ... + def clear(self) -> None: ... + @overload + def mode(self, mode: None = ...) -> str: ... + @overload + def mode(self, mode: str) -> None: ... + def setworldcoordinates(self, llx: float, lly: float, urx: float, ury: float) -> None: ... + def register_shape(self, name: str, shape: _PolygonCoords | Shape | None = ...) -> None: ... + @overload + def colormode(self, cmode: None = ...) -> float: ... + @overload + def colormode(self, cmode: float) -> None: ... + def reset(self) -> None: ... + def turtles(self) -> List[Turtle]: ... + @overload + def bgcolor(self) -> _AnyColor: ... + @overload + def bgcolor(self, color: _Color) -> None: ... + @overload + def bgcolor(self, r: float, g: float, b: float) -> None: ... + @overload + def tracer(self, n: None = ...) -> int: ... + @overload + def tracer(self, n: int, delay: int | None = ...) -> None: ... + @overload + def delay(self, delay: None = ...) -> int: ... + @overload + def delay(self, delay: int) -> None: ... + def update(self) -> None: ... + def window_width(self) -> int: ... + def window_height(self) -> int: ... + def getcanvas(self) -> Canvas: ... + def getshapes(self) -> List[str]: ... + def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... + def onkey(self, fun: Callable[[], Any], key: str) -> None: ... + def listen(self, xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... + def ontimer(self, fun: Callable[[], Any], t: int = ...) -> None: ... + @overload + def bgpic(self, picname: None = ...) -> str: ... + @overload + def bgpic(self, picname: str) -> None: ... + @overload + def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... + # Looks like if self.cv is not a ScrolledCanvas, this could return a tuple as well + @overload + def screensize(self, canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... + onscreenclick = onclick + resetscreen = reset + clearscreen = clear + addshape = register_shape + +class TNavigator(object): + START_ORIENTATION: Dict[str, Vec2D] = ... + DEFAULT_MODE: str = ... + DEFAULT_ANGLEOFFSET: int = ... + DEFAULT_ANGLEORIENT: int = ... + def __init__(self, mode: str = ...) -> None: ... + def reset(self) -> None: ... + def degrees(self, fullcircle: float = ...) -> None: ... + def radians(self) -> None: ... + def forward(self, distance: float) -> None: ... + def back(self, distance: float) -> None: ... + def right(self, angle: float) -> None: ... + def left(self, angle: float) -> None: ... + def pos(self) -> Vec2D: ... + def xcor(self) -> float: ... + def ycor(self) -> float: ... + @overload + def goto(self, x: Tuple[float, float], y: None = ...) -> None: ... + @overload + def goto(self, x: float, y: float) -> None: ... + def home(self) -> None: ... + def setx(self, x: float) -> None: ... + def sety(self, y: float) -> None: ... + @overload + def distance(self, x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... + @overload + def distance(self, x: float, y: float) -> float: ... + @overload + def towards(self, x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... + @overload + def towards(self, x: float, y: float) -> float: ... + def heading(self) -> float: ... + def setheading(self, to_angle: float) -> None: ... + def circle(self, radius: float, extent: float | None = ..., steps: int | None = ...) -> None: ... + fd = forward + bk = back + backward = back + rt = right + lt = left + position = pos + setpos = goto + setposition = goto + seth = setheading + +class TPen(object): + def __init__(self, resizemode: str = ...) -> None: ... + @overload + def resizemode(self, rmode: None = ...) -> str: ... + @overload + def resizemode(self, rmode: str) -> None: ... + @overload + def pensize(self, width: None = ...) -> int: ... + @overload + def pensize(self, width: int) -> None: ... + def penup(self) -> None: ... + def pendown(self) -> None: ... + def isdown(self) -> bool: ... + @overload + def speed(self, speed: None = ...) -> int: ... + @overload + def speed(self, speed: _Speed) -> None: ... + @overload + def pencolor(self) -> _AnyColor: ... + @overload + def pencolor(self, color: _Color) -> None: ... + @overload + def pencolor(self, r: float, g: float, b: float) -> None: ... + @overload + def fillcolor(self) -> _AnyColor: ... + @overload + def fillcolor(self, color: _Color) -> None: ... + @overload + def fillcolor(self, r: float, g: float, b: float) -> None: ... + @overload + def color(self) -> Tuple[_AnyColor, _AnyColor]: ... + @overload + def color(self, color: _Color) -> None: ... + @overload + def color(self, r: float, g: float, b: float) -> None: ... + @overload + def color(self, color1: _Color, color2: _Color) -> None: ... + def showturtle(self) -> None: ... + def hideturtle(self) -> None: ... + def isvisible(self) -> bool: ... + # Note: signatures 1 and 2 overlap unsafely when no arguments are provided + @overload + def pen(self) -> _PenState: ... # type: ignore + @overload + def pen( + self, + pen: _PenState | None = ..., + *, + shown: bool = ..., + pendown: bool = ..., + pencolor: _Color = ..., + fillcolor: _Color = ..., + pensize: int = ..., + speed: int = ..., + resizemode: str = ..., + stretchfactor: Tuple[float, float] = ..., + outline: int = ..., + tilt: float = ..., + ) -> None: ... + width = pensize + up = penup + pu = penup + pd = pendown + down = pendown + st = showturtle + ht = hideturtle + +_T = TypeVar("_T") + +class RawTurtle(TPen, TNavigator): + def __init__( + self, canvas: Canvas | TurtleScreen | None = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ... + ) -> None: ... + def reset(self) -> None: ... + def setundobuffer(self, size: int | None) -> None: ... + def undobufferentries(self) -> int: ... + def clear(self) -> None: ... + def clone(self: _T) -> _T: ... + @overload + def shape(self, name: None = ...) -> str: ... + @overload + def shape(self, name: str) -> None: ... + # Unsafely overlaps when no arguments are provided + @overload + def shapesize(self) -> Tuple[float, float, float]: ... # type: ignore + @overload + def shapesize( + self, stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ... + ) -> None: ... + def settiltangle(self, angle: float) -> None: ... + @overload + def tiltangle(self, angle: None = ...) -> float: ... + @overload + def tiltangle(self, angle: float) -> None: ... + def tilt(self, angle: float) -> None: ... + # Can return either 'int' or Tuple[int, ...] based on if the stamp is + # a compound stamp or not. So, as per the "no Union return" policy, + # we return Any. + def stamp(self) -> Any: ... + def clearstamp(self, stampid: int | Tuple[int, ...]) -> None: ... + def clearstamps(self, n: int | None = ...) -> None: ... + def filling(self) -> bool: ... + def begin_fill(self) -> None: ... + def end_fill(self) -> None: ... + def dot(self, size: int | None = ..., *color: _Color) -> None: ... + def write(self, arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... + def begin_poly(self) -> None: ... + def end_poly(self) -> None: ... + def get_poly(self) -> _PolygonCoords | None: ... + def getscreen(self) -> TurtleScreen: ... + def getturtle(self: _T) -> _T: ... + getpen = getturtle + def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... + def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... + def ondrag(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... + def undo(self) -> None: ... + turtlesize = shapesize + +class _Screen(TurtleScreen): + def __init__(self) -> None: ... + # Note int and float are interpreted differently, hence the Union instead of just float + def setup( + self, width: int | float = ..., height: int | float = ..., startx: int | None = ..., starty: int | None = ... + ) -> None: ... + def title(self, titlestring: str) -> None: ... + def bye(self) -> None: ... + def exitonclick(self) -> None: ... + +class Turtle(RawTurtle): + def __init__(self, shape: str = ..., undobuffersize: int = ..., visible: bool = ...) -> None: ... + +RawPen = RawTurtle +Pen = Turtle + +def write_docstringdict(filename: str = ...) -> None: ... + +# Note: it's somewhat unfortunate that we have to copy the function signatures. +# It would be nice if we could partially reduce the redundancy by doing something +# like the following: +# +# _screen: Screen +# clear = _screen.clear +# +# However, it seems pytype does not support this type of syntax in pyi files. + +# Functions copied from TurtleScreenBase: + +# Note: mainloop() was always present in the global scope, but was added to +# TurtleScreenBase in Python 3.0 +def mainloop() -> None: ... + +# Functions copied from TurtleScreen: + +def clear() -> None: ... +@overload +def mode(mode: None = ...) -> str: ... +@overload +def mode(mode: str) -> None: ... +def setworldcoordinates(llx: float, lly: float, urx: float, ury: float) -> None: ... +def register_shape(name: str, shape: _PolygonCoords | Shape | None = ...) -> None: ... +@overload +def colormode(cmode: None = ...) -> float: ... +@overload +def colormode(cmode: float) -> None: ... +def reset() -> None: ... +def turtles() -> List[Turtle]: ... +@overload +def bgcolor() -> _AnyColor: ... +@overload +def bgcolor(color: _Color) -> None: ... +@overload +def bgcolor(r: float, g: float, b: float) -> None: ... +@overload +def tracer(n: None = ...) -> int: ... +@overload +def tracer(n: int, delay: int | None = ...) -> None: ... +@overload +def delay(delay: None = ...) -> int: ... +@overload +def delay(delay: int) -> None: ... +def update() -> None: ... +def window_width() -> int: ... +def window_height() -> int: ... +def getcanvas() -> Canvas: ... +def getshapes() -> List[str]: ... +def onclick(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... +def onkey(fun: Callable[[], Any], key: str) -> None: ... +def listen(xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... +def ontimer(fun: Callable[[], Any], t: int = ...) -> None: ... +@overload +def bgpic(picname: None = ...) -> str: ... +@overload +def bgpic(picname: str) -> None: ... +@overload +def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... +@overload +def screensize(canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... + +onscreenclick = onclick +resetscreen = reset +clearscreen = clear +addshape = register_shape +# Functions copied from _Screen: + +def setup(width: float = ..., height: float = ..., startx: int | None = ..., starty: int | None = ...) -> None: ... +def title(titlestring: str) -> None: ... +def bye() -> None: ... +def exitonclick() -> None: ... +def Screen() -> _Screen: ... + +# Functions copied from TNavigator: + +def degrees(fullcircle: float = ...) -> None: ... +def radians() -> None: ... +def forward(distance: float) -> None: ... +def back(distance: float) -> None: ... +def right(angle: float) -> None: ... +def left(angle: float) -> None: ... +def pos() -> Vec2D: ... +def xcor() -> float: ... +def ycor() -> float: ... +@overload +def goto(x: Tuple[float, float], y: None = ...) -> None: ... +@overload +def goto(x: float, y: float) -> None: ... +def home() -> None: ... +def setx(x: float) -> None: ... +def sety(y: float) -> None: ... +@overload +def distance(x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... +@overload +def distance(x: float, y: float) -> float: ... +@overload +def towards(x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... +@overload +def towards(x: float, y: float) -> float: ... +def heading() -> float: ... +def setheading(to_angle: float) -> None: ... +def circle(radius: float, extent: float | None = ..., steps: int | None = ...) -> None: ... + +fd = forward +bk = back +backward = back +rt = right +lt = left +position = pos +setpos = goto +setposition = goto +seth = setheading + +# Functions copied from TPen: +@overload +def resizemode(rmode: None = ...) -> str: ... +@overload +def resizemode(rmode: str) -> None: ... +@overload +def pensize(width: None = ...) -> int: ... +@overload +def pensize(width: int) -> None: ... +def penup() -> None: ... +def pendown() -> None: ... +def isdown() -> bool: ... +@overload +def speed(speed: None = ...) -> int: ... +@overload +def speed(speed: _Speed) -> None: ... +@overload +def pencolor() -> _AnyColor: ... +@overload +def pencolor(color: _Color) -> None: ... +@overload +def pencolor(r: float, g: float, b: float) -> None: ... +@overload +def fillcolor() -> _AnyColor: ... +@overload +def fillcolor(color: _Color) -> None: ... +@overload +def fillcolor(r: float, g: float, b: float) -> None: ... +@overload +def color() -> Tuple[_AnyColor, _AnyColor]: ... +@overload +def color(color: _Color) -> None: ... +@overload +def color(r: float, g: float, b: float) -> None: ... +@overload +def color(color1: _Color, color2: _Color) -> None: ... +def showturtle() -> None: ... +def hideturtle() -> None: ... +def isvisible() -> bool: ... + +# Note: signatures 1 and 2 overlap unsafely when no arguments are provided +@overload +def pen() -> _PenState: ... # type: ignore +@overload +def pen( + pen: _PenState | None = ..., + *, + shown: bool = ..., + pendown: bool = ..., + pencolor: _Color = ..., + fillcolor: _Color = ..., + pensize: int = ..., + speed: int = ..., + resizemode: str = ..., + stretchfactor: Tuple[float, float] = ..., + outline: int = ..., + tilt: float = ..., +) -> None: ... + +width = pensize +up = penup +pu = penup +pd = pendown +down = pendown +st = showturtle +ht = hideturtle + +# Functions copied from RawTurtle: + +def setundobuffer(size: int | None) -> None: ... +def undobufferentries() -> int: ... +@overload +def shape(name: None = ...) -> str: ... +@overload +def shape(name: str) -> None: ... + +# Unsafely overlaps when no arguments are provided +@overload +def shapesize() -> Tuple[float, float, float]: ... # type: ignore +@overload +def shapesize(stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ...) -> None: ... +def settiltangle(angle: float) -> None: ... +@overload +def tiltangle(angle: None = ...) -> float: ... +@overload +def tiltangle(angle: float) -> None: ... +def tilt(angle: float) -> None: ... + +# Can return either 'int' or Tuple[int, ...] based on if the stamp is +# a compound stamp or not. So, as per the "no Union return" policy, +# we return Any. +def stamp() -> Any: ... +def clearstamp(stampid: int | Tuple[int, ...]) -> None: ... +def clearstamps(n: int | None = ...) -> None: ... +def filling() -> bool: ... +def begin_fill() -> None: ... +def end_fill() -> None: ... +def dot(size: int | None = ..., *color: _Color) -> None: ... +def write(arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... +def begin_poly() -> None: ... +def end_poly() -> None: ... +def get_poly() -> _PolygonCoords | None: ... +def getscreen() -> TurtleScreen: ... +def getturtle() -> Turtle: ... + +getpen = getturtle + +def onrelease(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... +def ondrag(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... +def undo() -> None: ... + +turtlesize = shapesize + +# Functions copied from RawTurtle with a few tweaks: + +def clone() -> Turtle: ... + +# Extra functions present only in the global scope: + +done = mainloop diff --git a/mypy/typeshed/stdlib/@python2/types.pyi b/mypy/typeshed/stdlib/@python2/types.pyi index cf57c6329665..72b9321a860f 100644 --- a/mypy/typeshed/stdlib/@python2/types.pyi +++ b/mypy/typeshed/stdlib/@python2/types.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Type, TypeVar, Union, overload +from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple, Type, TypeVar, overload _T = TypeVar("_T") @@ -27,11 +27,11 @@ class _Cell: cell_contents: Any class FunctionType: - func_closure: Optional[Tuple[_Cell, ...]] = ... + func_closure: Tuple[_Cell, ...] | None = ... func_code: CodeType = ... - func_defaults: Optional[Tuple[Any, ...]] = ... + func_defaults: Tuple[Any, ...] | None = ... func_dict: Dict[str, Any] = ... - func_doc: Optional[str] = ... + func_doc: str | None = ... func_globals: Dict[str, Any] = ... func_name: str = ... __closure__ = func_closure @@ -44,12 +44,12 @@ class FunctionType: self, code: CodeType, globals: Dict[str, Any], - name: Optional[str] = ..., - argdefs: Optional[Tuple[object, ...]] = ..., - closure: Optional[Tuple[_Cell, ...]] = ..., + name: str | None = ..., + argdefs: Tuple[object, ...] | None = ..., + closure: Tuple[_Cell, ...] | None = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __get__(self, obj: Optional[object], type: Optional[type]) -> UnboundMethodType: ... + def __get__(self, obj: object | None, type: type | None) -> UnboundMethodType: ... LambdaType = FunctionType @@ -95,11 +95,9 @@ class GeneratorType: def next(self) -> Any: ... def send(self, __arg: Any) -> Any: ... @overload - def throw( - self, __typ: Type[BaseException], __val: Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... - ) -> Any: ... + def throw(self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ...) -> Any: ... @overload - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> Any: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Any: ... class ClassType: ... @@ -118,19 +116,19 @@ class InstanceType(object): ... MethodType = UnboundMethodType class BuiltinFunctionType: - __self__: Optional[object] + __self__: object | None def __call__(self, *args: Any, **kwargs: Any) -> Any: ... BuiltinMethodType = BuiltinFunctionType class ModuleType: - __doc__: Optional[str] - __file__: Optional[str] + __doc__: str | None + __file__: str | None __name__: str - __package__: Optional[str] - __path__: Optional[Iterable[str]] + __package__: str | None + __path__: Iterable[str] | None __dict__: Dict[str, Any] - def __init__(self, name: str, doc: Optional[str] = ...) -> None: ... + def __init__(self, name: str, doc: str | None = ...) -> None: ... FileType = file XRangeType = xrange @@ -164,7 +162,7 @@ class DictProxyType: # TODO is it possible to have non-string keys? # no __init__ def copy(self) -> Dict[Any, Any]: ... - def get(self, key: str, default: _T = ...) -> Union[Any, _T]: ... + def get(self, key: str, default: _T = ...) -> Any | _T: ... def has_key(self, key: str) -> bool: ... def items(self) -> List[Tuple[str, Any]]: ... def iteritems(self) -> Iterator[Tuple[str, Any]]: ... diff --git a/mypy/typeshed/stdlib/@python2/typing.pyi b/mypy/typeshed/stdlib/@python2/typing.pyi index dfcac95197b0..a1b02e81990c 100644 --- a/mypy/typeshed/stdlib/@python2/typing.pyi +++ b/mypy/typeshed/stdlib/@python2/typing.pyi @@ -9,17 +9,12 @@ Any = object() class TypeVar: __name__: str - __bound__: Optional[Type[Any]] + __bound__: Type[Any] | None __constraints__: Tuple[Type[Any], ...] __covariant__: bool __contravariant__: bool def __init__( - self, - name: str, - *constraints: Type[Any], - bound: Optional[Type[Any]] = ..., - covariant: bool = ..., - contravariant: bool = ..., + self, name: str, *constraints: Type[Any], bound: Type[Any] | None = ..., covariant: bool = ..., contravariant: bool = ... ) -> None: ... _promote = object() @@ -144,11 +139,11 @@ class Generator(Iterator[_T_co], Generic[_T_co, _T_contra, _V_co]): @overload @abstractmethod def throw( - self, __typ: Type[BaseException], __val: Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload @abstractmethod - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> _T_co: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... @abstractmethod def close(self) -> None: ... @property @@ -218,9 +213,9 @@ class AbstractSet(Iterable[_T_co], Container[_T_co], Generic[_T_co]): def __gt__(self, s: AbstractSet[Any]) -> bool: ... def __ge__(self, s: AbstractSet[Any]) -> bool: ... def __and__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __or__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... + def __or__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... def __sub__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... + def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... # TODO: argument can be any container? def isdisjoint(self, s: AbstractSet[Any]) -> bool: ... # Implement Sized (but don't have it as a base class). @@ -236,9 +231,9 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def clear(self) -> None: ... def pop(self) -> _T: ... def remove(self, element: _T) -> None: ... - def __ior__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... + def __ior__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... def __iand__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... - def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... + def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... class MappingView(object): @@ -263,11 +258,8 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): class ContextManager(Protocol[_T_co]): def __enter__(self) -> _T_co: ... def __exit__( - self, - __exc_type: Optional[Type[BaseException]], - __exc_value: Optional[BaseException], - __traceback: Optional[TracebackType], - ) -> Optional[bool]: ... + self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> bool | None: ... class Mapping(Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): # TODO: We wish the key type could also be covariant, but that doesn't work, @@ -276,9 +268,9 @@ class Mapping(Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): def __getitem__(self, k: _KT) -> _VT_co: ... # Mixin methods @overload - def get(self, k: _KT) -> Optional[_VT_co]: ... + def get(self, k: _KT) -> _VT_co | None: ... @overload - def get(self, k: _KT, default: Union[_VT_co, _T]) -> Union[_VT_co, _T]: ... + def get(self, k: _KT, default: _VT_co | _T) -> _VT_co | _T: ... def keys(self) -> list[_KT]: ... def values(self) -> list[_VT_co]: ... def items(self) -> list[Tuple[_KT, _VT_co]]: ... @@ -299,7 +291,7 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @overload def pop(self, k: _KT) -> _VT: ... @overload - def pop(self, k: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... + def pop(self, k: _KT, default: _VT | _T = ...) -> _VT | _T: ... def popitem(self) -> Tuple[_KT, _VT]: ... def setdefault(self, k: _KT, default: _VT = ...) -> _VT: ... @overload @@ -346,7 +338,7 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): @abstractmethod def tell(self) -> int: ... @abstractmethod - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... @abstractmethod def writable(self) -> bool: ... # TODO buffer objects @@ -362,8 +354,8 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): def __enter__(self) -> IO[AnyStr]: ... @abstractmethod def __exit__( - self, t: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> Optional[bool]: ... + self, t: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... class BinaryIO(IO[str]): # TODO readinto @@ -379,7 +371,7 @@ class TextIO(IO[unicode]): @property def encoding(self) -> str: ... @property - def errors(self) -> Optional[str]: ... + def errors(self) -> str | None: ... @property def line_buffering(self) -> bool: ... @property @@ -392,7 +384,7 @@ class ByteString(Sequence[int], metaclass=ABCMeta): ... class Match(Generic[AnyStr]): pos: int endpos: int - lastindex: Optional[int] + lastindex: int | None string: AnyStr # The regular expression object whose match() or search() method produced @@ -404,8 +396,8 @@ class Match(Generic[AnyStr]): re: Pattern[Any] # Can be None if there are no groups or if the last group was unnamed; # otherwise matches the type of the pattern. - lastgroup: Optional[Any] - def expand(self, template: Union[str, Text]) -> Any: ... + lastgroup: Any | None + def expand(self, template: str | Text) -> Any: ... @overload def group(self, group1: int = ...) -> AnyStr: ... @overload @@ -416,9 +408,9 @@ class Match(Generic[AnyStr]): def group(self, group1: str, group2: str, *groups: str) -> Tuple[AnyStr, ...]: ... def groups(self, default: AnyStr = ...) -> Tuple[AnyStr, ...]: ... def groupdict(self, default: AnyStr = ...) -> Dict[str, AnyStr]: ... - def start(self, __group: Union[int, str] = ...) -> int: ... - def end(self, __group: Union[int, str] = ...) -> int: ... - def span(self, __group: Union[int, str] = ...) -> Tuple[int, int]: ... + def start(self, __group: int | str = ...) -> int: ... + def end(self, __group: int | str = ...) -> int: ... + def span(self, __group: int | str = ...) -> Tuple[int, int]: ... @property def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented @@ -433,12 +425,12 @@ class Pattern(Generic[AnyStr]): groupindex: Dict[AnyStr, int] groups: int pattern: AnyStr - def search(self, string: _AnyStr2, pos: int = ..., endpos: int = ...) -> Optional[Match[_AnyStr2]]: ... - def match(self, string: _AnyStr2, pos: int = ..., endpos: int = ...) -> Optional[Match[_AnyStr2]]: ... + def search(self, string: _AnyStr2, pos: int = ..., endpos: int = ...) -> Match[_AnyStr2] | None: ... + def match(self, string: _AnyStr2, pos: int = ..., endpos: int = ...) -> Match[_AnyStr2] | None: ... def split(self, string: _AnyStr2, maxsplit: int = ...) -> List[_AnyStr2]: ... # Returns either a list of _AnyStr2 or a list of tuples, depending on # whether there are groups in the pattern. - def findall(self, string: Union[bytes, Text], pos: int = ..., endpos: int = ...) -> List[Any]: ... + def findall(self, string: bytes | Text, pos: int = ..., endpos: int = ...) -> List[Any]: ... def finditer(self, string: _AnyStr2, pos: int = ..., endpos: int = ...) -> Iterator[Match[_AnyStr2]]: ... @overload def sub(self, repl: _AnyStr2, string: _AnyStr2, count: int = ...) -> _AnyStr2: ... @@ -452,7 +444,7 @@ class Pattern(Generic[AnyStr]): # Functions def get_type_hints( - obj: Callable[..., Any], globalns: Optional[Dict[Text, Any]] = ..., localns: Optional[Dict[Text, Any]] = ... + obj: Callable[..., Any], globalns: Dict[Text, Any] | None = ..., localns: Dict[Text, Any] | None = ... ) -> None: ... @overload def cast(tp: Type[_T], obj: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/@python2/typing_extensions.pyi b/mypy/typeshed/stdlib/@python2/typing_extensions.pyi new file mode 100644 index 000000000000..d946cc278d32 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/typing_extensions.pyi @@ -0,0 +1,105 @@ +import abc +from typing import ( + TYPE_CHECKING as TYPE_CHECKING, + Any, + Callable, + ClassVar as ClassVar, + ContextManager as ContextManager, + Counter as Counter, + DefaultDict as DefaultDict, + Deque as Deque, + Dict, + ItemsView, + KeysView, + Mapping, + NewType as NewType, + NoReturn as NoReturn, + Text as Text, + Tuple, + Type as Type, + TypeVar, + ValuesView, + _Alias, + overload as overload, +) + +_T = TypeVar("_T") +_F = TypeVar("_F", bound=Callable[..., Any]) +_TC = TypeVar("_TC", bound=Type[object]) + +class _SpecialForm: + def __getitem__(self, typeargs: Any) -> Any: ... + +def runtime_checkable(cls: _TC) -> _TC: ... + +# This alias for above is kept here for backwards compatibility. +runtime = runtime_checkable +Protocol: _SpecialForm = ... +Final: _SpecialForm = ... + +def final(f: _F) -> _F: ... + +Literal: _SpecialForm = ... + +def IntVar(name: str) -> Any: ... # returns a new TypeVar + +# Internal mypy fallback type for all typed dicts (does not exist at runtime) +class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): + def copy(self: _T) -> _T: ... + # Using NoReturn so that only calls using mypy plugin hook that specialize the signature + # can go through. + def setdefault(self, k: NoReturn, default: object) -> object: ... + # Mypy plugin hook for 'pop' expects that 'default' has a type variable type. + def pop(self, k: NoReturn, default: _T = ...) -> object: ... # type: ignore + def update(self: _T, __m: _T) -> None: ... + def has_key(self, k: str) -> bool: ... + def viewitems(self) -> ItemsView[str, object]: ... + def viewkeys(self) -> KeysView[str]: ... + def viewvalues(self) -> ValuesView[object]: ... + def __delitem__(self, k: NoReturn) -> None: ... + +# TypedDict is a (non-subscriptable) special form. +TypedDict: object = ... + +OrderedDict = _Alias() + +def get_type_hints( + obj: Callable[..., Any], + globalns: Dict[str, Any] | None = ..., + localns: Dict[str, Any] | None = ..., + include_extras: bool = ..., +) -> Dict[str, Any]: ... + +Annotated: _SpecialForm = ... +_AnnotatedAlias: Any = ... # undocumented + +@runtime_checkable +class SupportsIndex(Protocol, metaclass=abc.ABCMeta): + @abc.abstractmethod + def __index__(self) -> int: ... + +# PEP 612 support for Python < 3.9 +class ParamSpecArgs: + __origin__: ParamSpec + def __init__(self, origin: ParamSpec) -> None: ... + +class ParamSpecKwargs: + __origin__: ParamSpec + def __init__(self, origin: ParamSpec) -> None: ... + +class ParamSpec: + __name__: str + __bound__: Type[Any] | None + __covariant__: bool + __contravariant__: bool + def __init__( + self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... + ) -> None: ... + @property + def args(self) -> ParamSpecArgs: ... + @property + def kwargs(self) -> ParamSpecKwargs: ... + +Concatenate: _SpecialForm = ... +TypeAlias: _SpecialForm = ... +TypeGuard: _SpecialForm = ... diff --git a/mypy/typeshed/stdlib/@python2/unicodedata.pyi b/mypy/typeshed/stdlib/@python2/unicodedata.pyi new file mode 100644 index 000000000000..f4ca655e5c7e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/unicodedata.pyi @@ -0,0 +1,37 @@ +from typing import Any, Text, TypeVar + +ucd_3_2_0: UCD +ucnhash_CAPI: Any +unidata_version: str + +_T = TypeVar("_T") + +def bidirectional(__chr: Text) -> Text: ... +def category(__chr: Text) -> Text: ... +def combining(__chr: Text) -> int: ... +def decimal(__chr: Text, __default: _T = ...) -> int | _T: ... +def decomposition(__chr: Text) -> Text: ... +def digit(__chr: Text, __default: _T = ...) -> int | _T: ... +def east_asian_width(__chr: Text) -> Text: ... +def lookup(__name: Text | bytes) -> Text: ... +def mirrored(__chr: Text) -> int: ... +def name(__chr: Text, __default: _T = ...) -> Text | _T: ... +def normalize(__form: Text, __unistr: Text) -> Text: ... +def numeric(__chr: Text, __default: _T = ...) -> float | _T: ... + +class UCD(object): + # The methods below are constructed from the same array in C + # (unicodedata_functions) and hence identical to the methods above. + unidata_version: str + def bidirectional(self, __chr: Text) -> str: ... + def category(self, __chr: Text) -> str: ... + def combining(self, __chr: Text) -> int: ... + def decimal(self, __chr: Text, __default: _T = ...) -> int | _T: ... + def decomposition(self, __chr: Text) -> str: ... + def digit(self, __chr: Text, __default: _T = ...) -> int | _T: ... + def east_asian_width(self, __chr: Text) -> str: ... + def lookup(self, __name: Text | bytes) -> Text: ... + def mirrored(self, __chr: Text) -> int: ... + def name(self, __chr: Text, __default: _T = ...) -> Text | _T: ... + def normalize(self, __form: Text, __unistr: Text) -> Text: ... + def numeric(self, __chr: Text, __default: _T = ...) -> float | _T: ... diff --git a/mypy/typeshed/stdlib/@python2/unittest.pyi b/mypy/typeshed/stdlib/@python2/unittest.pyi index 57b73a762cfa..65a5a7878de6 100644 --- a/mypy/typeshed/stdlib/@python2/unittest.pyi +++ b/mypy/typeshed/stdlib/@python2/unittest.pyi @@ -11,7 +11,6 @@ from typing import ( List, Mapping, NoReturn, - Optional, Pattern, Sequence, Set, @@ -79,7 +78,7 @@ class _AssertRaisesContext(_AssertRaisesBaseContext): class TestCase(Testable): failureException: Type[BaseException] longMessage: bool - maxDiff: Optional[int] + maxDiff: int | None # undocumented _testMethodName: str def __init__(self, methodName: str = ...) -> None: ... @@ -144,9 +143,7 @@ class TestCase(Testable): ) -> None: ... def assertListEqual(self, first: List[Any], second: List[Any], msg: object = ...) -> None: ... def assertTupleEqual(self, first: Tuple[Any, ...], second: Tuple[Any, ...], msg: object = ...) -> None: ... - def assertSetEqual( - self, first: Union[Set[Any], FrozenSet[Any]], second: Union[Set[Any], FrozenSet[Any]], msg: object = ... - ) -> None: ... + def assertSetEqual(self, first: Set[Any] | FrozenSet[Any], second: Set[Any] | FrozenSet[Any], msg: object = ...) -> None: ... def assertDictEqual(self, first: Dict[Any, Any], second: Dict[Any, Any], msg: object = ...) -> None: ... def assertLess(self, first: Any, second: Any, msg: object = ...) -> None: ... def assertLessEqual(self, first: Any, second: Any, msg: object = ...) -> None: ... @@ -177,8 +174,8 @@ class TestCase(Testable): def assertIsNotNone(self, expr: Any, msg: object = ...) -> None: ... def assertIn(self, first: _T, second: Iterable[_T], msg: object = ...) -> None: ... def assertNotIn(self, first: _T, second: Iterable[_T], msg: object = ...) -> None: ... - def assertIsInstance(self, obj: Any, cls: Union[type, Tuple[type, ...]], msg: object = ...) -> None: ... - def assertNotIsInstance(self, obj: Any, cls: Union[type, Tuple[type, ...]], msg: object = ...) -> None: ... + def assertIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: object = ...) -> None: ... + def assertNotIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: object = ...) -> None: ... def fail(self, msg: object = ...) -> NoReturn: ... def countTestCases(self) -> int: ... def defaultTestResult(self) -> TestResult: ... @@ -187,16 +184,16 @@ class TestCase(Testable): def addCleanup(self, function: Any, *args: Any, **kwargs: Any) -> None: ... def doCleanups(self) -> bool: ... def skipTest(self, reason: Any) -> None: ... - def _formatMessage(self, msg: Optional[Text], standardMsg: Text) -> str: ... # undocumented + def _formatMessage(self, msg: Text | None, standardMsg: Text) -> str: ... # undocumented def _getAssertEqualityFunc(self, first: Any, second: Any) -> Callable[..., None]: ... # undocumented class FunctionTestCase(TestCase): def __init__( self, testFunc: Callable[[], None], - setUp: Optional[Callable[[], None]] = ..., - tearDown: Optional[Callable[[], None]] = ..., - description: Optional[str] = ..., + setUp: Callable[[], None] | None = ..., + tearDown: Callable[[], None] | None = ..., + description: str | None = ..., ) -> None: ... def debug(self) -> None: ... def countTestCases(self) -> int: ... @@ -212,13 +209,13 @@ class TestSuite(Testable): class TestLoader: testMethodPrefix: str - sortTestMethodsUsing: Optional[Callable[[str, str], int]] + sortTestMethodsUsing: Callable[[str, str], int] | None suiteClass: Callable[[List[TestCase]], TestSuite] def loadTestsFromTestCase(self, testCaseClass: Type[TestCase]) -> TestSuite: ... def loadTestsFromModule(self, module: types.ModuleType = ..., use_load_tests: bool = ...) -> TestSuite: ... - def loadTestsFromName(self, name: str = ..., module: Optional[types.ModuleType] = ...) -> TestSuite: ... - def loadTestsFromNames(self, names: List[str] = ..., module: Optional[types.ModuleType] = ...) -> TestSuite: ... - def discover(self, start_dir: str, pattern: str = ..., top_level_dir: Optional[str] = ...) -> TestSuite: ... + def loadTestsFromName(self, name: str = ..., module: types.ModuleType | None = ...) -> TestSuite: ... + def loadTestsFromNames(self, names: List[str] = ..., module: types.ModuleType | None = ...) -> TestSuite: ... + def discover(self, start_dir: str, pattern: str = ..., top_level_dir: str | None = ...) -> TestSuite: ... def getTestCaseNames(self, testCaseClass: Type[TestCase] = ...) -> List[str]: ... defaultTestLoader: TestLoader @@ -232,12 +229,12 @@ class TextTestResult(TestResult): class TextTestRunner: def __init__( self, - stream: Optional[TextIO] = ..., + stream: TextIO | None = ..., descriptions: bool = ..., verbosity: int = ..., failfast: bool = ..., buffer: bool = ..., - resultclass: Optional[Type[TestResult]] = ..., + resultclass: Type[TestResult] | None = ..., ) -> None: ... def _makeResult(self) -> TestResult: ... def run(self, test: Testable) -> TestResult: ... # undocumented @@ -245,10 +242,10 @@ class TextTestRunner: class SkipTest(Exception): ... # TODO precise types -def skipUnless(condition: Any, reason: Union[str, unicode]) -> Any: ... -def skipIf(condition: Any, reason: Union[str, unicode]) -> Any: ... +def skipUnless(condition: Any, reason: str | unicode) -> Any: ... +def skipIf(condition: Any, reason: str | unicode) -> Any: ... def expectedFailure(func: _FT) -> _FT: ... -def skip(reason: Union[str, unicode]) -> Any: ... +def skip(reason: str | unicode) -> Any: ... # not really documented class TestProgram: @@ -256,18 +253,18 @@ class TestProgram: def runTests(self) -> None: ... # undocumented def main( - module: Union[None, Text, types.ModuleType] = ..., - defaultTest: Optional[str] = ..., - argv: Optional[Sequence[str]] = ..., - testRunner: Union[Type[TextTestRunner], TextTestRunner, None] = ..., + module: None | Text | types.ModuleType = ..., + defaultTest: str | None = ..., + argv: Sequence[str] | None = ..., + testRunner: Type[TextTestRunner] | TextTestRunner | None = ..., testLoader: TestLoader = ..., exit: bool = ..., verbosity: int = ..., - failfast: Optional[bool] = ..., - catchbreak: Optional[bool] = ..., - buffer: Optional[bool] = ..., + failfast: bool | None = ..., + catchbreak: bool | None = ..., + buffer: bool | None = ..., ) -> TestProgram: ... -def load_tests(loader: TestLoader, tests: TestSuite, pattern: Optional[Text]) -> TestSuite: ... +def load_tests(loader: TestLoader, tests: TestSuite, pattern: Text | None) -> TestSuite: ... def installHandler() -> None: ... def registerResult(result: TestResult) -> None: ... def removeResult(result: TestResult) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/urllib.pyi b/mypy/typeshed/stdlib/@python2/urllib.pyi index c719c1faa693..f6bb555b9581 100644 --- a/mypy/typeshed/stdlib/@python2/urllib.pyi +++ b/mypy/typeshed/stdlib/@python2/urllib.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, AnyStr, List, Mapping, Sequence, Text, Tuple, TypeVar, Union +from typing import IO, Any, AnyStr, List, Mapping, Sequence, Text, Tuple, TypeVar def url2pathname(pathname: AnyStr) -> AnyStr: ... def pathname2url(pathname: AnyStr) -> AnyStr: ... @@ -125,9 +125,9 @@ def unquote(s: AnyStr) -> AnyStr: ... def unquote_plus(s: AnyStr) -> AnyStr: ... def quote(s: AnyStr, safe: Text = ...) -> AnyStr: ... def quote_plus(s: AnyStr, safe: Text = ...) -> AnyStr: ... -def urlencode(query: Union[Sequence[Tuple[Any, Any]], Mapping[Any, Any]], doseq=...) -> str: ... +def urlencode(query: Sequence[Tuple[Any, Any]] | Mapping[Any, Any], doseq=...) -> str: ... def getproxies() -> Mapping[str, str]: ... -def proxy_bypass(host: str) -> Any: ... # Undocumented +def proxy_bypass(host: str) -> Any: ... # undocumented # Names in __all__ with no definition: # basejoin diff --git a/mypy/typeshed/stdlib/@python2/urllib2.pyi b/mypy/typeshed/stdlib/@python2/urllib2.pyi index 8c355db46d75..bf6157b8428b 100644 --- a/mypy/typeshed/stdlib/@python2/urllib2.pyi +++ b/mypy/typeshed/stdlib/@python2/urllib2.pyi @@ -1,12 +1,12 @@ import ssl from httplib import HTTPConnectionProtocol, HTTPResponse -from typing import Any, AnyStr, Callable, Dict, List, Mapping, Optional, Sequence, Text, Tuple, Type, Union +from typing import Any, AnyStr, Callable, Dict, List, Mapping, Sequence, Text, Tuple, Type, Union from urllib import addinfourl _string = Union[str, unicode] class URLError(IOError): - reason: Union[str, BaseException] + reason: str | BaseException class HTTPError(URLError, addinfourl): code: int @@ -19,16 +19,16 @@ class Request(object): data: str headers: Dict[str, str] unverifiable: bool - type: Optional[str] + type: str | None origin_req_host = ... unredirected_hdrs: Dict[str, str] - timeout: Optional[float] # Undocumented, only set after __init__() by OpenerDirector.open() + timeout: float | None # Undocumented, only set after __init__() by OpenerDirector.open() def __init__( self, url: str, - data: Optional[str] = ..., + data: str | None = ..., headers: Dict[str, str] = ..., - origin_req_host: Optional[str] = ..., + origin_req_host: str | None = ..., unverifiable: bool = ..., ) -> None: ... def __getattr__(self, attr): ... @@ -47,30 +47,28 @@ class Request(object): def add_header(self, key: str, val: str) -> None: ... def add_unredirected_header(self, key: str, val: str) -> None: ... def has_header(self, header_name: str) -> bool: ... - def get_header(self, header_name: str, default: Optional[str] = ...) -> str: ... + def get_header(self, header_name: str, default: str | None = ...) -> str: ... def header_items(self): ... class OpenerDirector(object): addheaders: List[Tuple[str, str]] def add_handler(self, handler: BaseHandler) -> None: ... - def open( - self, fullurl: Union[Request, _string], data: Optional[_string] = ..., timeout: Optional[float] = ... - ) -> Optional[addinfourl]: ... + def open(self, fullurl: Request | _string, data: _string | None = ..., timeout: float | None = ...) -> addinfourl | None: ... def error(self, proto: _string, *args: Any): ... # Note that this type is somewhat a lie. The return *can* be None if # a custom opener has been installed that fails to handle the request. def urlopen( - url: Union[Request, _string], - data: Optional[_string] = ..., - timeout: Optional[float] = ..., - cafile: Optional[_string] = ..., - capath: Optional[_string] = ..., + url: Request | _string, + data: _string | None = ..., + timeout: float | None = ..., + cafile: _string | None = ..., + capath: _string | None = ..., cadefault: bool = ..., - context: Optional[ssl.SSLContext] = ..., + context: ssl.SSLContext | None = ..., ) -> addinfourl: ... def install_opener(opener: OpenerDirector) -> None: ... -def build_opener(*handlers: Union[BaseHandler, Type[BaseHandler]]) -> OpenerDirector: ... +def build_opener(*handlers: BaseHandler | Type[BaseHandler]) -> OpenerDirector: ... class BaseHandler: handler_order: int @@ -97,21 +95,21 @@ class HTTPRedirectHandler(BaseHandler): class ProxyHandler(BaseHandler): proxies: Mapping[str, str] - def __init__(self, proxies: Optional[Mapping[str, str]] = ...): ... + def __init__(self, proxies: Mapping[str, str] | None = ...): ... def proxy_open(self, req: Request, proxy, type): ... class HTTPPasswordMgr: def __init__(self) -> None: ... - def add_password(self, realm: Optional[Text], uri: Union[Text, Sequence[Text]], user: Text, passwd: Text) -> None: ... - def find_user_password(self, realm: Optional[Text], authuri: Text) -> Tuple[Any, Any]: ... + def add_password(self, realm: Text | None, uri: Text | Sequence[Text], user: Text, passwd: Text) -> None: ... + def find_user_password(self, realm: Text | None, authuri: Text) -> Tuple[Any, Any]: ... def reduce_uri(self, uri: _string, default_port: bool = ...) -> Tuple[Any, Any]: ... def is_suburi(self, base: _string, test: _string) -> bool: ... class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): ... class AbstractBasicAuthHandler: - def __init__(self, password_mgr: Optional[HTTPPasswordMgr] = ...) -> None: ... - def add_password(self, realm: Optional[Text], uri: Union[Text, Sequence[Text]], user: Text, passwd: Text) -> None: ... + def __init__(self, password_mgr: HTTPPasswordMgr | None = ...) -> None: ... + def add_password(self, realm: Text | None, uri: Text | Sequence[Text], user: Text, passwd: Text) -> None: ... def http_error_auth_reqed(self, authreq, host, req: Request, headers: Mapping[str, str]): ... def retry_http_basic_auth(self, host, req: Request, realm): ... @@ -124,15 +122,15 @@ class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): def http_error_407(self, req: Request, fp: addinfourl, code: int, msg: str, headers: Mapping[str, str]): ... class AbstractDigestAuthHandler: - def __init__(self, passwd: Optional[HTTPPasswordMgr] = ...) -> None: ... - def add_password(self, realm: Optional[Text], uri: Union[Text, Sequence[Text]], user: Text, passwd: Text) -> None: ... + def __init__(self, passwd: HTTPPasswordMgr | None = ...) -> None: ... + def add_password(self, realm: Text | None, uri: Text | Sequence[Text], user: Text, passwd: Text) -> None: ... def reset_retry_count(self) -> None: ... def http_error_auth_reqed(self, auth_header: str, host: str, req: Request, headers: Mapping[str, str]) -> None: ... - def retry_http_digest_auth(self, req: Request, auth: str) -> Optional[HTTPResponse]: ... + def retry_http_digest_auth(self, req: Request, auth: str) -> HTTPResponse | None: ... def get_cnonce(self, nonce: str) -> str: ... def get_authorization(self, req: Request, chal: Mapping[str, str]) -> str: ... def get_algorithm_impls(self, algorithm: str) -> Tuple[Callable[[str], str], Callable[[str, str], str]]: ... - def get_entity_digest(self, data: Optional[bytes], chal: Mapping[str, str]) -> Optional[str]: ... + def get_entity_digest(self, data: bytes | None, chal: Mapping[str, str]) -> str | None: ... class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): auth_header: str @@ -148,19 +146,19 @@ class AbstractHTTPHandler(BaseHandler): # undocumented def __init__(self, debuglevel: int = ...) -> None: ... def set_http_debuglevel(self, level: int) -> None: ... def do_request_(self, request: Request) -> Request: ... - def do_open(self, http_class: HTTPConnectionProtocol, req: Request, **http_conn_args: Optional[Any]) -> addinfourl: ... + def do_open(self, http_class: HTTPConnectionProtocol, req: Request, **http_conn_args: Any | None) -> addinfourl: ... class HTTPHandler(AbstractHTTPHandler): def http_open(self, req: Request) -> addinfourl: ... def http_request(self, request: Request) -> Request: ... # undocumented class HTTPSHandler(AbstractHTTPHandler): - def __init__(self, debuglevel: int = ..., context: Optional[ssl.SSLContext] = ...) -> None: ... + def __init__(self, debuglevel: int = ..., context: ssl.SSLContext | None = ...) -> None: ... def https_open(self, req: Request) -> addinfourl: ... def https_request(self, request: Request) -> Request: ... # undocumented class HTTPCookieProcessor(BaseHandler): - def __init__(self, cookiejar: Optional[Any] = ...): ... + def __init__(self, cookiejar: Any | None = ...): ... def http_request(self, request: Request): ... def http_response(self, request: Request, response): ... @@ -178,7 +176,7 @@ class FTPHandler(BaseHandler): class CacheFTPHandler(FTPHandler): def __init__(self) -> None: ... - def setTimeout(self, t: Optional[float]): ... + def setTimeout(self, t: float | None): ... def setMaxConns(self, m: int): ... def check_cache(self): ... def clear_cache(self): ... diff --git a/mypy/typeshed/stdlib/@python2/urlparse.pyi b/mypy/typeshed/stdlib/@python2/urlparse.pyi index 40691239a87b..6668c743373a 100644 --- a/mypy/typeshed/stdlib/@python2/urlparse.pyi +++ b/mypy/typeshed/stdlib/@python2/urlparse.pyi @@ -1,4 +1,4 @@ -from typing import AnyStr, Dict, List, NamedTuple, Optional, Sequence, Tuple, Union, overload +from typing import AnyStr, Dict, List, NamedTuple, Sequence, Tuple, Union, overload _String = Union[str, unicode] @@ -15,13 +15,13 @@ def clear_cache() -> None: ... class ResultMixin(object): @property - def username(self) -> Optional[str]: ... + def username(self) -> str | None: ... @property - def password(self) -> Optional[str]: ... + def password(self) -> str | None: ... @property - def hostname(self) -> Optional[str]: ... + def hostname(self) -> str | None: ... @property - def port(self) -> Optional[int]: ... + def port(self) -> int | None: ... class _SplitResult(NamedTuple): scheme: str diff --git a/mypy/typeshed/stdlib/@python2/uu.pyi b/mypy/typeshed/stdlib/@python2/uu.pyi new file mode 100644 index 000000000000..e8717aecbe36 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/uu.pyi @@ -0,0 +1,8 @@ +from typing import BinaryIO, Text, Union + +_File = Union[Text, BinaryIO] + +class Error(Exception): ... + +def encode(in_file: _File, out_file: _File, name: str | None = ..., mode: int | None = ...) -> None: ... +def decode(in_file: _File, out_file: _File | None = ..., mode: int | None = ..., quiet: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/uuid.pyi b/mypy/typeshed/stdlib/@python2/uuid.pyi new file mode 100644 index 000000000000..2c8a9fb1c097 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/uuid.pyi @@ -0,0 +1,81 @@ +from typing import Any, Text, Tuple + +# Because UUID has properties called int and bytes we need to rename these temporarily. +_Int = int +_Bytes = bytes +_FieldsType = Tuple[int, int, int, int, int, int] + +class UUID: + def __init__( + self, + hex: Text | None = ..., + bytes: _Bytes | None = ..., + bytes_le: _Bytes | None = ..., + fields: _FieldsType | None = ..., + int: _Int | None = ..., + version: _Int | None = ..., + ) -> None: ... + @property + def bytes(self) -> _Bytes: ... + @property + def bytes_le(self) -> _Bytes: ... + @property + def clock_seq(self) -> _Int: ... + @property + def clock_seq_hi_variant(self) -> _Int: ... + @property + def clock_seq_low(self) -> _Int: ... + @property + def fields(self) -> _FieldsType: ... + @property + def hex(self) -> str: ... + @property + def int(self) -> _Int: ... + @property + def node(self) -> _Int: ... + @property + def time(self) -> _Int: ... + @property + def time_hi_version(self) -> _Int: ... + @property + def time_low(self) -> _Int: ... + @property + def time_mid(self) -> _Int: ... + @property + def urn(self) -> str: ... + @property + def variant(self) -> str: ... + @property + def version(self) -> _Int | None: ... + def __int__(self) -> _Int: ... + def get_bytes(self) -> _Bytes: ... + def get_bytes_le(self) -> _Bytes: ... + def get_clock_seq(self) -> _Int: ... + def get_clock_seq_hi_variant(self) -> _Int: ... + def get_clock_seq_low(self) -> _Int: ... + def get_fields(self) -> _FieldsType: ... + def get_hex(self) -> str: ... + def get_node(self) -> _Int: ... + def get_time(self) -> _Int: ... + def get_time_hi_version(self) -> _Int: ... + def get_time_low(self) -> _Int: ... + def get_time_mid(self) -> _Int: ... + def get_urn(self) -> str: ... + def get_variant(self) -> str: ... + def get_version(self) -> _Int | None: ... + def __cmp__(self, other: Any) -> _Int: ... + +def getnode() -> int: ... +def uuid1(node: _Int | None = ..., clock_seq: _Int | None = ...) -> UUID: ... +def uuid3(namespace: UUID, name: str) -> UUID: ... +def uuid4() -> UUID: ... +def uuid5(namespace: UUID, name: str) -> UUID: ... + +NAMESPACE_DNS: UUID +NAMESPACE_URL: UUID +NAMESPACE_OID: UUID +NAMESPACE_X500: UUID +RESERVED_NCS: str +RFC_4122: str +RESERVED_MICROSOFT: str +RESERVED_FUTURE: str diff --git a/mypy/typeshed/stdlib/@python2/warnings.pyi b/mypy/typeshed/stdlib/@python2/warnings.pyi new file mode 100644 index 000000000000..0d187bf70c33 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/warnings.pyi @@ -0,0 +1,51 @@ +from _warnings import warn as warn, warn_explicit as warn_explicit +from types import ModuleType, TracebackType +from typing import List, TextIO, Type, overload +from typing_extensions import Literal + +def showwarning( + message: Warning | str, category: Type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... +) -> None: ... +def formatwarning(message: Warning | str, category: Type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... +def filterwarnings( + action: str, message: str = ..., category: Type[Warning] = ..., module: str = ..., lineno: int = ..., append: bool = ... +) -> None: ... +def simplefilter(action: str, category: Type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... +def resetwarnings() -> None: ... + +class _OptionError(Exception): ... + +class WarningMessage: + message: Warning | str + category: Type[Warning] + filename: str + lineno: int + file: TextIO | None + line: str | None + def __init__( + self, + message: Warning | str, + category: Type[Warning], + filename: str, + lineno: int, + file: TextIO | None = ..., + line: str | None = ..., + ) -> None: ... + +class catch_warnings: + @overload + def __new__(cls, *, record: Literal[False] = ..., module: ModuleType | None = ...) -> _catch_warnings_without_records: ... + @overload + def __new__(cls, *, record: Literal[True], module: ModuleType | None = ...) -> _catch_warnings_with_records: ... + @overload + def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... + def __enter__(self) -> List[WarningMessage] | None: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + +class _catch_warnings_without_records(catch_warnings): + def __enter__(self) -> None: ... + +class _catch_warnings_with_records(catch_warnings): + def __enter__(self) -> List[WarningMessage]: ... diff --git a/mypy/typeshed/stdlib/@python2/wave.pyi b/mypy/typeshed/stdlib/@python2/wave.pyi new file mode 100644 index 000000000000..0e9fe612cd24 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wave.pyi @@ -0,0 +1,56 @@ +from typing import IO, Any, BinaryIO, NoReturn, Text, Tuple, Union + +_File = Union[Text, IO[bytes]] + +class Error(Exception): ... + +WAVE_FORMAT_PCM: int + +_wave_params = Tuple[int, int, int, int, str, str] + +class Wave_read: + def __init__(self, f: _File) -> None: ... + def getfp(self) -> BinaryIO | None: ... + def rewind(self) -> None: ... + def close(self) -> None: ... + def tell(self) -> int: ... + def getnchannels(self) -> int: ... + def getnframes(self) -> int: ... + def getsampwidth(self) -> int: ... + def getframerate(self) -> int: ... + def getcomptype(self) -> str: ... + def getcompname(self) -> str: ... + def getparams(self) -> _wave_params: ... + def getmarkers(self) -> None: ... + def getmark(self, id: Any) -> NoReturn: ... + def setpos(self, pos: int) -> None: ... + def readframes(self, nframes: int) -> bytes: ... + +class Wave_write: + def __init__(self, f: _File) -> None: ... + def setnchannels(self, nchannels: int) -> None: ... + def getnchannels(self) -> int: ... + def setsampwidth(self, sampwidth: int) -> None: ... + def getsampwidth(self) -> int: ... + def setframerate(self, framerate: float) -> None: ... + def getframerate(self) -> int: ... + def setnframes(self, nframes: int) -> None: ... + def getnframes(self) -> int: ... + def setcomptype(self, comptype: str, compname: str) -> None: ... + def getcomptype(self) -> str: ... + def getcompname(self) -> str: ... + def setparams(self, params: _wave_params) -> None: ... + def getparams(self) -> _wave_params: ... + def setmark(self, id: Any, pos: Any, name: Any) -> NoReturn: ... + def getmark(self, id: Any) -> NoReturn: ... + def getmarkers(self) -> None: ... + def tell(self) -> int: ... + # should be any bytes-like object after 3.4, but we don't have a type for that + def writeframesraw(self, data: bytes) -> None: ... + def writeframes(self, data: bytes) -> None: ... + def close(self) -> None: ... + +# Returns a Wave_read if mode is rb and Wave_write if mode is wb +def open(f: _File, mode: str | None = ...) -> Any: ... + +openfp = open diff --git a/mypy/typeshed/stdlib/@python2/weakref.pyi b/mypy/typeshed/stdlib/@python2/weakref.pyi new file mode 100644 index 000000000000..6467f3a7517f --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/weakref.pyi @@ -0,0 +1,72 @@ +from _weakrefset import WeakSet as WeakSet +from typing import Any, Callable, Generic, Iterable, Iterator, List, Mapping, MutableMapping, Tuple, Type, TypeVar, overload + +from _weakref import ( + CallableProxyType as CallableProxyType, + ProxyType as ProxyType, + ReferenceType as ReferenceType, + getweakrefcount as getweakrefcount, + getweakrefs as getweakrefs, + proxy as proxy, + ref as ref, +) +from exceptions import ReferenceError as ReferenceError + +_S = TypeVar("_S") +_T = TypeVar("_T") +_KT = TypeVar("_KT") +_VT = TypeVar("_VT") + +ProxyTypes: Tuple[Type[Any], ...] + +class WeakValueDictionary(MutableMapping[_KT, _VT]): + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, __other: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __len__(self) -> int: ... + def __getitem__(self, k: _KT) -> _VT: ... + def __setitem__(self, k: _KT, v: _VT) -> None: ... + def __delitem__(self, v: _KT) -> None: ... + def has_key(self, key: object) -> bool: ... + def __contains__(self, o: object) -> bool: ... + def __iter__(self) -> Iterator[_KT]: ... + def __str__(self) -> str: ... + def copy(self) -> WeakValueDictionary[_KT, _VT]: ... + def keys(self) -> List[_KT]: ... + def values(self) -> List[_VT]: ... + def items(self) -> List[Tuple[_KT, _VT]]: ... + def iterkeys(self) -> Iterator[_KT]: ... + def itervalues(self) -> Iterator[_VT]: ... + def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ... + def valuerefs(self) -> List[KeyedRef[_KT, _VT]]: ... + +class KeyedRef(ref[_T], Generic[_KT, _T]): + key: _KT + # This __new__ method uses a non-standard name for the "cls" parameter + def __new__(type, ob: _T, callback: Callable[[_T], Any], key: _KT) -> KeyedRef[_KT, _T]: ... # type: ignore + def __init__(self, ob: _T, callback: Callable[[_T], Any], key: _KT) -> None: ... + +class WeakKeyDictionary(MutableMapping[_KT, _VT]): + @overload + def __init__(self, dict: None = ...) -> None: ... + @overload + def __init__(self, dict: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]]) -> None: ... + def __len__(self) -> int: ... + def __getitem__(self, k: _KT) -> _VT: ... + def __setitem__(self, k: _KT, v: _VT) -> None: ... + def __delitem__(self, v: _KT) -> None: ... + def has_key(self, key: object) -> bool: ... + def __contains__(self, o: object) -> bool: ... + def __iter__(self) -> Iterator[_KT]: ... + def __str__(self) -> str: ... + def copy(self) -> WeakKeyDictionary[_KT, _VT]: ... + def keys(self) -> List[_KT]: ... + def values(self) -> List[_VT]: ... + def items(self) -> List[Tuple[_KT, _VT]]: ... + def iterkeys(self) -> Iterator[_KT]: ... + def itervalues(self) -> Iterator[_VT]: ... + def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iterkeyrefs(self) -> Iterator[ref[_KT]]: ... + def keyrefs(self) -> List[ref[_KT]]: ... diff --git a/mypy/typeshed/stdlib/@python2/webbrowser.pyi b/mypy/typeshed/stdlib/@python2/webbrowser.pyi new file mode 100644 index 000000000000..f634bc11ca7d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/webbrowser.pyi @@ -0,0 +1,96 @@ +import sys +from typing import Callable, List, Sequence, Text + +class Error(Exception): ... + +def register( + name: Text, klass: Callable[[], BaseBrowser] | None, instance: BaseBrowser | None = ..., update_tryorder: int = ... +) -> None: ... +def get(using: Text | None = ...) -> BaseBrowser: ... +def open(url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... +def open_new(url: Text) -> bool: ... +def open_new_tab(url: Text) -> bool: ... + +class BaseBrowser: + args: List[str] + name: str + basename: str + def __init__(self, name: Text = ...) -> None: ... + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open_new(self, url: Text) -> bool: ... + def open_new_tab(self, url: Text) -> bool: ... + +class GenericBrowser(BaseBrowser): + args: List[str] + name: str + basename: str + def __init__(self, name: Text | Sequence[Text]) -> None: ... + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +class BackgroundBrowser(GenericBrowser): + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +class UnixBrowser(BaseBrowser): + raise_opts: List[str] | None + background: bool + redirect_stdout: bool + remote_args: List[str] + remote_action: str + remote_action_newwin: str + remote_action_newtab: str + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +class Mozilla(UnixBrowser): + remote_args: List[str] + remote_action: str + remote_action_newwin: str + remote_action_newtab: str + background: bool + +class Galeon(UnixBrowser): + raise_opts: List[str] + remote_args: List[str] + remote_action: str + remote_action_newwin: str + background: bool + +class Chrome(UnixBrowser): + remote_args: List[str] + remote_action: str + remote_action_newwin: str + remote_action_newtab: str + background: bool + +class Opera(UnixBrowser): + remote_args: List[str] + remote_action: str + remote_action_newwin: str + remote_action_newtab: str + background: bool + +class Elinks(UnixBrowser): + remote_args: List[str] + remote_action: str + remote_action_newwin: str + remote_action_newtab: str + background: bool + redirect_stdout: bool + +class Konqueror(BaseBrowser): + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +class Grail(BaseBrowser): + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +if sys.platform == "win32": + class WindowsDefault(BaseBrowser): + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + +if sys.platform == "darwin": + class MacOSX(BaseBrowser): + name: str + def __init__(self, name: Text) -> None: ... + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + class MacOSXOSAScript(BaseBrowser): + def __init__(self, name: Text) -> None: ... + def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/whichdb.pyi b/mypy/typeshed/stdlib/@python2/whichdb.pyi index 67542096d712..1c678e9392e8 100644 --- a/mypy/typeshed/stdlib/@python2/whichdb.pyi +++ b/mypy/typeshed/stdlib/@python2/whichdb.pyi @@ -1,3 +1,3 @@ -from typing import Optional, Text +from typing import Text -def whichdb(filename: Text) -> Optional[str]: ... +def whichdb(filename: Text) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/winsound.pyi b/mypy/typeshed/stdlib/@python2/winsound.pyi new file mode 100644 index 000000000000..3d79f3b043f2 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/winsound.pyi @@ -0,0 +1,27 @@ +import sys +from typing import overload +from typing_extensions import Literal + +if sys.platform == "win32": + SND_FILENAME: int + SND_ALIAS: int + SND_LOOP: int + SND_MEMORY: int + SND_PURGE: int + SND_ASYNC: int + SND_NODEFAULT: int + SND_NOSTOP: int + SND_NOWAIT: int + + MB_ICONASTERISK: int + MB_ICONEXCLAMATION: int + MB_ICONHAND: int + MB_ICONQUESTION: int + MB_OK: int + def Beep(frequency: int, duration: int) -> None: ... + # Can actually accept anything ORed with 4, and if not it's definitely str, but that's inexpressible + @overload + def PlaySound(sound: bytes | None, flags: Literal[4]) -> None: ... + @overload + def PlaySound(sound: str | bytes | None, flags: int) -> None: ... + def MessageBeep(type: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/__init__.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi new file mode 100644 index 000000000000..d7e35ba8aff6 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi @@ -0,0 +1,89 @@ +from abc import abstractmethod +from types import TracebackType +from typing import IO, Callable, List, MutableMapping, Optional, Text, Tuple, Type + +from .headers import Headers +from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment +from .util import FileWrapper + +_exc_info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] + +def format_date_time(timestamp: float | None) -> str: ... # undocumented + +class BaseHandler: + wsgi_version: Tuple[int, int] # undocumented + wsgi_multithread: bool + wsgi_multiprocess: bool + wsgi_run_once: bool + + origin_server: bool + http_version: str + server_software: str | None + + os_environ: MutableMapping[str, str] + + wsgi_file_wrapper: Type[FileWrapper] | None + headers_class: Type[Headers] # undocumented + + traceback_limit: int | None + error_status: str + error_headers: List[Tuple[Text, Text]] + error_body: bytes + def run(self, application: WSGIApplication) -> None: ... + def setup_environ(self) -> None: ... + def finish_response(self) -> None: ... + def get_scheme(self) -> str: ... + def set_content_length(self) -> None: ... + def cleanup_headers(self) -> None: ... + def start_response( + self, status: Text, headers: List[Tuple[Text, Text]], exc_info: _exc_info | None = ... + ) -> Callable[[bytes], None]: ... + def send_preamble(self) -> None: ... + def write(self, data: bytes) -> None: ... + def sendfile(self) -> bool: ... + def finish_content(self) -> None: ... + def close(self) -> None: ... + def send_headers(self) -> None: ... + def result_is_file(self) -> bool: ... + def client_is_modern(self) -> bool: ... + def log_exception(self, exc_info: _exc_info) -> None: ... + def handle_error(self) -> None: ... + def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... + @abstractmethod + def _write(self, data: bytes) -> None: ... + @abstractmethod + def _flush(self) -> None: ... + @abstractmethod + def get_stdin(self) -> InputStream: ... + @abstractmethod + def get_stderr(self) -> ErrorStream: ... + @abstractmethod + def add_cgi_vars(self) -> None: ... + +class SimpleHandler(BaseHandler): + stdin: InputStream + stdout: IO[bytes] + stderr: ErrorStream + base_env: MutableMapping[str, str] + def __init__( + self, + stdin: InputStream, + stdout: IO[bytes], + stderr: ErrorStream, + environ: MutableMapping[str, str], + multithread: bool = ..., + multiprocess: bool = ..., + ) -> None: ... + def get_stdin(self) -> InputStream: ... + def get_stderr(self) -> ErrorStream: ... + def add_cgi_vars(self) -> None: ... + def _write(self, data: bytes) -> None: ... + def _flush(self) -> None: ... + +class BaseCGIHandler(SimpleHandler): ... + +class CGIHandler(BaseCGIHandler): + def __init__(self) -> None: ... + +class IISCGIHandler(BaseCGIHandler): + def __init__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi new file mode 100644 index 000000000000..08061fee7664 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi @@ -0,0 +1,24 @@ +from typing import List, Pattern, Tuple, overload + +_HeaderList = List[Tuple[str, str]] + +tspecials: Pattern[str] # undocumented + +class Headers: + def __init__(self, headers: _HeaderList) -> None: ... + def __len__(self) -> int: ... + def __setitem__(self, name: str, val: str) -> None: ... + def __delitem__(self, name: str) -> None: ... + def __getitem__(self, name: str) -> str | None: ... + def has_key(self, name: str) -> bool: ... + def __contains__(self, name: str) -> bool: ... + def get_all(self, name: str) -> List[str]: ... + @overload + def get(self, name: str, default: str) -> str: ... + @overload + def get(self, name: str, default: str | None = ...) -> str | None: ... + def keys(self) -> List[str]: ... + def values(self) -> List[str]: ... + def items(self) -> _HeaderList: ... + def setdefault(self, name: str, value: str) -> str: ... + def add_header(self, _name: str, _value: str | None, **_params: str | None) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi new file mode 100644 index 000000000000..a74a26fed935 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi @@ -0,0 +1,37 @@ +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from typing import List, Type, TypeVar, overload + +from .handlers import SimpleHandler +from .types import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment + +server_version: str # undocumented +sys_version: str # undocumented +software_version: str # undocumented + +class ServerHandler(SimpleHandler): # undocumented + server_software: str + def close(self) -> None: ... + +class WSGIServer(HTTPServer): + application: WSGIApplication | None + base_environ: WSGIEnvironment # only available after call to setup_environ() + def setup_environ(self) -> None: ... + def get_app(self) -> WSGIApplication | None: ... + def set_app(self, application: WSGIApplication | None) -> None: ... + +class WSGIRequestHandler(BaseHTTPRequestHandler): + server_version: str + def get_environ(self) -> WSGIEnvironment: ... + def get_stderr(self) -> ErrorStream: ... + def handle(self) -> None: ... + +def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... + +_S = TypeVar("_S", bound=WSGIServer) + +@overload +def make_server(host: str, port: int, app: WSGIApplication, *, handler_class: Type[WSGIRequestHandler] = ...) -> WSGIServer: ... +@overload +def make_server( + host: str, port: int, app: WSGIApplication, server_class: Type[_S], handler_class: Type[WSGIRequestHandler] = ... +) -> _S: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/types.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/types.pyi new file mode 100644 index 000000000000..c272ae67c391 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/types.pyi @@ -0,0 +1,3 @@ +# Obsolete, use _typeshed.wsgi directly. + +from _typeshed.wsgi import * diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/util.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/util.pyi new file mode 100644 index 000000000000..c8e045a8cb8e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/util.pyi @@ -0,0 +1,19 @@ +from typing import IO, Any, Callable + +from .types import WSGIEnvironment + +class FileWrapper: + filelike: IO[bytes] + blksize: int + close: Callable[[], None] # only exists if filelike.close exists + def __init__(self, filelike: IO[bytes], blksize: int = ...) -> None: ... + def __getitem__(self, key: Any) -> bytes: ... + def __iter__(self) -> FileWrapper: ... + def next(self) -> bytes: ... + +def guess_scheme(environ: WSGIEnvironment) -> str: ... +def application_uri(environ: WSGIEnvironment) -> str: ... +def request_uri(environ: WSGIEnvironment, include_query: bool = ...) -> str: ... +def shift_path_info(environ: WSGIEnvironment) -> str | None: ... +def setup_testing_defaults(environ: WSGIEnvironment) -> None: ... +def is_hop_by_hop(header_name: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/validate.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/validate.pyi new file mode 100644 index 000000000000..b3e629b02d71 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/wsgiref/validate.pyi @@ -0,0 +1,44 @@ +from _typeshed.wsgi import ErrorStream, InputStream, WSGIApplication +from typing import Any, Callable, Iterable, Iterator, NoReturn + +class WSGIWarning(Warning): ... + +def validator(application: WSGIApplication) -> WSGIApplication: ... + +class InputWrapper: + input: InputStream + def __init__(self, wsgi_input: InputStream) -> None: ... + def read(self, size: int = ...) -> bytes: ... + def readline(self) -> bytes: ... + def readlines(self, hint: int = ...) -> bytes: ... + def __iter__(self) -> Iterable[bytes]: ... + def close(self) -> NoReturn: ... + +class ErrorWrapper: + errors: ErrorStream + def __init__(self, wsgi_errors: ErrorStream) -> None: ... + def write(self, s: str) -> None: ... + def flush(self) -> None: ... + def writelines(self, seq: Iterable[str]) -> None: ... + def close(self) -> NoReturn: ... + +class WriteWrapper: + writer: Callable[[bytes], Any] + def __init__(self, wsgi_writer: Callable[[bytes], Any]) -> None: ... + def __call__(self, s: bytes) -> None: ... + +class PartialIteratorWrapper: + iterator: Iterator[bytes] + def __init__(self, wsgi_iterator: Iterator[bytes]) -> None: ... + def __iter__(self) -> IteratorWrapper: ... + +class IteratorWrapper: + original_iterator: Iterator[bytes] + iterator: Iterator[bytes] + closed: bool + check_start_response: bool | None + def __init__(self, wsgi_iterator: Iterator[bytes], check_start_response: bool | None) -> None: ... + def __iter__(self) -> IteratorWrapper: ... + def next(self) -> bytes: ... + def close(self) -> None: ... + def __del__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/xdrlib.pyi b/mypy/typeshed/stdlib/@python2/xdrlib.pyi new file mode 100644 index 000000000000..378504c37227 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xdrlib.pyi @@ -0,0 +1,55 @@ +from typing import Callable, List, Sequence, TypeVar + +_T = TypeVar("_T") + +class Error(Exception): + msg: str + def __init__(self, msg: str) -> None: ... + +class ConversionError(Error): ... + +class Packer: + def __init__(self) -> None: ... + def reset(self) -> None: ... + def get_buffer(self) -> bytes: ... + def get_buf(self) -> bytes: ... + def pack_uint(self, x: int) -> None: ... + def pack_int(self, x: int) -> None: ... + def pack_enum(self, x: int) -> None: ... + def pack_bool(self, x: bool) -> None: ... + def pack_uhyper(self, x: int) -> None: ... + def pack_hyper(self, x: int) -> None: ... + def pack_float(self, x: float) -> None: ... + def pack_double(self, x: float) -> None: ... + def pack_fstring(self, n: int, s: bytes) -> None: ... + def pack_fopaque(self, n: int, s: bytes) -> None: ... + def pack_string(self, s: bytes) -> None: ... + def pack_opaque(self, s: bytes) -> None: ... + def pack_bytes(self, s: bytes) -> None: ... + def pack_list(self, list: Sequence[_T], pack_item: Callable[[_T], None]) -> None: ... + def pack_farray(self, n: int, list: Sequence[_T], pack_item: Callable[[_T], None]) -> None: ... + def pack_array(self, list: Sequence[_T], pack_item: Callable[[_T], None]) -> None: ... + +class Unpacker: + def __init__(self, data: bytes) -> None: ... + def reset(self, data: bytes) -> None: ... + def get_position(self) -> int: ... + def set_position(self, position: int) -> None: ... + def get_buffer(self) -> bytes: ... + def done(self) -> None: ... + def unpack_uint(self) -> int: ... + def unpack_int(self) -> int: ... + def unpack_enum(self) -> int: ... + def unpack_bool(self) -> bool: ... + def unpack_uhyper(self) -> int: ... + def unpack_hyper(self) -> int: ... + def unpack_float(self) -> float: ... + def unpack_double(self) -> float: ... + def unpack_fstring(self, n: int) -> bytes: ... + def unpack_fopaque(self, n: int) -> bytes: ... + def unpack_string(self) -> bytes: ... + def unpack_opaque(self) -> bytes: ... + def unpack_bytes(self) -> bytes: ... + def unpack_list(self, unpack_item: Callable[[], _T]) -> List[_T]: ... + def unpack_farray(self, n: int, unpack_item: Callable[[], _T]) -> List[_T]: ... + def unpack_array(self, unpack_item: Callable[[], _T]) -> List[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/__init__.pyi new file mode 100644 index 000000000000..c524ac2b1cfc --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/__init__.pyi @@ -0,0 +1 @@ +import xml.parsers as parsers diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/NodeFilter.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/NodeFilter.pyi new file mode 100644 index 000000000000..80fb73d23433 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/NodeFilter.pyi @@ -0,0 +1,19 @@ +class NodeFilter: + FILTER_ACCEPT: int + FILTER_REJECT: int + FILTER_SKIP: int + + SHOW_ALL: int + SHOW_ELEMENT: int + SHOW_ATTRIBUTE: int + SHOW_TEXT: int + SHOW_CDATA_SECTION: int + SHOW_ENTITY_REFERENCE: int + SHOW_ENTITY: int + SHOW_PROCESSING_INSTRUCTION: int + SHOW_COMMENT: int + SHOW_DOCUMENT: int + SHOW_DOCUMENT_TYPE: int + SHOW_DOCUMENT_FRAGMENT: int + SHOW_NOTATION: int + def acceptNode(self, node) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/__init__.pyi new file mode 100644 index 000000000000..c5766c326c3e --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/__init__.pyi @@ -0,0 +1,68 @@ +from typing import Any + +from .domreg import getDOMImplementation as getDOMImplementation, registerDOMImplementation as registerDOMImplementation + +class Node: + ELEMENT_NODE: int + ATTRIBUTE_NODE: int + TEXT_NODE: int + CDATA_SECTION_NODE: int + ENTITY_REFERENCE_NODE: int + ENTITY_NODE: int + PROCESSING_INSTRUCTION_NODE: int + COMMENT_NODE: int + DOCUMENT_NODE: int + DOCUMENT_TYPE_NODE: int + DOCUMENT_FRAGMENT_NODE: int + NOTATION_NODE: int + +# ExceptionCode +INDEX_SIZE_ERR: int +DOMSTRING_SIZE_ERR: int +HIERARCHY_REQUEST_ERR: int +WRONG_DOCUMENT_ERR: int +INVALID_CHARACTER_ERR: int +NO_DATA_ALLOWED_ERR: int +NO_MODIFICATION_ALLOWED_ERR: int +NOT_FOUND_ERR: int +NOT_SUPPORTED_ERR: int +INUSE_ATTRIBUTE_ERR: int +INVALID_STATE_ERR: int +SYNTAX_ERR: int +INVALID_MODIFICATION_ERR: int +NAMESPACE_ERR: int +INVALID_ACCESS_ERR: int +VALIDATION_ERR: int + +class DOMException(Exception): + code: int + def __init__(self, *args: Any, **kw: Any) -> None: ... + def _get_code(self) -> int: ... + +class IndexSizeErr(DOMException): ... +class DomstringSizeErr(DOMException): ... +class HierarchyRequestErr(DOMException): ... +class WrongDocumentErr(DOMException): ... +class NoDataAllowedErr(DOMException): ... +class NoModificationAllowedErr(DOMException): ... +class NotFoundErr(DOMException): ... +class NotSupportedErr(DOMException): ... +class InuseAttributeErr(DOMException): ... +class InvalidStateErr(DOMException): ... +class SyntaxErr(DOMException): ... +class InvalidModificationErr(DOMException): ... +class NamespaceErr(DOMException): ... +class InvalidAccessErr(DOMException): ... +class ValidationErr(DOMException): ... + +class UserDataHandler: + NODE_CLONED: int + NODE_IMPORTED: int + NODE_DELETED: int + NODE_RENAMED: int + +XML_NAMESPACE: str +XMLNS_NAMESPACE: str +XHTML_NAMESPACE: str +EMPTY_NAMESPACE: None +EMPTY_PREFIX: None diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi new file mode 100644 index 000000000000..2496b3884ea1 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi @@ -0,0 +1,8 @@ +from _typeshed.xml import DOMImplementation +from typing import Callable, Dict, Iterable, Tuple + +well_known_implementations: Dict[str, str] +registered: Dict[str, Callable[[], DOMImplementation]] + +def registerDOMImplementation(name: str, factory: Callable[[], DOMImplementation]) -> None: ... +def getDOMImplementation(name: str | None = ..., features: str | Iterable[Tuple[str, str | None]] = ...) -> DOMImplementation: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/expatbuilder.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/expatbuilder.pyi new file mode 100644 index 000000000000..964e6fa3f426 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/expatbuilder.pyi @@ -0,0 +1,3 @@ +from typing import Any + +def __getattr__(name: str) -> Any: ... # incomplete diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi new file mode 100644 index 000000000000..e9b0395ab50d --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi @@ -0,0 +1,17 @@ +from typing import Any, Iterable, List, Tuple, Type, TypeVar + +_T = TypeVar("_T") + +StringTypes: Tuple[Type[str]] + +class NodeList(List[_T]): + length: int + def item(self, index: int) -> _T | None: ... + +class EmptyNodeList(Tuple[Any, ...]): + length: int + def item(self, index: int) -> None: ... + def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore + def __radd__(self, other: Iterable[_T]) -> NodeList[_T]: ... + +def defproperty(klass: Type[Any], name: str, doc: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi new file mode 100644 index 000000000000..ed46ac4561ec --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi @@ -0,0 +1,292 @@ +import xml.dom +from typing import IO, Any, Text as _Text, TypeVar +from xml.dom.xmlbuilder import DocumentLS, DOMImplementationLS +from xml.sax.xmlreader import XMLReader + +_T = TypeVar("_T") + +def parse(file: str | IO[Any], parser: XMLReader | None = ..., bufsize: int | None = ...): ... +def parseString(string: bytes | _Text, parser: XMLReader | None = ...): ... +def getDOMImplementation(features=...): ... + +class Node(xml.dom.Node): + namespaceURI: str | None + parentNode: Any + ownerDocument: Any + nextSibling: Any + previousSibling: Any + prefix: Any + def toxml(self, encoding: Any | None = ...): ... + def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Any | None = ...): ... + def hasChildNodes(self) -> bool: ... + def insertBefore(self, newChild, refChild): ... + def appendChild(self, node): ... + def replaceChild(self, newChild, oldChild): ... + def removeChild(self, oldChild): ... + def normalize(self) -> None: ... + def cloneNode(self, deep): ... + def isSupported(self, feature, version): ... + def isSameNode(self, other): ... + def getInterface(self, feature): ... + def getUserData(self, key): ... + def setUserData(self, key, data, handler): ... + childNodes: Any + def unlink(self) -> None: ... + def __enter__(self: _T) -> _T: ... + def __exit__(self, et, ev, tb) -> None: ... + +class DocumentFragment(Node): + nodeType: Any + nodeName: str + nodeValue: Any + attributes: Any + parentNode: Any + childNodes: Any + def __init__(self) -> None: ... + +class Attr(Node): + name: str + nodeType: Any + attributes: Any + specified: bool + ownerElement: Any + namespaceURI: str | None + childNodes: Any + nodeName: Any + nodeValue: str + value: str + prefix: Any + def __init__( + self, qName: str, namespaceURI: str | None = ..., localName: Any | None = ..., prefix: Any | None = ... + ) -> None: ... + def unlink(self) -> None: ... + +class NamedNodeMap: + def __init__(self, attrs, attrsNS, ownerElement) -> None: ... + def item(self, index): ... + def items(self): ... + def itemsNS(self): ... + def __contains__(self, key): ... + def keys(self): ... + def keysNS(self): ... + def values(self): ... + def get(self, name, value: Any | None = ...): ... + def __len__(self) -> int: ... + def __eq__(self, other: Any) -> bool: ... + def __ge__(self, other: Any) -> bool: ... + def __gt__(self, other: Any) -> bool: ... + def __le__(self, other: Any) -> bool: ... + def __lt__(self, other: Any) -> bool: ... + def __getitem__(self, attname_or_tuple): ... + def __setitem__(self, attname, value) -> None: ... + def getNamedItem(self, name): ... + def getNamedItemNS(self, namespaceURI: str, localName): ... + def removeNamedItem(self, name): ... + def removeNamedItemNS(self, namespaceURI: str, localName): ... + def setNamedItem(self, node): ... + def setNamedItemNS(self, node): ... + def __delitem__(self, attname_or_tuple) -> None: ... + +AttributeList = NamedNodeMap + +class TypeInfo: + namespace: Any + name: Any + def __init__(self, namespace, name) -> None: ... + +class Element(Node): + nodeType: Any + nodeValue: Any + schemaType: Any + parentNode: Any + tagName: str + prefix: Any + namespaceURI: str | None + childNodes: Any + nextSibling: Any + def __init__( + self, tagName, namespaceURI: str | None = ..., prefix: Any | None = ..., localName: Any | None = ... + ) -> None: ... + def unlink(self) -> None: ... + def getAttribute(self, attname): ... + def getAttributeNS(self, namespaceURI: str, localName): ... + def setAttribute(self, attname, value) -> None: ... + def setAttributeNS(self, namespaceURI: str, qualifiedName: str, value) -> None: ... + def getAttributeNode(self, attrname): ... + def getAttributeNodeNS(self, namespaceURI: str, localName): ... + def setAttributeNode(self, attr): ... + setAttributeNodeNS: Any + def removeAttribute(self, name) -> None: ... + def removeAttributeNS(self, namespaceURI: str, localName) -> None: ... + def removeAttributeNode(self, node): ... + removeAttributeNodeNS: Any + def hasAttribute(self, name: str) -> bool: ... + def hasAttributeNS(self, namespaceURI: str, localName) -> bool: ... + def getElementsByTagName(self, name): ... + def getElementsByTagNameNS(self, namespaceURI: str, localName): ... + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + def hasAttributes(self) -> bool: ... + def setIdAttribute(self, name) -> None: ... + def setIdAttributeNS(self, namespaceURI: str, localName) -> None: ... + def setIdAttributeNode(self, idAttr) -> None: ... + +class Childless: + attributes: Any + childNodes: Any + firstChild: Any + lastChild: Any + def appendChild(self, node) -> None: ... + def hasChildNodes(self) -> bool: ... + def insertBefore(self, newChild, refChild) -> None: ... + def removeChild(self, oldChild) -> None: ... + def normalize(self) -> None: ... + def replaceChild(self, newChild, oldChild) -> None: ... + +class ProcessingInstruction(Childless, Node): + nodeType: Any + target: Any + data: Any + def __init__(self, target, data) -> None: ... + nodeValue: Any + nodeName: Any + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + +class CharacterData(Childless, Node): + ownerDocument: Any + previousSibling: Any + def __init__(self) -> None: ... + def __len__(self) -> int: ... + data: str + nodeValue: Any + def substringData(self, offset: int, count: int) -> str: ... + def appendData(self, arg: str) -> None: ... + def insertData(self, offset: int, arg: str) -> None: ... + def deleteData(self, offset: int, count: int) -> None: ... + def replaceData(self, offset: int, count: int, arg: str) -> None: ... + +class Text(CharacterData): + nodeType: Any + nodeName: str + attributes: Any + data: Any + def splitText(self, offset): ... + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + def replaceWholeText(self, content): ... + +class Comment(CharacterData): + nodeType: Any + nodeName: str + def __init__(self, data) -> None: ... + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + +class CDATASection(Text): + nodeType: Any + nodeName: str + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + +class ReadOnlySequentialNamedNodeMap: + def __init__(self, seq=...) -> None: ... + def __len__(self): ... + def getNamedItem(self, name): ... + def getNamedItemNS(self, namespaceURI: str, localName): ... + def __getitem__(self, name_or_tuple): ... + def item(self, index): ... + def removeNamedItem(self, name) -> None: ... + def removeNamedItemNS(self, namespaceURI: str, localName) -> None: ... + def setNamedItem(self, node) -> None: ... + def setNamedItemNS(self, node) -> None: ... + +class Identified: ... + +class DocumentType(Identified, Childless, Node): + nodeType: Any + nodeValue: Any + name: Any + publicId: Any + systemId: Any + internalSubset: Any + entities: Any + notations: Any + nodeName: Any + def __init__(self, qualifiedName: str) -> None: ... + def cloneNode(self, deep): ... + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... + +class Entity(Identified, Node): + attributes: Any + nodeType: Any + nodeValue: Any + actualEncoding: Any + encoding: Any + version: Any + nodeName: Any + notationName: Any + childNodes: Any + def __init__(self, name, publicId, systemId, notation) -> None: ... + def appendChild(self, newChild) -> None: ... + def insertBefore(self, newChild, refChild) -> None: ... + def removeChild(self, oldChild) -> None: ... + def replaceChild(self, newChild, oldChild) -> None: ... + +class Notation(Identified, Childless, Node): + nodeType: Any + nodeValue: Any + nodeName: Any + def __init__(self, name, publicId, systemId) -> None: ... + +class DOMImplementation(DOMImplementationLS): + def hasFeature(self, feature, version) -> bool: ... + def createDocument(self, namespaceURI: str, qualifiedName: str, doctype): ... + def createDocumentType(self, qualifiedName: str, publicId, systemId): ... + def getInterface(self, feature): ... + +class ElementInfo: + tagName: Any + def __init__(self, name) -> None: ... + def getAttributeType(self, aname): ... + def getAttributeTypeNS(self, namespaceURI: str, localName): ... + def isElementContent(self): ... + def isEmpty(self): ... + def isId(self, aname): ... + def isIdNS(self, namespaceURI: str, localName): ... + +class Document(Node, DocumentLS): + implementation: Any + nodeType: Any + nodeName: str + nodeValue: Any + attributes: Any + parentNode: Any + previousSibling: Any + nextSibling: Any + actualEncoding: Any + encoding: Any + standalone: Any + version: Any + strictErrorChecking: bool + errorHandler: Any + documentURI: Any + doctype: Any + childNodes: Any + def __init__(self) -> None: ... + def appendChild(self, node): ... + documentElement: Any + def removeChild(self, oldChild): ... + def unlink(self) -> None: ... + def cloneNode(self, deep): ... + def createDocumentFragment(self): ... + def createElement(self, tagName: str): ... + def createTextNode(self, data): ... + def createCDATASection(self, data): ... + def createComment(self, data): ... + def createProcessingInstruction(self, target, data): ... + def createAttribute(self, qName) -> Attr: ... + def createElementNS(self, namespaceURI: str, qualifiedName: str): ... + def createAttributeNS(self, namespaceURI: str, qualifiedName: str) -> Attr: ... + def getElementById(self, id): ... + def getElementsByTagName(self, name: str): ... + def getElementsByTagNameNS(self, namespaceURI: str, localName): ... + def isSupported(self, feature, version): ... + def importNode(self, node, deep): ... + def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ..., encoding: Any | None = ...) -> None: ... + def renameNode(self, n, namespaceURI: str, name): ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/pulldom.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/pulldom.pyi new file mode 100644 index 000000000000..964e6fa3f426 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/pulldom.pyi @@ -0,0 +1,3 @@ +from typing import Any + +def __getattr__(name: str) -> Any: ... # incomplete diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi new file mode 100644 index 000000000000..d8936bdc2ab4 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi @@ -0,0 +1,6 @@ +from typing import Any + +def __getattr__(name: str) -> Any: ... # incomplete + +class DocumentLS(Any): ... # type: ignore +class DOMImplementationLS(Any): ... # type: ignore diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/ElementInclude.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/ElementInclude.pyi new file mode 100644 index 000000000000..b74285d3e9b7 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/etree/ElementInclude.pyi @@ -0,0 +1,15 @@ +from typing import Callable +from xml.etree.ElementTree import Element + +XINCLUDE: str +XINCLUDE_INCLUDE: str +XINCLUDE_FALLBACK: str + +class FatalIncludeError(SyntaxError): ... + +def default_loader(href: str | bytes | int, parse: str, encoding: str | None = ...) -> str | Element: ... + +# TODO: loader is of type default_loader ie it takes a callable that has the +# same signature as default_loader. But default_loader has a keyword argument +# Which can't be represented using Callable... +def include(elem: Element, loader: Callable[..., str | Element] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi new file mode 100644 index 000000000000..02fe84567543 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi @@ -0,0 +1,31 @@ +from typing import Callable, Dict, Generator, List, Pattern, Tuple, TypeVar +from xml.etree.ElementTree import Element + +xpath_tokenizer_re: Pattern[str] + +_token = Tuple[str, str] +_next = Callable[[], _token] +_callback = Callable[[_SelectorContext, List[Element]], Generator[Element, None, None]] + +def xpath_tokenizer(pattern: str, namespaces: Dict[str, str] | None = ...) -> Generator[_token, None, None]: ... +def get_parent_map(context: _SelectorContext) -> Dict[Element, Element]: ... +def prepare_child(next: _next, token: _token) -> _callback: ... +def prepare_star(next: _next, token: _token) -> _callback: ... +def prepare_self(next: _next, token: _token) -> _callback: ... +def prepare_descendant(next: _next, token: _token) -> _callback: ... +def prepare_parent(next: _next, token: _token) -> _callback: ... +def prepare_predicate(next: _next, token: _token) -> _callback: ... + +ops: Dict[str, Callable[[_next, _token], _callback]] + +class _SelectorContext: + parent_map: Dict[Element, Element] | None + root: Element + def __init__(self, root: Element) -> None: ... + +_T = TypeVar("_T") + +def iterfind(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> Generator[Element, None, None]: ... +def find(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> Element | None: ... +def findall(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> List[Element]: ... +def findtext(elem: Element, path: str, default: _T | None = ..., namespaces: Dict[str, str] | None = ...) -> _T | str: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi new file mode 100644 index 000000000000..a7a0a1c65f46 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi @@ -0,0 +1,201 @@ +from _typeshed import FileDescriptor +from typing import ( + IO, + Any, + Callable, + Dict, + Generator, + ItemsView, + Iterable, + Iterator, + KeysView, + List, + MutableSequence, + Sequence, + Text, + Tuple, + TypeVar, + Union, + overload, +) + +VERSION: str + +class ParseError(SyntaxError): + code: int + position: Tuple[int, int] + +def iselement(element: object) -> bool: ... + +_T = TypeVar("_T") + +# Type for parser inputs. Parser will accept any unicode/str/bytes and coerce, +# and this is true in py2 and py3 (even fromstringlist() in python3 can be +# called with a heterogeneous list) +_parser_input_type = Union[bytes, Text] + +# Type for individual tag/attr/ns/text values in args to most functions. +# In py2, the library accepts str or unicode everywhere and coerces +# aggressively. +# In py3, bytes is not coerced to str and so use of bytes is probably an error, +# so we exclude it. (why? the parser never produces bytes when it parses XML, +# so e.g., element.get(b'name') will always return None for parsed XML, even if +# there is a 'name' attribute.) +_str_argument_type = Union[str, Text] + +# Type for return values from individual tag/attr/text values +# in python2, if the tag/attribute/text wasn't decode-able as ascii, it +# comes out as a unicode string; otherwise it comes out as str. (see +# _fixtext function in the source). Client code knows best: +_str_result_type = Any + +_file_or_filename = Union[Text, FileDescriptor, IO[Any]] + +class Element(MutableSequence[Element]): + tag: _str_result_type + attrib: Dict[_str_result_type, _str_result_type] + text: _str_result_type | None + tail: _str_result_type | None + def __init__( + self, + tag: _str_argument_type | Callable[..., Element], + attrib: Dict[_str_argument_type, _str_argument_type] = ..., + **extra: _str_argument_type, + ) -> None: ... + def append(self, __subelement: Element) -> None: ... + def clear(self) -> None: ... + def extend(self, __elements: Iterable[Element]) -> None: ... + def find( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> Element | None: ... + def findall( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> List[Element]: ... + @overload + def findtext( + self, path: _str_argument_type, default: None = ..., namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> _str_result_type | None: ... + @overload + def findtext( + self, path: _str_argument_type, default: _T, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> _T | _str_result_type: ... + @overload + def get(self, key: _str_argument_type, default: None = ...) -> _str_result_type | None: ... + @overload + def get(self, key: _str_argument_type, default: _T) -> _str_result_type | _T: ... + def insert(self, __index: int, __element: Element) -> None: ... + def items(self) -> ItemsView[_str_result_type, _str_result_type]: ... + def iter(self, tag: _str_argument_type | None = ...) -> Generator[Element, None, None]: ... + def iterfind( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> Generator[Element, None, None]: ... + def itertext(self) -> Generator[_str_result_type, None, None]: ... + def keys(self) -> KeysView[_str_result_type]: ... + def makeelement(self, __tag: _str_argument_type, __attrib: Dict[_str_argument_type, _str_argument_type]) -> Element: ... + def remove(self, __subelement: Element) -> None: ... + def set(self, __key: _str_argument_type, __value: _str_argument_type) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... + @overload + def __getitem__(self, i: int) -> Element: ... + @overload + def __getitem__(self, s: slice) -> MutableSequence[Element]: ... + def __len__(self) -> int: ... + @overload + def __setitem__(self, i: int, o: Element) -> None: ... + @overload + def __setitem__(self, s: slice, o: Iterable[Element]) -> None: ... + def getchildren(self) -> List[Element]: ... + def getiterator(self, tag: _str_argument_type | None = ...) -> List[Element]: ... + +def SubElement( + parent: Element, + tag: _str_argument_type, + attrib: Dict[_str_argument_type, _str_argument_type] = ..., + **extra: _str_argument_type, +) -> Element: ... +def Comment(text: _str_argument_type | None = ...) -> Element: ... +def ProcessingInstruction(target: _str_argument_type, text: _str_argument_type | None = ...) -> Element: ... + +PI: Callable[..., Element] + +class QName: + text: str + def __init__(self, text_or_uri: _str_argument_type, tag: _str_argument_type | None = ...) -> None: ... + +class ElementTree: + def __init__(self, element: Element | None = ..., file: _file_or_filename | None = ...) -> None: ... + def getroot(self) -> Element: ... + def parse(self, source: _file_or_filename, parser: XMLParser | None = ...) -> Element: ... + def iter(self, tag: _str_argument_type | None = ...) -> Generator[Element, None, None]: ... + def getiterator(self, tag: _str_argument_type | None = ...) -> List[Element]: ... + def find( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> Element | None: ... + @overload + def findtext( + self, path: _str_argument_type, default: None = ..., namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> _str_result_type | None: ... + @overload + def findtext( + self, path: _str_argument_type, default: _T, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> _T | _str_result_type: ... + def findall( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> List[Element]: ... + def iterfind( + self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + ) -> Generator[Element, None, None]: ... + def write( + self, + file_or_filename: _file_or_filename, + encoding: str | None = ..., + xml_declaration: bool | None = ..., + default_namespace: _str_argument_type | None = ..., + method: str | None = ..., + ) -> None: ... + def write_c14n(self, file: _file_or_filename) -> None: ... + +def register_namespace(prefix: _str_argument_type, uri: _str_argument_type) -> None: ... +def tostring(element: Element, encoding: str | None = ..., method: str | None = ...) -> bytes: ... +def tostringlist(element: Element, encoding: str | None = ..., method: str | None = ...) -> List[bytes]: ... +def dump(elem: Element) -> None: ... +def parse(source: _file_or_filename, parser: XMLParser | None = ...) -> ElementTree: ... +def iterparse( + source: _file_or_filename, events: Sequence[str] | None = ..., parser: XMLParser | None = ... +) -> Iterator[Tuple[str, Any]]: ... +def XML(text: _parser_input_type, parser: XMLParser | None = ...) -> Element: ... +def XMLID(text: _parser_input_type, parser: XMLParser | None = ...) -> Tuple[Element, Dict[_str_result_type, Element]]: ... + +# This is aliased to XML in the source. +fromstring = XML + +def fromstringlist(sequence: Sequence[_parser_input_type], parser: XMLParser | None = ...) -> Element: ... + +# This type is both not precise enough and too precise. The TreeBuilder +# requires the elementfactory to accept tag and attrs in its args and produce +# some kind of object that has .text and .tail properties. +# I've chosen to constrain the ElementFactory to always produce an Element +# because that is how almost everyone will use it. +# Unfortunately, the type of the factory arguments is dependent on how +# TreeBuilder is called by client code (they could pass strs, bytes or whatever); +# but we don't want to use a too-broad type, or it would be too hard to write +# elementfactories. +_ElementFactory = Callable[[Any, Dict[Any, Any]], Element] + +class TreeBuilder: + def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... + def close(self) -> Element: ... + def data(self, __data: _parser_input_type) -> None: ... + def start(self, __tag: _parser_input_type, __attrs: Dict[_parser_input_type, _parser_input_type]) -> Element: ... + def end(self, __tag: _parser_input_type) -> Element: ... + +class XMLParser: + parser: Any + target: Any + # TODO-what is entity used for??? + entity: Any + version: str + def __init__(self, html: int = ..., target: Any = ..., encoding: str | None = ...) -> None: ... + def doctype(self, __name: str, __pubid: str, __system: str) -> None: ... + def close(self) -> Any: ... + def feed(self, __data: _parser_input_type) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi new file mode 100644 index 000000000000..c41e2bee0eb1 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi @@ -0,0 +1 @@ +from xml.etree.ElementTree import * # noqa: F403 diff --git a/mypy/typeshed/stdlib/@python2/xml/parsers/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/parsers/__init__.pyi new file mode 100644 index 000000000000..cac086235cba --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/parsers/__init__.pyi @@ -0,0 +1 @@ +import xml.parsers.expat as expat diff --git a/mypy/typeshed/stdlib/@python2/xml/parsers/expat/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/__init__.pyi new file mode 100644 index 000000000000..73f3758c61ec --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/__init__.pyi @@ -0,0 +1 @@ +from pyexpat import * diff --git a/mypy/typeshed/stdlib/@python2/xml/parsers/expat/errors.pyi b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/errors.pyi new file mode 100644 index 000000000000..e22d769ec340 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/errors.pyi @@ -0,0 +1 @@ +from pyexpat.errors import * diff --git a/mypy/typeshed/stdlib/@python2/xml/parsers/expat/model.pyi b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/model.pyi new file mode 100644 index 000000000000..d8f44b47c51b --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/parsers/expat/model.pyi @@ -0,0 +1 @@ +from pyexpat.model import * diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi new file mode 100644 index 000000000000..0c6da9a87d13 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi @@ -0,0 +1,27 @@ +from typing import IO, Any, List, NoReturn, Text +from xml.sax.handler import ContentHandler, ErrorHandler +from xml.sax.xmlreader import Locator, XMLReader + +class SAXException(Exception): + def __init__(self, msg: str, exception: Exception | None = ...) -> None: ... + def getMessage(self) -> str: ... + def getException(self) -> Exception: ... + def __getitem__(self, ix: Any) -> NoReturn: ... + +class SAXParseException(SAXException): + def __init__(self, msg: str, exception: Exception, locator: Locator) -> None: ... + def getColumnNumber(self) -> int: ... + def getLineNumber(self) -> int: ... + def getPublicId(self): ... + def getSystemId(self): ... + +class SAXNotRecognizedException(SAXException): ... +class SAXNotSupportedException(SAXException): ... +class SAXReaderNotAvailable(SAXNotSupportedException): ... + +default_parser_list: List[str] + +def make_parser(parser_list: List[str] = ...) -> XMLReader: ... +def parse(source: str | IO[str] | IO[bytes], handler: ContentHandler, errorHandler: ErrorHandler = ...) -> None: ... +def parseString(string: bytes | Text, handler: ContentHandler, errorHandler: ErrorHandler | None = ...) -> None: ... +def _create_parser(parser_name: str) -> XMLReader: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/handler.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/handler.pyi new file mode 100644 index 000000000000..3a5193300981 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/sax/handler.pyi @@ -0,0 +1,46 @@ +from typing import Any + +version: Any + +class ErrorHandler: + def error(self, exception): ... + def fatalError(self, exception): ... + def warning(self, exception): ... + +class ContentHandler: + def __init__(self) -> None: ... + def setDocumentLocator(self, locator): ... + def startDocument(self): ... + def endDocument(self): ... + def startPrefixMapping(self, prefix, uri): ... + def endPrefixMapping(self, prefix): ... + def startElement(self, name, attrs): ... + def endElement(self, name): ... + def startElementNS(self, name, qname, attrs): ... + def endElementNS(self, name, qname): ... + def characters(self, content): ... + def ignorableWhitespace(self, whitespace): ... + def processingInstruction(self, target, data): ... + def skippedEntity(self, name): ... + +class DTDHandler: + def notationDecl(self, name, publicId, systemId): ... + def unparsedEntityDecl(self, name, publicId, systemId, ndata): ... + +class EntityResolver: + def resolveEntity(self, publicId, systemId): ... + +feature_namespaces: Any +feature_namespace_prefixes: Any +feature_string_interning: Any +feature_validation: Any +feature_external_ges: Any +feature_external_pes: Any +all_features: Any +property_lexical_handler: Any +property_declaration_handler: Any +property_dom_node: Any +property_xml_string: Any +property_encoding: Any +property_interning_dict: Any +all_properties: Any diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/saxutils.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/saxutils.pyi new file mode 100644 index 000000000000..1fc896490f54 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/sax/saxutils.pyi @@ -0,0 +1,59 @@ +from _typeshed import SupportsWrite +from codecs import StreamReaderWriter, StreamWriter +from io import RawIOBase, TextIOBase +from typing import Mapping, Text +from xml.sax import handler, xmlreader + +def escape(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... +def unescape(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... +def quoteattr(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... + +class XMLGenerator(handler.ContentHandler): + def __init__( + self, + out: TextIOBase | RawIOBase | StreamWriter | StreamReaderWriter | SupportsWrite[str] | None = ..., + encoding: Text = ..., + ) -> None: ... + def startDocument(self): ... + def endDocument(self): ... + def startPrefixMapping(self, prefix, uri): ... + def endPrefixMapping(self, prefix): ... + def startElement(self, name, attrs): ... + def endElement(self, name): ... + def startElementNS(self, name, qname, attrs): ... + def endElementNS(self, name, qname): ... + def characters(self, content): ... + def ignorableWhitespace(self, content): ... + def processingInstruction(self, target, data): ... + +class XMLFilterBase(xmlreader.XMLReader): + def __init__(self, parent: xmlreader.XMLReader | None = ...) -> None: ... + def error(self, exception): ... + def fatalError(self, exception): ... + def warning(self, exception): ... + def setDocumentLocator(self, locator): ... + def startDocument(self): ... + def endDocument(self): ... + def startPrefixMapping(self, prefix, uri): ... + def endPrefixMapping(self, prefix): ... + def startElement(self, name, attrs): ... + def endElement(self, name): ... + def startElementNS(self, name, qname, attrs): ... + def endElementNS(self, name, qname): ... + def characters(self, content): ... + def ignorableWhitespace(self, chars): ... + def processingInstruction(self, target, data): ... + def skippedEntity(self, name): ... + def notationDecl(self, name, publicId, systemId): ... + def unparsedEntityDecl(self, name, publicId, systemId, ndata): ... + def resolveEntity(self, publicId, systemId): ... + def parse(self, source): ... + def setLocale(self, locale): ... + def getFeature(self, name): ... + def setFeature(self, name, state): ... + def getProperty(self, name): ... + def setProperty(self, name, value): ... + def getParent(self): ... + def setParent(self, parent): ... + +def prepare_input_source(source, base=...): ... diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi new file mode 100644 index 000000000000..8afc566b16a1 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi @@ -0,0 +1,72 @@ +from typing import Mapping, Tuple + +class XMLReader: + def __init__(self) -> None: ... + def parse(self, source): ... + def getContentHandler(self): ... + def setContentHandler(self, handler): ... + def getDTDHandler(self): ... + def setDTDHandler(self, handler): ... + def getEntityResolver(self): ... + def setEntityResolver(self, resolver): ... + def getErrorHandler(self): ... + def setErrorHandler(self, handler): ... + def setLocale(self, locale): ... + def getFeature(self, name): ... + def setFeature(self, name, state): ... + def getProperty(self, name): ... + def setProperty(self, name, value): ... + +class IncrementalParser(XMLReader): + def __init__(self, bufsize: int = ...) -> None: ... + def parse(self, source): ... + def feed(self, data): ... + def prepareParser(self, source): ... + def close(self): ... + def reset(self): ... + +class Locator: + def getColumnNumber(self): ... + def getLineNumber(self): ... + def getPublicId(self): ... + def getSystemId(self): ... + +class InputSource: + def __init__(self, system_id: str | None = ...) -> None: ... + def setPublicId(self, public_id): ... + def getPublicId(self): ... + def setSystemId(self, system_id): ... + def getSystemId(self): ... + def setEncoding(self, encoding): ... + def getEncoding(self): ... + def setByteStream(self, bytefile): ... + def getByteStream(self): ... + def setCharacterStream(self, charfile): ... + def getCharacterStream(self): ... + +class AttributesImpl: + def __init__(self, attrs: Mapping[str, str]) -> None: ... + def getLength(self): ... + def getType(self, name): ... + def getValue(self, name): ... + def getValueByQName(self, name): ... + def getNameByQName(self, name): ... + def getQNameByName(self, name): ... + def getNames(self): ... + def getQNames(self): ... + def __len__(self): ... + def __getitem__(self, name): ... + def keys(self): ... + def __contains__(self, name): ... + def get(self, name, alternative=...): ... + def copy(self): ... + def items(self): ... + def values(self): ... + +class AttributesNSImpl(AttributesImpl): + def __init__(self, attrs: Mapping[Tuple[str, str], str], qnames: Mapping[Tuple[str, str], str]) -> None: ... + def getValueByQName(self, name): ... + def getNameByQName(self, name): ... + def getQNameByName(self, name): ... + def getQNames(self): ... + def copy(self): ... diff --git a/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi b/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi index 52e36b61a209..5a7d0fc34f0e 100644 --- a/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi +++ b/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi @@ -5,7 +5,7 @@ from ssl import SSLContext from StringIO import StringIO from time import struct_time from types import InstanceType -from typing import IO, Any, AnyStr, Callable, Iterable, List, Mapping, MutableMapping, Optional, Tuple, Type, TypeVar, Union +from typing import IO, Any, AnyStr, Callable, Iterable, List, Mapping, MutableMapping, Tuple, Type, Union _Unmarshaller = Any _timeTuple = Tuple[int, int, int, int, int, int, int, int, int] @@ -52,7 +52,7 @@ Boolean: Type[bool] class DateTime: value: str - def __init__(self, value: Union[str, unicode, datetime, float, int, _timeTuple, struct_time] = ...) -> None: ... + def __init__(self, value: str | unicode | datetime | float | int | _timeTuple | struct_time = ...) -> None: ... def make_comparable(self, other: _dateTimeComp) -> Tuple[unicode, unicode]: ... def __lt__(self, other: _dateTimeComp) -> bool: ... def __le__(self, other: _dateTimeComp) -> bool: ... @@ -67,7 +67,7 @@ class DateTime: class Binary: data: str - def __init__(self, data: Optional[str] = ...) -> None: ... + def __init__(self, data: str | None = ...) -> None: ... def __cmp__(self, other: Any) -> int: ... def decode(self, data: str) -> None: ... def encode(self, out: IO[str]) -> None: ... @@ -97,32 +97,28 @@ class SlowParser: class Marshaller: memo: MutableMapping[int, Any] - data: Optional[str] - encoding: Optional[str] + data: str | None + encoding: str | None allow_none: bool - def __init__(self, encoding: Optional[str] = ..., allow_none: bool = ...) -> None: ... + def __init__(self, encoding: str | None = ..., allow_none: bool = ...) -> None: ... dispatch: Mapping[type, Callable[[Marshaller, str, Callable[[str], None]], None]] def dumps( self, - values: Union[ - Iterable[ - Union[ - None, - int, - bool, - long, - float, - str, - unicode, - List[Any], - Tuple[Any, ...], - Mapping[Any, Any], - datetime, - InstanceType, - ] - ], - Fault, - ], + values: Iterable[ + None + | int + | bool + | long + | float + | str + | unicode + | List[Any] + | Tuple[Any, ...] + | Mapping[Any, Any] + | datetime + | InstanceType + ] + | Fault, ) -> str: ... def dump_nil(self, value: None, write: Callable[[str], None]) -> None: ... def dump_int(self, value: int, write: Callable[[str], None]) -> None: ... @@ -155,7 +151,7 @@ class Unmarshaller: def append(self, object: Any) -> None: ... def __init__(self, use_datetime: bool = ...) -> None: ... def close(self) -> Tuple[Any, ...]: ... - def getmethodname(self) -> Optional[str]: ... + def getmethodname(self) -> str | None: ... def xml(self, encoding: str, standalone: bool) -> None: ... def start(self, tag: str, attrs: Any) -> None: ... def data(self, text: str) -> None: ... @@ -187,15 +183,15 @@ class MultiCall: def __getattr__(self, name: str) -> _MultiCallMethod: ... def __call__(self) -> MultiCallIterator: ... -def getparser(use_datetime: bool = ...) -> Tuple[Union[ExpatParser, SlowParser], Unmarshaller]: ... +def getparser(use_datetime: bool = ...) -> Tuple[ExpatParser | SlowParser, Unmarshaller]: ... def dumps( - params: Union[Tuple[Any, ...], Fault], - methodname: Optional[str] = ..., - methodresponse: Optional[bool] = ..., - encoding: Optional[str] = ..., + params: Tuple[Any, ...] | Fault, + methodname: str | None = ..., + methodresponse: bool | None = ..., + encoding: str | None = ..., allow_none: bool = ..., ) -> str: ... -def loads(data: str, use_datetime: bool = ...) -> Tuple[Tuple[Any, ...], Optional[str]]: ... +def loads(data: str, use_datetime: bool = ...) -> Tuple[Tuple[Any, ...], str | None]: ... def gzip_encode(data: str) -> str: ... def gzip_decode(data: str, max_decode: int = ...) -> str: ... @@ -212,13 +208,13 @@ class _Method: class Transport: user_agent: str accept_gzip_encoding: bool - encode_threshold: Optional[int] + encode_threshold: int | None def __init__(self, use_datetime: bool = ...) -> None: ... def request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> Tuple[Any, ...]: ... verbose: bool def single_request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> Tuple[Any, ...]: ... - def getparser(self) -> Tuple[Union[ExpatParser, SlowParser], Unmarshaller]: ... - def get_host_info(self, host: _hostDesc) -> Tuple[str, Optional[List[Tuple[str, str]]], Optional[Mapping[Any, Any]]]: ... + def getparser(self) -> Tuple[ExpatParser | SlowParser, Unmarshaller]: ... + def get_host_info(self, host: _hostDesc) -> Tuple[str, List[Tuple[str, str]] | None, Mapping[Any, Any] | None]: ... def make_connection(self, host: _hostDesc) -> HTTPConnection: ... def close(self) -> None: ... def send_request(self, connection: HTTPConnection, handler: str, request_body: str) -> None: ... @@ -228,21 +224,21 @@ class Transport: def parse_response(self, response: HTTPResponse) -> Tuple[Any, ...]: ... class SafeTransport(Transport): - def __init__(self, use_datetime: bool = ..., context: Optional[SSLContext] = ...) -> None: ... + def __init__(self, use_datetime: bool = ..., context: SSLContext | None = ...) -> None: ... def make_connection(self, host: _hostDesc) -> HTTPSConnection: ... class ServerProxy: def __init__( self, uri: str, - transport: Optional[Transport] = ..., - encoding: Optional[str] = ..., + transport: Transport | None = ..., + encoding: str | None = ..., verbose: bool = ..., allow_none: bool = ..., use_datetime: bool = ..., - context: Optional[SSLContext] = ..., + context: SSLContext | None = ..., ) -> None: ... def __getattr__(self, name: str) -> _Method: ... - def __call__(self, attr: str) -> Optional[Transport]: ... + def __call__(self, attr: str) -> Transport | None: ... Server = ServerProxy diff --git a/mypy/typeshed/stdlib/@python2/zipfile.pyi b/mypy/typeshed/stdlib/@python2/zipfile.pyi new file mode 100644 index 000000000000..5a0879492a88 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/zipfile.pyi @@ -0,0 +1,101 @@ +import io +from _typeshed import StrPath +from types import TracebackType +from typing import IO, Any, Callable, Dict, Iterable, List, Pattern, Protocol, Sequence, Text, Tuple, Type, Union + +_SZI = Union[Text, ZipInfo] +_DT = Tuple[int, int, int, int, int, int] + +class BadZipfile(Exception): ... + +error = BadZipfile + +class LargeZipFile(Exception): ... + +class ZipExtFile(io.BufferedIOBase): + MAX_N: int = ... + MIN_READ_SIZE: int = ... + + PATTERN: Pattern[str] = ... + + newlines: List[bytes] | None + mode: str + name: str + def __init__( + self, + fileobj: IO[bytes], + mode: str, + zipinfo: ZipInfo, + decrypter: Callable[[Sequence[int]], bytes] | None = ..., + close_fileobj: bool = ..., + ) -> None: ... + def read(self, n: int | None = ...) -> bytes: ... + def readline(self, limit: int = ...) -> bytes: ... # type: ignore + def __repr__(self) -> str: ... + def peek(self, n: int = ...) -> bytes: ... + def read1(self, n: int | None) -> bytes: ... # type: ignore + +class _Writer(Protocol): + def write(self, __s: str) -> Any: ... + +class ZipFile: + filename: Text | None + debug: int + comment: bytes + filelist: List[ZipInfo] + fp: IO[bytes] | None + NameToInfo: Dict[Text, ZipInfo] + start_dir: int # undocumented + def __init__(self, file: StrPath | IO[bytes], mode: Text = ..., compression: int = ..., allowZip64: bool = ...) -> None: ... + def __enter__(self) -> ZipFile: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + def close(self) -> None: ... + def getinfo(self, name: Text) -> ZipInfo: ... + def infolist(self) -> List[ZipInfo]: ... + def namelist(self) -> List[Text]: ... + def open(self, name: _SZI, mode: Text = ..., pwd: bytes | None = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... + def extract(self, member: _SZI, path: StrPath | None = ..., pwd: bytes | None = ...) -> str: ... + def extractall(self, path: StrPath | None = ..., members: Iterable[Text] | None = ..., pwd: bytes | None = ...) -> None: ... + def printdir(self) -> None: ... + def setpassword(self, pwd: bytes) -> None: ... + def read(self, name: _SZI, pwd: bytes | None = ...) -> bytes: ... + def testzip(self) -> str | None: ... + def write(self, filename: StrPath, arcname: StrPath | None = ..., compress_type: int | None = ...) -> None: ... + def writestr(self, zinfo_or_arcname: _SZI, bytes: bytes, compress_type: int | None = ...) -> None: ... + +class PyZipFile(ZipFile): + def writepy(self, pathname: Text, basename: Text = ...) -> None: ... + +class ZipInfo: + filename: Text + date_time: _DT + compress_type: int + comment: bytes + extra: bytes + create_system: int + create_version: int + extract_version: int + reserved: int + flag_bits: int + volume: int + internal_attr: int + external_attr: int + header_offset: int + CRC: int + compress_size: int + file_size: int + def __init__(self, filename: Text | None = ..., date_time: _DT | None = ...) -> None: ... + def FileHeader(self, zip64: bool | None = ...) -> bytes: ... + +class _PathOpenProtocol(Protocol): + def __call__(self, mode: str = ..., pwd: bytes | None = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... + +def is_zipfile(filename: StrPath | IO[bytes]) -> bool: ... + +ZIP_STORED: int +ZIP_DEFLATED: int +ZIP64_LIMIT: int +ZIP_FILECOUNT_LIMIT: int +ZIP_MAX_COMMENT: int diff --git a/mypy/typeshed/stdlib/@python2/zipimport.pyi b/mypy/typeshed/stdlib/@python2/zipimport.pyi new file mode 100644 index 000000000000..bcefd6859059 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/zipimport.pyi @@ -0,0 +1,15 @@ +from types import CodeType, ModuleType + +class ZipImportError(ImportError): ... + +class zipimporter(object): + archive: str + prefix: str + def __init__(self, path: str | bytes) -> None: ... + def find_module(self, fullname: str, path: str | None = ...) -> zipimporter | None: ... + def get_code(self, fullname: str) -> CodeType: ... + def get_data(self, pathname: str) -> str: ... + def get_filename(self, fullname: str) -> str: ... + def get_source(self, fullname: str) -> str | None: ... + def is_package(self, fullname: str) -> bool: ... + def load_module(self, fullname: str) -> ModuleType: ... diff --git a/mypy/typeshed/stdlib/@python2/zlib.pyi b/mypy/typeshed/stdlib/@python2/zlib.pyi new file mode 100644 index 000000000000..2cee20fc0928 --- /dev/null +++ b/mypy/typeshed/stdlib/@python2/zlib.pyi @@ -0,0 +1,40 @@ +from array import array +from typing import Any + +DEFLATED: int +DEF_MEM_LEVEL: int +MAX_WBITS: int +ZLIB_VERSION: str +Z_BEST_COMPRESSION: int +Z_BEST_SPEED: int +Z_DEFAULT_COMPRESSION: int +Z_DEFAULT_STRATEGY: int +Z_FILTERED: int +Z_FINISH: int +Z_FIXED: int +Z_FULL_FLUSH: int +Z_HUFFMAN_ONLY: int +Z_NO_FLUSH: int +Z_RLE: int +Z_SYNC_FLUSH: int + +class error(Exception): ... + +class _Compress: + def compress(self, data: bytes) -> bytes: ... + def flush(self, mode: int = ...) -> bytes: ... + def copy(self) -> _Compress: ... + +class _Decompress: + unused_data: bytes + unconsumed_tail: bytes + def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... + def flush(self, length: int = ...) -> bytes: ... + def copy(self) -> _Decompress: ... + +def adler32(__data: bytes, __value: int = ...) -> int: ... +def compress(__data: bytes, level: int = ...) -> bytes: ... +def compressobj(level: int = ..., method: int = ..., wbits: int = ..., memlevel: int = ..., strategy: int = ...) -> _Compress: ... +def crc32(__data: array[Any] | bytes, __value: int = ...) -> int: ... +def decompress(__data: bytes, wbits: int = ..., bufsize: int = ...) -> bytes: ... +def decompressobj(wbits: int = ...) -> _Decompress: ... diff --git a/mypy/typeshed/stdlib/VERSIONS b/mypy/typeshed/stdlib/VERSIONS index 11219357c638..9b9271117fa7 100644 --- a/mypy/typeshed/stdlib/VERSIONS +++ b/mypy/typeshed/stdlib/VERSIONS @@ -1,6 +1,6 @@ # The structure of this file is as follows: -# - Blank lines and lines starting with `#` are ignored. -# - Lines contain the name of a top-level module, followed by a colon, +# - Blank lines and comments starting with `#` are ignored. +# - Lines contain the name of a module, followed by a colon, # a space, and a version range (for example: `symbol: 2.7-3.9`). # # Version ranges may be of the form "X.Y-A.B" or "X.Y-". The @@ -9,6 +9,9 @@ # introduced in version X.Y and is still available in the latest # version of Python. # +# If a submodule is not listed separately, it has the same lifetime as +# its parent module. +# # Python versions before 2.7 are ignored, so any module that was already # present in 2.7 will have "2.7" as its minimum version. Version ranges # for unsupported versions of Python 3 (currently 3.5 and lower) are @@ -20,7 +23,7 @@ _ast: 2.7- _bisect: 2.7- _bootlocale: 3.6-3.9 _codecs: 2.7- -_collections_abc: 3.6- +_collections_abc: 3.3- _compat_pickle: 3.6- _compression: 3.6- _csv: 2.7- @@ -40,12 +43,13 @@ _py_abc: 3.7- _pydecimal: 3.6- _random: 2.7- _sitebuiltins: 3.6- +_socket: 3.0- # present in 2.7 at runtime, but not in typeshed _stat: 3.6- _thread: 2.7- _threading_local: 3.6- _tkinter: 2.7- _tracemalloc: 3.6- -_typeshed: 2.7- +_typeshed: 2.7- # not present at runtime, only for type checking _warnings: 2.7- _weakref: 2.7- _weakrefset: 2.7- @@ -64,7 +68,7 @@ audioop: 2.7- base64: 2.7- bdb: 2.7- binascii: 2.7- -binhex: 2.7- +binhex: 2.7-3.10 bisect: 2.7- builtins: 3.0- bz2: 2.7- @@ -79,6 +83,7 @@ code: 2.7- codecs: 2.7- codeop: 2.7- collections: 2.7- +collections.abc: 3.3- colorsys: 2.7- compileall: 2.7- concurrent: 3.2- @@ -126,15 +131,17 @@ gzip: 2.7- hashlib: 2.7- heapq: 2.7- hmac: 2.7- -html: 2.7- +html: 3.0- http: 3.0- imaplib: 2.7- imghdr: 2.7- imp: 2.7- importlib: 2.7- +importlib.metadata: 3.8- +importlib.resources: 3.7- inspect: 2.7- io: 2.7- -ipaddress: 2.7- +ipaddress: 3.3- itertools: 2.7- json: 2.7- keyword: 2.7- @@ -188,12 +195,12 @@ pyclbr: 2.7- pydoc: 2.7- pydoc_data: 2.7- pyexpat: 2.7- -queue: 2.7- +queue: 3.0- quopri: 2.7- random: 2.7- re: 2.7- readline: 2.7- -reprlib: 2.7- +reprlib: 3.0- resource: 2.7- rlcompleter: 2.7- runpy: 2.7- @@ -210,7 +217,7 @@ smtpd: 2.7- smtplib: 2.7- sndhdr: 2.7- socket: 2.7- -socketserver: 2.7- +socketserver: 3.0- spwd: 2.7- sqlite3: 2.7- sre_compile: 2.7- @@ -260,7 +267,7 @@ warnings: 2.7- wave: 2.7- weakref: 2.7- webbrowser: 2.7- -winreg: 2.7- +winreg: 3.0- winsound: 2.7- wsgiref: 2.7- xdrlib: 2.7- diff --git a/mypy/typeshed/stdlib/__future__.pyi b/mypy/typeshed/stdlib/__future__.pyi index 8a5035271eec..1a465c3e213d 100644 --- a/mypy/typeshed/stdlib/__future__.pyi +++ b/mypy/typeshed/stdlib/__future__.pyi @@ -1,5 +1,4 @@ import sys -from typing import List class _Feature: def __init__(self, optionalRelease: sys._version_info, mandatoryRelease: sys._version_info, compiler_flag: int) -> None: ... @@ -14,13 +13,38 @@ nested_scopes: _Feature print_function: _Feature unicode_literals: _Feature with_statement: _Feature -if sys.version_info >= (3, 0): - barry_as_FLUFL: _Feature - -if sys.version_info >= (3, 5): - generator_stop: _Feature +barry_as_FLUFL: _Feature +generator_stop: _Feature if sys.version_info >= (3, 7): annotations: _Feature -all_feature_names: List[str] # undocumented +all_feature_names: list[str] # undocumented + +if sys.version_info >= (3, 7): + __all__ = [ + "all_feature_names", + "absolute_import", + "division", + "generators", + "nested_scopes", + "print_function", + "unicode_literals", + "with_statement", + "barry_as_FLUFL", + "generator_stop", + "annotations", + ] +else: + __all__ = [ + "all_feature_names", + "absolute_import", + "division", + "generators", + "nested_scopes", + "print_function", + "unicode_literals", + "with_statement", + "barry_as_FLUFL", + "generator_stop", + ] diff --git a/mypy/typeshed/stdlib/_ast.pyi b/mypy/typeshed/stdlib/_ast.pyi index 2d0d92d83032..08725cfc0b77 100644 --- a/mypy/typeshed/stdlib/_ast.pyi +++ b/mypy/typeshed/stdlib/_ast.pyi @@ -1,6 +1,7 @@ import sys import typing -from typing import Any, ClassVar, Optional +from typing import Any, ClassVar +from typing_extensions import Literal PyCF_ONLY_AST: int if sys.version_info >= (3, 8): @@ -17,9 +18,9 @@ class AST: lineno: int col_offset: int if sys.version_info >= (3, 8): - end_lineno: Optional[int] - end_col_offset: Optional[int] - type_comment: Optional[str] + end_lineno: int | None + end_col_offset: int | None + type_comment: str | None class mod(AST): ... @@ -28,16 +29,16 @@ if sys.version_info >= (3, 8): class TypeIgnore(type_ignore): tag: str class FunctionType(mod): - argtypes: typing.List[expr] + argtypes: list[expr] returns: expr class Module(mod): - body: typing.List[stmt] + body: list[stmt] if sys.version_info >= (3, 8): - type_ignores: typing.List[TypeIgnore] + type_ignores: list[TypeIgnore] class Interactive(mod): - body: typing.List[stmt] + body: list[stmt] class Expression(mod): body: expr @@ -47,32 +48,32 @@ class stmt(AST): ... class FunctionDef(stmt): name: _identifier args: arguments - body: typing.List[stmt] - decorator_list: typing.List[expr] - returns: Optional[expr] + body: list[stmt] + decorator_list: list[expr] + returns: expr | None class AsyncFunctionDef(stmt): name: _identifier args: arguments - body: typing.List[stmt] - decorator_list: typing.List[expr] - returns: Optional[expr] + body: list[stmt] + decorator_list: list[expr] + returns: expr | None class ClassDef(stmt): name: _identifier - bases: typing.List[expr] - keywords: typing.List[keyword] - body: typing.List[stmt] - decorator_list: typing.List[expr] + bases: list[expr] + keywords: list[keyword] + body: list[stmt] + decorator_list: list[expr] class Return(stmt): - value: Optional[expr] + value: expr | None class Delete(stmt): - targets: typing.List[expr] + targets: list[expr] class Assign(stmt): - targets: typing.List[expr] + targets: list[expr] value: expr class AugAssign(stmt): @@ -83,66 +84,66 @@ class AugAssign(stmt): class AnnAssign(stmt): target: expr annotation: expr - value: Optional[expr] + value: expr | None simple: int class For(stmt): target: expr iter: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class AsyncFor(stmt): target: expr iter: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class While(stmt): test: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class If(stmt): test: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class With(stmt): - items: typing.List[withitem] - body: typing.List[stmt] + items: list[withitem] + body: list[stmt] class AsyncWith(stmt): - items: typing.List[withitem] - body: typing.List[stmt] + items: list[withitem] + body: list[stmt] class Raise(stmt): - exc: Optional[expr] - cause: Optional[expr] + exc: expr | None + cause: expr | None class Try(stmt): - body: typing.List[stmt] - handlers: typing.List[ExceptHandler] - orelse: typing.List[stmt] - finalbody: typing.List[stmt] + body: list[stmt] + handlers: list[ExceptHandler] + orelse: list[stmt] + finalbody: list[stmt] class Assert(stmt): test: expr - msg: Optional[expr] + msg: expr | None class Import(stmt): - names: typing.List[alias] + names: list[alias] class ImportFrom(stmt): - module: Optional[_identifier] - names: typing.List[alias] + module: _identifier | None + names: list[alias] level: int class Global(stmt): - names: typing.List[_identifier] + names: list[_identifier] class Nonlocal(stmt): - names: typing.List[_identifier] + names: list[_identifier] class Expr(stmt): value: expr @@ -154,7 +155,7 @@ class expr(AST): ... class BoolOp(expr): op: boolop - values: typing.List[expr] + values: list[expr] class BinOp(expr): left: expr @@ -175,55 +176,55 @@ class IfExp(expr): orelse: expr class Dict(expr): - keys: typing.List[Optional[expr]] - values: typing.List[expr] + keys: list[expr | None] + values: list[expr] class Set(expr): - elts: typing.List[expr] + elts: list[expr] class ListComp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class SetComp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class DictComp(expr): key: expr value: expr - generators: typing.List[comprehension] + generators: list[comprehension] class GeneratorExp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class Await(expr): value: expr class Yield(expr): - value: Optional[expr] + value: expr | None class YieldFrom(expr): value: expr class Compare(expr): left: expr - ops: typing.List[cmpop] - comparators: typing.List[expr] + ops: list[cmpop] + comparators: list[expr] class Call(expr): func: expr - args: typing.List[expr] - keywords: typing.List[keyword] + args: list[expr] + keywords: list[keyword] class FormattedValue(expr): value: expr - conversion: Optional[int] - format_spec: Optional[expr] + conversion: int | None + format_spec: expr | None class JoinedStr(expr): - values: typing.List[expr] + values: list[expr] if sys.version_info < (3, 8): class Num(expr): # Deprecated in 3.8; use Constant @@ -238,7 +239,7 @@ if sys.version_info < (3, 8): class Constant(expr): value: Any # None, str, bytes, bool, int, float, complex, Ellipsis - kind: Optional[str] + kind: str | None # Aliases for value, for backwards compatibility s: Any n: complex @@ -260,13 +261,13 @@ else: _SliceT = slice class Slice(_SliceT): - lower: Optional[expr] - upper: Optional[expr] - step: Optional[expr] + lower: expr | None + upper: expr | None + step: expr | None if sys.version_info < (3, 9): class ExtSlice(slice): - dims: typing.List[slice] + dims: list[slice] class Index(slice): value: expr @@ -284,11 +285,11 @@ class Name(expr): ctx: expr_context class List(expr): - elts: typing.List[expr] + elts: list[expr] ctx: expr_context class Tuple(expr): - elts: typing.List[expr] + elts: list[expr] ctx: expr_context class expr_context(AST): ... @@ -298,7 +299,7 @@ if sys.version_info < (3, 9): class AugStore(expr_context): ... class Param(expr_context): ... class Suite(mod): - body: typing.List[stmt] + body: list[stmt] class Del(expr_context): ... class Load(expr_context): ... @@ -340,72 +341,72 @@ class NotIn(cmpop): ... class comprehension(AST): target: expr iter: expr - ifs: typing.List[expr] + ifs: list[expr] is_async: int class excepthandler(AST): ... class ExceptHandler(excepthandler): - type: Optional[expr] - name: Optional[_identifier] - body: typing.List[stmt] + type: expr | None + name: _identifier | None + body: list[stmt] class arguments(AST): if sys.version_info >= (3, 8): - posonlyargs: typing.List[arg] - args: typing.List[arg] - vararg: Optional[arg] - kwonlyargs: typing.List[arg] - kw_defaults: typing.List[Optional[expr]] - kwarg: Optional[arg] - defaults: typing.List[expr] + posonlyargs: list[arg] + args: list[arg] + vararg: arg | None + kwonlyargs: list[arg] + kw_defaults: list[expr | None] + kwarg: arg | None + defaults: list[expr] class arg(AST): arg: _identifier - annotation: Optional[expr] + annotation: expr | None class keyword(AST): - arg: Optional[_identifier] + arg: _identifier | None value: expr class alias(AST): name: _identifier - asname: Optional[_identifier] + asname: _identifier | None class withitem(AST): context_expr: expr - optional_vars: Optional[expr] + optional_vars: expr | None if sys.version_info >= (3, 10): class Match(stmt): subject: expr - cases: typing.List[match_case] + cases: list[match_case] class pattern(AST): ... # Without the alias, Pyright complains variables named pattern are recursively defined _pattern = pattern class match_case(AST): pattern: _pattern - guard: Optional[expr] - body: typing.List[stmt] + guard: expr | None + body: list[stmt] class MatchValue(pattern): value: expr class MatchSingleton(pattern): - value: Optional[bool] + value: Literal[True, False, None] class MatchSequence(pattern): - patterns: typing.List[pattern] + patterns: list[pattern] class MatchStar(pattern): - name: Optional[_identifier] + name: _identifier | None class MatchMapping(pattern): - keys: typing.List[expr] - patterns: typing.List[pattern] - rest: Optional[_identifier] + keys: list[expr] + patterns: list[pattern] + rest: _identifier | None class MatchClass(pattern): cls: expr - patterns: typing.List[pattern] - kwd_attrs: typing.List[_identifier] - kwd_patterns: typing.List[pattern] + patterns: list[pattern] + kwd_attrs: list[_identifier] + kwd_patterns: list[pattern] class MatchAs(pattern): - pattern: Optional[_pattern] - name: Optional[_identifier] + pattern: _pattern | None + name: _identifier | None class MatchOr(pattern): - patterns: typing.List[pattern] + patterns: list[pattern] diff --git a/mypy/typeshed/stdlib/_bisect.pyi b/mypy/typeshed/stdlib/_bisect.pyi index 3ca863a2e939..6da6e7f58823 100644 --- a/mypy/typeshed/stdlib/_bisect.pyi +++ b/mypy/typeshed/stdlib/_bisect.pyi @@ -1,35 +1,25 @@ import sys from _typeshed import SupportsLessThan -from typing import Callable, MutableSequence, Optional, Sequence, TypeVar +from typing import Callable, MutableSequence, Sequence, TypeVar _T = TypeVar("_T") if sys.version_info >= (3, 10): def bisect_left( - a: Sequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ..., *, key: Optional[Callable[[_T], SupportsLessThan]] = ... + a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... ) -> int: ... def bisect_right( - a: Sequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ..., *, key: Optional[Callable[[_T], SupportsLessThan]] = ... + a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... ) -> int: ... def insort_left( - a: MutableSequence[_T], - x: _T, - lo: int = ..., - hi: Optional[int] = ..., - *, - key: Optional[Callable[[_T], SupportsLessThan]] = ..., + a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... ) -> None: ... def insort_right( - a: MutableSequence[_T], - x: _T, - lo: int = ..., - hi: Optional[int] = ..., - *, - key: Optional[Callable[[_T], SupportsLessThan]] = ..., + a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... ) -> None: ... else: - def bisect_left(a: Sequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ...) -> int: ... - def bisect_right(a: Sequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ...) -> int: ... - def insort_left(a: MutableSequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ...) -> None: ... - def insort_right(a: MutableSequence[_T], x: _T, lo: int = ..., hi: Optional[int] = ...) -> None: ... + def bisect_left(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... + def bisect_right(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... + def insort_left(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... + def insort_right(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/_codecs.pyi b/mypy/typeshed/stdlib/_codecs.pyi index fbb014aadbfb..5e4a9ad6da3d 100644 --- a/mypy/typeshed/stdlib/_codecs.pyi +++ b/mypy/typeshed/stdlib/_codecs.pyi @@ -1,82 +1,66 @@ import codecs import sys -from typing import Any, Callable, Dict, Optional, Text, Tuple, Union - -# For convenience: -_Handler = Callable[[Exception], Tuple[Text, int]] -_String = Union[bytes, str] -_Errors = Union[str, Text, None] -if sys.version_info >= (3, 0): - _Decodable = bytes - _Encodable = str -else: - _Decodable = Union[bytes, Text] - _Encodable = Union[bytes, Text] +from typing import Any, Callable, Dict, Tuple, Union # This type is not exposed; it is defined in unicodeobject.c -class _EncodingMap(object): +class _EncodingMap: def size(self) -> int: ... _MapT = Union[Dict[int, int], _EncodingMap] +_Handler = Callable[[Exception], Tuple[str, int]] def register(__search_function: Callable[[str], Any]) -> None: ... -def register_error(__errors: Union[str, Text], __handler: _Handler) -> None: ... -def lookup(__encoding: Union[str, Text]) -> codecs.CodecInfo: ... -def lookup_error(__name: Union[str, Text]) -> _Handler: ... -def decode(obj: Any, encoding: Union[str, Text] = ..., errors: _Errors = ...) -> Any: ... -def encode(obj: Any, encoding: Union[str, Text] = ..., errors: _Errors = ...) -> Any: ... -def charmap_build(__map: Text) -> _MapT: ... -def ascii_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def ascii_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... - -if sys.version_info < (3, 2): - def charbuffer_encode(__data: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... - -def charmap_decode(__data: _Decodable, __errors: _Errors = ..., __mapping: Optional[_MapT] = ...) -> Tuple[Text, int]: ... -def charmap_encode(__str: _Encodable, __errors: _Errors = ..., __mapping: Optional[_MapT] = ...) -> Tuple[bytes, int]: ... -def escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[str, int]: ... -def escape_encode(__data: bytes, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def latin_1_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def latin_1_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def raw_unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def raw_unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def readbuffer_encode(__data: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +def register_error(__errors: str, __handler: _Handler) -> None: ... +def lookup(__encoding: str) -> codecs.CodecInfo: ... +def lookup_error(__name: str) -> _Handler: ... +def decode(obj: Any, encoding: str = ..., errors: str | None = ...) -> Any: ... +def encode(obj: Any, encoding: str = ..., errors: str | None = ...) -> Any: ... +def charmap_build(__map: str) -> _MapT: ... +def ascii_decode(__data: bytes, __errors: str | None = ...) -> tuple[str, int]: ... +def ascii_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def charmap_decode(__data: bytes, __errors: str | None = ..., __mapping: _MapT | None = ...) -> tuple[str, int]: ... +def charmap_encode(__str: str, __errors: str | None = ..., __mapping: _MapT | None = ...) -> tuple[bytes, int]: ... +def escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... +def escape_encode(__data: bytes, __errors: str | None = ...) -> tuple[bytes, int]: ... +def latin_1_decode(__data: bytes, __errors: str | None = ...) -> tuple[str, int]: ... +def latin_1_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def raw_unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... +def raw_unicode_escape_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def readbuffer_encode(__data: str | bytes, __errors: str | None = ...) -> tuple[bytes, int]: ... +def unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... +def unicode_escape_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... if sys.version_info < (3, 8): - def unicode_internal_decode(__obj: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... - def unicode_internal_encode(__obj: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... + def unicode_internal_decode(__obj: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... + def unicode_internal_encode(__obj: str | bytes, __errors: str | None = ...) -> tuple[bytes, int]: ... -def utf_16_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_16_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... +def utf_16_be_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_16_be_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def utf_16_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_16_encode(__str: str, __errors: str | None = ..., __byteorder: int = ...) -> tuple[bytes, int]: ... def utf_16_ex_decode( - __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... -) -> Tuple[Text, int, int]: ... -def utf_16_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_32_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_32_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... + __data: bytes, __errors: str | None = ..., __byteorder: int = ..., __final: int = ... +) -> tuple[str, int, int]: ... +def utf_16_le_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_16_le_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def utf_32_be_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_32_be_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def utf_32_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_32_encode(__str: str, __errors: str | None = ..., __byteorder: int = ...) -> tuple[bytes, int]: ... def utf_32_ex_decode( - __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... -) -> Tuple[Text, int, int]: ... -def utf_32_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_7_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_7_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_8_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_8_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... + __data: bytes, __errors: str | None = ..., __byteorder: int = ..., __final: int = ... +) -> tuple[str, int, int]: ... +def utf_32_le_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_32_le_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def utf_7_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_7_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def utf_8_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... +def utf_8_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... if sys.platform == "win32": - def mbcs_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... - def mbcs_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... - if sys.version_info >= (3, 0): - def code_page_decode(__codepage: int, __data: bytes, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... - def code_page_encode(__code_page: int, __str: Text, __errors: _Errors = ...) -> Tuple[bytes, int]: ... - if sys.version_info >= (3, 6): - def oem_decode(__data: bytes, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... - def oem_encode(__str: Text, __errors: _Errors = ...) -> Tuple[bytes, int]: ... + def mbcs_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... + def mbcs_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... + def code_page_decode(__codepage: int, __data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... + def code_page_encode(__code_page: int, __str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... + def oem_decode(__data: bytes, __errors: str | None = ..., __final: int = ...) -> tuple[str, int]: ... + def oem_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... diff --git a/mypy/typeshed/stdlib/_collections_abc.pyi b/mypy/typeshed/stdlib/_collections_abc.pyi index 27d5234432f3..223b5fb8d62e 100644 --- a/mypy/typeshed/stdlib/_collections_abc.pyi +++ b/mypy/typeshed/stdlib/_collections_abc.pyi @@ -1,3 +1,5 @@ +import sys +from types import MappingProxyType from typing import ( AbstractSet as Set, AsyncGenerator as AsyncGenerator, @@ -10,6 +12,7 @@ from typing import ( Container as Container, Coroutine as Coroutine, Generator as Generator, + Generic, Hashable as Hashable, ItemsView as ItemsView, Iterable as Iterable, @@ -23,8 +26,10 @@ from typing import ( Reversible as Reversible, Sequence as Sequence, Sized as Sized, + TypeVar, ValuesView as ValuesView, ) +from typing_extensions import final __all__ = [ "Awaitable", @@ -53,3 +58,21 @@ __all__ = [ "MutableSequence", "ByteString", ] + +_KT_co = TypeVar("_KT_co", covariant=True) # Key type covariant containers. +_VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers. + +@final +class dict_keys(KeysView[_KT_co], Generic[_KT_co, _VT_co]): # undocumented + if sys.version_info >= (3, 10): + mapping: MappingProxyType[_KT_co, _VT_co] + +@final +class dict_values(ValuesView[_VT_co], Generic[_KT_co, _VT_co]): # undocumented + if sys.version_info >= (3, 10): + mapping: MappingProxyType[_KT_co, _VT_co] + +@final +class dict_items(ItemsView[_KT_co, _VT_co], Generic[_KT_co, _VT_co]): # undocumented + if sys.version_info >= (3, 10): + mapping: MappingProxyType[_KT_co, _VT_co] diff --git a/mypy/typeshed/stdlib/_compat_pickle.pyi b/mypy/typeshed/stdlib/_compat_pickle.pyi index 5be4c9b9d829..76aba3020321 100644 --- a/mypy/typeshed/stdlib/_compat_pickle.pyi +++ b/mypy/typeshed/stdlib/_compat_pickle.pyi @@ -1,10 +1,10 @@ -from typing import Dict, Tuple +from typing import Tuple -IMPORT_MAPPING: Dict[str, str] -NAME_MAPPING: Dict[Tuple[str, str], Tuple[str, str]] +IMPORT_MAPPING: dict[str, str] +NAME_MAPPING: dict[tuple[str, str], tuple[str, str]] PYTHON2_EXCEPTIONS: Tuple[str, ...] MULTIPROCESSING_EXCEPTIONS: Tuple[str, ...] -REVERSE_IMPORT_MAPPING: Dict[str, str] -REVERSE_NAME_MAPPING: Dict[Tuple[str, str], Tuple[str, str]] +REVERSE_IMPORT_MAPPING: dict[str, str] +REVERSE_NAME_MAPPING: dict[tuple[str, str], tuple[str, str]] PYTHON3_OSERROR_EXCEPTIONS: Tuple[str, ...] PYTHON3_IMPORTERROR_EXCEPTIONS: Tuple[str, ...] diff --git a/mypy/typeshed/stdlib/_compression.pyi b/mypy/typeshed/stdlib/_compression.pyi index 6cbf5e9ffdff..8f81847ff492 100644 --- a/mypy/typeshed/stdlib/_compression.pyi +++ b/mypy/typeshed/stdlib/_compression.pyi @@ -1,6 +1,6 @@ from _typeshed import WriteableBuffer from io import BufferedIOBase, RawIOBase -from typing import Any, Callable, Protocol, Tuple, Type, Union +from typing import Any, Callable, Protocol, Tuple, Type BUFFER_SIZE: Any @@ -16,7 +16,7 @@ class DecompressReader(RawIOBase): self, fp: _Reader, decomp_factory: Callable[..., object], - trailing_error: Union[Type[Exception], Tuple[Type[Exception], ...]] = ..., + trailing_error: Type[Exception] | Tuple[Type[Exception], ...] = ..., **decomp_args: Any, ) -> None: ... def readable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/_csv.pyi b/mypy/typeshed/stdlib/_csv.pyi index 2b4b1a743865..1dc43780f687 100644 --- a/mypy/typeshed/stdlib/_csv.pyi +++ b/mypy/typeshed/stdlib/_csv.pyi @@ -1,5 +1,4 @@ -import sys -from typing import Any, Iterable, Iterator, List, Optional, Protocol, Sequence, Text, Type, Union +from typing import Any, Iterable, Iterator, List, Protocol, Type, Union QUOTE_ALL: int QUOTE_MINIMAL: int @@ -10,8 +9,8 @@ class Error(Exception): ... class Dialect: delimiter: str - quotechar: Optional[str] - escapechar: Optional[str] + quotechar: str | None + escapechar: str | None doublequote: bool skipinitialspace: bool lineterminator: str @@ -24,28 +23,20 @@ _DialectLike = Union[str, Dialect, Type[Dialect]] class _reader(Iterator[List[str]]): dialect: Dialect line_num: int - if sys.version_info >= (3, 0): - def __next__(self) -> List[str]: ... - else: - def next(self) -> List[str]: ... + def __next__(self) -> list[str]: ... class _writer: dialect: Dialect - - if sys.version_info >= (3, 5): - def writerow(self, row: Iterable[Any]) -> Any: ... - def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ... - else: - def writerow(self, row: Sequence[Any]) -> Any: ... - def writerows(self, rows: Iterable[Sequence[Any]]) -> None: ... + def writerow(self, row: Iterable[Any]) -> Any: ... + def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ... class _Writer(Protocol): def write(self, s: str) -> Any: ... def writer(csvfile: _Writer, dialect: _DialectLike = ..., **fmtparams: Any) -> _writer: ... -def reader(csvfile: Iterable[Text], dialect: _DialectLike = ..., **fmtparams: Any) -> _reader: ... +def reader(csvfile: Iterable[str], dialect: _DialectLike = ..., **fmtparams: Any) -> _reader: ... def register_dialect(name: str, dialect: Any = ..., **fmtparams: Any) -> None: ... def unregister_dialect(name: str) -> None: ... def get_dialect(name: str) -> Dialect: ... -def list_dialects() -> List[str]: ... +def list_dialects() -> list[str]: ... def field_size_limit(new_limit: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/_curses.pyi b/mypy/typeshed/stdlib/_curses.pyi index 1ccd54e35edd..d2eb1e1a4efb 100644 --- a/mypy/typeshed/stdlib/_curses.pyi +++ b/mypy/typeshed/stdlib/_curses.pyi @@ -1,5 +1,6 @@ import sys -from typing import IO, Any, BinaryIO, NamedTuple, Optional, Tuple, Union, overload +from _typeshed import SupportsRead +from typing import IO, Any, NamedTuple, Union, overload _chtype = Union[str, bytes, int] @@ -89,6 +90,13 @@ BUTTON4_DOUBLE_CLICKED: int BUTTON4_PRESSED: int BUTTON4_RELEASED: int BUTTON4_TRIPLE_CLICKED: int +# Darwin ncurses doesn't provide BUTTON5_* constants +if sys.version_info >= (3, 10) and sys.platform != "darwin": + BUTTON5_PRESSED: int + BUTTON5_RELEASED: int + BUTTON5_CLICKED: int + BUTTON5_DOUBLE_CLICKED: int + BUTTON5_TRIPLE_CLICKED: int BUTTON_ALT: int BUTTON_CTRL: int BUTTON_SHIFT: int @@ -266,7 +274,7 @@ def baudrate() -> int: ... def beep() -> None: ... def can_change_color() -> bool: ... def cbreak(__flag: bool = ...) -> None: ... -def color_content(__color_number: int) -> Tuple[int, int, int]: ... +def color_content(__color_number: int) -> tuple[int, int, int]: ... # Changed in Python 3.8.8 and 3.9.2 if sys.version_info >= (3, 8): @@ -286,11 +294,20 @@ def erasechar() -> bytes: ... def filter() -> None: ... def flash() -> None: ... def flushinp() -> None: ... -def getmouse() -> Tuple[int, int, int, int, int]: ... -def getsyx() -> Tuple[int, int]: ... -def getwin(__file: BinaryIO) -> _CursesWindow: ... + +if sys.version_info >= (3, 9): + def get_escdelay() -> int: ... + def get_tabsize() -> int: ... + +def getmouse() -> tuple[int, int, int, int, int]: ... +def getsyx() -> tuple[int, int]: ... +def getwin(__file: SupportsRead[bytes]) -> _CursesWindow: ... def halfdelay(__tenths: int) -> None: ... def has_colors() -> bool: ... + +if sys.version_info >= (3, 10): + def has_extended_color_support() -> bool: ... + def has_ic() -> bool: ... def has_il() -> bool: ... def has_key(__key: int) -> bool: ... @@ -305,7 +322,7 @@ def killchar() -> bytes: ... def longname() -> bytes: ... def meta(__yes: bool) -> None: ... def mouseinterval(__interval: int) -> None: ... -def mousemask(__newmask: int) -> Tuple[int, int]: ... +def mousemask(__newmask: int) -> tuple[int, int]: ... def napms(__ms: int) -> int: ... def newpad(__nlines: int, __ncols: int) -> _CursesWindow: ... def newwin(__nlines: int, __ncols: int, __begin_y: int = ..., __begin_x: int = ...) -> _CursesWindow: ... @@ -315,7 +332,7 @@ def noecho() -> None: ... def nonl() -> None: ... def noqiflush() -> None: ... def noraw() -> None: ... -def pair_content(__pair_number: int) -> Tuple[int, int]: ... +def pair_content(__pair_number: int) -> tuple[int, int]: ... def pair_number(__attr: int) -> int: ... def putp(__string: bytes) -> None: ... def qiflush(__flag: bool = ...) -> None: ... @@ -326,14 +343,19 @@ def resetty() -> None: ... def resize_term(__nlines: int, __ncols: int) -> None: ... def resizeterm(__nlines: int, __ncols: int) -> None: ... def savetty() -> None: ... + +if sys.version_info >= (3, 9): + def set_escdelay(__ms: int) -> None: ... + def set_tabsize(__size: int) -> None: ... + def setsyx(__y: int, __x: int) -> None: ... -def setupterm(term: Optional[str] = ..., fd: int = ...) -> None: ... +def setupterm(term: str | None = ..., fd: int = ...) -> None: ... def start_color() -> None: ... def termattrs() -> int: ... def termname() -> bytes: ... def tigetflag(__capname: str) -> int: ... def tigetnum(__capname: str) -> int: ... -def tigetstr(__capname: str) -> bytes: ... +def tigetstr(__capname: str) -> bytes | None: ... def tparm( __str: bytes, __i1: int = ..., @@ -348,24 +370,17 @@ def tparm( ) -> bytes: ... def typeahead(__fd: int) -> None: ... def unctrl(__ch: _chtype) -> bytes: ... - -if sys.version_info >= (3, 3): - def unget_wch(__ch: Union[int, str]) -> None: ... - +def unget_wch(__ch: int | str) -> None: ... def ungetch(__ch: _chtype) -> None: ... def ungetmouse(__id: int, __x: int, __y: int, __z: int, __bstate: int) -> None: ... - -if sys.version_info >= (3, 5): - def update_lines_cols() -> int: ... - +def update_lines_cols() -> None: ... def use_default_colors() -> None: ... def use_env(__flag: bool) -> None: ... class error(Exception): ... class _CursesWindow: - if sys.version_info >= (3, 3): - encoding: str + encoding: str @overload def addch(self, ch: _chtype, attr: int = ...) -> None: ... @overload @@ -423,32 +438,31 @@ class _CursesWindow: def echochar(self, __ch: _chtype, __attr: int = ...) -> None: ... def enclose(self, __y: int, __x: int) -> bool: ... def erase(self) -> None: ... - def getbegyx(self) -> Tuple[int, int]: ... - def getbkgd(self) -> Tuple[int, int]: ... + def getbegyx(self) -> tuple[int, int]: ... + def getbkgd(self) -> tuple[int, int]: ... @overload def getch(self) -> int: ... @overload def getch(self, y: int, x: int) -> int: ... - if sys.version_info >= (3, 3): - @overload - def get_wch(self) -> Union[int, str]: ... - @overload - def get_wch(self, y: int, x: int) -> Union[int, str]: ... + @overload + def get_wch(self) -> int | str: ... + @overload + def get_wch(self, y: int, x: int) -> int | str: ... @overload def getkey(self) -> str: ... @overload def getkey(self, y: int, x: int) -> str: ... - def getmaxyx(self) -> Tuple[int, int]: ... - def getparyx(self) -> Tuple[int, int]: ... + def getmaxyx(self) -> tuple[int, int]: ... + def getparyx(self) -> tuple[int, int]: ... @overload - def getstr(self) -> _chtype: ... + def getstr(self) -> bytes: ... @overload - def getstr(self, n: int) -> _chtype: ... + def getstr(self, n: int) -> bytes: ... @overload - def getstr(self, y: int, x: int) -> _chtype: ... + def getstr(self, y: int, x: int) -> bytes: ... @overload - def getstr(self, y: int, x: int, n: int) -> _chtype: ... - def getyx(self) -> Tuple[int, int]: ... + def getstr(self, y: int, x: int, n: int) -> bytes: ... + def getyx(self) -> tuple[int, int]: ... @overload def hline(self, ch: _chtype, n: int) -> None: ... @overload @@ -457,9 +471,9 @@ class _CursesWindow: def idlok(self, yes: bool) -> None: ... def immedok(self, flag: bool) -> None: ... @overload - def inch(self) -> _chtype: ... + def inch(self) -> int: ... @overload - def inch(self, y: int, x: int) -> _chtype: ... + def inch(self, y: int, x: int) -> int: ... @overload def insch(self, ch: _chtype, attr: int = ...) -> None: ... @overload @@ -475,9 +489,9 @@ class _CursesWindow: @overload def insstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... @overload - def instr(self, n: int = ...) -> _chtype: ... + def instr(self, n: int = ...) -> bytes: ... @overload - def instr(self, y: int, x: int, n: int = ...) -> _chtype: ... + def instr(self, y: int, x: int, n: int = ...) -> bytes: ... def is_linetouched(self, __line: int) -> bool: ... def is_wintouched(self) -> bool: ... def keypad(self, yes: bool) -> None: ... @@ -487,8 +501,11 @@ class _CursesWindow: def mvwin(self, new_y: int, new_x: int) -> None: ... def nodelay(self, yes: bool) -> None: ... def notimeout(self, yes: bool) -> None: ... + @overload def noutrefresh(self) -> None: ... @overload + def noutrefresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... + @overload def overlay(self, destwin: _CursesWindow) -> None: ... @overload def overlay( diff --git a/mypy/typeshed/stdlib/_dummy_thread.pyi b/mypy/typeshed/stdlib/_dummy_thread.pyi index 1260d42de958..886d9d739780 100644 --- a/mypy/typeshed/stdlib/_dummy_thread.pyi +++ b/mypy/typeshed/stdlib/_dummy_thread.pyi @@ -1,19 +1,19 @@ -from typing import Any, Callable, Dict, NoReturn, Optional, Tuple +from typing import Any, Callable, NoReturn, Tuple TIMEOUT_MAX: int error = RuntimeError -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any] = ...) -> None: ... +def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: dict[str, Any] = ...) -> None: ... def exit() -> NoReturn: ... def get_ident() -> int: ... def allocate_lock() -> LockType: ... -def stack_size(size: Optional[int] = ...) -> int: ... +def stack_size(size: int | None = ...) -> int: ... class LockType(object): locked_status: bool def __init__(self) -> None: ... - def acquire(self, waitflag: Optional[bool] = ..., timeout: int = ...) -> bool: ... - def __enter__(self, waitflag: Optional[bool] = ..., timeout: int = ...) -> bool: ... + def acquire(self, waitflag: bool | None = ..., timeout: int = ...) -> bool: ... + def __enter__(self, waitflag: bool | None = ..., timeout: int = ...) -> bool: ... def __exit__(self, typ: Any, val: Any, tb: Any) -> None: ... def release(self) -> bool: ... def locked(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/_dummy_threading.pyi b/mypy/typeshed/stdlib/_dummy_threading.pyi index af0b0af89d9b..64998d86bf9f 100644 --- a/mypy/typeshed/stdlib/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/_dummy_threading.pyi @@ -1,6 +1,6 @@ import sys from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar, Union +from typing import Any, Callable, Iterable, Mapping, Optional, Type, TypeVar # TODO recursive type _TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] @@ -8,33 +8,23 @@ _TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] _PF = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") -__all__: List[str] +__all__: list[str] def active_count() -> int: ... - -if sys.version_info < (3,): - def activeCount() -> int: ... - def current_thread() -> Thread: ... def currentThread() -> Thread: ... - -if sys.version_info >= (3,): - def get_ident() -> int: ... - -def enumerate() -> List[Thread]: ... - -if sys.version_info >= (3, 4): - def main_thread() -> Thread: ... +def get_ident() -> int: ... +def enumerate() -> list[Thread]: ... +def main_thread() -> Thread: ... if sys.version_info >= (3, 8): from _thread import get_native_id as get_native_id def settrace(func: _TF) -> None: ... -def setprofile(func: Optional[_PF]) -> None: ... +def setprofile(func: _PF | None) -> None: ... def stack_size(size: int = ...) -> int: ... -if sys.version_info >= (3,): - TIMEOUT_MAX: float +TIMEOUT_MAX: float class ThreadError(Exception): ... @@ -45,36 +35,26 @@ class local(object): class Thread: name: str - ident: Optional[int] + ident: int | None daemon: bool - if sys.version_info >= (3,): - def __init__( - self, - group: None = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[str] = ..., - args: Iterable[Any] = ..., - kwargs: Optional[Mapping[str, Any]] = ..., - *, - daemon: Optional[bool] = ..., - ) -> None: ... - else: - def __init__( - self, - group: None = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[Text] = ..., - args: Iterable[Any] = ..., - kwargs: Optional[Mapping[Text, Any]] = ..., - ) -> None: ... + def __init__( + self, + group: None = ..., + target: Callable[..., Any] | None = ..., + name: str | None = ..., + args: Iterable[Any] = ..., + kwargs: Mapping[str, Any] | None = ..., + *, + daemon: bool | None = ..., + ) -> None: ... def start(self) -> None: ... def run(self) -> None: ... - def join(self, timeout: Optional[float] = ...) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... def getName(self) -> str: ... - def setName(self, name: Text) -> None: ... + def setName(self, name: str) -> None: ... if sys.version_info >= (3, 8): @property - def native_id(self) -> Optional[int]: ... # only available on some platforms + def native_id(self) -> int | None: ... # only available on some platforms def is_alive(self) -> bool: ... if sys.version_info < (3, 9): def isAlive(self) -> bool: ... @@ -87,12 +67,9 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... def locked(self) -> bool: ... @@ -100,30 +77,23 @@ class _RLock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... RLock = _RLock class Condition: - def __init__(self, lock: Union[Lock, _RLock, None] = ...) -> None: ... + def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... - if sys.version_info >= (3,): - def wait_for(self, predicate: Callable[[], _T], timeout: Optional[float] = ...) -> _T: ... + def wait(self, timeout: float | None = ...) -> bool: ... + def wait_for(self, predicate: Callable[[], _T], timeout: float | None = ...) -> _T: ... def notify(self, n: int = ...) -> None: ... def notify_all(self) -> None: ... def notifyAll(self) -> None: ... @@ -131,14 +101,10 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: Optional[float] = ...) -> bool: ... - def __enter__(self, blocking: bool = ..., timeout: Optional[float] = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... - def __enter__(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... + def __enter__(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... if sys.version_info >= (3, 9): def release(self, n: int = ...) -> None: ... else: @@ -149,11 +115,9 @@ class BoundedSemaphore(Semaphore): ... class Event: def __init__(self) -> None: ... def is_set(self) -> bool: ... - if sys.version_info < (3,): - def isSet(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... + def wait(self, timeout: float | None = ...) -> bool: ... if sys.version_info >= (3, 8): from _thread import _excepthook, _ExceptHookArgs @@ -162,27 +126,22 @@ if sys.version_info >= (3, 8): ExceptHookArgs = _ExceptHookArgs class Timer(Thread): - if sys.version_info >= (3,): - def __init__( - self, - interval: float, - function: Callable[..., Any], - args: Optional[Iterable[Any]] = ..., - kwargs: Optional[Mapping[str, Any]] = ..., - ) -> None: ... - else: - def __init__( - self, interval: float, function: Callable[..., Any], args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ... - ) -> None: ... + def __init__( + self, + interval: float, + function: Callable[..., Any], + args: Iterable[Any] | None = ..., + kwargs: Mapping[str, Any] | None = ..., + ) -> None: ... def cancel(self) -> None: ... -if sys.version_info >= (3,): - class Barrier: - parties: int - n_waiting: int - broken: bool - def __init__(self, parties: int, action: Optional[Callable[[], None]] = ..., timeout: Optional[float] = ...) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> int: ... - def reset(self) -> None: ... - def abort(self) -> None: ... - class BrokenBarrierError(RuntimeError): ... +class Barrier: + parties: int + n_waiting: int + broken: bool + def __init__(self, parties: int, action: Callable[[], None] | None = ..., timeout: float | None = ...) -> None: ... + def wait(self, timeout: float | None = ...) -> int: ... + def reset(self) -> None: ... + def abort(self) -> None: ... + +class BrokenBarrierError(RuntimeError): ... diff --git a/mypy/typeshed/stdlib/_heapq.pyi b/mypy/typeshed/stdlib/_heapq.pyi index 5b14a9de773d..87e0fe0fa777 100644 --- a/mypy/typeshed/stdlib/_heapq.pyi +++ b/mypy/typeshed/stdlib/_heapq.pyi @@ -1,14 +1,9 @@ -import sys -from typing import Any, Callable, Iterable, List, Optional, TypeVar +from typing import Any, TypeVar _T = TypeVar("_T") -def heapify(__heap: List[Any]) -> None: ... -def heappop(__heap: List[_T]) -> _T: ... -def heappush(__heap: List[_T], __item: _T) -> None: ... -def heappushpop(__heap: List[_T], __item: _T) -> _T: ... -def heapreplace(__heap: List[_T], __item: _T) -> _T: ... - -if sys.version_info < (3,): - def nlargest(__n: int, __iterable: Iterable[_T], __key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ... - def nsmallest(__n: int, __iterable: Iterable[_T], __key: Optional[Callable[[_T], Any]] = ...) -> List[_T]: ... +def heapify(__heap: list[Any]) -> None: ... +def heappop(__heap: list[_T]) -> _T: ... +def heappush(__heap: list[_T], __item: _T) -> None: ... +def heappushpop(__heap: list[_T], __item: _T) -> _T: ... +def heapreplace(__heap: list[_T], __item: _T) -> _T: ... diff --git a/mypy/typeshed/stdlib/_imp.pyi b/mypy/typeshed/stdlib/_imp.pyi index bfc4d42cd065..b61c9f29b96d 100644 --- a/mypy/typeshed/stdlib/_imp.pyi +++ b/mypy/typeshed/stdlib/_imp.pyi @@ -1,13 +1,13 @@ import types from importlib.machinery import ModuleSpec -from typing import Any, List +from typing import Any def create_builtin(__spec: ModuleSpec) -> types.ModuleType: ... def create_dynamic(__spec: ModuleSpec, __file: Any = ...) -> None: ... def acquire_lock() -> None: ... def exec_builtin(__mod: types.ModuleType) -> int: ... def exec_dynamic(__mod: types.ModuleType) -> int: ... -def extension_suffixes() -> List[str]: ... +def extension_suffixes() -> list[str]: ... def get_frozen_object(__name: str) -> types.CodeType: ... def init_frozen(__name: str) -> types.ModuleType: ... def is_builtin(__name: str) -> int: ... diff --git a/mypy/typeshed/stdlib/_json.pyi b/mypy/typeshed/stdlib/_json.pyi index af2b024af5af..7395288afdbc 100644 --- a/mypy/typeshed/stdlib/_json.pyi +++ b/mypy/typeshed/stdlib/_json.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Optional, Tuple +from typing import Any, Callable class make_encoder: sort_keys: Any @@ -11,10 +11,10 @@ class make_encoder: item_separator: Any def __init__( self, - markers: Optional[Dict[int, Any]], + markers: dict[int, Any] | None, default: Callable[[Any], Any], encoder: Callable[[str], str], - indent: Optional[int], + indent: int | None, key_separator: str, item_separator: str, sort_keys: bool, @@ -32,7 +32,7 @@ class make_scanner: strict: bool # TODO: 'context' needs the attrs above (ducktype), but not __call__. def __init__(self, context: make_scanner) -> None: ... - def __call__(self, string: str, index: int) -> Tuple[Any, int]: ... + def __call__(self, string: str, index: int) -> tuple[Any, int]: ... def encode_basestring_ascii(s: str) -> str: ... -def scanstring(string: str, end: int, strict: bool = ...) -> Tuple[str, int]: ... +def scanstring(string: str, end: int, strict: bool = ...) -> tuple[str, int]: ... diff --git a/mypy/typeshed/stdlib/_markupbase.pyi b/mypy/typeshed/stdlib/_markupbase.pyi index d8bc79f34e8c..368d32bd5b4c 100644 --- a/mypy/typeshed/stdlib/_markupbase.pyi +++ b/mypy/typeshed/stdlib/_markupbase.pyi @@ -1,8 +1,6 @@ -from typing import Tuple - class ParserBase: def __init__(self) -> None: ... def error(self, message: str) -> None: ... def reset(self) -> None: ... - def getpos(self) -> Tuple[int, int]: ... + def getpos(self) -> tuple[int, int]: ... def unknown_decl(self, data: str) -> None: ... diff --git a/mypy/typeshed/stdlib/_msi.pyi b/mypy/typeshed/stdlib/_msi.pyi index a8f9c60bbadd..754febe68da9 100644 --- a/mypy/typeshed/stdlib/_msi.pyi +++ b/mypy/typeshed/stdlib/_msi.pyi @@ -1,11 +1,10 @@ import sys -from typing import List, Optional, Union if sys.platform == "win32": # Actual typename View, not exposed by the implementation class _View: - def Execute(self, params: Optional[_Record] = ...) -> None: ... + def Execute(self, params: _Record | None = ...) -> None: ... def GetColumnInfo(self, kind: int) -> _Record: ... def Fetch(self) -> _Record: ... def Modify(self, mode: int, record: _Record) -> None: ... @@ -15,9 +14,9 @@ if sys.platform == "win32": __init__: None # type: ignore # Actual typename Summary, not exposed by the implementation class _Summary: - def GetProperty(self, propid: int) -> Optional[Union[str, bytes]]: ... + def GetProperty(self, propid: int) -> str | bytes | None: ... def GetPropertyCount(self) -> int: ... - def SetProperty(self, propid: int, value: Union[str, bytes]) -> None: ... + def SetProperty(self, propid: int, value: str | bytes) -> None: ... def Persist(self) -> None: ... # Don't exist at runtime __new__: None # type: ignore @@ -44,6 +43,6 @@ if sys.platform == "win32": __new__: None # type: ignore __init__: None # type: ignore def UuidCreate() -> str: ... - def FCICreate(cabname: str, files: List[str]) -> None: ... + def FCICreate(cabname: str, files: list[str]) -> None: ... def OpenDatabase(name: str, flags: int) -> _Database: ... def CreateRecord(count: int) -> _Record: ... diff --git a/mypy/typeshed/stdlib/_osx_support.pyi b/mypy/typeshed/stdlib/_osx_support.pyi index 5d67d996b30a..ce1fffc00e8c 100644 --- a/mypy/typeshed/stdlib/_osx_support.pyi +++ b/mypy/typeshed/stdlib/_osx_support.pyi @@ -1,33 +1,33 @@ -from typing import Dict, Iterable, List, Optional, Sequence, Tuple, TypeVar, Union +from typing import Iterable, Sequence, Tuple, TypeVar _T = TypeVar("_T") _K = TypeVar("_K") _V = TypeVar("_V") -__all__: List[str] +__all__: list[str] _UNIVERSAL_CONFIG_VARS: Tuple[str, ...] # undocumented _COMPILER_CONFIG_VARS: Tuple[str, ...] # undocumented _INITPRE: str # undocumented -def _find_executable(executable: str, path: Optional[str] = ...) -> Optional[str]: ... # undocumented -def _read_output(commandstring: str) -> Optional[str]: ... # undocumented +def _find_executable(executable: str, path: str | None = ...) -> str | None: ... # undocumented +def _read_output(commandstring: str) -> str | None: ... # undocumented def _find_build_tool(toolname: str) -> str: ... # undocumented -_SYSTEM_VERSION: Optional[str] # undocumented +_SYSTEM_VERSION: str | None # undocumented def _get_system_version() -> str: ... # undocumented -def _remove_original_values(_config_vars: Dict[str, str]) -> None: ... # undocumented -def _save_modified_value(_config_vars: Dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented +def _remove_original_values(_config_vars: dict[str, str]) -> None: ... # undocumented +def _save_modified_value(_config_vars: dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented def _supports_universal_builds() -> bool: ... # undocumented -def _find_appropriate_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _remove_universal_flags(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _remove_unsupported_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _override_all_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _check_for_unavailable_sdk(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> List[str]: ... -def customize_config_vars(_config_vars: Dict[str, str]) -> Dict[str, str]: ... -def customize_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... +def _find_appropriate_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _remove_universal_flags(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _remove_unsupported_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _override_all_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _check_for_unavailable_sdk(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> list[str]: ... +def customize_config_vars(_config_vars: dict[str, str]) -> dict[str, str]: ... +def customize_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ... def get_platform_osx( - _config_vars: Dict[str, str], osname: _T, release: _K, machine: _V -) -> Tuple[Union[str, _T], Union[str, _K], Union[str, _V]]: ... + _config_vars: dict[str, str], osname: _T, release: _K, machine: _V +) -> tuple[str | _T, str | _K, str | _V]: ... diff --git a/mypy/typeshed/stdlib/_posixsubprocess.pyi b/mypy/typeshed/stdlib/_posixsubprocess.pyi index 05209ba05b9b..0eae723e7a67 100644 --- a/mypy/typeshed/stdlib/_posixsubprocess.pyi +++ b/mypy/typeshed/stdlib/_posixsubprocess.pyi @@ -1,8 +1,8 @@ # NOTE: These are incomplete! -from typing import Callable, Sequence, Tuple +from typing import Callable, Sequence -def cloexec_pipe() -> Tuple[int, int]: ... +def cloexec_pipe() -> tuple[int, int]: ... def fork_exec( args: Sequence[str], executable_list: Sequence[bytes], diff --git a/mypy/typeshed/stdlib/_py_abc.pyi b/mypy/typeshed/stdlib/_py_abc.pyi index 9b0812d67c0f..8d7938918271 100644 --- a/mypy/typeshed/stdlib/_py_abc.pyi +++ b/mypy/typeshed/stdlib/_py_abc.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Tuple, Type, TypeVar +from typing import Any, Tuple, Type, TypeVar _T = TypeVar("_T") @@ -6,5 +6,5 @@ _T = TypeVar("_T") def get_cache_token() -> object: ... class ABCMeta(type): - def __new__(__mcls, __name: str, __bases: Tuple[Type[Any], ...], __namespace: Dict[str, Any]) -> ABCMeta: ... + def __new__(__mcls, __name: str, __bases: Tuple[Type[Any], ...], __namespace: dict[str, Any]) -> ABCMeta: ... def register(cls, subclass: Type[_T]) -> Type[_T]: ... diff --git a/mypy/typeshed/stdlib/_random.pyi b/mypy/typeshed/stdlib/_random.pyi index aa09693420ca..fa80c6d98144 100644 --- a/mypy/typeshed/stdlib/_random.pyi +++ b/mypy/typeshed/stdlib/_random.pyi @@ -1,4 +1,3 @@ -import sys from typing import Tuple # Actually Tuple[(int,) * 625] @@ -11,5 +10,3 @@ class Random(object): def setstate(self, __state: _State) -> None: ... def random(self) -> float: ... def getrandbits(self, __k: int) -> int: ... - if sys.version_info < (3,): - def jumpahead(self, i: int) -> None: ... diff --git a/mypy/typeshed/stdlib/_sitebuiltins.pyi b/mypy/typeshed/stdlib/_sitebuiltins.pyi index e0e9316aa290..a71364b8db65 100644 --- a/mypy/typeshed/stdlib/_sitebuiltins.pyi +++ b/mypy/typeshed/stdlib/_sitebuiltins.pyi @@ -1,11 +1,11 @@ -from typing import ClassVar, Iterable, NoReturn, Optional +from typing import ClassVar, Iterable, NoReturn from typing_extensions import Literal class Quitter: name: str eof: str def __init__(self, name: str, eof: str) -> None: ... - def __call__(self, code: Optional[int] = ...) -> NoReturn: ... + def __call__(self, code: int | None = ...) -> NoReturn: ... class _Printer: MAXLINES: ClassVar[Literal[23]] diff --git a/mypy/typeshed/stdlib/_socket.pyi b/mypy/typeshed/stdlib/_socket.pyi new file mode 100644 index 000000000000..846f64d5a433 --- /dev/null +++ b/mypy/typeshed/stdlib/_socket.pyi @@ -0,0 +1,633 @@ +import sys +from _typeshed import ReadableBuffer, WriteableBuffer +from collections.abc import Iterable +from typing import Any, SupportsInt, Tuple, Union, overload + +if sys.version_info >= (3, 8): + from typing import SupportsIndex + + _FD = SupportsIndex +else: + _FD = SupportsInt + +_CMSG = Tuple[int, int, bytes] +_CMSGArg = Tuple[int, int, ReadableBuffer] + +# Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, +# AF_NETLINK, AF_TIPC) or strings (AF_UNIX). +_Address = Union[Tuple[Any, ...], str] +_RetAddress = Any +# TODO Most methods allow bytes as address objects + +# ----- Constants ----- +# Some socket families are listed in the "Socket families" section of the docs, +# but not the "Constants" section. These are listed at the end of the list of +# constants. +# +# Besides those and the first few constants listed, the constants are listed in +# documentation order. + +has_ipv6: bool + +# Per socketmodule.c, only these three families are portable +AF_UNIX: int +AF_INET: int +AF_INET6: int + +SOCK_STREAM: int +SOCK_DGRAM: int +SOCK_RAW: int +SOCK_RDM: int +SOCK_SEQPACKET: int + +if sys.platform == "linux": + SOCK_CLOEXEC: int + SOCK_NONBLOCK: int + +# Address families not mentioned in the docs +AF_AAL5: int +AF_APPLETALK: int +AF_ASH: int +AF_ATMPVC: int +AF_ATMSVC: int +AF_AX25: int +AF_BRIDGE: int +AF_DECnet: int +AF_ECONET: int +AF_IPX: int +AF_IRDA: int +AF_KEY: int +AF_LLC: int +AF_NETBEUI: int +AF_NETROM: int +AF_PPPOX: int +AF_ROSE: int +AF_ROUTE: int +AF_SECURITY: int +AF_SNA: int +AF_SYSTEM: int +AF_UNSPEC: int +AF_WANPIPE: int +AF_X25: int + +# The "many constants" referenced by the docs +SOMAXCONN: int +AI_ADDRCONFIG: int +AI_ALL: int +AI_CANONNAME: int +AI_DEFAULT: int +AI_MASK: int +AI_NUMERICHOST: int +AI_NUMERICSERV: int +AI_PASSIVE: int +AI_V4MAPPED: int +AI_V4MAPPED_CFG: int +EAI_ADDRFAMILY: int +EAI_AGAIN: int +EAI_BADFLAGS: int +EAI_BADHINTS: int +EAI_FAIL: int +EAI_FAMILY: int +EAI_MAX: int +EAI_MEMORY: int +EAI_NODATA: int +EAI_NONAME: int +EAI_OVERFLOW: int +EAI_PROTOCOL: int +EAI_SERVICE: int +EAI_SOCKTYPE: int +EAI_SYSTEM: int +INADDR_ALLHOSTS_GROUP: int +INADDR_ANY: int +INADDR_BROADCAST: int +INADDR_LOOPBACK: int +INADDR_MAX_LOCAL_GROUP: int +INADDR_NONE: int +INADDR_UNSPEC_GROUP: int +IPPORT_RESERVED: int +IPPORT_USERRESERVED: int +IPPROTO_AH: int +IPPROTO_BIP: int +IPPROTO_DSTOPTS: int +IPPROTO_EGP: int +IPPROTO_EON: int +IPPROTO_ESP: int +IPPROTO_FRAGMENT: int +IPPROTO_GGP: int +IPPROTO_GRE: int +IPPROTO_HELLO: int +IPPROTO_HOPOPTS: int +IPPROTO_ICMP: int +IPPROTO_ICMPV6: int +IPPROTO_IDP: int +IPPROTO_IGMP: int +IPPROTO_IP: int +IPPROTO_IPCOMP: int +IPPROTO_IPIP: int +IPPROTO_IPV4: int +IPPROTO_IPV6: int +IPPROTO_MAX: int +IPPROTO_MOBILE: int +IPPROTO_ND: int +IPPROTO_NONE: int +IPPROTO_PIM: int +IPPROTO_PUP: int +IPPROTO_RAW: int +IPPROTO_ROUTING: int +IPPROTO_RSVP: int +IPPROTO_SCTP: int +IPPROTO_TCP: int +IPPROTO_TP: int +IPPROTO_UDP: int +IPPROTO_VRRP: int +IPPROTO_XTP: int +IPV6_CHECKSUM: int +IPV6_DONTFRAG: int +IPV6_DSTOPTS: int +IPV6_HOPLIMIT: int +IPV6_HOPOPTS: int +IPV6_JOIN_GROUP: int +IPV6_LEAVE_GROUP: int +IPV6_MULTICAST_HOPS: int +IPV6_MULTICAST_IF: int +IPV6_MULTICAST_LOOP: int +IPV6_NEXTHOP: int +IPV6_PATHMTU: int +IPV6_PKTINFO: int +IPV6_RECVDSTOPTS: int +IPV6_RECVHOPLIMIT: int +IPV6_RECVHOPOPTS: int +IPV6_RECVPATHMTU: int +IPV6_RECVPKTINFO: int +IPV6_RECVRTHDR: int +IPV6_RECVTCLASS: int +IPV6_RTHDR: int +IPV6_RTHDRDSTOPTS: int +IPV6_RTHDR_TYPE_0: int +IPV6_TCLASS: int +IPV6_UNICAST_HOPS: int +IPV6_USE_MIN_MTU: int +IPV6_V6ONLY: int +IPX_TYPE: int +IP_ADD_MEMBERSHIP: int +IP_DEFAULT_MULTICAST_LOOP: int +IP_DEFAULT_MULTICAST_TTL: int +IP_DROP_MEMBERSHIP: int +IP_HDRINCL: int +IP_MAX_MEMBERSHIPS: int +IP_MULTICAST_IF: int +IP_MULTICAST_LOOP: int +IP_MULTICAST_TTL: int +IP_OPTIONS: int +IP_RECVDSTADDR: int +IP_RECVOPTS: int +IP_RECVRETOPTS: int +IP_RETOPTS: int +IP_TOS: int +IP_TRANSPARENT: int +IP_TTL: int +LOCAL_PEERCRED: int +MSG_BCAST: int +MSG_BTAG: int +MSG_CMSG_CLOEXEC: int +MSG_CONFIRM: int +MSG_CTRUNC: int +MSG_DONTROUTE: int +MSG_DONTWAIT: int +MSG_EOF: int +MSG_EOR: int +MSG_ERRQUEUE: int +MSG_ETAG: int +MSG_FASTOPEN: int +MSG_MCAST: int +MSG_MORE: int +MSG_NOSIGNAL: int +MSG_NOTIFICATION: int +MSG_OOB: int +MSG_PEEK: int +MSG_TRUNC: int +MSG_WAITALL: int +NI_DGRAM: int +NI_MAXHOST: int +NI_MAXSERV: int +NI_NAMEREQD: int +NI_NOFQDN: int +NI_NUMERICHOST: int +NI_NUMERICSERV: int +SCM_CREDENTIALS: int +SCM_CREDS: int +SCM_RIGHTS: int +SHUT_RD: int +SHUT_RDWR: int +SHUT_WR: int +SOL_ATALK: int +SOL_AX25: int +SOL_HCI: int +SOL_IP: int +SOL_IPX: int +SOL_NETROM: int +SOL_ROSE: int +SOL_SOCKET: int +SOL_TCP: int +SOL_UDP: int +SO_ACCEPTCONN: int +SO_BINDTODEVICE: int +SO_BROADCAST: int +SO_DEBUG: int +SO_DONTROUTE: int +SO_ERROR: int +SO_EXCLUSIVEADDRUSE: int +SO_KEEPALIVE: int +SO_LINGER: int +SO_MARK: int +SO_OOBINLINE: int +SO_PASSCRED: int +SO_PEERCRED: int +SO_PRIORITY: int +SO_RCVBUF: int +SO_RCVLOWAT: int +SO_RCVTIMEO: int +SO_REUSEADDR: int +SO_REUSEPORT: int +SO_SETFIB: int +SO_SNDBUF: int +SO_SNDLOWAT: int +SO_SNDTIMEO: int +SO_TYPE: int +SO_USELOOPBACK: int +TCP_CORK: int +TCP_DEFER_ACCEPT: int +TCP_FASTOPEN: int +TCP_INFO: int +TCP_KEEPCNT: int +TCP_KEEPIDLE: int +TCP_KEEPINTVL: int +TCP_LINGER2: int +TCP_MAXSEG: int +TCP_NODELAY: int +TCP_QUICKACK: int +TCP_SYNCNT: int +TCP_WINDOW_CLAMP: int +if sys.version_info >= (3, 7): + TCP_NOTSENT_LOWAT: int + +# Specifically-documented constants + +if sys.platform == "linux": + AF_CAN: int + PF_CAN: int + SOL_CAN_BASE: int + SOL_CAN_RAW: int + CAN_EFF_FLAG: int + CAN_EFF_MASK: int + CAN_ERR_FLAG: int + CAN_ERR_MASK: int + CAN_RAW: int + CAN_RAW_ERR_FILTER: int + CAN_RAW_FILTER: int + CAN_RAW_LOOPBACK: int + CAN_RAW_RECV_OWN_MSGS: int + CAN_RTR_FLAG: int + CAN_SFF_MASK: int + + CAN_BCM: int + CAN_BCM_TX_SETUP: int + CAN_BCM_TX_DELETE: int + CAN_BCM_TX_READ: int + CAN_BCM_TX_SEND: int + CAN_BCM_RX_SETUP: int + CAN_BCM_RX_DELETE: int + CAN_BCM_RX_READ: int + CAN_BCM_TX_STATUS: int + CAN_BCM_TX_EXPIRED: int + CAN_BCM_RX_STATUS: int + CAN_BCM_RX_TIMEOUT: int + CAN_BCM_RX_CHANGED: int + + CAN_RAW_FD_FRAMES: int + +if sys.platform == "linux" and sys.version_info >= (3, 8): + CAN_BCM_SETTIMER: int + CAN_BCM_STARTTIMER: int + CAN_BCM_TX_COUNTEVT: int + CAN_BCM_TX_ANNOUNCE: int + CAN_BCM_TX_CP_CAN_ID: int + CAN_BCM_RX_FILTER_ID: int + CAN_BCM_RX_CHECK_DLC: int + CAN_BCM_RX_NO_AUTOTIMER: int + CAN_BCM_RX_ANNOUNCE_RESUME: int + CAN_BCM_TX_RESET_MULTI_IDX: int + CAN_BCM_RX_RTR_FRAME: int + CAN_BCM_CAN_FD_FRAME: int + +if sys.platform == "linux" and sys.version_info >= (3, 7): + CAN_ISOTP: int + +if sys.platform == "linux" and sys.version_info >= (3, 9): + CAN_J1939: int + CAN_RAW_JOIN_FILTERS: int + + J1939_MAX_UNICAST_ADDR: int + J1939_IDLE_ADDR: int + J1939_NO_ADDR: int + J1939_NO_NAME: int + J1939_PGN_REQUEST: int + J1939_PGN_ADDRESS_CLAIMED: int + J1939_PGN_ADDRESS_COMMANDED: int + J1939_PGN_PDU1_MAX: int + J1939_PGN_MAX: int + J1939_NO_PGN: int + + SO_J1939_FILTER: int + SO_J1939_PROMISC: int + SO_J1939_SEND_PRIO: int + SO_J1939_ERRQUEUE: int + + SCM_J1939_DEST_ADDR: int + SCM_J1939_DEST_NAME: int + SCM_J1939_PRIO: int + SCM_J1939_ERRQUEUE: int + + J1939_NLA_PAD: int + J1939_NLA_BYTES_ACKED: int + + J1939_EE_INFO_NONE: int + J1939_EE_INFO_TX_ABORT: int + + J1939_FILTER_MAX: int + +if sys.platform == "linux": + AF_PACKET: int + PF_PACKET: int + PACKET_BROADCAST: int + PACKET_FASTROUTE: int + PACKET_HOST: int + PACKET_LOOPBACK: int + PACKET_MULTICAST: int + PACKET_OTHERHOST: int + PACKET_OUTGOING: int + +if sys.platform == "linux": + AF_RDS: int + PF_RDS: int + SOL_RDS: int + RDS_CANCEL_SENT_TO: int + RDS_CMSG_RDMA_ARGS: int + RDS_CMSG_RDMA_DEST: int + RDS_CMSG_RDMA_MAP: int + RDS_CMSG_RDMA_STATUS: int + RDS_CMSG_RDMA_UPDATE: int + RDS_CONG_MONITOR: int + RDS_FREE_MR: int + RDS_GET_MR: int + RDS_GET_MR_FOR_DEST: int + RDS_RDMA_DONTWAIT: int + RDS_RDMA_FENCE: int + RDS_RDMA_INVALIDATE: int + RDS_RDMA_NOTIFY_ME: int + RDS_RDMA_READWRITE: int + RDS_RDMA_SILENT: int + RDS_RDMA_USE_ONCE: int + RDS_RECVERR: int + +if sys.platform == "win32": + SIO_RCVALL: int + SIO_KEEPALIVE_VALS: int + SIO_LOOPBACK_FAST_PATH: int + RCVALL_IPLEVEL: int + RCVALL_MAX: int + RCVALL_OFF: int + RCVALL_ON: int + RCVALL_SOCKETLEVELONLY: int + +if sys.platform == "linux": + AF_TIPC: int + SOL_TIPC: int + TIPC_ADDR_ID: int + TIPC_ADDR_NAME: int + TIPC_ADDR_NAMESEQ: int + TIPC_CFG_SRV: int + TIPC_CLUSTER_SCOPE: int + TIPC_CONN_TIMEOUT: int + TIPC_CRITICAL_IMPORTANCE: int + TIPC_DEST_DROPPABLE: int + TIPC_HIGH_IMPORTANCE: int + TIPC_IMPORTANCE: int + TIPC_LOW_IMPORTANCE: int + TIPC_MEDIUM_IMPORTANCE: int + TIPC_NODE_SCOPE: int + TIPC_PUBLISHED: int + TIPC_SRC_DROPPABLE: int + TIPC_SUBSCR_TIMEOUT: int + TIPC_SUB_CANCEL: int + TIPC_SUB_PORTS: int + TIPC_SUB_SERVICE: int + TIPC_TOP_SRV: int + TIPC_WAIT_FOREVER: int + TIPC_WITHDRAWN: int + TIPC_ZONE_SCOPE: int + +if sys.platform == "linux": + AF_ALG: int + SOL_ALG: int + ALG_OP_DECRYPT: int + ALG_OP_ENCRYPT: int + ALG_OP_SIGN: int + ALG_OP_VERIFY: int + ALG_SET_AEAD_ASSOCLEN: int + ALG_SET_AEAD_AUTHSIZE: int + ALG_SET_IV: int + ALG_SET_KEY: int + ALG_SET_OP: int + ALG_SET_PUBKEY: int + +if sys.platform == "linux" and sys.version_info >= (3, 7): + AF_VSOCK: int + IOCTL_VM_SOCKETS_GET_LOCAL_CID: int + VMADDR_CID_ANY: int + VMADDR_CID_HOST: int + VMADDR_PORT_ANY: int + SO_VM_SOCKETS_BUFFER_MAX_SIZE: int + SO_VM_SOCKETS_BUFFER_SIZE: int + SO_VM_SOCKETS_BUFFER_MIN_SIZE: int + VM_SOCKETS_INVALID_VERSION: int + +AF_LINK: int # Availability: BSD, macOS + +# BDADDR_* and HCI_* listed with other bluetooth constants below + +SO_DOMAIN: int +SO_PASSSEC: int +SO_PEERSEC: int +SO_PROTOCOL: int +TCP_CONGESTION: int +TCP_USER_TIMEOUT: int + +if sys.platform == "linux" and sys.version_info >= (3, 8): + AF_QIPCRTR: int + +# Semi-documented constants +# (Listed under "Socket families" in the docs, but not "Constants") + +if sys.platform == "linux": + # Netlink is defined by Linux + AF_NETLINK: int + NETLINK_ARPD: int + NETLINK_CRYPTO: int + NETLINK_DNRTMSG: int + NETLINK_FIREWALL: int + NETLINK_IP6_FW: int + NETLINK_NFLOG: int + NETLINK_ROUTE6: int + NETLINK_ROUTE: int + NETLINK_SKIP: int + NETLINK_TAPBASE: int + NETLINK_TCPDIAG: int + NETLINK_USERSOCK: int + NETLINK_W1: int + NETLINK_XFRM: int + +if sys.platform != "win32" and sys.platform != "darwin": + # Linux and some BSD support is explicit in the docs + # Windows and macOS do not support in practice + AF_BLUETOOTH: int + BTPROTO_HCI: int + BTPROTO_L2CAP: int + BTPROTO_RFCOMM: int + BTPROTO_SCO: int # not in FreeBSD + + BDADDR_ANY: str + BDADDR_LOCAL: str + + HCI_FILTER: int # not in NetBSD or DragonFlyBSD + # not in FreeBSD, NetBSD, or DragonFlyBSD + HCI_TIME_STAMP: int + HCI_DATA_DIR: int + +if sys.platform == "darwin": + # PF_SYSTEM is defined by macOS + PF_SYSTEM: int + SYSPROTO_CONTROL: int + +# ----- Exceptions ----- + +error = OSError + +class herror(error): ... +class gaierror(error): ... + +if sys.version_info >= (3, 10): + timeout = TimeoutError +else: + class timeout(error): ... + +# ----- Classes ----- + +class socket: + family: int + type: int + proto: int + def __init__(self, family: int = ..., type: int = ..., proto: int = ..., fileno: _FD | None = ...) -> None: ... + def bind(self, __address: _Address | bytes) -> None: ... + def close(self) -> None: ... + def connect(self, __address: _Address | bytes) -> None: ... + def connect_ex(self, __address: _Address | bytes) -> int: ... + def detach(self) -> int: ... + def fileno(self) -> int: ... + def getpeername(self) -> _RetAddress: ... + def getsockname(self) -> _RetAddress: ... + @overload + def getsockopt(self, __level: int, __optname: int) -> int: ... + @overload + def getsockopt(self, __level: int, __optname: int, __buflen: int) -> bytes: ... + if sys.version_info >= (3, 7): + def getblocking(self) -> bool: ... + def gettimeout(self) -> float | None: ... + if sys.platform == "win32": + def ioctl(self, __control: int, __option: int | tuple[int, int, int] | bool) -> None: ... + def listen(self, __backlog: int = ...) -> None: ... + def recv(self, __bufsize: int, __flags: int = ...) -> bytes: ... + def recvfrom(self, __bufsize: int, __flags: int = ...) -> tuple[bytes, _RetAddress]: ... + if sys.platform != "win32": + def recvmsg(self, __bufsize: int, __ancbufsize: int = ..., __flags: int = ...) -> tuple[bytes, list[_CMSG], int, Any]: ... + def recvmsg_into( + self, __buffers: Iterable[WriteableBuffer], __ancbufsize: int = ..., __flags: int = ... + ) -> tuple[int, list[_CMSG], int, Any]: ... + def recvfrom_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ... + def recv_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> int: ... + def send(self, __data: ReadableBuffer, __flags: int = ...) -> int: ... + def sendall(self, __data: ReadableBuffer, __flags: int = ...) -> None: ... + @overload + def sendto(self, __data: ReadableBuffer, __address: _Address) -> int: ... + @overload + def sendto(self, __data: ReadableBuffer, __flags: int, __address: _Address) -> int: ... + if sys.platform != "win32": + def sendmsg( + self, + __buffers: Iterable[ReadableBuffer], + __ancdata: Iterable[_CMSGArg] = ..., + __flags: int = ..., + __address: _Address = ..., + ) -> int: ... + if sys.platform == "linux": + def sendmsg_afalg( + self, msg: Iterable[ReadableBuffer] = ..., *, op: int, iv: Any = ..., assoclen: int = ..., flags: int = ... + ) -> int: ... + def setblocking(self, __flag: bool) -> None: ... + def settimeout(self, __value: float | None) -> None: ... + @overload + def setsockopt(self, __level: int, __optname: int, __value: int | bytes) -> None: ... + @overload + def setsockopt(self, __level: int, __optname: int, __value: None, __optlen: int) -> None: ... + if sys.platform == "win32": + def share(self, __process_id: int) -> bytes: ... + def shutdown(self, __how: int) -> None: ... + +SocketType = socket + +# ----- Functions ----- + +if sys.version_info >= (3, 7): + def close(__fd: _FD) -> None: ... + +def dup(__fd: _FD) -> int: ... + +# the 5th tuple item is an address +def getaddrinfo( + host: bytes | str | None, + port: bytes | str | int | None, + family: int = ..., + type: int = ..., + proto: int = ..., + flags: int = ..., +) -> list[tuple[int, int, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... +def gethostbyname(__hostname: str) -> str: ... +def gethostbyname_ex(__hostname: str) -> tuple[str, list[str], list[str]]: ... +def gethostname() -> str: ... +def gethostbyaddr(__ip_address: str) -> tuple[str, list[str], list[str]]: ... +def getnameinfo(__sockaddr: tuple[str, int] | tuple[str, int, int, int], __flags: int) -> tuple[str, str]: ... +def getprotobyname(__protocolname: str) -> int: ... +def getservbyname(__servicename: str, __protocolname: str = ...) -> int: ... +def getservbyport(__port: int, __protocolname: str = ...) -> str: ... +def ntohl(__x: int) -> int: ... # param & ret val are 32-bit ints +def ntohs(__x: int) -> int: ... # param & ret val are 16-bit ints +def htonl(__x: int) -> int: ... # param & ret val are 32-bit ints +def htons(__x: int) -> int: ... # param & ret val are 16-bit ints +def inet_aton(__ip_string: str) -> bytes: ... # ret val 4 bytes in length +def inet_ntoa(__packed_ip: bytes) -> str: ... +def inet_pton(__address_family: int, __ip_string: str) -> bytes: ... +def inet_ntop(__address_family: int, __packed_ip: bytes) -> str: ... +def CMSG_LEN(__length: int) -> int: ... +def CMSG_SPACE(__length: int) -> int: ... +def getdefaulttimeout() -> float | None: ... +def setdefaulttimeout(__timeout: float | None) -> None: ... +def socketpair(__family: int = ..., __type: int = ..., __proto: int = ...) -> tuple[socket, socket]: ... + +if sys.platform != "win32": + def sethostname(__name: str) -> None: ... + +# Windows added these in 3.8, but didn't have them before +if sys.platform != "win32" or sys.version_info >= (3, 8): + def if_nameindex() -> list[tuple[int, str]]: ... + def if_nametoindex(__name: str) -> int: ... + def if_indextoname(__index: int) -> str: ... diff --git a/mypy/typeshed/stdlib/_thread.pyi b/mypy/typeshed/stdlib/_thread.pyi index 513678499223..2f4252981b68 100644 --- a/mypy/typeshed/stdlib/_thread.pyi +++ b/mypy/typeshed/stdlib/_thread.pyi @@ -1,7 +1,8 @@ import sys from threading import Thread from types import TracebackType -from typing import Any, Callable, Dict, NoReturn, Optional, Tuple, Type +from typing import Any, Callable, NoReturn, Optional, Tuple, Type +from typing_extensions import final error = RuntimeError @@ -9,16 +10,17 @@ def _count() -> int: ... _dangling: Any +@final class LockType: def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... def locked(self) -> bool: ... def __enter__(self) -> bool: ... def __exit__( - self, type: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType] + self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any] = ...) -> int: ... +def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ... def interrupt_main() -> None: ... def exit() -> NoReturn: ... def allocate_lock() -> LockType: ... @@ -29,13 +31,14 @@ TIMEOUT_MAX: float if sys.version_info >= (3, 8): def get_native_id() -> int: ... # only available on some platforms + @final class _ExceptHookArgs(Tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]]): @property def exc_type(self) -> Type[BaseException]: ... @property - def exc_value(self) -> Optional[BaseException]: ... + def exc_value(self) -> BaseException | None: ... @property - def exc_traceback(self) -> Optional[TracebackType]: ... + def exc_traceback(self) -> TracebackType | None: ... @property - def thread(self) -> Optional[Thread]: ... + def thread(self) -> Thread | None: ... _excepthook: Callable[[_ExceptHookArgs], Any] diff --git a/mypy/typeshed/stdlib/_threading_local.pyi b/mypy/typeshed/stdlib/_threading_local.pyi index ed6eb8d9513e..bab69a7c2e7d 100644 --- a/mypy/typeshed/stdlib/_threading_local.pyi +++ b/mypy/typeshed/stdlib/_threading_local.pyi @@ -1,11 +1,11 @@ -from typing import Any, Dict, Tuple +from typing import Any, Dict from weakref import ReferenceType localdict = Dict[Any, Any] class _localimpl: key: str - dicts: Dict[int, Tuple[ReferenceType[Any], localdict]] + dicts: dict[int, tuple[ReferenceType[Any], localdict]] def __init__(self) -> None: ... def get_dict(self) -> localdict: ... def create_dict(self) -> localdict: ... diff --git a/mypy/typeshed/stdlib/_tkinter.pyi b/mypy/typeshed/stdlib/_tkinter.pyi index 378b04202c4f..e97edf5b4fae 100644 --- a/mypy/typeshed/stdlib/_tkinter.pyi +++ b/mypy/typeshed/stdlib/_tkinter.pyi @@ -1,5 +1,5 @@ from typing import Any -from typing_extensions import Literal +from typing_extensions import Literal, final # _tkinter is meant to be only used internally by tkinter, but some tkinter # functions e.g. return _tkinter.Tcl_Obj objects. Tcl_Obj represents a Tcl @@ -14,6 +14,7 @@ from typing_extensions import Literal # >>> text.tag_add('foo', '1.0', 'end') # >>> text.tag_ranges('foo') # (, ) +@final class Tcl_Obj: string: str # str(tclobj) returns this typename: str @@ -37,6 +38,7 @@ class TclError(Exception): ... # # eval always returns str because _tkinter_tkapp_eval_impl in _tkinter.c calls # Tkapp_UnicodeResult, and it returns a string when it succeeds. +@final class TkappType: # Please keep in sync with tkinter.Tk def call(self, __command: Any, *args: Any) -> Any: ... diff --git a/mypy/typeshed/stdlib/_tracemalloc.pyi b/mypy/typeshed/stdlib/_tracemalloc.pyi index 4319ed46da64..fd159dc586cb 100644 --- a/mypy/typeshed/stdlib/_tracemalloc.pyi +++ b/mypy/typeshed/stdlib/_tracemalloc.pyi @@ -1,12 +1,12 @@ import sys from tracemalloc import _FrameTupleT, _TraceTupleT -from typing import Optional, Sequence, Tuple +from typing import Sequence -def _get_object_traceback(__obj: object) -> Optional[Sequence[_FrameTupleT]]: ... +def _get_object_traceback(__obj: object) -> Sequence[_FrameTupleT] | None: ... def _get_traces() -> Sequence[_TraceTupleT]: ... def clear_traces() -> None: ... def get_traceback_limit() -> int: ... -def get_traced_memory() -> Tuple[int, int]: ... +def get_traced_memory() -> tuple[int, int]: ... def get_tracemalloc_memory() -> int: ... def is_tracing() -> bool: ... diff --git a/mypy/typeshed/stdlib/_typeshed/README.md b/mypy/typeshed/stdlib/_typeshed/README.md new file mode 100644 index 000000000000..f4808944fa7b --- /dev/null +++ b/mypy/typeshed/stdlib/_typeshed/README.md @@ -0,0 +1,34 @@ +# Utility types for typeshed + +This package and its submodules contains various common types used by +typeshed. It can also be used by packages outside typeshed, but beware +the API stability guarantees below. + +## Usage + +The `_typeshed` package and its types do not exist at runtime, but can be +used freely in stubs (`.pyi`) files. To import the types from this package in +implementation (`.py`) files, use the following construct: + +```python +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from _typeshed import ... +``` + +Types can then be used in annotations by either quoting them or +using: + +```python +from __future__ import annotations +``` + +## API Stability + +You can use this package and its submodules outside of typeshed, but we +guarantee only limited API stability. Items marked as "stable" will not be +removed or changed in an incompatible way for at least one year. +Before making such a change, the "stable" moniker will be removed +and we will mark the type in question as deprecated. No guarantees +are made about unmarked types. diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index 948d4269f575..0d4c42afc285 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -1,21 +1,13 @@ # Utility types for typeshed - -# This module contains various common types to be used by typeshed. The -# module and its types do not exist at runtime. You can use this module -# outside of typeshed, but no API stability guarantees are made. To use -# it in implementation (.py) files, the following construct must be used: -# -# from typing import TYPE_CHECKING -# if TYPE_CHECKING: -# from _typeshed import ... # -# If on Python versions < 3.10 and "from __future__ import annotations" -# is not used, types from this module must be quoted. +# See the README.md file in this directory for more information. import array +import ctypes import mmap import sys -from typing import AbstractSet, Any, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union +from os import PathLike +from typing import AbstractSet, Any, Awaitable, Container, Iterable, Protocol, TypeVar, Union from typing_extensions import Literal, final _KT = TypeVar("_KT") @@ -23,52 +15,93 @@ _KT_co = TypeVar("_KT_co", covariant=True) _KT_contra = TypeVar("_KT_contra", contravariant=True) _VT = TypeVar("_VT") _VT_co = TypeVar("_VT_co", covariant=True) +_T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) +# Use for "self" annotations: +# def __enter__(self: Self) -> Self: ... +Self = TypeVar("Self") # noqa Y001 + +# stable +class IdentityFunction(Protocol): + def __call__(self, __x: _T) -> _T: ... + +# stable +class SupportsNext(Protocol[_T_co]): + def __next__(self) -> _T_co: ... + +# stable +class SupportsAnext(Protocol[_T_co]): + def __anext__(self) -> Awaitable[_T_co]: ... + class SupportsLessThan(Protocol): def __lt__(self, __other: Any) -> bool: ... SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001 +class SupportsGreaterThan(Protocol): + def __gt__(self, __other: Any) -> bool: ... + +SupportsGreaterThanT = TypeVar("SupportsGreaterThanT", bound=SupportsGreaterThan) # noqa: Y001 + +# Comparison protocols + +class SupportsDunderLT(Protocol): + def __lt__(self, __other: Any) -> Any: ... + +class SupportsDunderGT(Protocol): + def __gt__(self, __other: Any) -> Any: ... + +class SupportsDunderLE(Protocol): + def __le__(self, __other: Any) -> Any: ... + +class SupportsDunderGE(Protocol): + def __ge__(self, __other: Any) -> Any: ... + +class SupportsAllComparisons(SupportsDunderLT, SupportsDunderGT, SupportsDunderLE, SupportsDunderGE, Protocol): ... + +SupportsRichComparison = Union[SupportsDunderLT, SupportsDunderGT] +SupportsRichComparisonT = TypeVar("SupportsRichComparisonT", bound=SupportsRichComparison) # noqa: Y001 +SupportsAnyComparison = Union[SupportsDunderLE, SupportsDunderGE, SupportsDunderGT, SupportsDunderLT] + class SupportsDivMod(Protocol[_T_contra, _T_co]): def __divmod__(self, __other: _T_contra) -> _T_co: ... class SupportsRDivMod(Protocol[_T_contra, _T_co]): def __rdivmod__(self, __other: _T_contra) -> _T_co: ... +class SupportsLenAndGetItem(Protocol[_T_co]): + def __len__(self) -> int: ... + def __getitem__(self, __k: int) -> _T_co: ... + +class SupportsTrunc(Protocol): + def __trunc__(self) -> int: ... + # Mapping-like protocols +# stable class SupportsItems(Protocol[_KT_co, _VT_co]): - if sys.version_info >= (3,): - def items(self) -> AbstractSet[Tuple[_KT_co, _VT_co]]: ... - else: - # We want dictionaries to support this on Python 2. - def items(self) -> Iterable[Tuple[_KT_co, _VT_co]]: ... + def items(self) -> AbstractSet[tuple[_KT_co, _VT_co]]: ... +# stable class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]): def keys(self) -> Iterable[_KT]: ... def __getitem__(self, __k: _KT) -> _VT_co: ... +# stable class SupportsGetItem(Container[_KT_contra], Protocol[_KT_contra, _VT_co]): def __getitem__(self, __k: _KT_contra) -> _VT_co: ... +# stable class SupportsItemAccess(SupportsGetItem[_KT_contra, _VT], Protocol[_KT_contra, _VT]): def __setitem__(self, __k: _KT_contra, __v: _VT) -> None: ... def __delitem__(self, __v: _KT_contra) -> None: ... -# StrPath and AnyPath can be used in places where a -# path can be used instead of a string, starting with Python 3.6. -if sys.version_info >= (3, 6): - from os import PathLike - - StrPath = Union[str, PathLike[str]] - BytesPath = Union[bytes, PathLike[bytes]] - AnyPath = Union[str, bytes, PathLike[str], PathLike[bytes]] -else: - StrPath = Text - BytesPath = bytes - AnyPath = Union[Text, bytes] +# These aliases are simple strings in Python 2. +StrPath = Union[str, PathLike[str]] # stable +BytesPath = Union[bytes, PathLike[bytes]] # stable +StrOrBytesPath = Union[str, bytes, PathLike[str], PathLike[bytes]] # stable OpenTextModeUpdating = Literal[ "r+", @@ -137,31 +170,38 @@ OpenBinaryModeWriting = Literal["wb", "bw", "ab", "ba", "xb", "bx"] OpenBinaryModeReading = Literal["rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr"] OpenBinaryMode = Union[OpenBinaryModeUpdating, OpenBinaryModeReading, OpenBinaryModeWriting] +# stable class HasFileno(Protocol): def fileno(self) -> int: ... -FileDescriptor = int -FileDescriptorLike = Union[int, HasFileno] +FileDescriptor = int # stable +FileDescriptorLike = Union[int, HasFileno] # stable +# stable class SupportsRead(Protocol[_T_co]): def read(self, __length: int = ...) -> _T_co: ... +# stable class SupportsReadline(Protocol[_T_co]): def readline(self, __length: int = ...) -> _T_co: ... +# stable class SupportsNoArgReadline(Protocol[_T_co]): def readline(self) -> _T_co: ... +# stable class SupportsWrite(Protocol[_T_contra]): def write(self, __s: _T_contra) -> Any: ... -if sys.version_info >= (3,): - ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap] - WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap] -else: - ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap, buffer] - WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap, buffer] +ReadOnlyBuffer = bytes # stable +# Anything that implements the read-write buffer interface. +# The buffer interface is defined purely on the C level, so we cannot define a normal Protocol +# for it. Instead we have to list the most common stdlib buffer classes in a Union. +WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap, ctypes._CData] # stable +# Same as _WriteableBuffer, but also includes read-only buffer types (like bytes). +ReadableBuffer = Union[ReadOnlyBuffer, WriteableBuffer] # stable +# stable if sys.version_info >= (3, 10): from types import NoneType as NoneType else: diff --git a/mypy/typeshed/stdlib/_typeshed/tkinter.pyi b/mypy/typeshed/stdlib/_typeshed/tkinter.pyi deleted file mode 100644 index 565635adbb74..000000000000 --- a/mypy/typeshed/stdlib/_typeshed/tkinter.pyi +++ /dev/null @@ -1,7 +0,0 @@ -import sys -from typing import Optional, Protocol - -if sys.version_info >= (3,): - from tkinter import Event, Misc, Widget - class DndSource(Protocol): - def dnd_end(self, target: Optional[Widget], event: Optional[Event[Misc]]) -> None: ... diff --git a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi index bafaf7bc5f66..658b0fed2c6c 100644 --- a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi +++ b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi @@ -1,31 +1,31 @@ # Types to support PEP 3333 (WSGI) # -# This module doesn't exist at runtime and neither do the types defined in this -# file. They are provided for type checking purposes. +# See the README.md file in this directory for more information. from sys import _OptExcInfo -from typing import Any, Callable, Dict, Iterable, List, Optional, Protocol, Text, Tuple +from typing import Any, Callable, Dict, Iterable, Protocol +# stable class StartResponse(Protocol): def __call__( - self, status: str, headers: List[Tuple[str, str]], exc_info: Optional[_OptExcInfo] = ... + self, status: str, headers: list[tuple[str, str]], exc_info: _OptExcInfo | None = ... ) -> Callable[[bytes], Any]: ... -WSGIEnvironment = Dict[Text, Any] -WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] +WSGIEnvironment = Dict[str, Any] # stable +WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable -# WSGI input streams per PEP 3333 +# WSGI input streams per PEP 3333, stable class InputStream(Protocol): def read(self, size: int = ...) -> bytes: ... def readline(self, size: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> List[bytes]: ... + def readlines(self, hint: int = ...) -> list[bytes]: ... def __iter__(self) -> Iterable[bytes]: ... -# WSGI error streams per PEP 3333 +# WSGI error streams per PEP 3333, stable class ErrorStream(Protocol): def flush(self) -> None: ... def write(self, s: str) -> None: ... - def writelines(self, seq: List[str]) -> None: ... + def writelines(self, seq: list[str]) -> None: ... class _Readable(Protocol): def read(self, size: int = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/_typeshed/xml.pyi b/mypy/typeshed/stdlib/_typeshed/xml.pyi index 7ad28aef1b75..d53b743af2d3 100644 --- a/mypy/typeshed/stdlib/_typeshed/xml.pyi +++ b/mypy/typeshed/stdlib/_typeshed/xml.pyi @@ -1,10 +1,10 @@ -# Stub-only types. This module does not exist at runtime. +# See the README.md file in this directory for more information. -from typing import Any, Optional +from typing import Any from typing_extensions import Protocol # As defined https://docs.python.org/3/library/xml.dom.html#domimplementation-objects class DOMImplementation(Protocol): - def hasFeature(self, feature: str, version: Optional[str]) -> bool: ... - def createDocument(self, namespaceUri: str, qualifiedName: str, doctype: Optional[Any]) -> Any: ... + def hasFeature(self, feature: str, version: str | None) -> bool: ... + def createDocument(self, namespaceUri: str, qualifiedName: str, doctype: Any | None) -> Any: ... def createDocumentType(self, qualifiedName: str, publicId: str, systemId: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/_warnings.pyi b/mypy/typeshed/stdlib/_warnings.pyi index b4ec4e6ee794..e5b180b14fea 100644 --- a/mypy/typeshed/stdlib/_warnings.pyi +++ b/mypy/typeshed/stdlib/_warnings.pyi @@ -1,67 +1,32 @@ -import sys -from typing import Any, Dict, List, Optional, Tuple, Type, Union, overload +from typing import Any, Type, overload -if sys.version_info >= (3, 0): - _defaultaction: str - _onceregistry: Dict[Any, Any] -else: - default_action: str - once_registry: Dict[Any, Any] +_defaultaction: str +_onceregistry: dict[Any, Any] +filters: list[tuple[str, str | None, Type[Warning], str | None, int]] -filters: List[Tuple[Any, ...]] - -if sys.version_info >= (3, 6): - @overload - def warn( - message: str, category: Optional[Type[Warning]] = ..., stacklevel: int = ..., source: Optional[Any] = ... - ) -> None: ... - @overload - def warn(message: Warning, category: Any = ..., stacklevel: int = ..., source: Optional[Any] = ...) -> None: ... - @overload - def warn_explicit( - message: str, - category: Type[Warning], - filename: str, - lineno: int, - module: Optional[str] = ..., - registry: Optional[Dict[Union[str, Tuple[str, Type[Warning], int]], int]] = ..., - module_globals: Optional[Dict[str, Any]] = ..., - source: Optional[Any] = ..., - ) -> None: ... - @overload - def warn_explicit( - message: Warning, - category: Any, - filename: str, - lineno: int, - module: Optional[str] = ..., - registry: Optional[Dict[Union[str, Tuple[str, Type[Warning], int]], int]] = ..., - module_globals: Optional[Dict[str, Any]] = ..., - source: Optional[Any] = ..., - ) -> None: ... - -else: - @overload - def warn(message: str, category: Optional[Type[Warning]] = ..., stacklevel: int = ...) -> None: ... - @overload - def warn(message: Warning, category: Any = ..., stacklevel: int = ...) -> None: ... - @overload - def warn_explicit( - message: str, - category: Type[Warning], - filename: str, - lineno: int, - module: Optional[str] = ..., - registry: Optional[Dict[Union[str, Tuple[str, Type[Warning], int]], int]] = ..., - module_globals: Optional[Dict[str, Any]] = ..., - ) -> None: ... - @overload - def warn_explicit( - message: Warning, - category: Any, - filename: str, - lineno: int, - module: Optional[str] = ..., - registry: Optional[Dict[Union[str, Tuple[str, Type[Warning], int]], int]] = ..., - module_globals: Optional[Dict[str, Any]] = ..., - ) -> None: ... +@overload +def warn(message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ...) -> None: ... +@overload +def warn(message: Warning, category: Any = ..., stacklevel: int = ..., source: Any | None = ...) -> None: ... +@overload +def warn_explicit( + message: str, + category: Type[Warning], + filename: str, + lineno: int, + module: str | None = ..., + registry: dict[str | tuple[str, Type[Warning], int], int] | None = ..., + module_globals: dict[str, Any] | None = ..., + source: Any | None = ..., +) -> None: ... +@overload +def warn_explicit( + message: Warning, + category: Any, + filename: str, + lineno: int, + module: str | None = ..., + registry: dict[str | tuple[str, Type[Warning], int], int] | None = ..., + module_globals: dict[str, Any] | None = ..., + source: Any | None = ..., +) -> None: ... diff --git a/mypy/typeshed/stdlib/_weakref.pyi b/mypy/typeshed/stdlib/_weakref.pyi index 115a591ce4c8..dcaef25b3f0f 100644 --- a/mypy/typeshed/stdlib/_weakref.pyi +++ b/mypy/typeshed/stdlib/_weakref.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, Generic, List, Optional, TypeVar, overload +from typing import Any, Callable, Generic, TypeVar, overload +from typing_extensions import final if sys.version_info >= (3, 9): from types import GenericAlias @@ -7,17 +8,18 @@ if sys.version_info >= (3, 9): _C = TypeVar("_C", bound=Callable[..., Any]) _T = TypeVar("_T") +@final class CallableProxyType(Generic[_C]): # "weakcallableproxy" def __getattr__(self, attr: str) -> Any: ... +@final class ProxyType(Generic[_T]): # "weakproxy" def __getattr__(self, attr: str) -> Any: ... class ReferenceType(Generic[_T]): - if sys.version_info >= (3, 4): - __callback__: Callable[[ReferenceType[_T]], Any] - def __init__(self, o: _T, callback: Optional[Callable[[ReferenceType[_T]], Any]] = ...) -> None: ... - def __call__(self) -> Optional[_T]: ... + __callback__: Callable[[ReferenceType[_T]], Any] + def __init__(self, o: _T, callback: Callable[[ReferenceType[_T]], Any] | None = ...) -> None: ... + def __call__(self) -> _T | None: ... def __hash__(self) -> int: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -25,10 +27,10 @@ class ReferenceType(Generic[_T]): ref = ReferenceType def getweakrefcount(__object: Any) -> int: ... -def getweakrefs(object: Any) -> List[Any]: ... +def getweakrefs(object: Any) -> list[Any]: ... @overload -def proxy(object: _C, callback: Optional[Callable[[_C], Any]] = ...) -> CallableProxyType[_C]: ... +def proxy(object: _C, callback: Callable[[_C], Any] | None = ...) -> CallableProxyType[_C]: ... # Return CallableProxyType if object is callable, ProxyType otherwise @overload -def proxy(object: _T, callback: Optional[Callable[[_T], Any]] = ...) -> Any: ... +def proxy(object: _T, callback: Callable[[_T], Any] | None = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/_weakrefset.pyi b/mypy/typeshed/stdlib/_weakrefset.pyi index c369584aa243..1f0132f4c240 100644 --- a/mypy/typeshed/stdlib/_weakrefset.pyi +++ b/mypy/typeshed/stdlib/_weakrefset.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Generic, Iterable, Iterator, MutableSet, Optional, TypeVar, Union +from typing import Any, Generic, Iterable, Iterator, MutableSet, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -9,7 +9,7 @@ _T = TypeVar("_T") _SelfT = TypeVar("_SelfT", bound=WeakSet[Any]) class WeakSet(MutableSet[_T], Generic[_T]): - def __init__(self, data: Optional[Iterable[_T]] = ...) -> None: ... + def __init__(self, data: Iterable[_T] | None = ...) -> None: ... def add(self, item: _T) -> None: ... def clear(self) -> None: ... def discard(self, item: _T) -> None: ... @@ -20,7 +20,7 @@ class WeakSet(MutableSet[_T], Generic[_T]): def __contains__(self, item: object) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __ior__(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... + def __ior__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def difference(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... def __sub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... def difference_update(self, other: Iterable[_T]) -> None: ... @@ -36,12 +36,12 @@ class WeakSet(MutableSet[_T], Generic[_T]): def __ge__(self, other: Iterable[_T]) -> bool: ... def __gt__(self, other: Iterable[_T]) -> bool: ... def __eq__(self, other: object) -> bool: ... - def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... - def __xor__(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... + def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def __xor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def symmetric_difference_update(self, other: Iterable[Any]) -> None: ... - def __ixor__(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... - def union(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... - def __or__(self, other: Iterable[_S]) -> WeakSet[Union[_S, _T]]: ... + def __ixor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def union(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def __or__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def isdisjoint(self, other: Iterable[_T]) -> bool: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... diff --git a/mypy/typeshed/stdlib/_winapi.pyi b/mypy/typeshed/stdlib/_winapi.pyi index 09245b5218c1..83089d485c17 100644 --- a/mypy/typeshed/stdlib/_winapi.pyi +++ b/mypy/typeshed/stdlib/_winapi.pyi @@ -1,6 +1,6 @@ import sys -from typing import Any, Dict, NoReturn, Optional, Sequence, Tuple, Union, overload -from typing_extensions import Literal +from typing import Any, NoReturn, Sequence, overload +from typing_extensions import Literal, final CREATE_NEW_CONSOLE: int CREATE_NEW_PROCESS_GROUP: int @@ -52,7 +52,7 @@ def ConnectNamedPipe(handle: int, overlapped: Literal[True]) -> Overlapped: ... @overload def ConnectNamedPipe(handle: int, overlapped: Literal[False] = ...) -> None: ... @overload -def ConnectNamedPipe(handle: int, overlapped: bool) -> Optional[Overlapped]: ... +def ConnectNamedPipe(handle: int, overlapped: bool) -> Overlapped | None: ... def CreateFile( __file_name: str, __desired_access: int, @@ -73,18 +73,18 @@ def CreateNamedPipe( __default_timeout: int, __security_attributes: int, ) -> int: ... -def CreatePipe(__pipe_attrs: Any, __size: int) -> Tuple[int, int]: ... +def CreatePipe(__pipe_attrs: Any, __size: int) -> tuple[int, int]: ... def CreateProcess( - __application_name: Optional[str], - __command_line: Optional[str], + __application_name: str | None, + __command_line: str | None, __proc_attrs: Any, __thread_attrs: Any, __inherit_handles: bool, __creation_flags: int, - __env_mapping: Dict[str, str], - __current_directory: Optional[str], + __env_mapping: dict[str, str], + __current_directory: str | None, __startup_info: Any, -) -> Tuple[int, int, int, int]: ... +) -> tuple[int, int, int, int]: ... def DuplicateHandle( __source_process_handle: int, __source_handle: int, @@ -106,29 +106,29 @@ def GetModuleFileName(__module_handle: int) -> str: ... def GetStdHandle(__std_handle: int) -> int: ... def GetVersion() -> int: ... def OpenProcess(__desired_access: int, __inherit_handle: bool, __process_id: int) -> int: ... -def PeekNamedPipe(__handle: int, __size: int = ...) -> Union[Tuple[int, int], Tuple[bytes, int, int]]: ... +def PeekNamedPipe(__handle: int, __size: int = ...) -> tuple[int, int] | tuple[bytes, int, int]: ... @overload -def ReadFile(handle: int, size: int, overlapped: Literal[True]) -> Tuple[Overlapped, int]: ... +def ReadFile(handle: int, size: int, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... @overload -def ReadFile(handle: int, size: int, overlapped: Literal[False] = ...) -> Tuple[bytes, int]: ... +def ReadFile(handle: int, size: int, overlapped: Literal[False] = ...) -> tuple[bytes, int]: ... @overload -def ReadFile(handle: int, size: int, overlapped: Union[int, bool]) -> Tuple[Any, int]: ... +def ReadFile(handle: int, size: int, overlapped: int | bool) -> tuple[Any, int]: ... def SetNamedPipeHandleState( - __named_pipe: int, __mode: Optional[int], __max_collection_count: Optional[int], __collect_data_timeout: Optional[int] + __named_pipe: int, __mode: int | None, __max_collection_count: int | None, __collect_data_timeout: int | None ) -> None: ... def TerminateProcess(__handle: int, __exit_code: int) -> None: ... def WaitForMultipleObjects(__handle_seq: Sequence[int], __wait_flag: bool, __milliseconds: int = ...) -> int: ... def WaitForSingleObject(__handle: int, __milliseconds: int) -> int: ... def WaitNamedPipe(__name: str, __timeout: int) -> None: ... @overload -def WriteFile(handle: int, buffer: bytes, overlapped: Literal[True]) -> Tuple[Overlapped, int]: ... +def WriteFile(handle: int, buffer: bytes, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... @overload -def WriteFile(handle: int, buffer: bytes, overlapped: Literal[False] = ...) -> Tuple[int, int]: ... +def WriteFile(handle: int, buffer: bytes, overlapped: Literal[False] = ...) -> tuple[int, int]: ... @overload -def WriteFile(handle: int, buffer: bytes, overlapped: Union[int, bool]) -> Tuple[Any, int]: ... - +def WriteFile(handle: int, buffer: bytes, overlapped: int | bool) -> tuple[Any, int]: ... +@final class Overlapped: - event: int = ... - def GetOverlappedResult(self, __wait: bool) -> Tuple[int, int]: ... + event: int + def GetOverlappedResult(self, __wait: bool) -> tuple[int, int]: ... def cancel(self) -> None: ... - def getbuffer(self) -> Optional[bytes]: ... + def getbuffer(self) -> bytes | None: ... diff --git a/mypy/typeshed/stdlib/abc.pyi b/mypy/typeshed/stdlib/abc.pyi index 5dd21763a9ce..7896e910c81f 100644 --- a/mypy/typeshed/stdlib/abc.pyi +++ b/mypy/typeshed/stdlib/abc.pyi @@ -1,10 +1,16 @@ -from typing import Any, Callable, Type, TypeVar +from _typeshed import SupportsWrite +from typing import Any, Callable, Tuple, Type, TypeVar _T = TypeVar("_T") _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) # These definitions have special processing in mypy class ABCMeta(type): + __abstractmethods__: frozenset[str] + def __init__(self, name: str, bases: Tuple[type, ...], namespace: dict[str, Any]) -> None: ... + def __instancecheck__(cls: ABCMeta, instance: Any) -> Any: ... + def __subclasscheck__(cls: ABCMeta, subclass: Any) -> Any: ... + def _dump_registry(cls: ABCMeta, file: SupportsWrite[str] | None = ...) -> None: ... def register(cls: ABCMeta, subclass: Type[_T]) -> Type[_T]: ... def abstractmethod(funcobj: _FuncT) -> _FuncT: ... diff --git a/mypy/typeshed/stdlib/aifc.pyi b/mypy/typeshed/stdlib/aifc.pyi index f812ac593e97..79f470a366bb 100644 --- a/mypy/typeshed/stdlib/aifc.pyi +++ b/mypy/typeshed/stdlib/aifc.pyi @@ -1,6 +1,7 @@ import sys +from _typeshed import Self from types import TracebackType -from typing import IO, Any, List, NamedTuple, Optional, Text, Tuple, Type, Union, overload +from typing import IO, Any, NamedTuple, Tuple, Type, Union, overload from typing_extensions import Literal class Error(Exception): ... @@ -13,16 +14,15 @@ class _aifc_params(NamedTuple): comptype: bytes compname: bytes -_File = Union[Text, IO[bytes]] +_File = Union[str, IO[bytes]] _Marker = Tuple[int, int, bytes] class Aifc_read: def __init__(self, f: _File) -> None: ... - if sys.version_info >= (3, 4): - def __enter__(self) -> Aifc_read: ... - def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... def initfp(self, file: IO[bytes]) -> None: ... def getfp(self) -> IO[bytes]: ... def rewind(self) -> None: ... @@ -35,7 +35,7 @@ class Aifc_read: def getcomptype(self) -> bytes: ... def getcompname(self) -> bytes: ... def getparams(self) -> _aifc_params: ... - def getmarkers(self) -> Optional[List[_Marker]]: ... + def getmarkers(self) -> list[_Marker] | None: ... def getmark(self, id: int) -> _Marker: ... def setpos(self, pos: int) -> None: ... def readframes(self, nframes: int) -> bytes: ... @@ -43,11 +43,10 @@ class Aifc_read: class Aifc_write: def __init__(self, f: _File) -> None: ... def __del__(self) -> None: ... - if sys.version_info >= (3, 4): - def __enter__(self) -> Aifc_write: ... - def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... def initfp(self, file: IO[bytes]) -> None: ... def aiff(self) -> None: ... def aifc(self) -> None: ... @@ -62,11 +61,11 @@ class Aifc_write: def setcomptype(self, comptype: bytes, compname: bytes) -> None: ... def getcomptype(self) -> bytes: ... def getcompname(self) -> bytes: ... - def setparams(self, params: Tuple[int, int, int, int, bytes, bytes]) -> None: ... + def setparams(self, params: tuple[int, int, int, int, bytes, bytes]) -> None: ... def getparams(self) -> _aifc_params: ... def setmark(self, id: int, pos: int, name: bytes) -> None: ... def getmark(self, id: int) -> _Marker: ... - def getmarkers(self) -> Optional[List[_Marker]]: ... + def getmarkers(self) -> list[_Marker] | None: ... def tell(self) -> int: ... def writeframesraw(self, data: Any) -> None: ... # Actual type for data is Buffer Protocol def writeframes(self, data: Any) -> None: ... @@ -77,7 +76,7 @@ def open(f: _File, mode: Literal["r", "rb"]) -> Aifc_read: ... @overload def open(f: _File, mode: Literal["w", "wb"]) -> Aifc_write: ... @overload -def open(f: _File, mode: Optional[str] = ...) -> Any: ... +def open(f: _File, mode: str | None = ...) -> Any: ... if sys.version_info < (3, 9): @overload @@ -85,4 +84,4 @@ if sys.version_info < (3, 9): @overload def openfp(f: _File, mode: Literal["w", "wb"]) -> Aifc_write: ... @overload - def openfp(f: _File, mode: Optional[str] = ...) -> Any: ... + def openfp(f: _File, mode: str | None = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/antigravity.pyi b/mypy/typeshed/stdlib/antigravity.pyi index 52e2c5d96bef..e30917511030 100644 --- a/mypy/typeshed/stdlib/antigravity.pyi +++ b/mypy/typeshed/stdlib/antigravity.pyi @@ -1,4 +1 @@ -import sys - -if sys.version_info >= (3, 0): - def geohash(latitude: float, longitude: float, datedow: bytes) -> None: ... +def geohash(latitude: float, longitude: float, datedow: bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index 9dceaabd4631..b9a09f56a812 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -3,32 +3,24 @@ from typing import ( IO, Any, Callable, - Dict, Generator, + Generic, Iterable, - List, NoReturn, - Optional, Pattern, Protocol, Sequence, - Text, Tuple, Type, TypeVar, - Union, overload, ) _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) +_ArgumentParserT = TypeVar("_ArgumentParserT", bound=ArgumentParser) _N = TypeVar("_N") -if sys.version_info >= (3,): - _Text = str -else: - _Text = Union[str, unicode] - ONE_OR_MORE: str OPTIONAL: str PARSER: str @@ -38,51 +30,49 @@ ZERO_OR_MORE: str _UNRECOGNIZED_ARGS_ATTR: str # undocumented class ArgumentError(Exception): - argument_name: Optional[str] + argument_name: str | None message: str - def __init__(self, argument: Optional[Action], message: str) -> None: ... + def __init__(self, argument: Action | None, message: str) -> None: ... # undocumented class _AttributeHolder: - def _get_kwargs(self) -> List[Tuple[str, Any]]: ... - def _get_args(self) -> List[Any]: ... + def _get_kwargs(self) -> list[tuple[str, Any]]: ... + def _get_args(self) -> list[Any]: ... # undocumented class _ActionsContainer: - description: Optional[_Text] - prefix_chars: _Text + description: str | None + prefix_chars: str argument_default: Any - conflict_handler: _Text - - _registries: Dict[_Text, Dict[Any, Any]] - _actions: List[Action] - _option_string_actions: Dict[_Text, Action] - _action_groups: List[_ArgumentGroup] - _mutually_exclusive_groups: List[_MutuallyExclusiveGroup] - _defaults: Dict[str, Any] + conflict_handler: str + + _registries: dict[str, dict[Any, Any]] + _actions: list[Action] + _option_string_actions: dict[str, Action] + _action_groups: list[_ArgumentGroup] + _mutually_exclusive_groups: list[_MutuallyExclusiveGroup] + _defaults: dict[str, Any] _negative_number_matcher: Pattern[str] - _has_negative_number_optionals: List[bool] - def __init__( - self, description: Optional[Text], prefix_chars: Text, argument_default: Any, conflict_handler: Text - ) -> None: ... - def register(self, registry_name: Text, value: Any, object: Any) -> None: ... - def _registry_get(self, registry_name: Text, value: Any, default: Any = ...) -> Any: ... + _has_negative_number_optionals: list[bool] + def __init__(self, description: str | None, prefix_chars: str, argument_default: Any, conflict_handler: str) -> None: ... + def register(self, registry_name: str, value: Any, object: Any) -> None: ... + def _registry_get(self, registry_name: str, value: Any, default: Any = ...) -> Any: ... def set_defaults(self, **kwargs: Any) -> None: ... - def get_default(self, dest: Text) -> Any: ... + def get_default(self, dest: str) -> Any: ... def add_argument( self, - *name_or_flags: Text, - action: Union[Text, Type[Action]] = ..., - nargs: Union[int, Text] = ..., + *name_or_flags: str, + action: str | Type[Action] = ..., + nargs: int | str = ..., const: Any = ..., default: Any = ..., - type: Union[Callable[[Text], _T], Callable[[str], _T], FileType] = ..., - choices: Iterable[_T] = ..., + type: Callable[[str], _T] | Callable[[str], _T] | FileType = ..., + choices: Iterable[_T] | None = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., - dest: Optional[Text] = ..., - version: Text = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., + dest: str | None = ..., + version: str = ..., **kwargs: Any, ) -> Action: ... def add_argument_group(self, *args: Any, **kwargs: Any) -> _ArgumentGroup: ... @@ -90,158 +80,168 @@ class _ActionsContainer: def _add_action(self, action: _ActionT) -> _ActionT: ... def _remove_action(self, action: Action) -> None: ... def _add_container_actions(self, container: _ActionsContainer) -> None: ... - def _get_positional_kwargs(self, dest: Text, **kwargs: Any) -> Dict[str, Any]: ... - def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ... - def _pop_action_class(self, kwargs: Any, default: Optional[Type[Action]] = ...) -> Type[Action]: ... - def _get_handler(self) -> Callable[[Action, Iterable[Tuple[Text, Action]]], Any]: ... + def _get_positional_kwargs(self, dest: str, **kwargs: Any) -> dict[str, Any]: ... + def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ... + def _pop_action_class(self, kwargs: Any, default: Type[Action] | None = ...) -> Type[Action]: ... + def _get_handler(self) -> Callable[[Action, Iterable[tuple[str, Action]]], Any]: ... def _check_conflict(self, action: Action) -> None: ... - def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> NoReturn: ... - def _handle_conflict_resolve(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> None: ... + def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[tuple[str, Action]]) -> NoReturn: ... + def _handle_conflict_resolve(self, action: Action, conflicting_actions: Iterable[tuple[str, Action]]) -> None: ... class _FormatterClass(Protocol): def __call__(self, prog: str) -> HelpFormatter: ... class ArgumentParser(_AttributeHolder, _ActionsContainer): - prog: _Text - usage: Optional[_Text] - epilog: Optional[_Text] + prog: str + usage: str | None + epilog: str | None formatter_class: _FormatterClass - fromfile_prefix_chars: Optional[_Text] + fromfile_prefix_chars: str | None add_help: bool - - if sys.version_info >= (3, 5): - allow_abbrev: bool + allow_abbrev: bool # undocumented _positionals: _ArgumentGroup _optionals: _ArgumentGroup - _subparsers: Optional[_ArgumentGroup] + _subparsers: _ArgumentGroup | None if sys.version_info >= (3, 9): def __init__( self, - prog: Optional[str] = ..., - usage: Optional[str] = ..., - description: Optional[str] = ..., - epilog: Optional[str] = ..., + prog: str | None = ..., + usage: str | None = ..., + description: str | None = ..., + epilog: str | None = ..., parents: Sequence[ArgumentParser] = ..., formatter_class: _FormatterClass = ..., prefix_chars: str = ..., - fromfile_prefix_chars: Optional[str] = ..., + fromfile_prefix_chars: str | None = ..., argument_default: Any = ..., conflict_handler: str = ..., add_help: bool = ..., allow_abbrev: bool = ..., exit_on_error: bool = ..., ) -> None: ... - elif sys.version_info >= (3, 5): + else: def __init__( self, - prog: Optional[str] = ..., - usage: Optional[str] = ..., - description: Optional[str] = ..., - epilog: Optional[str] = ..., + prog: str | None = ..., + usage: str | None = ..., + description: str | None = ..., + epilog: str | None = ..., parents: Sequence[ArgumentParser] = ..., formatter_class: _FormatterClass = ..., prefix_chars: str = ..., - fromfile_prefix_chars: Optional[str] = ..., + fromfile_prefix_chars: str | None = ..., argument_default: Any = ..., conflict_handler: str = ..., add_help: bool = ..., allow_abbrev: bool = ..., ) -> None: ... - else: - def __init__( - self, - prog: Optional[Text] = ..., - usage: Optional[Text] = ..., - description: Optional[Text] = ..., - epilog: Optional[Text] = ..., - parents: Sequence[ArgumentParser] = ..., - formatter_class: _FormatterClass = ..., - prefix_chars: Text = ..., - fromfile_prefix_chars: Optional[Text] = ..., - argument_default: Any = ..., - conflict_handler: Text = ..., - add_help: bool = ..., - ) -> None: ... # The type-ignores in these overloads should be temporary. See: # https://github.com/python/typeshed/pull/2643#issuecomment-442280277 @overload - def parse_args(self, args: Optional[Sequence[Text]] = ...) -> Namespace: ... + def parse_args(self, args: Sequence[str] | None = ...) -> Namespace: ... @overload - def parse_args(self, args: Optional[Sequence[Text]], namespace: None) -> Namespace: ... # type: ignore + def parse_args(self, args: Sequence[str] | None, namespace: None) -> Namespace: ... # type: ignore @overload - def parse_args(self, args: Optional[Sequence[Text]], namespace: _N) -> _N: ... + def parse_args(self, args: Sequence[str] | None, namespace: _N) -> _N: ... @overload def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore @overload def parse_args(self, *, namespace: _N) -> _N: ... if sys.version_info >= (3, 7): + @overload + def add_subparsers( + self: _ArgumentParserT, + *, + title: str = ..., + description: str | None = ..., + prog: str = ..., + action: Type[Action] = ..., + option_string: str = ..., + dest: str | None = ..., + required: bool = ..., + help: str | None = ..., + metavar: str | None = ..., + ) -> _SubParsersAction[_ArgumentParserT]: ... + @overload def add_subparsers( self, *, title: str = ..., - description: Optional[str] = ..., + description: str | None = ..., prog: str = ..., - parser_class: Type[ArgumentParser] = ..., + parser_class: Type[_ArgumentParserT] = ..., action: Type[Action] = ..., option_string: str = ..., - dest: Optional[str] = ..., + dest: str | None = ..., required: bool = ..., - help: Optional[str] = ..., - metavar: Optional[str] = ..., - ) -> _SubParsersAction: ... + help: str | None = ..., + metavar: str | None = ..., + ) -> _SubParsersAction[_ArgumentParserT]: ... else: + @overload + def add_subparsers( + self: _ArgumentParserT, + *, + title: str = ..., + description: str | None = ..., + prog: str = ..., + action: Type[Action] = ..., + option_string: str = ..., + dest: str | None = ..., + help: str | None = ..., + metavar: str | None = ..., + ) -> _SubParsersAction[_ArgumentParserT]: ... + @overload def add_subparsers( self, *, - title: Text = ..., - description: Optional[Text] = ..., - prog: Text = ..., - parser_class: Type[ArgumentParser] = ..., + title: str = ..., + description: str | None = ..., + prog: str = ..., + parser_class: Type[_ArgumentParserT] = ..., action: Type[Action] = ..., - option_string: Text = ..., - dest: Optional[Text] = ..., - help: Optional[Text] = ..., - metavar: Optional[Text] = ..., - ) -> _SubParsersAction: ... - def print_usage(self, file: Optional[IO[str]] = ...) -> None: ... - def print_help(self, file: Optional[IO[str]] = ...) -> None: ... + option_string: str = ..., + dest: str | None = ..., + help: str | None = ..., + metavar: str | None = ..., + ) -> _SubParsersAction[_ArgumentParserT]: ... + def print_usage(self, file: IO[str] | None = ...) -> None: ... + def print_help(self, file: IO[str] | None = ...) -> None: ... def format_usage(self) -> str: ... def format_help(self) -> str: ... def parse_known_args( - self, args: Optional[Sequence[Text]] = ..., namespace: Optional[Namespace] = ... - ) -> Tuple[Namespace, List[str]]: ... - def convert_arg_line_to_args(self, arg_line: Text) -> List[str]: ... - def exit(self, status: int = ..., message: Optional[Text] = ...) -> NoReturn: ... - def error(self, message: Text) -> NoReturn: ... + self, args: Sequence[str] | None = ..., namespace: Namespace | None = ... + ) -> tuple[Namespace, list[str]]: ... + def convert_arg_line_to_args(self, arg_line: str) -> list[str]: ... + def exit(self, status: int = ..., message: str | None = ...) -> NoReturn: ... + def error(self, message: str) -> NoReturn: ... if sys.version_info >= (3, 7): - def parse_intermixed_args( - self, args: Optional[Sequence[str]] = ..., namespace: Optional[Namespace] = ... - ) -> Namespace: ... + def parse_intermixed_args(self, args: Sequence[str] | None = ..., namespace: Namespace | None = ...) -> Namespace: ... def parse_known_intermixed_args( - self, args: Optional[Sequence[str]] = ..., namespace: Optional[Namespace] = ... - ) -> Tuple[Namespace, List[str]]: ... + self, args: Sequence[str] | None = ..., namespace: Namespace | None = ... + ) -> tuple[Namespace, list[str]]: ... # undocumented - def _get_optional_actions(self) -> List[Action]: ... - def _get_positional_actions(self) -> List[Action]: ... - def _parse_known_args(self, arg_strings: List[Text], namespace: Namespace) -> Tuple[Namespace, List[str]]: ... - def _read_args_from_files(self, arg_strings: List[Text]) -> List[Text]: ... - def _match_argument(self, action: Action, arg_strings_pattern: Text) -> int: ... - def _match_arguments_partial(self, actions: Sequence[Action], arg_strings_pattern: Text) -> List[int]: ... - def _parse_optional(self, arg_string: Text) -> Optional[Tuple[Optional[Action], Text, Optional[Text]]]: ... - def _get_option_tuples(self, option_string: Text) -> List[Tuple[Action, Text, Optional[Text]]]: ... - def _get_nargs_pattern(self, action: Action) -> _Text: ... - def _get_values(self, action: Action, arg_strings: List[Text]) -> Any: ... - def _get_value(self, action: Action, arg_string: Text) -> Any: ... + def _get_optional_actions(self) -> list[Action]: ... + def _get_positional_actions(self) -> list[Action]: ... + def _parse_known_args(self, arg_strings: list[str], namespace: Namespace) -> tuple[Namespace, list[str]]: ... + def _read_args_from_files(self, arg_strings: list[str]) -> list[str]: ... + def _match_argument(self, action: Action, arg_strings_pattern: str) -> int: ... + def _match_arguments_partial(self, actions: Sequence[Action], arg_strings_pattern: str) -> list[int]: ... + def _parse_optional(self, arg_string: str) -> tuple[Action | None, str, str | None] | None: ... + def _get_option_tuples(self, option_string: str) -> list[tuple[Action, str, str | None]]: ... + def _get_nargs_pattern(self, action: Action) -> str: ... + def _get_values(self, action: Action, arg_strings: list[str]) -> Any: ... + def _get_value(self, action: Action, arg_string: str) -> Any: ... def _check_value(self, action: Action, value: Any) -> None: ... def _get_formatter(self) -> HelpFormatter: ... - def _print_message(self, message: str, file: Optional[IO[str]] = ...) -> None: ... + def _print_message(self, message: str, file: IO[str] | None = ...) -> None: ... class HelpFormatter: # undocumented - _prog: _Text + _prog: str _indent_increment: int _max_help_position: int _width: int @@ -253,76 +253,68 @@ class HelpFormatter: _whitespace_matcher: Pattern[str] _long_break_matcher: Pattern[str] _Section: Type[Any] # Nested class - def __init__( - self, prog: Text, indent_increment: int = ..., max_help_position: int = ..., width: Optional[int] = ... - ) -> None: ... + def __init__(self, prog: str, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ...) -> None: ... def _indent(self) -> None: ... def _dedent(self) -> None: ... - def _add_item(self, func: Callable[..., _Text], args: Iterable[Any]) -> None: ... - def start_section(self, heading: Optional[Text]) -> None: ... + def _add_item(self, func: Callable[..., str], args: Iterable[Any]) -> None: ... + def start_section(self, heading: str | None) -> None: ... def end_section(self) -> None: ... - def add_text(self, text: Optional[Text]) -> None: ... + def add_text(self, text: str | None) -> None: ... def add_usage( - self, usage: Optional[Text], actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: Optional[Text] = ... + self, usage: str | None, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: str | None = ... ) -> None: ... def add_argument(self, action: Action) -> None: ... def add_arguments(self, actions: Iterable[Action]) -> None: ... - def format_help(self) -> _Text: ... - def _join_parts(self, part_strings: Iterable[Text]) -> _Text: ... + def format_help(self) -> str: ... + def _join_parts(self, part_strings: Iterable[str]) -> str: ... def _format_usage( - self, usage: Text, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: Optional[Text] - ) -> _Text: ... - def _format_actions_usage(self, actions: Iterable[Action], groups: Iterable[_ArgumentGroup]) -> _Text: ... - def _format_text(self, text: Text) -> _Text: ... - def _format_action(self, action: Action) -> _Text: ... - def _format_action_invocation(self, action: Action) -> _Text: ... - def _metavar_formatter(self, action: Action, default_metavar: Text) -> Callable[[int], Tuple[_Text, ...]]: ... - def _format_args(self, action: Action, default_metavar: Text) -> _Text: ... - def _expand_help(self, action: Action) -> _Text: ... + self, usage: str, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: str | None + ) -> str: ... + def _format_actions_usage(self, actions: Iterable[Action], groups: Iterable[_ArgumentGroup]) -> str: ... + def _format_text(self, text: str) -> str: ... + def _format_action(self, action: Action) -> str: ... + def _format_action_invocation(self, action: Action) -> str: ... + def _metavar_formatter(self, action: Action, default_metavar: str) -> Callable[[int], Tuple[str, ...]]: ... + def _format_args(self, action: Action, default_metavar: str) -> str: ... + def _expand_help(self, action: Action) -> str: ... def _iter_indented_subactions(self, action: Action) -> Generator[Action, None, None]: ... - def _split_lines(self, text: Text, width: int) -> List[_Text]: ... - def _fill_text(self, text: Text, width: int, indent: Text) -> _Text: ... - def _get_help_string(self, action: Action) -> Optional[_Text]: ... - def _get_default_metavar_for_optional(self, action: Action) -> _Text: ... - def _get_default_metavar_for_positional(self, action: Action) -> _Text: ... + def _split_lines(self, text: str, width: int) -> list[str]: ... + def _fill_text(self, text: str, width: int, indent: str) -> str: ... + def _get_help_string(self, action: Action) -> str | None: ... + def _get_default_metavar_for_optional(self, action: Action) -> str: ... + def _get_default_metavar_for_positional(self, action: Action) -> str: ... class RawDescriptionHelpFormatter(HelpFormatter): ... class RawTextHelpFormatter(RawDescriptionHelpFormatter): ... class ArgumentDefaultsHelpFormatter(HelpFormatter): ... - -if sys.version_info >= (3,): - class MetavarTypeHelpFormatter(HelpFormatter): ... +class MetavarTypeHelpFormatter(HelpFormatter): ... class Action(_AttributeHolder): - option_strings: Sequence[_Text] - dest: _Text - nargs: Optional[Union[int, _Text]] + option_strings: Sequence[str] + dest: str + nargs: int | str | None const: Any default: Any - type: Union[Callable[[str], Any], FileType, None] - choices: Optional[Iterable[Any]] + type: Callable[[str], Any] | FileType | None + choices: Iterable[Any] | None required: bool - help: Optional[_Text] - metavar: Optional[Union[_Text, Tuple[_Text, ...]]] + help: str | None + metavar: str | Tuple[str, ...] | None def __init__( self, - option_strings: Sequence[Text], - dest: Text, - nargs: Optional[Union[int, Text]] = ..., - const: Optional[_T] = ..., - default: Union[_T, str, None] = ..., - type: Optional[Union[Callable[[Text], _T], Callable[[str], _T], FileType]] = ..., - choices: Optional[Iterable[_T]] = ..., + option_strings: Sequence[str], + dest: str, + nargs: int | str | None = ..., + const: _T | None = ..., + default: _T | str | None = ..., + type: Callable[[str], _T] | Callable[[str], _T] | FileType | None = ..., + choices: Iterable[_T] | None = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... def __call__( - self, - parser: ArgumentParser, - namespace: Namespace, - values: Union[Text, Sequence[Any], None], - option_string: Optional[Text] = ..., + self, parser: ArgumentParser, namespace: Namespace, values: str | Sequence[Any] | None, option_string: str | None = ... ) -> None: ... if sys.version_info >= (3, 9): def format_usage(self) -> str: ... @@ -333,40 +325,35 @@ if sys.version_info >= (3, 9): self, option_strings: Sequence[str], dest: str, - default: Union[_T, str, None] = ..., - type: Optional[Union[Callable[[Text], _T], Callable[[str], _T], FileType]] = ..., - choices: Optional[Iterable[_T]] = ..., + default: _T | str | None = ..., + type: Callable[[str], _T] | Callable[[str], _T] | FileType | None = ..., + choices: Iterable[_T] | None = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... class Namespace(_AttributeHolder): def __init__(self, **kwargs: Any) -> None: ... - def __getattr__(self, name: Text) -> Any: ... - def __setattr__(self, name: Text, value: Any) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... def __contains__(self, key: str) -> bool: ... class FileType: # undocumented - _mode: _Text + _mode: str _bufsize: int - if sys.version_info >= (3,): - _encoding: Optional[str] - _errors: Optional[str] - def __init__( - self, mode: str = ..., bufsize: int = ..., encoding: Optional[str] = ..., errors: Optional[str] = ... - ) -> None: ... - else: - def __init__(self, mode: Text = ..., bufsize: Optional[int] = ...) -> None: ... - def __call__(self, string: Text) -> IO[Any]: ... + _encoding: str | None + _errors: str | None + def __init__(self, mode: str = ..., bufsize: int = ..., encoding: str | None = ..., errors: str | None = ...) -> None: ... + def __call__(self, string: str) -> IO[Any]: ... # undocumented class _ArgumentGroup(_ActionsContainer): - title: Optional[_Text] - _group_actions: List[Action] + title: str | None + _group_actions: list[Action] def __init__( - self, container: _ActionsContainer, title: Optional[Text] = ..., description: Optional[Text] = ..., **kwargs: Any + self, container: _ActionsContainer, title: str | None = ..., description: str | None = ..., **kwargs: Any ) -> None: ... # undocumented @@ -382,25 +369,25 @@ class _StoreAction(Action): ... class _StoreConstAction(Action): def __init__( self, - option_strings: Sequence[Text], - dest: Text, + option_strings: Sequence[str], + dest: str, const: Any, default: Any = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... # undocumented class _StoreTrueAction(_StoreConstAction): def __init__( - self, option_strings: Sequence[Text], dest: Text, default: bool = ..., required: bool = ..., help: Optional[Text] = ... + self, option_strings: Sequence[str], dest: str, default: bool = ..., required: bool = ..., help: str | None = ... ) -> None: ... # undocumented class _StoreFalseAction(_StoreConstAction): def __init__( - self, option_strings: Sequence[Text], dest: Text, default: bool = ..., required: bool = ..., help: Optional[Text] = ... + self, option_strings: Sequence[str], dest: str, default: bool = ..., required: bool = ..., help: str | None = ... ) -> None: ... # undocumented @@ -410,78 +397,71 @@ class _AppendAction(Action): ... class _AppendConstAction(Action): def __init__( self, - option_strings: Sequence[Text], - dest: Text, + option_strings: Sequence[str], + dest: str, const: Any, default: Any = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... # undocumented class _CountAction(Action): def __init__( - self, option_strings: Sequence[Text], dest: Text, default: Any = ..., required: bool = ..., help: Optional[Text] = ... + self, option_strings: Sequence[str], dest: str, default: Any = ..., required: bool = ..., help: str | None = ... ) -> None: ... # undocumented class _HelpAction(Action): - def __init__( - self, option_strings: Sequence[Text], dest: Text = ..., default: Text = ..., help: Optional[Text] = ... - ) -> None: ... + def __init__(self, option_strings: Sequence[str], dest: str = ..., default: str = ..., help: str | None = ...) -> None: ... # undocumented class _VersionAction(Action): - version: Optional[_Text] + version: str | None def __init__( - self, - option_strings: Sequence[Text], - version: Optional[Text] = ..., - dest: Text = ..., - default: Text = ..., - help: Text = ..., + self, option_strings: Sequence[str], version: str | None = ..., dest: str = ..., default: str = ..., help: str = ... ) -> None: ... # undocumented -class _SubParsersAction(Action): +class _SubParsersAction(Action, Generic[_ArgumentParserT]): _ChoicesPseudoAction: Type[Any] # nested class - _prog_prefix: _Text - _parser_class: Type[ArgumentParser] - _name_parser_map: Dict[_Text, ArgumentParser] - choices: Dict[_Text, ArgumentParser] - _choices_actions: List[Action] + _prog_prefix: str + _parser_class: Type[_ArgumentParserT] + _name_parser_map: dict[str, _ArgumentParserT] + choices: dict[str, _ArgumentParserT] + _choices_actions: list[Action] if sys.version_info >= (3, 7): def __init__( self, - option_strings: Sequence[Text], - prog: Text, - parser_class: Type[ArgumentParser], - dest: Text = ..., + option_strings: Sequence[str], + prog: str, + parser_class: Type[_ArgumentParserT], + dest: str = ..., required: bool = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... else: def __init__( self, - option_strings: Sequence[Text], - prog: Text, - parser_class: Type[ArgumentParser], - dest: Text = ..., - help: Optional[Text] = ..., - metavar: Optional[Union[Text, Tuple[Text, ...]]] = ..., + option_strings: Sequence[str], + prog: str, + parser_class: Type[_ArgumentParserT], + dest: str = ..., + help: str | None = ..., + metavar: str | Tuple[str, ...] | None = ..., ) -> None: ... # TODO: Type keyword args properly. - def add_parser(self, name: Text, **kwargs: Any) -> ArgumentParser: ... - def _get_subactions(self) -> List[Action]: ... + def add_parser(self, name: str, **kwargs: Any) -> _ArgumentParserT: ... + def _get_subactions(self) -> list[Action]: ... # undocumented class ArgumentTypeError(Exception): ... if sys.version_info < (3, 7): # undocumented - def _ensure_value(namespace: Namespace, name: Text, value: Any) -> Any: ... + def _ensure_value(namespace: Namespace, name: str, value: Any) -> Any: ... # undocumented -def _get_action_name(argument: Optional[Action]) -> Optional[str]: ... +def _get_action_name(argument: Action | None) -> str | None: ... diff --git a/mypy/typeshed/stdlib/array.pyi b/mypy/typeshed/stdlib/array.pyi index 498bf92919f1..6f4444b10f96 100644 --- a/mypy/typeshed/stdlib/array.pyi +++ b/mypy/typeshed/stdlib/array.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, BinaryIO, Generic, Iterable, List, MutableSequence, Text, Tuple, TypeVar, Union, overload +from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, TypeVar, Union, overload from typing_extensions import Literal _IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] @@ -7,31 +7,29 @@ _FloatTypeCode = Literal["f", "d"] _UnicodeTypeCode = Literal["u"] _TypeCode = Union[_IntTypeCode, _FloatTypeCode, _UnicodeTypeCode] -_T = TypeVar("_T", int, float, Text) +_T = TypeVar("_T", int, float, str) -if sys.version_info >= (3,): - typecodes: str +typecodes: str class array(MutableSequence[_T], Generic[_T]): typecode: _TypeCode itemsize: int @overload - def __init__(self: array[int], typecode: _IntTypeCode, __initializer: Union[bytes, Iterable[_T]] = ...) -> None: ... + def __init__(self: array[int], __typecode: _IntTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... @overload - def __init__(self: array[float], typecode: _FloatTypeCode, __initializer: Union[bytes, Iterable[_T]] = ...) -> None: ... + def __init__(self: array[float], __typecode: _FloatTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... @overload - def __init__(self: array[Text], typecode: _UnicodeTypeCode, __initializer: Union[bytes, Iterable[_T]] = ...) -> None: ... + def __init__(self: array[str], __typecode: _UnicodeTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... @overload - def __init__(self, typecode: str, __initializer: Union[bytes, Iterable[_T]] = ...) -> None: ... + def __init__(self, typecode: str, __initializer: bytes | Iterable[_T] = ...) -> None: ... def append(self, __v: _T) -> None: ... - def buffer_info(self) -> Tuple[int, int]: ... + def buffer_info(self) -> tuple[int, int]: ... def byteswap(self) -> None: ... def count(self, __v: Any) -> int: ... def extend(self, __bb: Iterable[_T]) -> None: ... - if sys.version_info >= (3, 2): - def frombytes(self, __buffer: bytes) -> None: ... + def frombytes(self, __buffer: bytes) -> None: ... def fromfile(self, __f: BinaryIO, __n: int) -> None: ... - def fromlist(self, __list: List[_T]) -> None: ... + def fromlist(self, __list: list[_T]) -> None: ... def fromunicode(self, __ustr: str) -> None: ... if sys.version_info >= (3, 10): def index(self, __v: _T, __start: int = ..., __stop: int = ...) -> int: ... @@ -39,42 +37,33 @@ class array(MutableSequence[_T], Generic[_T]): def index(self, __v: _T) -> int: ... # type: ignore # Overrides Sequence def insert(self, __i: int, __v: _T) -> None: ... def pop(self, __i: int = ...) -> _T: ... - if sys.version_info < (3,): - def read(self, f: BinaryIO, n: int) -> None: ... def remove(self, __v: Any) -> None: ... def reverse(self) -> None: ... - if sys.version_info >= (3, 2): - def tobytes(self) -> bytes: ... + def tobytes(self) -> bytes: ... def tofile(self, __f: BinaryIO) -> None: ... - def tolist(self) -> List[_T]: ... + def tolist(self) -> list[_T]: ... def tounicode(self) -> str: ... - if sys.version_info < (3,): - def write(self, f: BinaryIO) -> None: ... if sys.version_info < (3, 9): def fromstring(self, __buffer: bytes) -> None: ... def tostring(self) -> bytes: ... def __len__(self) -> int: ... @overload - def __getitem__(self, i: int) -> _T: ... + def __getitem__(self, __i: int) -> _T: ... @overload - def __getitem__(self, s: slice) -> array[_T]: ... + def __getitem__(self, __s: slice) -> array[_T]: ... @overload # type: ignore # Overrides MutableSequence - def __setitem__(self, i: int, o: _T) -> None: ... + def __setitem__(self, __i: int, __o: _T) -> None: ... @overload - def __setitem__(self, s: slice, o: array[_T]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... - def __add__(self, x: array[_T]) -> array[_T]: ... - def __ge__(self, other: array[_T]) -> bool: ... - def __gt__(self, other: array[_T]) -> bool: ... - def __iadd__(self, x: array[_T]) -> array[_T]: ... # type: ignore # Overrides MutableSequence - def __imul__(self, n: int) -> array[_T]: ... - def __le__(self, other: array[_T]) -> bool: ... - def __lt__(self, other: array[_T]) -> bool: ... - def __mul__(self, n: int) -> array[_T]: ... - def __rmul__(self, n: int) -> array[_T]: ... - if sys.version_info < (3,): - def __delslice__(self, i: int, j: int) -> None: ... - def __getslice__(self, i: int, j: int) -> array[_T]: ... - def __setslice__(self, i: int, j: int, y: array[_T]) -> None: ... + def __setitem__(self, __s: slice, __o: array[_T]) -> None: ... + def __delitem__(self, __i: int | slice) -> None: ... + def __add__(self, __x: array[_T]) -> array[_T]: ... + def __ge__(self, __other: array[_T]) -> bool: ... + def __gt__(self, __other: array[_T]) -> bool: ... + def __iadd__(self, __x: array[_T]) -> array[_T]: ... # type: ignore # Overrides MutableSequence + def __imul__(self, __n: int) -> array[_T]: ... + def __le__(self, __other: array[_T]) -> bool: ... + def __lt__(self, __other: array[_T]) -> bool: ... + def __mul__(self, __n: int) -> array[_T]: ... + def __rmul__(self, __n: int) -> array[_T]: ... ArrayType = array diff --git a/mypy/typeshed/stdlib/ast.pyi b/mypy/typeshed/stdlib/ast.pyi index ff1cd00c7757..00c62c30c037 100644 --- a/mypy/typeshed/stdlib/ast.pyi +++ b/mypy/typeshed/stdlib/ast.pyi @@ -8,10 +8,9 @@ # sys. import sys import typing as _typing -from typing import Any, Iterator, Optional, TypeVar, Union, overload -from typing_extensions import Literal - from _ast import * # type: ignore +from typing import Any, Iterator, TypeVar, overload +from typing_extensions import Literal if sys.version_info >= (3, 8): class Num(Constant): @@ -150,7 +149,7 @@ class NodeVisitor: class NodeTransformer(NodeVisitor): def generic_visit(self, node: AST) -> AST: ... # TODO: Override the visit_* methods with better return types. - # The usual return type is Optional[AST], but Iterable[AST] + # The usual return type is AST | None, but Iterable[AST] # is also allowed in some cases -- this needs to be mapped. _T = TypeVar("_T", bound=AST) @@ -158,28 +157,28 @@ _T = TypeVar("_T", bound=AST) if sys.version_info >= (3, 8): @overload def parse( - source: Union[str, bytes], - filename: Union[str, bytes] = ..., + source: str | bytes, + filename: str | bytes = ..., mode: Literal["exec"] = ..., *, type_comments: bool = ..., - feature_version: Union[None, int, _typing.Tuple[int, int]] = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., ) -> Module: ... @overload def parse( - source: Union[str, bytes], - filename: Union[str, bytes] = ..., + source: str | bytes, + filename: str | bytes = ..., mode: str = ..., *, type_comments: bool = ..., - feature_version: Union[None, int, _typing.Tuple[int, int]] = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., ) -> AST: ... else: @overload - def parse(source: Union[str, bytes], filename: Union[str, bytes] = ..., mode: Literal["exec"] = ...) -> Module: ... + def parse(source: str | bytes, filename: str | bytes = ..., mode: Literal["exec"] = ...) -> Module: ... @overload - def parse(source: Union[str, bytes], filename: Union[str, bytes] = ..., mode: str = ...) -> AST: ... + def parse(source: str | bytes, filename: str | bytes = ..., mode: str = ...) -> AST: ... if sys.version_info >= (3, 9): def unparse(ast_obj: AST) -> str: ... @@ -188,20 +187,20 @@ def copy_location(new_node: _T, old_node: AST) -> _T: ... if sys.version_info >= (3, 9): def dump( - node: AST, annotate_fields: bool = ..., include_attributes: bool = ..., *, indent: Union[int, str, None] = ... + node: AST, annotate_fields: bool = ..., include_attributes: bool = ..., *, indent: int | str | None = ... ) -> str: ... else: def dump(node: AST, annotate_fields: bool = ..., include_attributes: bool = ...) -> str: ... def fix_missing_locations(node: _T) -> _T: ... -def get_docstring(node: AST, clean: bool = ...) -> Optional[str]: ... +def get_docstring(node: AST, clean: bool = ...) -> str | None: ... def increment_lineno(node: _T, n: int = ...) -> _T: ... def iter_child_nodes(node: AST) -> Iterator[AST]: ... def iter_fields(node: AST) -> Iterator[_typing.Tuple[str, Any]]: ... -def literal_eval(node_or_string: Union[str, AST]) -> Any: ... +def literal_eval(node_or_string: str | AST) -> Any: ... if sys.version_info >= (3, 8): - def get_source_segment(source: str, node: AST, *, padded: bool = ...) -> Optional[str]: ... + def get_source_segment(source: str, node: AST, *, padded: bool = ...) -> str | None: ... def walk(node: AST) -> Iterator[AST]: ... diff --git a/mypy/typeshed/stdlib/asynchat.pyi b/mypy/typeshed/stdlib/asynchat.pyi index 34039b993400..e1787ca98b4f 100644 --- a/mypy/typeshed/stdlib/asynchat.pyi +++ b/mypy/typeshed/stdlib/asynchat.pyi @@ -1,8 +1,6 @@ import asyncore import socket -import sys from abc import abstractmethod -from typing import Optional, Sequence, Tuple, Union class simple_producer: def __init__(self, data: bytes, buffer_size: int = ...) -> None: ... @@ -11,13 +9,13 @@ class simple_producer: class async_chat(asyncore.dispatcher): ac_in_buffer_size: int ac_out_buffer_size: int - def __init__(self, sock: Optional[socket.socket] = ..., map: Optional[asyncore._maptype] = ...) -> None: ... + def __init__(self, sock: socket.socket | None = ..., map: asyncore._maptype | None = ...) -> None: ... @abstractmethod def collect_incoming_data(self, data: bytes) -> None: ... @abstractmethod def found_terminator(self) -> None: ... - def set_terminator(self, term: Union[bytes, int, None]) -> None: ... - def get_terminator(self) -> Union[bytes, int, None]: ... + def set_terminator(self, term: bytes | int | None) -> None: ... + def get_terminator(self) -> bytes | int | None: ... def handle_read(self) -> None: ... def handle_write(self) -> None: ... def handle_close(self) -> None: ... @@ -28,12 +26,3 @@ class async_chat(asyncore.dispatcher): def close_when_done(self) -> None: ... def initiate_send(self) -> None: ... def discard_buffers(self) -> None: ... - -if sys.version_info < (3, 0): - class fifo: - def __init__(self, list: Sequence[Union[bytes, simple_producer]] = ...) -> None: ... - def __len__(self) -> int: ... - def is_empty(self) -> bool: ... - def first(self) -> bytes: ... - def push(self, data: Union[bytes, simple_producer]) -> None: ... - def pop(self) -> Tuple[int, bytes]: ... diff --git a/mypy/typeshed/stdlib/asyncio/base_events.pyi b/mypy/typeshed/stdlib/asyncio/base_events.pyi index c2ad4a609c01..15471f54483f 100644 --- a/mypy/typeshed/stdlib/asyncio/base_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_events.pyi @@ -7,8 +7,9 @@ from asyncio.futures import Future from asyncio.protocols import BaseProtocol from asyncio.tasks import Task from asyncio.transports import BaseTransport +from collections.abc import Iterable from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Dict, Generator, List, Optional, Sequence, Tuple, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Dict, Generator, Sequence, Tuple, TypeVar, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 7): @@ -26,14 +27,22 @@ class Server(AbstractServer): def __init__( self, loop: AbstractEventLoop, - sockets: List[socket], + sockets: Iterable[socket], protocol_factory: _ProtocolFactory, ssl_context: _SSLContext, backlog: int, - ssl_handshake_timeout: Optional[float], + ssl_handshake_timeout: float | None, ) -> None: ... else: - def __init__(self, loop: AbstractEventLoop, sockets: List[socket]) -> None: ... + def __init__(self, loop: AbstractEventLoop, sockets: list[socket]) -> None: ... + if sys.version_info >= (3, 8): + @property + def sockets(self) -> Tuple[socket, ...]: ... + elif sys.version_info >= (3, 7): + @property + def sockets(self) -> list[socket]: ... + else: + sockets: list[socket] | None class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): def run_forever(self) -> None: ... @@ -49,12 +58,12 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): async def shutdown_asyncgens(self) -> None: ... # Methods scheduling callbacks. All these return Handles. if sys.version_info >= (3, 7): - def call_soon(self, callback: Callable[..., Any], *args: Any, context: Optional[Context] = ...) -> Handle: ... + def call_soon(self, callback: Callable[..., Any], *args: Any, context: Context | None = ...) -> Handle: ... def call_later( - self, delay: float, callback: Callable[..., Any], *args: Any, context: Optional[Context] = ... + self, delay: float, callback: Callable[..., Any], *args: Any, context: Context | None = ... ) -> TimerHandle: ... def call_at( - self, when: float, callback: Callable[..., Any], *args: Any, context: Optional[Context] = ... + self, when: float, callback: Callable[..., Any], *args: Any, context: Context | None = ... ) -> TimerHandle: ... else: def call_soon(self, callback: Callable[..., Any], *args: Any) -> Handle: ... @@ -65,34 +74,23 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): def create_future(self) -> Future[Any]: ... # Tasks methods if sys.version_info >= (3, 8): - def create_task(self, coro: Union[Awaitable[_T], Generator[Any, None, _T]], *, name: Optional[str] = ...) -> Task[_T]: ... + def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T], *, name: object = ...) -> Task[_T]: ... else: - def create_task(self, coro: Union[Awaitable[_T], Generator[Any, None, _T]]) -> Task[_T]: ... - def set_task_factory( - self, factory: Optional[Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]]] - ) -> None: ... - def get_task_factory(self) -> Optional[Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]]]: ... + def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T]) -> Task[_T]: ... + def set_task_factory(self, factory: Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None) -> None: ... + def get_task_factory(self) -> Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None: ... # Methods for interacting with threads if sys.version_info >= (3, 7): - def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any, context: Optional[Context] = ...) -> Handle: ... + def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any, context: Context | None = ...) -> Handle: ... else: def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any) -> Handle: ... def run_in_executor(self, executor: Any, func: Callable[..., _T], *args: Any) -> Future[_T]: ... def set_default_executor(self, executor: Any) -> None: ... # Network I/O methods returning Futures. async def getaddrinfo( - self, - host: Optional[str], - port: Union[str, int, None], - *, - family: int = ..., - type: int = ..., - proto: int = ..., - flags: int = ..., - ) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int]]]]: ... - async def getnameinfo( - self, sockaddr: Union[Tuple[str, int], Tuple[str, int, int, int]], flags: int = ... - ) -> Tuple[str, str]: ... + self, host: str | None, port: str | int | None, *, family: int = ..., type: int = ..., proto: int = ..., flags: int = ... + ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... + async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... if sys.version_info >= (3, 8): @overload async def create_connection( @@ -106,11 +104,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., - happy_eyeballs_delay: Optional[float] = ..., - interleave: Optional[int] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., ) -> _TransProtPair: ... @overload async def create_connection( @@ -125,10 +123,10 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., - happy_eyeballs_delay: Optional[float] = ..., - interleave: Optional[int] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., ) -> _TransProtPair: ... elif sys.version_info >= (3, 7): @overload @@ -143,9 +141,9 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... @overload async def create_connection( @@ -160,8 +158,8 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... else: @overload @@ -176,8 +174,8 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., ) -> _TransProtPair: ... @overload async def create_connection( @@ -192,17 +190,17 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., + server_hostname: str | None = ..., ) -> _TransProtPair: ... if sys.version_info >= (3, 7): async def sock_sendfile( - self, sock: socket, file: IO[bytes], offset: int = ..., count: Optional[int] = ..., *, fallback: Optional[bool] = ... + self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... ) -> int: ... @overload async def create_server( self, protocol_factory: _ProtocolFactory, - host: Optional[Union[str, Sequence[str]]] = ..., + host: str | Sequence[str] | None = ..., port: int = ..., *, family: int = ..., @@ -210,9 +208,9 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: None = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ssl_handshake_timeout: Optional[float] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... @overload @@ -227,9 +225,9 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: socket = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ssl_handshake_timeout: Optional[float] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... async def connect_accepted_socket( @@ -238,16 +236,10 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: socket, *, ssl: _SSLContext = ..., - ssl_handshake_timeout: Optional[float] = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... async def sendfile( - self, - transport: BaseTransport, - file: IO[bytes], - offset: int = ..., - count: Optional[int] = ..., - *, - fallback: bool = ..., + self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... ) -> int: ... async def start_tls( self, @@ -256,15 +248,15 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sslcontext: ssl.SSLContext, *, server_side: bool = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> BaseTransport: ... else: @overload async def create_server( self, protocol_factory: _ProtocolFactory, - host: Optional[Union[str, Sequence[str]]] = ..., + host: str | Sequence[str] | None = ..., port: int = ..., *, family: int = ..., @@ -272,8 +264,8 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: None = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., ) -> Server: ... @overload async def create_server( @@ -287,8 +279,8 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: socket, backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., ) -> Server: ... async def connect_accepted_socket( self, protocol_factory: _ProtocolFactory, sock: socket, *, ssl: _SSLContext = ... @@ -296,16 +288,16 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): async def create_datagram_endpoint( self, protocol_factory: _ProtocolFactory, - local_addr: Optional[Tuple[str, int]] = ..., - remote_addr: Optional[Tuple[str, int]] = ..., + local_addr: tuple[str, int] | None = ..., + remote_addr: tuple[str, int] | None = ..., *, family: int = ..., proto: int = ..., flags: int = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - allow_broadcast: Optional[bool] = ..., - sock: Optional[socket] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + allow_broadcast: bool | None = ..., + sock: socket | None = ..., ) -> _TransProtPair: ... # Pipes and subprocesses. async def connect_read_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... @@ -313,11 +305,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): async def subprocess_shell( self, protocol_factory: _ProtocolFactory, - cmd: Union[bytes, str], + cmd: bytes | str, *, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., universal_newlines: Literal[False] = ..., shell: Literal[True] = ..., bufsize: Literal[0] = ..., @@ -331,9 +323,9 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): protocol_factory: _ProtocolFactory, program: Any, *args: Any, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., universal_newlines: Literal[False] = ..., shell: Literal[True] = ..., bufsize: Literal[0] = ..., @@ -351,18 +343,18 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): async def sock_recv_into(self, sock: socket, buf: bytearray) -> int: ... async def sock_sendall(self, sock: socket, data: bytes) -> None: ... async def sock_connect(self, sock: socket, address: _Address) -> None: ... - async def sock_accept(self, sock: socket) -> Tuple[socket, _RetAddress]: ... + async def sock_accept(self, sock: socket) -> tuple[socket, _RetAddress]: ... else: def sock_recv(self, sock: socket, nbytes: int) -> Future[bytes]: ... def sock_sendall(self, sock: socket, data: bytes) -> Future[None]: ... def sock_connect(self, sock: socket, address: _Address) -> Future[None]: ... - def sock_accept(self, sock: socket) -> Future[Tuple[socket, _RetAddress]]: ... + def sock_accept(self, sock: socket) -> Future[tuple[socket, _RetAddress]]: ... # Signal handling. def add_signal_handler(self, sig: int, callback: Callable[..., Any], *args: Any) -> None: ... def remove_signal_handler(self, sig: int) -> bool: ... # Error handlers. - def set_exception_handler(self, handler: Optional[_ExceptionHandler]) -> None: ... - def get_exception_handler(self) -> Optional[_ExceptionHandler]: ... + def set_exception_handler(self, handler: _ExceptionHandler | None) -> None: ... + def get_exception_handler(self) -> _ExceptionHandler | None: ... def default_exception_handler(self, context: _Context) -> None: ... def call_exception_handler(self, context: _Context) -> None: ... # Debug flag management. diff --git a/mypy/typeshed/stdlib/asyncio/base_futures.pyi b/mypy/typeshed/stdlib/asyncio/base_futures.pyi index 270a69685c24..72ba6163e9d3 100644 --- a/mypy/typeshed/stdlib/asyncio/base_futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_futures.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Callable, List, Sequence, Tuple +from typing import Any, Callable, Sequence from typing_extensions import Literal if sys.version_info >= (3, 7): @@ -14,9 +14,9 @@ _FINISHED: Literal["FINISHED"] # undocumented def isfuture(obj: object) -> bool: ... if sys.version_info >= (3, 7): - def _format_callbacks(cb: Sequence[Tuple[Callable[[futures.Future[Any]], None], Context]]) -> str: ... # undocumented + def _format_callbacks(cb: Sequence[tuple[Callable[[futures.Future[Any]], None], Context]]) -> str: ... # undocumented else: def _format_callbacks(cb: Sequence[Callable[[futures.Future[Any]], None]]) -> str: ... # undocumented -def _future_repr_info(future: futures.Future[Any]) -> List[str]: ... # undocumented +def _future_repr_info(future: futures.Future[Any]) -> list[str]: ... # undocumented diff --git a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi index acdf985205ab..23034790a4a9 100644 --- a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi @@ -1,5 +1,6 @@ import subprocess -from typing import IO, Any, Callable, Deque, Dict, List, Optional, Sequence, Tuple, Union +from collections import deque +from typing import IO, Any, Callable, Optional, Sequence, Tuple, Union from . import events, futures, protocols, transports @@ -10,30 +11,30 @@ class BaseSubprocessTransport(transports.SubprocessTransport): _closed: bool # undocumented _protocol: protocols.SubprocessProtocol # undocumented _loop: events.AbstractEventLoop # undocumented - _proc: Optional[subprocess.Popen[Any]] # undocumented - _pid: Optional[int] # undocumented - _returncode: Optional[int] # undocumented - _exit_waiters: List[futures.Future[Any]] # undocumented - _pending_calls: Deque[Tuple[Callable[..., Any], Tuple[Any, ...]]] # undocumented - _pipes: Dict[int, _File] # undocumented + _proc: subprocess.Popen[Any] | None # undocumented + _pid: int | None # undocumented + _returncode: int | None # undocumented + _exit_waiters: list[futures.Future[Any]] # undocumented + _pending_calls: deque[tuple[Callable[..., Any], Tuple[Any, ...]]] # undocumented + _pipes: dict[int, _File] # undocumented _finished: bool # undocumented def __init__( self, loop: events.AbstractEventLoop, protocol: protocols.SubprocessProtocol, - args: Union[str, bytes, Sequence[Union[str, bytes]]], + args: str | bytes | Sequence[str | bytes], shell: bool, stdin: _File, stdout: _File, stderr: _File, bufsize: int, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Any] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Any | None = ..., **kwargs: Any, ) -> None: ... def _start( self, - args: Union[str, bytes, Sequence[Union[str, bytes]]], + args: str | bytes | Sequence[str | bytes], shell: bool, stdin: _File, stdout: _File, @@ -45,26 +46,26 @@ class BaseSubprocessTransport(transports.SubprocessTransport): def get_protocol(self) -> protocols.BaseProtocol: ... def is_closing(self) -> bool: ... def close(self) -> None: ... - def get_pid(self) -> Optional[int]: ... # type: ignore - def get_returncode(self) -> Optional[int]: ... + def get_pid(self) -> int | None: ... # type: ignore + def get_returncode(self) -> int | None: ... def get_pipe_transport(self, fd: int) -> _File: ... # type: ignore def _check_proc(self) -> None: ... # undocumented def send_signal(self, signal: int) -> None: ... # type: ignore def terminate(self) -> None: ... def kill(self) -> None: ... - async def _connect_pipes(self, waiter: Optional[futures.Future[Any]]) -> None: ... # undocumented + async def _connect_pipes(self, waiter: futures.Future[Any] | None) -> None: ... # undocumented def _call(self, cb: Callable[..., Any], *data: Any) -> None: ... # undocumented - def _pipe_connection_lost(self, fd: int, exc: Optional[BaseException]) -> None: ... # undocumented + def _pipe_connection_lost(self, fd: int, exc: BaseException | None) -> None: ... # undocumented def _pipe_data_received(self, fd: int, data: bytes) -> None: ... # undocumented def _process_exited(self, returncode: int) -> None: ... # undocumented async def _wait(self) -> int: ... # undocumented def _try_finish(self) -> None: ... # undocumented - def _call_connection_lost(self, exc: Optional[BaseException]) -> None: ... # undocumented + def _call_connection_lost(self, exc: BaseException | None) -> None: ... # undocumented class WriteSubprocessPipeProto(protocols.BaseProtocol): # undocumented def __init__(self, proc: BaseSubprocessTransport, fd: int) -> None: ... def connection_made(self, transport: transports.BaseTransport) -> None: ... - def connection_lost(self, exc: Optional[BaseException]) -> None: ... + def connection_lost(self, exc: BaseException | None) -> None: ... def pause_writing(self) -> None: ... def resume_writing(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/base_tasks.pyi b/mypy/typeshed/stdlib/asyncio/base_tasks.pyi index fbe0a03e8755..42e952ffacaf 100644 --- a/mypy/typeshed/stdlib/asyncio/base_tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_tasks.pyi @@ -1,9 +1,9 @@ -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from types import FrameType -from typing import Any, List, Optional +from typing import Any from . import tasks -def _task_repr_info(task: tasks.Task[Any]) -> List[str]: ... # undocumented -def _task_get_stack(task: tasks.Task[Any], limit: Optional[int]) -> List[FrameType]: ... # undocumented -def _task_print_stack(task: tasks.Task[Any], limit: Optional[int], file: AnyPath) -> None: ... # undocumented +def _task_repr_info(task: tasks.Task[Any]) -> list[str]: ... # undocumented +def _task_get_stack(task: tasks.Task[Any], limit: int | None) -> list[FrameType]: ... # undocumented +def _task_print_stack(task: tasks.Task[Any], limit: int | None, file: StrOrBytesPath) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/asyncio/compat.pyi b/mypy/typeshed/stdlib/asyncio/compat.pyi index 2dbc03d543dc..1beeea9d6c3f 100644 --- a/mypy/typeshed/stdlib/asyncio/compat.pyi +++ b/mypy/typeshed/stdlib/asyncio/compat.pyi @@ -1,8 +1,7 @@ import sys -from typing import List if sys.version_info < (3, 7): PY34: bool PY35: bool PY352: bool - def flatten_list_bytes(list_of_data: List[bytes]) -> bytes: ... + def flatten_list_bytes(list_of_data: list[bytes]) -> bytes: ... diff --git a/mypy/typeshed/stdlib/asyncio/constants.pyi b/mypy/typeshed/stdlib/asyncio/constants.pyi index 14681f330f02..2010fe9123ae 100644 --- a/mypy/typeshed/stdlib/asyncio/constants.pyi +++ b/mypy/typeshed/stdlib/asyncio/constants.pyi @@ -9,6 +9,6 @@ if sys.version_info >= (3, 7): SENDFILE_FALLBACK_READBUFFER_SIZE: int class _SendfileMode(enum.Enum): - UNSUPPORTED: int = ... - TRY_NATIVE: int = ... - FALLBACK: int = ... + UNSUPPORTED: int + TRY_NATIVE: int + FALLBACK: int diff --git a/mypy/typeshed/stdlib/asyncio/coroutines.pyi b/mypy/typeshed/stdlib/asyncio/coroutines.pyi index dea090682f2b..df94d5ba156a 100644 --- a/mypy/typeshed/stdlib/asyncio/coroutines.pyi +++ b/mypy/typeshed/stdlib/asyncio/coroutines.pyi @@ -1,7 +1,16 @@ -from typing import Any, Callable, TypeVar +import sys +import types +from collections.abc import Callable, Coroutine +from typing import Any, TypeVar +from typing_extensions import TypeGuard _F = TypeVar("_F", bound=Callable[..., Any]) def coroutine(func: _F) -> _F: ... -def iscoroutinefunction(func: Callable[..., Any]) -> bool: ... -def iscoroutine(obj: Any) -> bool: ... +def iscoroutinefunction(func: object) -> bool: ... + +if sys.version_info < (3, 8): + def iscoroutine(obj: object) -> TypeGuard[types.GeneratorType[Any, Any, Any] | Coroutine[Any, Any, Any]]: ... + +else: + def iscoroutine(obj: object) -> TypeGuard[Coroutine[Any, Any, Any]]: ... diff --git a/mypy/typeshed/stdlib/asyncio/events.pyi b/mypy/typeshed/stdlib/asyncio/events.pyi index 9159af4eb20b..6ef9117b6491 100644 --- a/mypy/typeshed/stdlib/asyncio/events.pyi +++ b/mypy/typeshed/stdlib/asyncio/events.pyi @@ -1,16 +1,18 @@ import ssl import sys -from _typeshed import FileDescriptorLike +from _typeshed import FileDescriptorLike, Self from abc import ABCMeta, abstractmethod -from asyncio.futures import Future -from asyncio.protocols import BaseProtocol -from asyncio.tasks import Task -from asyncio.transports import BaseTransport -from asyncio.unix_events import AbstractChildWatcher from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Dict, Generator, List, Optional, Sequence, Tuple, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Dict, Generator, Sequence, Tuple, TypeVar, Union, overload from typing_extensions import Literal +from .base_events import Server +from .futures import Future +from .protocols import BaseProtocol +from .tasks import Task +from .transports import BaseTransport +from .unix_events import AbstractChildWatcher + if sys.version_info >= (3, 7): from contextvars import Context @@ -26,7 +28,7 @@ class Handle: _args: Sequence[Any] if sys.version_info >= (3, 7): def __init__( - self, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop, context: Optional[Context] = ... + self, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop, context: Context | None = ... ) -> None: ... else: def __init__(self, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop) -> None: ... @@ -44,7 +46,7 @@ class TimerHandle(Handle): callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop, - context: Optional[Context] = ..., + context: Context | None = ..., ) -> None: ... else: def __init__(self, when: float, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop) -> None: ... @@ -53,10 +55,9 @@ class TimerHandle(Handle): def when(self) -> float: ... class AbstractServer: - sockets: Optional[List[socket]] def close(self) -> None: ... if sys.version_info >= (3, 7): - async def __aenter__(self: _T) -> _T: ... + async def __aenter__(self: Self) -> Self: ... async def __aexit__(self, *exc: Any) -> None: ... def get_loop(self) -> AbstractEventLoop: ... def is_serving(self) -> bool: ... @@ -65,7 +66,7 @@ class AbstractServer: async def wait_closed(self) -> None: ... class AbstractEventLoop(metaclass=ABCMeta): - slow_callback_duration: float = ... + slow_callback_duration: float @abstractmethod def run_forever(self) -> None: ... # Can't use a union, see mypy issue # 1873. @@ -100,39 +101,28 @@ class AbstractEventLoop(metaclass=ABCMeta): # Tasks methods if sys.version_info >= (3, 8): @abstractmethod - def create_task(self, coro: Union[Awaitable[_T], Generator[Any, None, _T]], *, name: Optional[str] = ...) -> Task[_T]: ... + def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T], *, name: str | None = ...) -> Task[_T]: ... else: @abstractmethod - def create_task(self, coro: Union[Awaitable[_T], Generator[Any, None, _T]]) -> Task[_T]: ... + def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T]) -> Task[_T]: ... @abstractmethod - def set_task_factory( - self, factory: Optional[Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]]] - ) -> None: ... + def set_task_factory(self, factory: Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None) -> None: ... @abstractmethod - def get_task_factory(self) -> Optional[Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]]]: ... + def get_task_factory(self) -> Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None: ... # Methods for interacting with threads @abstractmethod def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any) -> Handle: ... @abstractmethod - def run_in_executor(self, executor: Any, func: Callable[..., _T], *args: Any) -> Awaitable[_T]: ... + def run_in_executor(self, executor: Any, func: Callable[..., _T], *args: Any) -> Future[_T]: ... @abstractmethod def set_default_executor(self, executor: Any) -> None: ... # Network I/O methods returning Futures. @abstractmethod async def getaddrinfo( - self, - host: Optional[str], - port: Union[str, int, None], - *, - family: int = ..., - type: int = ..., - proto: int = ..., - flags: int = ..., - ) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int]]]]: ... + self, host: str | None, port: str | int | None, *, family: int = ..., type: int = ..., proto: int = ..., flags: int = ... + ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... @abstractmethod - async def getnameinfo( - self, sockaddr: Union[Tuple[str, int], Tuple[str, int, int, int]], flags: int = ... - ) -> Tuple[str, str]: ... + async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... if sys.version_info >= (3, 8): @overload @abstractmethod @@ -147,11 +137,11 @@ class AbstractEventLoop(metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., - happy_eyeballs_delay: Optional[float] = ..., - interleave: Optional[int] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., ) -> _TransProtPair: ... @overload @abstractmethod @@ -167,10 +157,10 @@ class AbstractEventLoop(metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., - happy_eyeballs_delay: Optional[float] = ..., - interleave: Optional[int] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., ) -> _TransProtPair: ... elif sys.version_info >= (3, 7): @overload @@ -186,9 +176,9 @@ class AbstractEventLoop(metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... @overload @abstractmethod @@ -204,8 +194,8 @@ class AbstractEventLoop(metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... else: @overload @@ -221,8 +211,8 @@ class AbstractEventLoop(metaclass=ABCMeta): proto: int = ..., flags: int = ..., sock: None = ..., - local_addr: Optional[Tuple[str, int]] = ..., - server_hostname: Optional[str] = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., ) -> _TransProtPair: ... @overload @abstractmethod @@ -238,19 +228,19 @@ class AbstractEventLoop(metaclass=ABCMeta): flags: int = ..., sock: socket, local_addr: None = ..., - server_hostname: Optional[str] = ..., + server_hostname: str | None = ..., ) -> _TransProtPair: ... if sys.version_info >= (3, 7): @abstractmethod async def sock_sendfile( - self, sock: socket, file: IO[bytes], offset: int = ..., count: Optional[int] = ..., *, fallback: Optional[bool] = ... + self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... ) -> int: ... @overload @abstractmethod async def create_server( self, protocol_factory: _ProtocolFactory, - host: Optional[Union[str, Sequence[str]]] = ..., + host: str | Sequence[str] | None = ..., port: int = ..., *, family: int = ..., @@ -258,11 +248,11 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: None = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ssl_handshake_timeout: Optional[float] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., start_serving: bool = ..., - ) -> AbstractServer: ... + ) -> Server: ... @overload @abstractmethod async def create_server( @@ -276,41 +266,35 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: socket = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ssl_handshake_timeout: Optional[float] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., start_serving: bool = ..., - ) -> AbstractServer: ... + ) -> Server: ... async def create_unix_connection( self, protocol_factory: _ProtocolFactory, - path: Optional[str] = ..., + path: str | None = ..., *, ssl: _SSLContext = ..., - sock: Optional[socket] = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + sock: socket | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> _TransProtPair: ... async def create_unix_server( self, protocol_factory: _ProtocolFactory, - path: Optional[str] = ..., + path: str | None = ..., *, - sock: Optional[socket] = ..., + sock: socket | None = ..., backlog: int = ..., ssl: _SSLContext = ..., - ssl_handshake_timeout: Optional[float] = ..., + ssl_handshake_timeout: float | None = ..., start_serving: bool = ..., - ) -> AbstractServer: ... + ) -> Server: ... @abstractmethod async def sendfile( - self, - transport: BaseTransport, - file: IO[bytes], - offset: int = ..., - count: Optional[int] = ..., - *, - fallback: bool = ..., + self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... ) -> int: ... @abstractmethod async def start_tls( @@ -320,8 +304,8 @@ class AbstractEventLoop(metaclass=ABCMeta): sslcontext: ssl.SSLContext, *, server_side: bool = ..., - server_hostname: Optional[str] = ..., - ssl_handshake_timeout: Optional[float] = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., ) -> BaseTransport: ... else: @overload @@ -329,7 +313,7 @@ class AbstractEventLoop(metaclass=ABCMeta): async def create_server( self, protocol_factory: _ProtocolFactory, - host: Optional[Union[str, Sequence[str]]] = ..., + host: str | Sequence[str] | None = ..., port: int = ..., *, family: int = ..., @@ -337,9 +321,9 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: None = ..., backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ) -> AbstractServer: ... + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ) -> Server: ... @overload @abstractmethod async def create_server( @@ -353,41 +337,41 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: socket, backlog: int = ..., ssl: _SSLContext = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - ) -> AbstractServer: ... + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ) -> Server: ... async def create_unix_connection( self, protocol_factory: _ProtocolFactory, path: str, *, ssl: _SSLContext = ..., - sock: Optional[socket] = ..., - server_hostname: Optional[str] = ..., + sock: socket | None = ..., + server_hostname: str | None = ..., ) -> _TransProtPair: ... async def create_unix_server( self, protocol_factory: _ProtocolFactory, path: str, *, - sock: Optional[socket] = ..., + sock: socket | None = ..., backlog: int = ..., ssl: _SSLContext = ..., - ) -> AbstractServer: ... + ) -> Server: ... @abstractmethod async def create_datagram_endpoint( self, protocol_factory: _ProtocolFactory, - local_addr: Optional[Tuple[str, int]] = ..., - remote_addr: Optional[Tuple[str, int]] = ..., + local_addr: tuple[str, int] | None = ..., + remote_addr: tuple[str, int] | None = ..., *, family: int = ..., proto: int = ..., flags: int = ..., - reuse_address: Optional[bool] = ..., - reuse_port: Optional[bool] = ..., - allow_broadcast: Optional[bool] = ..., - sock: Optional[socket] = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + allow_broadcast: bool | None = ..., + sock: socket | None = ..., ) -> _TransProtPair: ... # Pipes and subprocesses. @abstractmethod @@ -398,11 +382,11 @@ class AbstractEventLoop(metaclass=ABCMeta): async def subprocess_shell( self, protocol_factory: _ProtocolFactory, - cmd: Union[bytes, str], + cmd: bytes | str, *, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., universal_newlines: Literal[False] = ..., shell: Literal[True] = ..., bufsize: Literal[0] = ..., @@ -417,9 +401,9 @@ class AbstractEventLoop(metaclass=ABCMeta): protocol_factory: _ProtocolFactory, program: Any, *args: Any, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., universal_newlines: Literal[False] = ..., shell: Literal[True] = ..., bufsize: Literal[0] = ..., @@ -446,7 +430,7 @@ class AbstractEventLoop(metaclass=ABCMeta): @abstractmethod async def sock_connect(self, sock: socket, address: _Address) -> None: ... @abstractmethod - async def sock_accept(self, sock: socket) -> Tuple[socket, _RetAddress]: ... + async def sock_accept(self, sock: socket) -> tuple[socket, _RetAddress]: ... else: @abstractmethod def sock_recv(self, sock: socket, nbytes: int) -> Future[bytes]: ... @@ -455,7 +439,7 @@ class AbstractEventLoop(metaclass=ABCMeta): @abstractmethod def sock_connect(self, sock: socket, address: _Address) -> Future[None]: ... @abstractmethod - def sock_accept(self, sock: socket) -> Future[Tuple[socket, _RetAddress]]: ... + def sock_accept(self, sock: socket) -> Future[tuple[socket, _RetAddress]]: ... # Signal handling. @abstractmethod def add_signal_handler(self, sig: int, callback: Callable[..., Any], *args: Any) -> None: ... @@ -463,9 +447,9 @@ class AbstractEventLoop(metaclass=ABCMeta): def remove_signal_handler(self, sig: int) -> bool: ... # Error handlers. @abstractmethod - def set_exception_handler(self, handler: Optional[_ExceptionHandler]) -> None: ... + def set_exception_handler(self, handler: _ExceptionHandler | None) -> None: ... @abstractmethod - def get_exception_handler(self) -> Optional[_ExceptionHandler]: ... + def get_exception_handler(self) -> _ExceptionHandler | None: ... @abstractmethod def default_exception_handler(self, context: _Context) -> None: ... @abstractmethod @@ -483,7 +467,7 @@ class AbstractEventLoopPolicy(metaclass=ABCMeta): @abstractmethod def get_event_loop(self) -> AbstractEventLoop: ... @abstractmethod - def set_event_loop(self, loop: Optional[AbstractEventLoop]) -> None: ... + def set_event_loop(self, loop: AbstractEventLoop | None) -> None: ... @abstractmethod def new_event_loop(self) -> AbstractEventLoop: ... # Child processes handling (Unix only). @@ -495,17 +479,17 @@ class AbstractEventLoopPolicy(metaclass=ABCMeta): class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy, metaclass=ABCMeta): def __init__(self) -> None: ... def get_event_loop(self) -> AbstractEventLoop: ... - def set_event_loop(self, loop: Optional[AbstractEventLoop]) -> None: ... + def set_event_loop(self, loop: AbstractEventLoop | None) -> None: ... def new_event_loop(self) -> AbstractEventLoop: ... def get_event_loop_policy() -> AbstractEventLoopPolicy: ... -def set_event_loop_policy(policy: Optional[AbstractEventLoopPolicy]) -> None: ... +def set_event_loop_policy(policy: AbstractEventLoopPolicy | None) -> None: ... def get_event_loop() -> AbstractEventLoop: ... -def set_event_loop(loop: Optional[AbstractEventLoop]) -> None: ... +def set_event_loop(loop: AbstractEventLoop | None) -> None: ... def new_event_loop() -> AbstractEventLoop: ... def get_child_watcher() -> AbstractChildWatcher: ... def set_child_watcher(watcher: AbstractChildWatcher) -> None: ... -def _set_running_loop(__loop: Optional[AbstractEventLoop]) -> None: ... +def _set_running_loop(__loop: AbstractEventLoop | None) -> None: ... def _get_running_loop() -> AbstractEventLoop: ... if sys.version_info >= (3, 7): diff --git a/mypy/typeshed/stdlib/asyncio/exceptions.pyi b/mypy/typeshed/stdlib/asyncio/exceptions.pyi index ecec9560a850..5b99966329ac 100644 --- a/mypy/typeshed/stdlib/asyncio/exceptions.pyi +++ b/mypy/typeshed/stdlib/asyncio/exceptions.pyi @@ -1,5 +1,4 @@ import sys -from typing import Optional if sys.version_info >= (3, 8): class CancelledError(BaseException): ... @@ -7,9 +6,9 @@ if sys.version_info >= (3, 8): class InvalidStateError(Exception): ... class SendfileNotAvailableError(RuntimeError): ... class IncompleteReadError(EOFError): - expected: Optional[int] + expected: int | None partial: bytes - def __init__(self, partial: bytes, expected: Optional[int]) -> None: ... + def __init__(self, partial: bytes, expected: int | None) -> None: ... class LimitOverrunError(Exception): consumed: int def __init__(self, message: str, consumed: int) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi index 5c075a910931..be80efe266b1 100644 --- a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi +++ b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi @@ -2,19 +2,19 @@ import functools import sys import traceback from types import FrameType, FunctionType -from typing import Any, Dict, Iterable, Optional, Tuple, Union, overload +from typing import Any, Iterable, Union, overload class _HasWrapper: - __wrapper__: Union[_HasWrapper, FunctionType] + __wrapper__: _HasWrapper | FunctionType _FuncType = Union[FunctionType, _HasWrapper, functools.partial[Any], functools.partialmethod[Any]] if sys.version_info >= (3, 7): @overload - def _get_function_source(func: _FuncType) -> Tuple[str, int]: ... + def _get_function_source(func: _FuncType) -> tuple[str, int]: ... @overload - def _get_function_source(func: object) -> Optional[Tuple[str, int]]: ... + def _get_function_source(func: object) -> tuple[str, int] | None: ... def _format_callback_source(func: object, args: Iterable[Any]) -> str: ... - def _format_args_and_kwargs(args: Iterable[Any], kwargs: Dict[str, Any]) -> str: ... - def _format_callback(func: object, args: Iterable[Any], kwargs: Dict[str, Any], suffix: str = ...) -> str: ... - def extract_stack(f: Optional[FrameType] = ..., limit: Optional[int] = ...) -> traceback.StackSummary: ... + def _format_args_and_kwargs(args: Iterable[Any], kwargs: dict[str, Any]) -> str: ... + def _format_callback(func: object, args: Iterable[Any], kwargs: dict[str, Any], suffix: str = ...) -> str: ... + def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> traceback.StackSummary: ... diff --git a/mypy/typeshed/stdlib/asyncio/futures.pyi b/mypy/typeshed/stdlib/asyncio/futures.pyi index 1252c02cb58d..9788123f427e 100644 --- a/mypy/typeshed/stdlib/asyncio/futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/futures.pyi @@ -1,6 +1,6 @@ import sys from concurrent.futures._base import Error, Future as _ConcurrentFuture -from typing import Any, Awaitable, Callable, Generator, Iterable, List, Optional, Tuple, TypeVar, Union +from typing import Any, Awaitable, Callable, Generator, Iterable, TypeVar from .events import AbstractEventLoop @@ -20,7 +20,7 @@ _S = TypeVar("_S") if sys.version_info < (3, 7): class _TracebackLogger: exc: BaseException - tb: List[str] + tb: list[str] def __init__(self, exc: Any, loop: AbstractEventLoop) -> None: ... def activate(self) -> None: ... def clear(self) -> None: ... @@ -33,28 +33,28 @@ class Future(Awaitable[_T], Iterable[_T]): _exception: BaseException _blocking = False _log_traceback = False - def __init__(self, *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... def __repr__(self) -> str: ... def __del__(self) -> None: ... if sys.version_info >= (3, 7): def get_loop(self) -> AbstractEventLoop: ... - def _callbacks(self: _S) -> List[Tuple[Callable[[_S], Any], Context]]: ... - def add_done_callback(self: _S, __fn: Callable[[_S], Any], *, context: Optional[Context] = ...) -> None: ... + def _callbacks(self: _S) -> list[tuple[Callable[[_S], Any], Context]]: ... + def add_done_callback(self: _S, __fn: Callable[[_S], Any], *, context: Context | None = ...) -> None: ... else: @property - def _callbacks(self: _S) -> List[Callable[[_S], Any]]: ... + def _callbacks(self: _S) -> list[Callable[[_S], Any]]: ... def add_done_callback(self: _S, __fn: Callable[[_S], Any]) -> None: ... if sys.version_info >= (3, 9): - def cancel(self, msg: Optional[str] = ...) -> bool: ... + def cancel(self, msg: Any | None = ...) -> bool: ... else: def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... def result(self) -> _T: ... - def exception(self) -> Optional[BaseException]: ... + def exception(self) -> BaseException | None: ... def remove_done_callback(self: _S, __fn: Callable[[_S], Any]) -> int: ... def set_result(self, __result: _T) -> None: ... - def set_exception(self, __exception: Union[type, BaseException]) -> None: ... + def set_exception(self, __exception: type | BaseException) -> None: ... def __iter__(self) -> Generator[Any, None, _T]: ... def __await__(self) -> Generator[Any, None, _T]: ... @property @@ -62,4 +62,4 @@ class Future(Awaitable[_T], Iterable[_T]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -def wrap_future(future: Union[_ConcurrentFuture[_T], Future[_T]], *, loop: Optional[AbstractEventLoop] = ...) -> Future[_T]: ... +def wrap_future(future: _ConcurrentFuture[_T] | Future[_T], *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... diff --git a/mypy/typeshed/stdlib/asyncio/locks.pyi b/mypy/typeshed/stdlib/asyncio/locks.pyi index 7480c3394e70..7c4f40d9e4ca 100644 --- a/mypy/typeshed/stdlib/asyncio/locks.pyi +++ b/mypy/typeshed/stdlib/asyncio/locks.pyi @@ -1,6 +1,7 @@ import sys +from collections import deque from types import TracebackType -from typing import Any, Awaitable, Callable, Deque, Generator, Optional, Type, TypeVar, Union +from typing import Any, Awaitable, Callable, Generator, Type, TypeVar from .events import AbstractEventLoop from .futures import Future @@ -9,19 +10,19 @@ _T = TypeVar("_T") if sys.version_info >= (3, 9): class _ContextManagerMixin: - def __init__(self, lock: Union[Lock, Semaphore]) -> None: ... + def __init__(self, lock: Lock | Semaphore) -> None: ... def __aenter__(self) -> Awaitable[None]: ... def __aexit__( - self, exc_type: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None ) -> Awaitable[None]: ... else: class _ContextManager: - def __init__(self, lock: Union[Lock, Semaphore]) -> None: ... + def __init__(self, lock: Lock | Semaphore) -> None: ... def __enter__(self) -> object: ... def __exit__(self, *args: Any) -> None: ... class _ContextManagerMixin: - def __init__(self, lock: Union[Lock, Semaphore]) -> None: ... + def __init__(self, lock: Lock | Semaphore) -> None: ... # Apparently this exists to *prohibit* use as a context manager. def __enter__(self) -> object: ... def __exit__(self, *args: Any) -> None: ... @@ -29,24 +30,24 @@ else: def __await__(self) -> Generator[Any, None, _ContextManager]: ... def __aenter__(self) -> Awaitable[None]: ... def __aexit__( - self, exc_type: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None ) -> Awaitable[None]: ... class Lock(_ContextManagerMixin): - def __init__(self, *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... async def acquire(self) -> bool: ... def release(self) -> None: ... class Event: - def __init__(self, *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... def is_set(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... async def wait(self) -> bool: ... class Condition(_ContextManagerMixin): - def __init__(self, lock: Optional[Lock] = ..., *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, lock: Lock | None = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... async def acquire(self) -> bool: ... def release(self) -> None: ... @@ -57,12 +58,12 @@ class Condition(_ContextManagerMixin): class Semaphore(_ContextManagerMixin): _value: int - _waiters: Deque[Future[Any]] - def __init__(self, value: int = ..., *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + _waiters: deque[Future[Any]] + def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... async def acquire(self) -> bool: ... def release(self) -> None: ... def _wake_up_next(self) -> None: ... class BoundedSemaphore(Semaphore): - def __init__(self, value: int = ..., *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi index b4598cec8ef8..6c8c558e5dfa 100644 --- a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi @@ -1,6 +1,6 @@ import sys from socket import socket -from typing import Any, Mapping, Optional, Type +from typing import Any, Mapping, Type from typing_extensions import Literal, Protocol from . import base_events, constants, events, futures, streams, transports @@ -8,7 +8,7 @@ from . import base_events, constants, events, futures, streams, transports if sys.version_info >= (3, 8): class _WarnCallbackProtocol(Protocol): def __call__( - self, message: str, category: Optional[Type[Warning]] = ..., stacklevel: int = ..., source: Optional[Any] = ... + self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... ) -> None: ... class _ProactorBasePipeTransport(transports._FlowControlMixin, transports.BaseTransport): @@ -17,9 +17,9 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, transports.BaseTr loop: events.AbstractEventLoop, sock: socket, protocol: streams.StreamReaderProtocol, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Mapping[Any, Any]] = ..., - server: Optional[events.AbstractServer] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., ) -> None: ... def __repr__(self) -> str: ... if sys.version_info >= (3, 8): @@ -34,9 +34,9 @@ class _ProactorReadPipeTransport(_ProactorBasePipeTransport, transports.ReadTran loop: events.AbstractEventLoop, sock: socket, protocol: streams.StreamReaderProtocol, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Mapping[Any, Any]] = ..., - server: Optional[events.AbstractServer] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., ) -> None: ... class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, transports.WriteTransport): @@ -45,9 +45,9 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, transports.Wri loop: events.AbstractEventLoop, sock: socket, protocol: streams.StreamReaderProtocol, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Mapping[Any, Any]] = ..., - server: Optional[events.AbstractServer] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., ) -> None: ... class _ProactorWritePipeTransport(_ProactorBaseWritePipeTransport): @@ -56,24 +56,24 @@ class _ProactorWritePipeTransport(_ProactorBaseWritePipeTransport): loop: events.AbstractEventLoop, sock: socket, protocol: streams.StreamReaderProtocol, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Mapping[Any, Any]] = ..., - server: Optional[events.AbstractServer] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., ) -> None: ... class _ProactorDuplexPipeTransport(_ProactorReadPipeTransport, _ProactorBaseWritePipeTransport, transports.Transport): ... class _ProactorSocketTransport(_ProactorReadPipeTransport, _ProactorBaseWritePipeTransport, transports.Transport): - _sendfile_compatible: constants._SendfileMode = ... + _sendfile_compatible: constants._SendfileMode def __init__( self, loop: events.AbstractEventLoop, sock: socket, protocol: streams.StreamReaderProtocol, - waiter: Optional[futures.Future[Any]] = ..., - extra: Optional[Mapping[Any, Any]] = ..., - server: Optional[events.AbstractServer] = ..., + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., ) -> None: ... def _set_extra(self, sock: socket) -> None: ... def can_write_eof(self) -> Literal[True]: ... diff --git a/mypy/typeshed/stdlib/asyncio/protocols.pyi b/mypy/typeshed/stdlib/asyncio/protocols.pyi index ec89a299956f..754f02c8bb4b 100644 --- a/mypy/typeshed/stdlib/asyncio/protocols.pyi +++ b/mypy/typeshed/stdlib/asyncio/protocols.pyi @@ -1,16 +1,15 @@ import sys from asyncio import transports -from typing import Optional, Tuple class BaseProtocol: def connection_made(self, transport: transports.BaseTransport) -> None: ... - def connection_lost(self, exc: Optional[Exception]) -> None: ... + def connection_lost(self, exc: Exception | None) -> None: ... def pause_writing(self) -> None: ... def resume_writing(self) -> None: ... class Protocol(BaseProtocol): def data_received(self, data: bytes) -> None: ... - def eof_received(self) -> Optional[bool]: ... + def eof_received(self) -> bool | None: ... if sys.version_info >= (3, 7): class BufferedProtocol(BaseProtocol): @@ -18,10 +17,11 @@ if sys.version_info >= (3, 7): def buffer_updated(self, nbytes: int) -> None: ... class DatagramProtocol(BaseProtocol): - def datagram_received(self, data: bytes, addr: Tuple[str, int]) -> None: ... + def connection_made(self, transport: transports.DatagramTransport) -> None: ... # type: ignore[override] + def datagram_received(self, data: bytes, addr: tuple[str, int]) -> None: ... def error_received(self, exc: Exception) -> None: ... class SubprocessProtocol(BaseProtocol): def pipe_data_received(self, fd: int, data: bytes) -> None: ... - def pipe_connection_lost(self, fd: int, exc: Optional[Exception]) -> None: ... + def pipe_connection_lost(self, fd: int, exc: Exception | None) -> None: ... def process_exited(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/queues.pyi b/mypy/typeshed/stdlib/asyncio/queues.pyi index 2d4bada035b3..aff4af727b08 100644 --- a/mypy/typeshed/stdlib/asyncio/queues.pyi +++ b/mypy/typeshed/stdlib/asyncio/queues.pyi @@ -1,6 +1,6 @@ import sys from asyncio.events import AbstractEventLoop -from typing import Any, Generic, Optional, TypeVar +from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -11,7 +11,7 @@ class QueueFull(Exception): ... _T = TypeVar("_T") class Queue(Generic[_T]): - def __init__(self, maxsize: int = ..., *, loop: Optional[AbstractEventLoop] = ...) -> None: ... + def __init__(self, maxsize: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... def _init(self, maxsize: int) -> None: ... def _get(self) -> _T: ... def _put(self, item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/runners.pyi b/mypy/typeshed/stdlib/asyncio/runners.pyi index 1628cb3e89f1..3f0f42eef48b 100644 --- a/mypy/typeshed/stdlib/asyncio/runners.pyi +++ b/mypy/typeshed/stdlib/asyncio/runners.pyi @@ -1,10 +1,10 @@ import sys if sys.version_info >= (3, 7): - from typing import Awaitable, Optional, TypeVar + from typing import Awaitable, TypeVar _T = TypeVar("_T") if sys.version_info >= (3, 8): - def run(main: Awaitable[_T], *, debug: Optional[bool] = ...) -> _T: ... + def run(main: Awaitable[_T], *, debug: bool | None = ...) -> _T: ... else: def run(main: Awaitable[_T], *, debug: bool = ...) -> _T: ... diff --git a/mypy/typeshed/stdlib/asyncio/selector_events.pyi b/mypy/typeshed/stdlib/asyncio/selector_events.pyi index 8946bb050ac2..bcbcd2fbe4b8 100644 --- a/mypy/typeshed/stdlib/asyncio/selector_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/selector_events.pyi @@ -1,7 +1,6 @@ import selectors -from typing import Optional from . import base_events class BaseSelectorEventLoop(base_events.BaseEventLoop): - def __init__(self, selector: Optional[selectors.BaseSelector] = ...) -> None: ... + def __init__(self, selector: selectors.BaseSelector | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/sslproto.pyi b/mypy/typeshed/stdlib/asyncio/sslproto.pyi index a267736ec997..082e96dc0233 100644 --- a/mypy/typeshed/stdlib/asyncio/sslproto.pyi +++ b/mypy/typeshed/stdlib/asyncio/sslproto.pyi @@ -1,11 +1,12 @@ import ssl import sys -from typing import Any, Callable, ClassVar, Deque, Dict, List, Optional, Tuple +from collections import deque +from typing import Any, Callable, ClassVar from typing_extensions import Literal from . import constants, events, futures, protocols, transports -def _create_transport_context(server_side: bool, server_hostname: Optional[str]) -> ssl.SSLContext: ... +def _create_transport_context(server_side: bool, server_hostname: str | None) -> ssl.SSLContext: ... _UNWRAPPED: Literal["UNWRAPPED"] _DO_HANDSHAKE: Literal["DO_HANDSHAKE"] @@ -18,28 +19,28 @@ class _SSLPipe: _context: ssl.SSLContext _server_side: bool - _server_hostname: Optional[str] + _server_hostname: str | None _state: str _incoming: ssl.MemoryBIO _outgoing: ssl.MemoryBIO - _sslobj: Optional[ssl.SSLObject] + _sslobj: ssl.SSLObject | None _need_ssldata: bool - _handshake_cb: Optional[Callable[[Optional[BaseException]], None]] - _shutdown_cb: Optional[Callable[[], None]] - def __init__(self, context: ssl.SSLContext, server_side: bool, server_hostname: Optional[str] = ...) -> None: ... + _handshake_cb: Callable[[BaseException | None], None] | None + _shutdown_cb: Callable[[], None] | None + def __init__(self, context: ssl.SSLContext, server_side: bool, server_hostname: str | None = ...) -> None: ... @property def context(self) -> ssl.SSLContext: ... @property - def ssl_object(self) -> Optional[ssl.SSLObject]: ... + def ssl_object(self) -> ssl.SSLObject | None: ... @property def need_ssldata(self) -> bool: ... @property def wrapped(self) -> bool: ... - def do_handshake(self, callback: Optional[Callable[[Optional[BaseException]], None]] = ...) -> List[bytes]: ... - def shutdown(self, callback: Optional[Callable[[], None]] = ...) -> List[bytes]: ... + def do_handshake(self, callback: Callable[[BaseException | None], None] | None = ...) -> list[bytes]: ... + def shutdown(self, callback: Callable[[], None] | None = ...) -> list[bytes]: ... def feed_eof(self) -> None: ... - def feed_ssldata(self, data: bytes, only_handshake: bool = ...) -> Tuple[List[bytes], List[bytes]]: ... - def feed_appdata(self, data: bytes, offset: int = ...) -> Tuple[List[bytes], int]: ... + def feed_ssldata(self, data: bytes, only_handshake: bool = ...) -> tuple[list[bytes], list[bytes]]: ... + def feed_appdata(self, data: bytes, offset: int = ...) -> tuple[list[bytes], int]: ... class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): @@ -49,7 +50,7 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): _ssl_protocol: SSLProtocol _closed: bool def __init__(self, loop: events.AbstractEventLoop, ssl_protocol: SSLProtocol) -> None: ... - def get_extra_info(self, name: str, default: Optional[Any] = ...) -> Dict[str, Any]: ... + def get_extra_info(self, name: str, default: Any | None = ...) -> dict[str, Any]: ... def set_protocol(self, protocol: protocols.BaseProtocol) -> None: ... def get_protocol(self) -> protocols.BaseProtocol: ... def is_closing(self) -> bool: ... @@ -58,7 +59,7 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): def is_reading(self) -> bool: ... def pause_reading(self) -> None: ... def resume_reading(self) -> None: ... - def set_write_buffer_limits(self, high: Optional[int] = ..., low: Optional[int] = ...) -> None: ... + def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... def get_write_buffer_size(self) -> int: ... if sys.version_info >= (3, 7): @property @@ -70,21 +71,21 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): class SSLProtocol(protocols.Protocol): _server_side: bool - _server_hostname: Optional[str] + _server_hostname: str | None _sslcontext: ssl.SSLContext - _extra: Dict[str, Any] - _write_backlog: Deque[Tuple[bytes, int]] + _extra: dict[str, Any] + _write_backlog: deque[tuple[bytes, int]] _write_buffer_size: int _waiter: futures.Future[Any] _loop: events.AbstractEventLoop _app_transport: _SSLProtocolTransport - _sslpipe: Optional[_SSLPipe] + _sslpipe: _SSLPipe | None _session_established: bool _in_handshake: bool _in_shutdown: bool - _transport: Optional[transports.BaseTransport] + _transport: transports.BaseTransport | None _call_connection_made: bool - _ssl_handshake_timeout: Optional[int] + _ssl_handshake_timeout: int | None _app_protocol: protocols.BaseProtocol _app_protocol_is_buffer: bool @@ -96,9 +97,9 @@ class SSLProtocol(protocols.Protocol): sslcontext: ssl.SSLContext, waiter: futures.Future[Any], server_side: bool = ..., - server_hostname: Optional[str] = ..., + server_hostname: str | None = ..., call_connection_made: bool = ..., - ssl_handshake_timeout: Optional[int] = ..., + ssl_handshake_timeout: int | None = ..., ) -> None: ... else: def __init__( @@ -108,25 +109,25 @@ class SSLProtocol(protocols.Protocol): sslcontext: ssl.SSLContext, waiter: futures.Future[Any], server_side: bool = ..., - server_hostname: Optional[str] = ..., + server_hostname: str | None = ..., call_connection_made: bool = ..., ) -> None: ... if sys.version_info >= (3, 7): def _set_app_protocol(self, app_protocol: protocols.BaseProtocol) -> None: ... - def _wakeup_waiter(self, exc: Optional[BaseException] = ...) -> None: ... + def _wakeup_waiter(self, exc: BaseException | None = ...) -> None: ... def connection_made(self, transport: transports.BaseTransport) -> None: ... - def connection_lost(self, exc: Optional[BaseException]) -> None: ... + def connection_lost(self, exc: BaseException | None) -> None: ... def pause_writing(self) -> None: ... def resume_writing(self) -> None: ... def data_received(self, data: bytes) -> None: ... def eof_received(self) -> None: ... - def _get_extra_info(self, name: str, default: Optional[Any] = ...) -> Any: ... + def _get_extra_info(self, name: str, default: Any | None = ...) -> Any: ... def _start_shutdown(self) -> None: ... def _write_appdata(self, data: bytes) -> None: ... def _start_handshake(self) -> None: ... if sys.version_info >= (3, 7): def _check_handshake_timeout(self) -> None: ... - def _on_handshake_complete(self, handshake_exc: Optional[BaseException]) -> None: ... + def _on_handshake_complete(self, handshake_exc: BaseException | None) -> None: ... def _process_write_backlog(self) -> None: ... def _fatal_error(self, exc: BaseException, message: str = ...) -> None: ... def _finalize(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/staggered.pyi b/mypy/typeshed/stdlib/asyncio/staggered.pyi index 057883e0ab2c..1d76d382555d 100644 --- a/mypy/typeshed/stdlib/asyncio/staggered.pyi +++ b/mypy/typeshed/stdlib/asyncio/staggered.pyi @@ -1,12 +1,9 @@ import sys -from typing import Any, Awaitable, Callable, Iterable, List, Optional, Tuple +from typing import Any, Awaitable, Callable, Iterable from . import events if sys.version_info >= (3, 8): async def staggered_race( - coro_fns: Iterable[Callable[[], Awaitable[Any]]], - delay: Optional[float], - *, - loop: Optional[events.AbstractEventLoop] = ..., - ) -> Tuple[Any, Optional[int], List[Optional[Exception]]]: ... + coro_fns: Iterable[Callable[[], Awaitable[Any]]], delay: float | None, *, loop: events.AbstractEventLoop | None = ... + ) -> tuple[Any, int | None, list[Exception | None]]: ... diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index a6367201052b..595222280d58 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -1,70 +1,70 @@ import sys -from typing import Any, AsyncIterator, Awaitable, Callable, Iterable, Optional, Tuple, Union +from _typeshed import StrPath +from typing import Any, AsyncIterator, Awaitable, Callable, Iterable, Optional from . import events, protocols, transports +from .base_events import Server _ClientConnectedCallback = Callable[[StreamReader, StreamWriter], Optional[Awaitable[None]]] if sys.version_info < (3, 8): class IncompleteReadError(EOFError): - expected: Optional[int] + expected: int | None partial: bytes - def __init__(self, partial: bytes, expected: Optional[int]) -> None: ... + def __init__(self, partial: bytes, expected: int | None) -> None: ... class LimitOverrunError(Exception): consumed: int def __init__(self, message: str, consumed: int) -> None: ... async def open_connection( - host: Optional[str] = ..., - port: Optional[Union[int, str]] = ..., + host: str | None = ..., + port: int | str | None = ..., *, - loop: Optional[events.AbstractEventLoop] = ..., + loop: events.AbstractEventLoop | None = ..., limit: int = ..., - ssl_handshake_timeout: Optional[float] = ..., + ssl_handshake_timeout: float | None = ..., **kwds: Any, -) -> Tuple[StreamReader, StreamWriter]: ... +) -> tuple[StreamReader, StreamWriter]: ... async def start_server( client_connected_cb: _ClientConnectedCallback, - host: Optional[str] = ..., - port: Optional[Union[int, str]] = ..., + host: str | None = ..., + port: int | str | None = ..., *, - loop: Optional[events.AbstractEventLoop] = ..., + loop: events.AbstractEventLoop | None = ..., limit: int = ..., - ssl_handshake_timeout: Optional[float] = ..., + ssl_handshake_timeout: float | None = ..., **kwds: Any, -) -> events.AbstractServer: ... +) -> Server: ... if sys.platform != "win32": if sys.version_info >= (3, 7): - from os import PathLike - - _PathType = Union[str, PathLike[str]] + _PathType = StrPath else: _PathType = str async def open_unix_connection( - path: Optional[_PathType] = ..., *, loop: Optional[events.AbstractEventLoop] = ..., limit: int = ..., **kwds: Any - ) -> Tuple[StreamReader, StreamWriter]: ... + path: _PathType | None = ..., *, loop: events.AbstractEventLoop | None = ..., limit: int = ..., **kwds: Any + ) -> tuple[StreamReader, StreamWriter]: ... async def start_unix_server( client_connected_cb: _ClientConnectedCallback, - path: Optional[_PathType] = ..., + path: _PathType | None = ..., *, - loop: Optional[events.AbstractEventLoop] = ..., + loop: events.AbstractEventLoop | None = ..., limit: int = ..., **kwds: Any, - ) -> events.AbstractServer: ... + ) -> Server: ... class FlowControlMixin(protocols.Protocol): - def __init__(self, loop: Optional[events.AbstractEventLoop] = ...) -> None: ... + def __init__(self, loop: events.AbstractEventLoop | None = ...) -> None: ... class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): def __init__( self, stream_reader: StreamReader, - client_connected_cb: Optional[_ClientConnectedCallback] = ..., - loop: Optional[events.AbstractEventLoop] = ..., + client_connected_cb: _ClientConnectedCallback | None = ..., + loop: events.AbstractEventLoop | None = ..., ) -> None: ... def connection_made(self, transport: transports.BaseTransport) -> None: ... - def connection_lost(self, exc: Optional[Exception]) -> None: ... + def connection_lost(self, exc: Exception | None) -> None: ... def data_received(self, data: bytes) -> None: ... def eof_received(self) -> bool: ... @@ -73,7 +73,7 @@ class StreamWriter: self, transport: transports.BaseTransport, protocol: protocols.BaseProtocol, - reader: Optional[StreamReader], + reader: StreamReader | None, loop: events.AbstractEventLoop, ) -> None: ... @property @@ -90,7 +90,7 @@ class StreamWriter: async def drain(self) -> None: ... class StreamReader: - def __init__(self, limit: int = ..., loop: Optional[events.AbstractEventLoop] = ...) -> None: ... + def __init__(self, limit: int = ..., loop: events.AbstractEventLoop | None = ...) -> None: ... def exception(self) -> Exception: ... def set_exception(self, exc: Exception) -> None: ... def set_transport(self, transport: transports.BaseTransport) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/subprocess.pyi b/mypy/typeshed/stdlib/asyncio/subprocess.pyi index d443625db28a..d835c12af3d8 100644 --- a/mypy/typeshed/stdlib/asyncio/subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/subprocess.pyi @@ -1,12 +1,12 @@ import subprocess import sys -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from asyncio import events, protocols, streams, transports -from typing import IO, Any, Callable, Optional, Tuple, Union +from typing import IO, Any, Callable, Union from typing_extensions import Literal if sys.version_info >= (3, 8): - _ExecArg = AnyPath + _ExecArg = StrOrBytesPath else: _ExecArg = Union[str, bytes] @@ -15,37 +15,37 @@ STDOUT: int DEVNULL: int class SubprocessStreamProtocol(streams.FlowControlMixin, protocols.SubprocessProtocol): - stdin: Optional[streams.StreamWriter] - stdout: Optional[streams.StreamReader] - stderr: Optional[streams.StreamReader] + stdin: streams.StreamWriter | None + stdout: streams.StreamReader | None + stderr: streams.StreamReader | None def __init__(self, limit: int, loop: events.AbstractEventLoop) -> None: ... def connection_made(self, transport: transports.BaseTransport) -> None: ... - def pipe_data_received(self, fd: int, data: Union[bytes, str]) -> None: ... - def pipe_connection_lost(self, fd: int, exc: Optional[Exception]) -> None: ... + def pipe_data_received(self, fd: int, data: bytes | str) -> None: ... + def pipe_connection_lost(self, fd: int, exc: Exception | None) -> None: ... def process_exited(self) -> None: ... class Process: - stdin: Optional[streams.StreamWriter] - stdout: Optional[streams.StreamReader] - stderr: Optional[streams.StreamReader] + stdin: streams.StreamWriter | None + stdout: streams.StreamReader | None + stderr: streams.StreamReader | None pid: int def __init__( self, transport: transports.BaseTransport, protocol: protocols.BaseProtocol, loop: events.AbstractEventLoop ) -> None: ... @property - def returncode(self) -> Optional[int]: ... + def returncode(self) -> int | None: ... async def wait(self) -> int: ... def send_signal(self, signal: int) -> None: ... def terminate(self) -> None: ... def kill(self) -> None: ... - async def communicate(self, input: Optional[bytes] = ...) -> Tuple[bytes, bytes]: ... + async def communicate(self, input: bytes | None = ...) -> tuple[bytes, bytes]: ... if sys.version_info >= (3, 10): async def create_subprocess_shell( - cmd: Union[str, bytes], - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + cmd: str | bytes, + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., limit: int = ..., *, # These parameters are forced to these values by BaseEventLoop.subprocess_shell @@ -56,12 +56,12 @@ if sys.version_info >= (3, 10): errors: None = ..., text: Literal[False, None] = ..., # These parameters are taken by subprocess.Popen, which this ultimately delegates to - executable: Optional[AnyPath] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[subprocess._ENV] = ..., - startupinfo: Optional[Any] = ..., + cwd: StrOrBytesPath | None = ..., + env: subprocess._ENV | None = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., @@ -70,9 +70,9 @@ if sys.version_info >= (3, 10): async def create_subprocess_exec( program: _ExecArg, *args: _ExecArg, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., limit: int = ..., # These parameters are forced to these values by BaseEventLoop.subprocess_shell universal_newlines: Literal[False] = ..., @@ -81,13 +81,13 @@ if sys.version_info >= (3, 10): encoding: None = ..., errors: None = ..., # These parameters are taken by subprocess.Popen, which this ultimately delegates to - text: Optional[bool] = ..., - executable: Optional[AnyPath] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + text: bool | None = ..., + executable: StrOrBytesPath | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[subprocess._ENV] = ..., - startupinfo: Optional[Any] = ..., + cwd: StrOrBytesPath | None = ..., + env: subprocess._ENV | None = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., @@ -96,11 +96,11 @@ if sys.version_info >= (3, 10): else: async def create_subprocess_shell( - cmd: Union[str, bytes], - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., - loop: Optional[events.AbstractEventLoop] = ..., + cmd: str | bytes, + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., + loop: events.AbstractEventLoop | None = ..., limit: int = ..., *, # These parameters are forced to these values by BaseEventLoop.subprocess_shell @@ -111,12 +111,12 @@ else: errors: None = ..., text: Literal[False, None] = ..., # These parameters are taken by subprocess.Popen, which this ultimately delegates to - executable: Optional[AnyPath] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[subprocess._ENV] = ..., - startupinfo: Optional[Any] = ..., + cwd: StrOrBytesPath | None = ..., + env: subprocess._ENV | None = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., @@ -125,10 +125,10 @@ else: async def create_subprocess_exec( program: _ExecArg, *args: _ExecArg, - stdin: Union[int, IO[Any], None] = ..., - stdout: Union[int, IO[Any], None] = ..., - stderr: Union[int, IO[Any], None] = ..., - loop: Optional[events.AbstractEventLoop] = ..., + stdin: int | IO[Any] | None = ..., + stdout: int | IO[Any] | None = ..., + stderr: int | IO[Any] | None = ..., + loop: events.AbstractEventLoop | None = ..., limit: int = ..., # These parameters are forced to these values by BaseEventLoop.subprocess_shell universal_newlines: Literal[False] = ..., @@ -137,13 +137,13 @@ else: encoding: None = ..., errors: None = ..., # These parameters are taken by subprocess.Popen, which this ultimately delegates to - text: Optional[bool] = ..., - executable: Optional[AnyPath] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + text: bool | None = ..., + executable: StrOrBytesPath | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[subprocess._ENV] = ..., - startupinfo: Optional[Any] = ..., + cwd: StrOrBytesPath | None = ..., + env: subprocess._ENV | None = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., diff --git a/mypy/typeshed/stdlib/asyncio/tasks.pyi b/mypy/typeshed/stdlib/asyncio/tasks.pyi index 0ff0e3895252..15c12909f3c3 100644 --- a/mypy/typeshed/stdlib/asyncio/tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/tasks.pyi @@ -2,7 +2,7 @@ import concurrent.futures import sys from collections.abc import Awaitable, Generator, Iterable, Iterator from types import FrameType -from typing import Any, Generic, List, Optional, Set, TextIO, Tuple, TypeVar, Union, overload +from typing import Any, Generic, Optional, TextIO, TypeVar, Union, overload from typing_extensions import Literal from .events import AbstractEventLoop @@ -26,17 +26,17 @@ FIRST_COMPLETED: str ALL_COMPLETED: str if sys.version_info >= (3, 10): - def as_completed(fs: Iterable[_FutureT[_T]], *, timeout: Optional[float] = ...) -> Iterator[Future[_T]]: ... + def as_completed(fs: Iterable[_FutureT[_T]], *, timeout: float | None = ...) -> Iterator[Future[_T]]: ... else: def as_completed( - fs: Iterable[_FutureT[_T]], *, loop: Optional[AbstractEventLoop] = ..., timeout: Optional[float] = ... + fs: Iterable[_FutureT[_T]], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ... ) -> Iterator[Future[_T]]: ... @overload -def ensure_future(coro_or_future: _FT, *, loop: Optional[AbstractEventLoop] = ...) -> _FT: ... # type: ignore +def ensure_future(coro_or_future: _FT, *, loop: AbstractEventLoop | None = ...) -> _FT: ... # type: ignore @overload -def ensure_future(coro_or_future: Awaitable[_T], *, loop: Optional[AbstractEventLoop] = ...) -> Task[_T]: ... +def ensure_future(coro_or_future: Awaitable[_T], *, loop: AbstractEventLoop | None = ...) -> Task[_T]: ... # Prior to Python 3.7 'async' was an alias for 'ensure_future'. # It became a keyword in 3.7. @@ -47,11 +47,11 @@ def ensure_future(coro_or_future: Awaitable[_T], *, loop: Optional[AbstractEvent # typing PR #1550 for discussion. if sys.version_info >= (3, 10): @overload - def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: Literal[False] = ...) -> Future[Tuple[_T1]]: ... + def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: Literal[False] = ...) -> Future[tuple[_T1]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, return_exceptions: Literal[False] = ... - ) -> Future[Tuple[_T1, _T2]]: ... + ) -> Future[tuple[_T1, _T2]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -59,7 +59,7 @@ if sys.version_info >= (3, 10): coro_or_future3: _FutureT[_T3], *, return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3]]: ... + ) -> Future[tuple[_T1, _T2, _T3]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -68,7 +68,7 @@ if sys.version_info >= (3, 10): coro_or_future4: _FutureT[_T4], *, return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3, _T4]]: ... + ) -> Future[tuple[_T1, _T2, _T3, _T4]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -78,7 +78,7 @@ if sys.version_info >= (3, 10): coro_or_future5: _FutureT[_T5], *, return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... + ) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def gather( coro_or_future1: _FutureT[Any], @@ -89,13 +89,13 @@ if sys.version_info >= (3, 10): coro_or_future6: _FutureT[Any], *coros_or_futures: _FutureT[Any], return_exceptions: bool = ..., - ) -> Future[List[Any]]: ... + ) -> Future[list[Any]]: ... @overload - def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: bool = ...) -> Future[Tuple[Union[_T1, BaseException]]]: ... + def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: bool = ...) -> Future[tuple[_T1 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, return_exceptions: bool = ... - ) -> Future[Tuple[Union[_T1, BaseException], Union[_T2, BaseException]]]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -103,7 +103,7 @@ if sys.version_info >= (3, 10): coro_or_future3: _FutureT[_T3], *, return_exceptions: bool = ..., - ) -> Future[Tuple[Union[_T1, BaseException], Union[_T2, BaseException], Union[_T3, BaseException]]]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -112,9 +112,7 @@ if sys.version_info >= (3, 10): coro_or_future4: _FutureT[_T4], *, return_exceptions: bool = ..., - ) -> Future[ - Tuple[Union[_T1, BaseException], Union[_T2, BaseException], Union[_T3, BaseException], Union[_T4, BaseException]] - ]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -125,37 +123,31 @@ if sys.version_info >= (3, 10): *, return_exceptions: bool = ..., ) -> Future[ - Tuple[ - Union[_T1, BaseException], - Union[_T2, BaseException], - Union[_T3, BaseException], - Union[_T4, BaseException], - Union[_T5, BaseException], - ] + tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException, _T5 | BaseException] ]: ... else: @overload def gather( - coro_or_future1: _FutureT[_T1], *, loop: Optional[AbstractEventLoop] = ..., return_exceptions: Literal[False] = ... - ) -> Future[Tuple[_T1]]: ... + coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ... + ) -> Future[tuple[_T1]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2]]: ... + ) -> Future[tuple[_T1, _T2]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], coro_or_future3: _FutureT[_T3], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3]]: ... + ) -> Future[tuple[_T1, _T2, _T3]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -163,9 +155,9 @@ else: coro_or_future3: _FutureT[_T3], coro_or_future4: _FutureT[_T4], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3, _T4]]: ... + ) -> Future[tuple[_T1, _T2, _T3, _T4]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -174,9 +166,9 @@ else: coro_or_future4: _FutureT[_T4], coro_or_future5: _FutureT[_T5], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., - ) -> Future[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... + ) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def gather( coro_or_future1: _FutureT[Any], @@ -186,30 +178,30 @@ else: coro_or_future5: _FutureT[Any], coro_or_future6: _FutureT[Any], *coros_or_futures: _FutureT[Any], - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., - ) -> Future[List[Any]]: ... + ) -> Future[list[Any]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], *, loop: Optional[AbstractEventLoop] = ..., return_exceptions: bool = ... - ) -> Future[Tuple[Union[_T1, BaseException]]]: ... + coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ... + ) -> Future[tuple[_T1 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., - ) -> Future[Tuple[Union[_T1, BaseException], Union[_T2, BaseException]]]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], coro_or_future3: _FutureT[_T3], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., - ) -> Future[Tuple[Union[_T1, BaseException], Union[_T2, BaseException], Union[_T3, BaseException]]]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -217,11 +209,9 @@ else: coro_or_future3: _FutureT[_T3], coro_or_future4: _FutureT[_T4], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., - ) -> Future[ - Tuple[Union[_T1, BaseException], Union[_T2, BaseException], Union[_T3, BaseException], Union[_T4, BaseException]] - ]: ... + ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException]]: ... @overload def gather( coro_or_future1: _FutureT[_T1], @@ -230,16 +220,10 @@ else: coro_or_future4: _FutureT[_T4], coro_or_future5: _FutureT[_T5], *, - loop: Optional[AbstractEventLoop] = ..., + loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., ) -> Future[ - Tuple[ - Union[_T1, BaseException], - Union[_T2, BaseException], - Union[_T3, BaseException], - Union[_T4, BaseException], - Union[_T5, BaseException], - ] + tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException, _T5 | BaseException] ]: ... def run_coroutine_threadsafe(coro: _FutureT[_T], loop: AbstractEventLoop) -> concurrent.futures.Future[_T]: ... @@ -248,68 +232,62 @@ if sys.version_info >= (3, 10): def shield(arg: _FutureT[_T]) -> Future[_T]: ... def sleep(delay: float, result: _T = ...) -> Future[_T]: ... @overload - def wait(fs: Iterable[_FT], *, timeout: Optional[float] = ..., return_when: str = ...) -> Future[Tuple[Set[_FT], Set[_FT]]]: ... # type: ignore + def wait(fs: Iterable[_FT], *, timeout: float | None = ..., return_when: str = ...) -> Future[tuple[set[_FT], set[_FT]]]: ... # type: ignore @overload def wait( - fs: Iterable[Awaitable[_T]], *, timeout: Optional[float] = ..., return_when: str = ... - ) -> Future[Tuple[Set[Task[_T]], Set[Task[_T]]]]: ... - def wait_for(fut: _FutureT[_T], timeout: Optional[float]) -> Future[_T]: ... + fs: Iterable[Awaitable[_T]], *, timeout: float | None = ..., return_when: str = ... + ) -> Future[tuple[set[Task[_T]], set[Task[_T]]]]: ... + def wait_for(fut: _FutureT[_T], timeout: float | None) -> Future[_T]: ... else: - def shield(arg: _FutureT[_T], *, loop: Optional[AbstractEventLoop] = ...) -> Future[_T]: ... - def sleep(delay: float, result: _T = ..., *, loop: Optional[AbstractEventLoop] = ...) -> Future[_T]: ... + def shield(arg: _FutureT[_T], *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... + def sleep(delay: float, result: _T = ..., *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... @overload - def wait(fs: Iterable[_FT], *, loop: Optional[AbstractEventLoop] = ..., timeout: Optional[float] = ..., return_when: str = ...) -> Future[Tuple[Set[_FT], Set[_FT]]]: ... # type: ignore + def wait(fs: Iterable[_FT], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ...) -> Future[tuple[set[_FT], set[_FT]]]: ... # type: ignore @overload def wait( - fs: Iterable[Awaitable[_T]], - *, - loop: Optional[AbstractEventLoop] = ..., - timeout: Optional[float] = ..., - return_when: str = ..., - ) -> Future[Tuple[Set[Task[_T]], Set[Task[_T]]]]: ... - def wait_for(fut: _FutureT[_T], timeout: Optional[float], *, loop: Optional[AbstractEventLoop] = ...) -> Future[_T]: ... + fs: Iterable[Awaitable[_T]], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ... + ) -> Future[tuple[set[Task[_T]], set[Task[_T]]]]: ... + def wait_for(fut: _FutureT[_T], timeout: float | None, *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... class Task(Future[_T], Generic[_T]): if sys.version_info >= (3, 8): def __init__( self, - coro: Union[Generator[_TaskYieldType, None, _T], Awaitable[_T]], + coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T], *, loop: AbstractEventLoop = ..., - name: Optional[str] = ..., + name: str | None = ..., ) -> None: ... else: def __init__( - self, coro: Union[Generator[_TaskYieldType, None, _T], Awaitable[_T]], *, loop: AbstractEventLoop = ... + self, coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T], *, loop: AbstractEventLoop = ... ) -> None: ... def __repr__(self) -> str: ... if sys.version_info >= (3, 8): - def get_coro(self) -> Any: ... + def get_coro(self) -> Generator[_TaskYieldType, None, _T] | Awaitable[_T]: ... def get_name(self) -> str: ... def set_name(self, __value: object) -> None: ... - def get_stack(self, *, limit: Optional[int] = ...) -> List[FrameType]: ... - def print_stack(self, *, limit: Optional[int] = ..., file: Optional[TextIO] = ...) -> None: ... + def get_stack(self, *, limit: int | None = ...) -> list[FrameType]: ... + def print_stack(self, *, limit: int | None = ..., file: TextIO | None = ...) -> None: ... if sys.version_info >= (3, 9): - def cancel(self, msg: Optional[str] = ...) -> bool: ... + def cancel(self, msg: Any | None = ...) -> bool: ... else: def cancel(self) -> bool: ... if sys.version_info < (3, 9): @classmethod - def current_task(cls, loop: Optional[AbstractEventLoop] = ...) -> Optional[Task[Any]]: ... + def current_task(cls, loop: AbstractEventLoop | None = ...) -> Task[Any] | None: ... @classmethod - def all_tasks(cls, loop: Optional[AbstractEventLoop] = ...) -> Set[Task[Any]]: ... + def all_tasks(cls, loop: AbstractEventLoop | None = ...) -> set[Task[Any]]: ... if sys.version_info < (3, 7): def _wakeup(self, fut: Future[Any]) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... if sys.version_info >= (3, 7): - def all_tasks(loop: Optional[AbstractEventLoop] = ...) -> Set[Task[Any]]: ... + def all_tasks(loop: AbstractEventLoop | None = ...) -> set[Task[Any]]: ... if sys.version_info >= (3, 8): - def create_task( - coro: Union[Generator[_TaskYieldType, None, _T], Awaitable[_T]], *, name: Optional[str] = ... - ) -> Task[_T]: ... + def create_task(coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T], *, name: str | None = ...) -> Task[_T]: ... else: - def create_task(coro: Union[Generator[_TaskYieldType, None, _T], Awaitable[_T]]) -> Task[_T]: ... - def current_task(loop: Optional[AbstractEventLoop] = ...) -> Optional[Task[Any]]: ... + def create_task(coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T]) -> Task[_T]: ... + def current_task(loop: AbstractEventLoop | None = ...) -> Task[Any] | None: ... diff --git a/mypy/typeshed/stdlib/asyncio/transports.pyi b/mypy/typeshed/stdlib/asyncio/transports.pyi index 636ac36301c1..acca0e4c28b4 100644 --- a/mypy/typeshed/stdlib/asyncio/transports.pyi +++ b/mypy/typeshed/stdlib/asyncio/transports.pyi @@ -2,10 +2,10 @@ import sys from asyncio.events import AbstractEventLoop from asyncio.protocols import BaseProtocol from socket import _Address -from typing import Any, List, Mapping, Optional, Tuple +from typing import Any, Mapping class BaseTransport: - def __init__(self, extra: Optional[Mapping[Any, Any]] = ...) -> None: ... + def __init__(self, extra: Mapping[Any, Any] | None = ...) -> None: ... def get_extra_info(self, name: Any, default: Any = ...) -> Any: ... def is_closing(self) -> bool: ... def close(self) -> None: ... @@ -19,10 +19,10 @@ class ReadTransport(BaseTransport): def resume_reading(self) -> None: ... class WriteTransport(BaseTransport): - def set_write_buffer_limits(self, high: Optional[int] = ..., low: Optional[int] = ...) -> None: ... + def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... def get_write_buffer_size(self) -> int: ... def write(self, data: Any) -> None: ... - def writelines(self, list_of_data: List[Any]) -> None: ... + def writelines(self, list_of_data: list[Any]) -> None: ... def write_eof(self) -> None: ... def can_write_eof(self) -> bool: ... def abort(self) -> None: ... @@ -30,17 +30,17 @@ class WriteTransport(BaseTransport): class Transport(ReadTransport, WriteTransport): ... class DatagramTransport(BaseTransport): - def sendto(self, data: Any, addr: Optional[_Address] = ...) -> None: ... + def sendto(self, data: Any, addr: _Address | None = ...) -> None: ... def abort(self) -> None: ... class SubprocessTransport(BaseTransport): def get_pid(self) -> int: ... - def get_returncode(self) -> Optional[int]: ... - def get_pipe_transport(self, fd: int) -> Optional[BaseTransport]: ... + def get_returncode(self) -> int | None: ... + def get_pipe_transport(self, fd: int) -> BaseTransport | None: ... def send_signal(self, signal: int) -> int: ... def terminate(self) -> None: ... def kill(self) -> None: ... class _FlowControlMixin(Transport): - def __init__(self, extra: Optional[Mapping[Any, Any]] = ..., loop: Optional[AbstractEventLoop] = ...) -> None: ... - def get_write_buffer_limits(self) -> Tuple[int, int]: ... + def __init__(self, extra: Mapping[Any, Any] | None = ..., loop: AbstractEventLoop | None = ...) -> None: ... + def get_write_buffer_limits(self) -> tuple[int, int]: ... diff --git a/mypy/typeshed/stdlib/asyncio/trsock.pyi b/mypy/typeshed/stdlib/asyncio/trsock.pyi index 0bd3f0adb142..33ec5d67aaf9 100644 --- a/mypy/typeshed/stdlib/asyncio/trsock.pyi +++ b/mypy/typeshed/stdlib/asyncio/trsock.pyi @@ -1,7 +1,7 @@ import socket import sys from types import TracebackType -from typing import Any, BinaryIO, Iterable, List, NoReturn, Optional, Tuple, Type, Union, overload +from typing import Any, BinaryIO, Iterable, NoReturn, Tuple, Type, Union, overload if sys.version_info >= (3, 8): # These are based in socket, maybe move them out into _typeshed.pyi or such @@ -28,23 +28,23 @@ if sys.version_info >= (3, 8): @overload def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... @overload - def setsockopt(self, level: int, optname: int, value: Union[int, bytes]) -> None: ... + def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... @overload def setsockopt(self, level: int, optname: int, value: None, optlen: int) -> None: ... def getpeername(self) -> _RetAddress: ... def getsockname(self) -> _RetAddress: ... def getsockbyname(self) -> NoReturn: ... # This method doesn't exist on socket, yet is passed through? - def accept(self) -> Tuple[socket.socket, _RetAddress]: ... - def connect(self, address: Union[_Address, bytes]) -> None: ... - def connect_ex(self, address: Union[_Address, bytes]) -> int: ... - def bind(self, address: Union[_Address, bytes]) -> None: ... + def accept(self) -> tuple[socket.socket, _RetAddress]: ... + def connect(self, address: _Address | bytes) -> None: ... + def connect_ex(self, address: _Address | bytes) -> int: ... + def bind(self, address: _Address | bytes) -> None: ... if sys.platform == "win32": - def ioctl(self, control: int, option: Union[int, Tuple[int, int, int], bool]) -> None: ... + def ioctl(self, control: int, option: int | tuple[int, int, int] | bool) -> None: ... else: - def ioctl(self, control: int, option: Union[int, Tuple[int, int, int], bool]) -> NoReturn: ... + def ioctl(self, control: int, option: int | tuple[int, int, int] | bool) -> NoReturn: ... def listen(self, __backlog: int = ...) -> None: ... def makefile(self) -> BinaryIO: ... - def sendfile(self, file: BinaryIO, offset: int = ..., count: Optional[int] = ...) -> int: ... + def sendfile(self, file: BinaryIO, offset: int = ..., count: int | None = ...) -> int: ... def close(self) -> None: ... def detach(self) -> int: ... if sys.platform == "linux": @@ -70,17 +70,17 @@ if sys.version_info >= (3, 8): else: def share(self, process_id: int) -> NoReturn: ... def recv_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> int: ... - def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> Tuple[int, _RetAddress]: ... + def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ... def recvmsg_into( self, __buffers: Iterable[_WriteBuffer], __ancbufsize: int = ..., __flags: int = ... - ) -> Tuple[int, List[_CMSG], int, Any]: ... - def recvmsg(self, __bufsize: int, __ancbufsize: int = ..., __flags: int = ...) -> Tuple[bytes, List[_CMSG], int, Any]: ... - def recvfrom(self, bufsize: int, flags: int = ...) -> Tuple[bytes, _RetAddress]: ... + ) -> tuple[int, list[_CMSG], int, Any]: ... + def recvmsg(self, __bufsize: int, __ancbufsize: int = ..., __flags: int = ...) -> tuple[bytes, list[_CMSG], int, Any]: ... + def recvfrom(self, bufsize: int, flags: int = ...) -> tuple[bytes, _RetAddress]: ... def recv(self, bufsize: int, flags: int = ...) -> bytes: ... - def settimeout(self, value: Optional[float]) -> None: ... - def gettimeout(self) -> Optional[float]: ... + def settimeout(self, value: float | None) -> None: ... + def gettimeout(self) -> float | None: ... def setblocking(self, flag: bool) -> None: ... def __enter__(self) -> socket.socket: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/unix_events.pyi b/mypy/typeshed/stdlib/asyncio/unix_events.pyi index 855fca43469b..e8e57a20a765 100644 --- a/mypy/typeshed/stdlib/asyncio/unix_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/unix_events.pyi @@ -1,24 +1,20 @@ import sys import types +from _typeshed import Self from socket import socket -from typing import Any, Callable, Optional, Type, TypeVar +from typing import Any, Callable, Type -from .events import AbstractEventLoop, AbstractServer, BaseDefaultEventLoopPolicy, _ProtocolFactory, _SSLContext +from .base_events import Server +from .events import AbstractEventLoop, BaseDefaultEventLoopPolicy, _ProtocolFactory, _SSLContext from .selector_events import BaseSelectorEventLoop -_T1 = TypeVar("_T1", bound=AbstractChildWatcher) -_T2 = TypeVar("_T2", bound=SafeChildWatcher) -_T3 = TypeVar("_T3", bound=FastChildWatcher) - class AbstractChildWatcher: def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... def remove_child_handler(self, pid: int) -> bool: ... - def attach_loop(self, loop: Optional[AbstractEventLoop]) -> None: ... + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... def close(self) -> None: ... - def __enter__(self: _T1) -> _T1: ... - def __exit__( - self, typ: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[types.TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... if sys.version_info >= (3, 8): def is_active(self) -> bool: ... @@ -26,26 +22,26 @@ class BaseChildWatcher(AbstractChildWatcher): def __init__(self) -> None: ... class SafeChildWatcher(BaseChildWatcher): - def __enter__(self: _T2) -> _T2: ... + def __enter__(self: Self) -> Self: ... class FastChildWatcher(BaseChildWatcher): - def __enter__(self: _T3) -> _T3: ... + def __enter__(self: Self) -> Self: ... class _UnixSelectorEventLoop(BaseSelectorEventLoop): if sys.version_info < (3, 7): async def create_unix_server( self, protocol_factory: _ProtocolFactory, - path: Optional[str] = ..., + path: str | None = ..., *, - sock: Optional[socket] = ..., + sock: socket | None = ..., backlog: int = ..., ssl: _SSLContext = ..., - ) -> AbstractServer: ... + ) -> Server: ... class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): def get_child_watcher(self) -> AbstractChildWatcher: ... - def set_child_watcher(self, watcher: Optional[AbstractChildWatcher]) -> None: ... + def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... SelectorEventLoop = _UnixSelectorEventLoop @@ -54,15 +50,12 @@ DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy if sys.version_info >= (3, 8): from typing import Protocol - - _T4 = TypeVar("_T4", bound=MultiLoopChildWatcher) - _T5 = TypeVar("_T5", bound=ThreadedChildWatcher) class _Warn(Protocol): def __call__( - self, message: str, category: Optional[Type[Warning]] = ..., stacklevel: int = ..., source: Optional[Any] = ... + self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... ) -> None: ... class MultiLoopChildWatcher(AbstractChildWatcher): - def __enter__(self: _T4) -> _T4: ... + def __enter__(self: Self) -> Self: ... class ThreadedChildWatcher(AbstractChildWatcher): - def __enter__(self: _T5) -> _T5: ... + def __enter__(self: Self) -> Self: ... def __del__(self, _warn: _Warn = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/windows_events.pyi b/mypy/typeshed/stdlib/asyncio/windows_events.pyi index 8b12a9f3539c..f0a206a4e139 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_events.pyi @@ -1,6 +1,7 @@ import socket import sys -from typing import IO, Any, Callable, ClassVar, List, NoReturn, Optional, Tuple, Type +from _typeshed import WriteableBuffer +from typing import IO, Any, Callable, ClassVar, NoReturn, Type from . import events, futures, proactor_events, selector_events, streams, windows_utils @@ -29,31 +30,31 @@ class PipeServer: class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop): ... class ProactorEventLoop(proactor_events.BaseProactorEventLoop): - def __init__(self, proactor: Optional[IocpProactor] = ...) -> None: ... + def __init__(self, proactor: IocpProactor | None = ...) -> None: ... async def create_pipe_connection( self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str - ) -> Tuple[proactor_events._ProactorDuplexPipeTransport, streams.StreamReaderProtocol]: ... + ) -> tuple[proactor_events._ProactorDuplexPipeTransport, streams.StreamReaderProtocol]: ... async def start_serving_pipe( self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str - ) -> List[PipeServer]: ... + ) -> list[PipeServer]: ... class IocpProactor: def __init__(self, concurrency: int = ...) -> None: ... def __repr__(self) -> str: ... def __del__(self) -> None: ... def set_loop(self, loop: events.AbstractEventLoop) -> None: ... - def select(self, timeout: Optional[int] = ...) -> List[futures.Future[Any]]: ... + def select(self, timeout: int | None = ...) -> list[futures.Future[Any]]: ... def recv(self, conn: socket.socket, nbytes: int, flags: int = ...) -> futures.Future[bytes]: ... if sys.version_info >= (3, 7): - def recv_into(self, conn: socket.socket, buf: socket._WriteBuffer, flags: int = ...) -> futures.Future[Any]: ... - def send(self, conn: socket.socket, buf: socket._WriteBuffer, flags: int = ...) -> futures.Future[Any]: ... + def recv_into(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... + def send(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... def accept(self, listener: socket.socket) -> futures.Future[Any]: ... def connect(self, conn: socket.socket, address: bytes) -> futures.Future[Any]: ... if sys.version_info >= (3, 7): def sendfile(self, sock: socket.socket, file: IO[bytes], offset: int, count: int) -> futures.Future[Any]: ... def accept_pipe(self, pipe: socket.socket) -> futures.Future[Any]: ... async def connect_pipe(self, address: bytes) -> windows_utils.PipeHandle: ... - def wait_for_handle(self, handle: windows_utils.PipeHandle, timeout: Optional[int] = ...) -> bool: ... + def wait_for_handle(self, handle: windows_utils.PipeHandle, timeout: int | None = ...) -> bool: ... def close(self) -> None: ... SelectorEventLoop = _WindowsSelectorEventLoop diff --git a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi index e6009d58ebc7..bf9cdde25a78 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi @@ -1,6 +1,7 @@ import sys +from _typeshed import Self from types import TracebackType -from typing import Callable, Optional, Protocol, Tuple, Type +from typing import Callable, Protocol, Type class _WarnFunction(Protocol): def __call__(self, message: str, category: Type[Warning] = ..., stacklevel: int = ..., source: PipeHandle = ...) -> None: ... @@ -9,7 +10,7 @@ BUFSIZE: int PIPE: int STDOUT: int -def pipe(*, duplex: bool = ..., overlapped: Tuple[bool, bool] = ..., bufsize: int = ...) -> Tuple[int, int]: ... +def pipe(*, duplex: bool = ..., overlapped: tuple[bool, bool] = ..., bufsize: int = ...) -> tuple[int, int]: ... class PipeHandle: def __init__(self, handle: int) -> None: ... @@ -18,8 +19,8 @@ class PipeHandle: def __del__(self, _warn: _WarnFunction = ...) -> None: ... else: def __del__(self) -> None: ... - def __enter__(self) -> PipeHandle: ... - def __exit__(self, t: Optional[type], v: Optional[BaseException], tb: Optional[TracebackType]) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: type | None, v: BaseException | None, tb: TracebackType | None) -> None: ... @property def handle(self) -> int: ... def fileno(self) -> int: ... diff --git a/mypy/typeshed/stdlib/asyncore.pyi b/mypy/typeshed/stdlib/asyncore.pyi index a05a205115f3..e135221134a5 100644 --- a/mypy/typeshed/stdlib/asyncore.pyi +++ b/mypy/typeshed/stdlib/asyncore.pyi @@ -1,24 +1,25 @@ import sys from _typeshed import FileDescriptorLike -from socket import SocketType -from typing import Any, Dict, Optional, Tuple, Union, overload +from socket import socket +from typing import Any, Dict, Tuple, overload # cyclic dependence with asynchat _maptype = Dict[int, Any] +_socket = socket -socket_map: _maptype = ... # Undocumented +socket_map: _maptype # undocumented class ExitNow(Exception): ... def read(obj: Any) -> None: ... def write(obj: Any) -> None: ... def readwrite(obj: Any, flags: int) -> None: ... -def poll(timeout: float = ..., map: Optional[_maptype] = ...) -> None: ... -def poll2(timeout: float = ..., map: Optional[_maptype] = ...) -> None: ... +def poll(timeout: float = ..., map: _maptype | None = ...) -> None: ... +def poll2(timeout: float = ..., map: _maptype | None = ...) -> None: ... poll3 = poll2 -def loop(timeout: float = ..., use_poll: bool = ..., map: Optional[_maptype] = ..., count: Optional[int] = ...) -> None: ... +def loop(timeout: float = ..., use_poll: bool = ..., map: _maptype | None = ..., count: int | None = ...) -> None: ... # Not really subclass of socket.socket; it's only delegation. # It is not covariant to it. @@ -30,19 +31,19 @@ class dispatcher: connecting: bool closing: bool ignore_log_types: frozenset[str] - socket: Optional[SocketType] - def __init__(self, sock: Optional[SocketType] = ..., map: Optional[_maptype] = ...) -> None: ... - def add_channel(self, map: Optional[_maptype] = ...) -> None: ... - def del_channel(self, map: Optional[_maptype] = ...) -> None: ... + socket: _socket | None + def __init__(self, sock: _socket | None = ..., map: _maptype | None = ...) -> None: ... + def add_channel(self, map: _maptype | None = ...) -> None: ... + def del_channel(self, map: _maptype | None = ...) -> None: ... def create_socket(self, family: int = ..., type: int = ...) -> None: ... - def set_socket(self, sock: SocketType, map: Optional[_maptype] = ...) -> None: ... + def set_socket(self, sock: _socket, map: _maptype | None = ...) -> None: ... def set_reuse_addr(self) -> None: ... def readable(self) -> bool: ... def writable(self) -> bool: ... def listen(self, num: int) -> None: ... - def bind(self, addr: Union[Tuple[Any, ...], str]) -> None: ... - def connect(self, address: Union[Tuple[Any, ...], str]) -> None: ... - def accept(self) -> Optional[Tuple[SocketType, Any]]: ... + def bind(self, addr: Tuple[Any, ...] | str) -> None: ... + def connect(self, address: Tuple[Any, ...] | str) -> None: ... + def accept(self) -> tuple[_socket, Any] | None: ... def send(self, data: bytes) -> int: ... def recv(self, buffer_size: int) -> bytes: ... def close(self) -> None: ... @@ -59,46 +60,16 @@ class dispatcher: def handle_connect(self) -> None: ... def handle_accept(self) -> None: ... def handle_close(self) -> None: ... - if sys.version_info < (3, 5): - # Historically, some methods were "imported" from `self.socket` by - # means of `__getattr__`. This was long deprecated, and as of Python - # 3.5 has been removed; simply call the relevant methods directly on - # self.socket if necessary. - def detach(self) -> int: ... - def fileno(self) -> int: ... - # return value is an address - def getpeername(self) -> Any: ... - def getsockname(self) -> Any: ... - @overload - def getsockopt(self, level: int, optname: int, buflen: None = ...) -> int: ... - @overload - def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... - def gettimeout(self) -> float: ... - def ioctl(self, control: object, option: Tuple[int, int, int]) -> None: ... - # TODO the return value may be BinaryIO or TextIO, depending on mode - def makefile( - self, mode: str = ..., buffering: int = ..., encoding: str = ..., errors: str = ..., newline: str = ... - ) -> Any: ... - # return type is an address - def recvfrom(self, bufsize: int, flags: int = ...) -> Any: ... - def recvfrom_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... - def recv_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... - def sendall(self, data: bytes, flags: int = ...) -> None: ... - def sendto(self, data: bytes, address: Union[Tuple[str, int], str], flags: int = ...) -> int: ... - def setblocking(self, flag: bool) -> None: ... - def settimeout(self, value: Union[float, None]) -> None: ... - def setsockopt(self, level: int, optname: int, value: Union[int, bytes]) -> None: ... - def shutdown(self, how: int) -> None: ... class dispatcher_with_send(dispatcher): - def __init__(self, sock: SocketType = ..., map: Optional[_maptype] = ...) -> None: ... + def __init__(self, sock: socket | None = ..., map: _maptype | None = ...) -> None: ... def initiate_send(self) -> None: ... def handle_write(self) -> None: ... # incompatible signature: - # def send(self, data: bytes) -> Optional[int]: ... + # def send(self, data: bytes) -> int | None: ... -def compact_traceback() -> Tuple[Tuple[str, str, str], type, type, str]: ... -def close_all(map: Optional[_maptype] = ..., ignore_all: bool = ...) -> None: ... +def compact_traceback() -> tuple[tuple[str, str, str], type, type, str]: ... +def close_all(map: _maptype | None = ..., ignore_all: bool = ...) -> None: ... if sys.platform != "win32": class file_wrapper: @@ -115,5 +86,5 @@ if sys.platform != "win32": def close(self) -> None: ... def fileno(self) -> int: ... class file_dispatcher(dispatcher): - def __init__(self, fd: FileDescriptorLike, map: Optional[_maptype] = ...) -> None: ... + def __init__(self, fd: FileDescriptorLike, map: _maptype | None = ...) -> None: ... def set_file(self, fd: int) -> None: ... diff --git a/mypy/typeshed/stdlib/atexit.pyi b/mypy/typeshed/stdlib/atexit.pyi index f068a3ded323..9395c60678b8 100644 --- a/mypy/typeshed/stdlib/atexit.pyi +++ b/mypy/typeshed/stdlib/atexit.pyi @@ -1,7 +1,11 @@ -from typing import Any, Callable +from typing import Any, Callable, TypeVar +from typing_extensions import ParamSpec + +_T = TypeVar("_T") +_P = ParamSpec("_P") def _clear() -> None: ... def _ncallbacks() -> int: ... def _run_exitfuncs() -> None: ... -def register(func: Callable[..., Any], *args: Any, **kwargs: Any) -> Callable[..., Any]: ... +def register(func: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> Callable[_P, _T]: ... # type: ignore def unregister(func: Callable[..., Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/audioop.pyi b/mypy/typeshed/stdlib/audioop.pyi index 606f4b9f5f7e..321bfe55c4b0 100644 --- a/mypy/typeshed/stdlib/audioop.pyi +++ b/mypy/typeshed/stdlib/audioop.pyi @@ -1,4 +1,4 @@ -from typing import Optional, Tuple +from typing import Tuple AdpcmState = Tuple[int, int] RatecvState = Tuple[int, Tuple[Tuple[int, int], ...]] @@ -6,7 +6,7 @@ RatecvState = Tuple[int, Tuple[Tuple[int, int], ...]] class error(Exception): ... def add(__fragment1: bytes, __fragment2: bytes, __width: int) -> bytes: ... -def adpcm2lin(__fragment: bytes, __width: int, __state: Optional[AdpcmState]) -> Tuple[bytes, AdpcmState]: ... +def adpcm2lin(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... def alaw2lin(__fragment: bytes, __width: int) -> bytes: ... def avg(__fragment: bytes, __width: int) -> int: ... def avgpp(__fragment: bytes, __width: int) -> int: ... @@ -14,16 +14,16 @@ def bias(__fragment: bytes, __width: int, __bias: int) -> bytes: ... def byteswap(__fragment: bytes, __width: int) -> bytes: ... def cross(__fragment: bytes, __width: int) -> int: ... def findfactor(__fragment: bytes, __reference: bytes) -> float: ... -def findfit(__fragment: bytes, __reference: bytes) -> Tuple[int, float]: ... +def findfit(__fragment: bytes, __reference: bytes) -> tuple[int, float]: ... def findmax(__fragment: bytes, __length: int) -> int: ... def getsample(__fragment: bytes, __width: int, __index: int) -> int: ... -def lin2adpcm(__fragment: bytes, __width: int, __state: Optional[AdpcmState]) -> Tuple[bytes, AdpcmState]: ... +def lin2adpcm(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... def lin2alaw(__fragment: bytes, __width: int) -> bytes: ... def lin2lin(__fragment: bytes, __width: int, __newwidth: int) -> bytes: ... def lin2ulaw(__fragment: bytes, __width: int) -> bytes: ... def max(__fragment: bytes, __width: int) -> int: ... def maxpp(__fragment: bytes, __width: int) -> int: ... -def minmax(__fragment: bytes, __width: int) -> Tuple[int, int]: ... +def minmax(__fragment: bytes, __width: int) -> tuple[int, int]: ... def mul(__fragment: bytes, __width: int, __factor: float) -> bytes: ... def ratecv( __fragment: bytes, @@ -31,10 +31,10 @@ def ratecv( __nchannels: int, __inrate: int, __outrate: int, - __state: Optional[RatecvState], + __state: RatecvState | None, __weightA: int = ..., __weightB: int = ..., -) -> Tuple[bytes, RatecvState]: ... +) -> tuple[bytes, RatecvState]: ... def reverse(__fragment: bytes, __width: int) -> bytes: ... def rms(__fragment: bytes, __width: int) -> int: ... def tomono(__fragment: bytes, __width: int, __lfactor: float, __rfactor: float) -> bytes: ... diff --git a/mypy/typeshed/stdlib/base64.pyi b/mypy/typeshed/stdlib/base64.pyi index e217d6d3dbf2..8610eea17b52 100644 --- a/mypy/typeshed/stdlib/base64.pyi +++ b/mypy/typeshed/stdlib/base64.pyi @@ -1,40 +1,29 @@ import sys -from typing import IO, Optional, Union +from typing import IO -if sys.version_info >= (3, 0): - _encodable = bytes - _decodable = Union[bytes, str] -else: - _encodable = Union[bytes, unicode] - _decodable = Union[bytes, unicode] - -def b64encode(s: _encodable, altchars: Optional[bytes] = ...) -> bytes: ... -def b64decode(s: _decodable, altchars: Optional[bytes] = ..., validate: bool = ...) -> bytes: ... -def standard_b64encode(s: _encodable) -> bytes: ... -def standard_b64decode(s: _decodable) -> bytes: ... -def urlsafe_b64encode(s: _encodable) -> bytes: ... -def urlsafe_b64decode(s: _decodable) -> bytes: ... -def b32encode(s: _encodable) -> bytes: ... -def b32decode(s: _decodable, casefold: bool = ..., map01: Optional[bytes] = ...) -> bytes: ... -def b16encode(s: _encodable) -> bytes: ... -def b16decode(s: _decodable, casefold: bool = ...) -> bytes: ... +def b64encode(s: bytes, altchars: bytes | None = ...) -> bytes: ... +def b64decode(s: str | bytes, altchars: bytes | None = ..., validate: bool = ...) -> bytes: ... +def standard_b64encode(s: bytes) -> bytes: ... +def standard_b64decode(s: str | bytes) -> bytes: ... +def urlsafe_b64encode(s: bytes) -> bytes: ... +def urlsafe_b64decode(s: str | bytes) -> bytes: ... +def b32encode(s: bytes) -> bytes: ... +def b32decode(s: str | bytes, casefold: bool = ..., map01: bytes | None = ...) -> bytes: ... +def b16encode(s: bytes) -> bytes: ... +def b16decode(s: str | bytes, casefold: bool = ...) -> bytes: ... if sys.version_info >= (3, 10): - def b32hexencode(s: _encodable) -> bytes: ... - def b32hexdecode(s: _decodable, casefold: bool = ...) -> bytes: ... - -if sys.version_info >= (3, 4): - def a85encode(b: _encodable, *, foldspaces: bool = ..., wrapcol: int = ..., pad: bool = ..., adobe: bool = ...) -> bytes: ... - def a85decode(b: _decodable, *, foldspaces: bool = ..., adobe: bool = ..., ignorechars: Union[str, bytes] = ...) -> bytes: ... - def b85encode(b: _encodable, pad: bool = ...) -> bytes: ... - def b85decode(b: _decodable) -> bytes: ... + def b32hexencode(s: bytes) -> bytes: ... + def b32hexdecode(s: str | bytes, casefold: bool = ...) -> bytes: ... +def a85encode(b: bytes, *, foldspaces: bool = ..., wrapcol: int = ..., pad: bool = ..., adobe: bool = ...) -> bytes: ... +def a85decode(b: str | bytes, *, foldspaces: bool = ..., adobe: bool = ..., ignorechars: str | bytes = ...) -> bytes: ... +def b85encode(b: bytes, pad: bool = ...) -> bytes: ... +def b85decode(b: str | bytes) -> bytes: ... def decode(input: IO[bytes], output: IO[bytes]) -> None: ... def encode(input: IO[bytes], output: IO[bytes]) -> None: ... - -if sys.version_info >= (3,): - def encodebytes(s: bytes) -> bytes: ... - def decodebytes(s: bytes) -> bytes: ... +def encodebytes(s: bytes) -> bytes: ... +def decodebytes(s: bytes) -> bytes: ... if sys.version_info < (3, 9): def encodestring(s: bytes) -> bytes: ... diff --git a/mypy/typeshed/stdlib/bdb.pyi b/mypy/typeshed/stdlib/bdb.pyi index 9d76b3afde22..1d03ddf19a0e 100644 --- a/mypy/typeshed/stdlib/bdb.pyi +++ b/mypy/typeshed/stdlib/bdb.pyi @@ -1,26 +1,26 @@ from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, Dict, Iterable, List, Mapping, Optional, Set, SupportsInt, Tuple, Type, TypeVar, Union +from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, Tuple, Type, TypeVar _T = TypeVar("_T") _TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type _ExcInfo = Tuple[Type[BaseException], BaseException, FrameType] -GENERATOR_AND_COROUTINE_FLAGS: int = ... +GENERATOR_AND_COROUTINE_FLAGS: int class BdbQuit(Exception): ... class Bdb: - skip: Optional[Set[str]] - breaks: Dict[str, List[int]] - fncache: Dict[str, str] - frame_returning: Optional[FrameType] - botframe: Optional[FrameType] + skip: set[str] | None + breaks: dict[str, list[int]] + fncache: dict[str, str] + frame_returning: FrameType | None + botframe: FrameType | None quitting: bool - stopframe: Optional[FrameType] - returnframe: Optional[FrameType] + stopframe: FrameType | None + returnframe: FrameType | None stoplineno: int - def __init__(self, skip: Optional[Iterable[str]] = ...) -> None: ... + def __init__(self, skip: Iterable[str] | None = ...) -> None: ... def canonic(self, filename: str) -> str: ... def reset(self) -> None: ... def trace_dispatch(self, frame: FrameType, event: str, arg: Any) -> _TraceDispatch: ... @@ -31,21 +31,21 @@ class Bdb: def is_skipped_module(self, module_name: str) -> bool: ... def stop_here(self, frame: FrameType) -> bool: ... def break_here(self, frame: FrameType) -> bool: ... - def do_clear(self, arg: Any) -> Optional[bool]: ... + def do_clear(self, arg: Any) -> bool | None: ... def break_anywhere(self, frame: FrameType) -> bool: ... def user_call(self, frame: FrameType, argument_list: None) -> None: ... def user_line(self, frame: FrameType) -> None: ... def user_return(self, frame: FrameType, return_value: Any) -> None: ... def user_exception(self, frame: FrameType, exc_info: _ExcInfo) -> None: ... - def set_until(self, frame: FrameType, lineno: Optional[int] = ...) -> None: ... + def set_until(self, frame: FrameType, lineno: int | None = ...) -> None: ... def set_step(self) -> None: ... def set_next(self, frame: FrameType) -> None: ... def set_return(self, frame: FrameType) -> None: ... - def set_trace(self, frame: Optional[FrameType] = ...) -> None: ... + def set_trace(self, frame: FrameType | None = ...) -> None: ... def set_continue(self) -> None: ... def set_quit(self) -> None: ... def set_break( - self, filename: str, lineno: int, temporary: bool = ..., cond: Optional[str] = ..., funcname: Optional[str] = ... + self, filename: str, lineno: int, temporary: bool = ..., cond: str | None = ..., funcname: str | None = ... ) -> None: ... def clear_break(self, filename: str, lineno: int) -> None: ... def clear_bpbynumber(self, arg: SupportsInt) -> None: ... @@ -53,46 +53,42 @@ class Bdb: def clear_all_breaks(self) -> None: ... def get_bpbynumber(self, arg: SupportsInt) -> Breakpoint: ... def get_break(self, filename: str, lineno: int) -> bool: ... - def get_breaks(self, filename: str, lineno: int) -> List[Breakpoint]: ... - def get_file_breaks(self, filename: str) -> List[Breakpoint]: ... - def get_all_breaks(self) -> List[Breakpoint]: ... - def get_stack(self, f: Optional[FrameType], t: Optional[TracebackType]) -> Tuple[List[Tuple[FrameType, int]], int]: ... + def get_breaks(self, filename: str, lineno: int) -> list[Breakpoint]: ... + def get_file_breaks(self, filename: str) -> list[Breakpoint]: ... + def get_all_breaks(self) -> list[Breakpoint]: ... + def get_stack(self, f: FrameType | None, t: TracebackType | None) -> tuple[list[tuple[FrameType, int]], int]: ... def format_stack_entry(self, frame_lineno: int, lprefix: str = ...) -> str: ... - def run( - self, cmd: Union[str, CodeType], globals: Optional[Dict[str, Any]] = ..., locals: Optional[Mapping[str, Any]] = ... - ) -> None: ... - def runeval(self, expr: str, globals: Optional[Dict[str, Any]] = ..., locals: Optional[Mapping[str, Any]] = ...) -> None: ... - def runctx( - self, cmd: Union[str, CodeType], globals: Optional[Dict[str, Any]], locals: Optional[Mapping[str, Any]] - ) -> None: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kwds: Any) -> Optional[_T]: ... + def run(self, cmd: str | CodeType, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runeval(self, expr: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runctx(self, cmd: str | CodeType, globals: dict[str, Any] | None, locals: Mapping[str, Any] | None) -> None: ... + def runcall(self, __func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... class Breakpoint: - next: int = ... - bplist: Dict[Tuple[str, int], List[Breakpoint]] = ... - bpbynumber: List[Optional[Breakpoint]] = ... + next: int + bplist: dict[tuple[str, int], list[Breakpoint]] + bpbynumber: list[Breakpoint | None] - funcname: Optional[str] - func_first_executable_line: Optional[int] + funcname: str | None + func_first_executable_line: int | None file: str line: int temporary: bool - cond: Optional[str] + cond: str | None enabled: bool ignore: int hits: int number: int def __init__( - self, file: str, line: int, temporary: bool = ..., cond: Optional[str] = ..., funcname: Optional[str] = ... + self, file: str, line: int, temporary: bool = ..., cond: str | None = ..., funcname: str | None = ... ) -> None: ... def deleteMe(self) -> None: ... def enable(self) -> None: ... def disable(self) -> None: ... - def bpprint(self, out: Optional[IO[str]] = ...) -> None: ... + def bpprint(self, out: IO[str] | None = ...) -> None: ... def bpformat(self) -> str: ... def __str__(self) -> str: ... def checkfuncname(b: Breakpoint, frame: FrameType) -> bool: ... -def effective(file: str, line: int, frame: FrameType) -> Union[Tuple[Breakpoint, bool], Tuple[None, None]]: ... +def effective(file: str, line: int, frame: FrameType) -> tuple[Breakpoint, bool] | tuple[None, None]: ... def set_trace() -> None: ... diff --git a/mypy/typeshed/stdlib/binascii.pyi b/mypy/typeshed/stdlib/binascii.pyi index db843ad6ca31..962f5666b284 100644 --- a/mypy/typeshed/stdlib/binascii.pyi +++ b/mypy/typeshed/stdlib/binascii.pyi @@ -1,50 +1,33 @@ import sys -from typing import Text, Union -if sys.version_info >= (3, 0): - # But since Python 3.3 ASCII-only unicode strings are accepted by the - # a2b_* functions. - _Bytes = bytes - _Ascii = Union[bytes, str] -else: - # Python 2 accepts unicode ascii pretty much everywhere. - _Bytes = Text - _Ascii = Text - -def a2b_uu(__data: _Ascii) -> bytes: ... +def a2b_uu(__data: str | bytes) -> bytes: ... if sys.version_info >= (3, 7): - def b2a_uu(__data: _Bytes, *, backtick: bool = ...) -> bytes: ... - -else: - def b2a_uu(__data: _Bytes) -> bytes: ... - -def a2b_base64(__data: _Ascii) -> bytes: ... - -if sys.version_info >= (3, 6): - def b2a_base64(__data: _Bytes, *, newline: bool = ...) -> bytes: ... + def b2a_uu(__data: bytes, *, backtick: bool = ...) -> bytes: ... else: - def b2a_base64(__data: _Bytes) -> bytes: ... - -def a2b_qp(data: _Ascii, header: bool = ...) -> bytes: ... -def b2a_qp(data: _Bytes, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... -def a2b_hqx(__data: _Ascii) -> bytes: ... -def rledecode_hqx(__data: _Bytes) -> bytes: ... -def rlecode_hqx(__data: _Bytes) -> bytes: ... -def b2a_hqx(__data: _Bytes) -> bytes: ... -def crc_hqx(__data: _Bytes, __crc: int) -> int: ... -def crc32(__data: _Bytes, __crc: int = ...) -> int: ... -def b2a_hex(__data: _Bytes) -> bytes: ... + def b2a_uu(__data: bytes) -> bytes: ... + +def a2b_base64(__data: str | bytes) -> bytes: ... +def b2a_base64(__data: bytes, *, newline: bool = ...) -> bytes: ... +def a2b_qp(data: str | bytes, header: bool = ...) -> bytes: ... +def b2a_qp(data: bytes, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... +def a2b_hqx(__data: str | bytes) -> bytes: ... +def rledecode_hqx(__data: bytes) -> bytes: ... +def rlecode_hqx(__data: bytes) -> bytes: ... +def b2a_hqx(__data: bytes) -> bytes: ... +def crc_hqx(__data: bytes, __crc: int) -> int: ... +def crc32(__data: bytes, __crc: int = ...) -> int: ... +def b2a_hex(__data: bytes) -> bytes: ... if sys.version_info >= (3, 8): - def hexlify(data: bytes, sep: Union[str, bytes] = ..., bytes_per_sep: int = ...) -> bytes: ... + def hexlify(data: bytes, sep: str | bytes = ..., bytes_per_sep: int = ...) -> bytes: ... else: - def hexlify(__data: _Bytes) -> bytes: ... + def hexlify(__data: bytes) -> bytes: ... -def a2b_hex(__hexstr: _Ascii) -> bytes: ... -def unhexlify(__hexstr: _Ascii) -> bytes: ... +def a2b_hex(__hexstr: str | bytes) -> bytes: ... +def unhexlify(__hexstr: str | bytes) -> bytes: ... class Error(ValueError): ... class Incomplete(Exception): ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 69da371906d0..71efda9b979a 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -1,21 +1,27 @@ import sys import types +from _ast import AST +from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import ( - AnyPath, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, OpenBinaryModeWriting, OpenTextMode, ReadableBuffer, + Self, + StrOrBytesPath, + SupportsAnext, SupportsDivMod, SupportsKeysAndGetItem, - SupportsLessThan, - SupportsLessThanT, + SupportsLenAndGetItem, + SupportsNext, SupportsRDivMod, + SupportsRichComparison, + SupportsRichComparisonT, + SupportsTrunc, SupportsWrite, ) -from ast import AST, mod from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from types import CodeType, TracebackType from typing import ( @@ -27,24 +33,17 @@ from typing import ( BinaryIO, ByteString, Callable, - Dict, - FrozenSet, Generic, - ItemsView, Iterable, Iterator, - KeysView, - List, Mapping, MutableMapping, MutableSequence, MutableSet, NoReturn, - Optional, Protocol, Reversible, Sequence, - Set, Sized, SupportsAbs, SupportsBytes, @@ -56,17 +55,13 @@ from typing import ( Type, TypeVar, Union, - ValuesView, overload, ) -from typing_extensions import Literal, SupportsIndex, final +from typing_extensions import Literal, SupportsIndex, TypeGuard, final if sys.version_info >= (3, 9): from types import GenericAlias -class _SupportsTrunc(Protocol): - def __trunc__(self) -> int: ... - _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) @@ -80,54 +75,67 @@ _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _TT = TypeVar("_TT", bound="type") _TBE = TypeVar("_TBE", bound="BaseException") +_R = TypeVar("_R") # Return-type TypeVar class object: - __doc__: Optional[str] - __dict__: Dict[str, Any] - __slots__: Union[str, Iterable[str]] + __doc__: str | None + __dict__: dict[str, Any] + __slots__: str | Iterable[str] __module__: str - __annotations__: Dict[str, Any] + __annotations__: dict[str, Any] @property def __class__(self: _T) -> Type[_T]: ... # Ignore errors about type mismatch between property getter and setter @__class__.setter def __class__(self, __type: Type[object]) -> None: ... # type: ignore # noqa: F811 def __init__(self) -> None: ... - def __new__(cls) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __eq__(self, o: object) -> bool: ... - def __ne__(self, o: object) -> bool: ... + def __new__(cls: Type[_T]) -> _T: ... + def __setattr__(self, __name: str, __value: Any) -> None: ... + def __eq__(self, __o: object) -> bool: ... + def __ne__(self, __o: object) -> bool: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... def __hash__(self) -> int: ... - def __format__(self, format_spec: str) -> str: ... - def __getattribute__(self, name: str) -> Any: ... - def __delattr__(self, name: str) -> None: ... + def __format__(self, __format_spec: str) -> str: ... + def __getattribute__(self, __name: str) -> Any: ... + def __delattr__(self, __name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> Union[str, Tuple[Any, ...]]: ... - def __reduce_ex__(self, protocol: int) -> Union[str, Tuple[Any, ...]]: ... + def __reduce__(self) -> str | Tuple[object, ...]: ... + if sys.version_info >= (3, 8): + def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[object, ...]: ... + else: + def __reduce_ex__(self, __protocol: int) -> str | Tuple[object, ...]: ... def __dir__(self) -> Iterable[str]: ... def __init_subclass__(cls) -> None: ... -class staticmethod(object): # Special, only valid as a decorator. - __func__: Callable[..., Any] +class staticmethod(Generic[_R]): # Special, only valid as a decorator. + __func__: Callable[..., _R] __isabstractmethod__: bool - def __init__(self, f: Callable[..., Any]) -> None: ... + def __init__(self: staticmethod[_R], __f: Callable[..., _R]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, __obj: _T, __type: Type[_T] | None = ...) -> Callable[..., _R]: ... + if sys.version_info >= (3, 10): + __name__: str + __qualname__: str + __wrapped__: Callable[..., _R] + def __call__(self, *args: Any, **kwargs: Any) -> _R: ... -class classmethod(object): # Special, only valid as a decorator. - __func__: Callable[..., Any] +class classmethod(Generic[_R]): # Special, only valid as a decorator. + __func__: Callable[..., _R] __isabstractmethod__: bool - def __init__(self, f: Callable[..., Any]) -> None: ... + def __init__(self: classmethod[_R], __f: Callable[..., _R]) -> None: ... def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Optional[Type[_T]] = ...) -> Callable[..., Any]: ... + def __get__(self, __obj: _T, __type: Type[_T] | None = ...) -> Callable[..., _R]: ... + if sys.version_info >= (3, 10): + __name__: str + __qualname__: str + __wrapped__: Callable[..., _R] class type(object): __base__: type __bases__: Tuple[type, ...] __basicsize__: int - __dict__: Dict[str, Any] + __dict__: dict[str, Any] __dictoffset__: int __flags__: int __itemsize__: int @@ -135,43 +143,47 @@ class type(object): __mro__: Tuple[type, ...] __name__: str __qualname__: str - __text_signature__: Optional[str] + __text_signature__: str | None __weakrefoffset__: int @overload - def __init__(self, o: object) -> None: ... + def __init__(self, __o: object) -> None: ... @overload - def __init__(self, name: str, bases: Tuple[type, ...], dict: Dict[str, Any], **kwds: Any) -> None: ... + def __init__(self, __name: str, __bases: Tuple[type, ...], __dict: dict[str, Any], **kwds: Any) -> None: ... @overload - def __new__(cls, o: object) -> type: ... + def __new__(cls, __o: object) -> type: ... @overload - def __new__(cls: Type[_TT], name: str, bases: Tuple[type, ...], namespace: Dict[str, Any], **kwds: Any) -> _TT: ... + def __new__(cls: Type[_TT], __name: str, __bases: Tuple[type, ...], __namespace: dict[str, Any], **kwds: Any) -> _TT: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... - def __subclasses__(self: _TT) -> List[_TT]: ... - # Note: the documentation doesnt specify what the return type is, the standard + def __subclasses__(self: _TT) -> list[_TT]: ... + # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. - def mro(self) -> List[type]: ... - def __instancecheck__(self, instance: Any) -> bool: ... - def __subclasscheck__(self, subclass: type) -> bool: ... + def mro(self) -> list[type]: ... + def __instancecheck__(self, __instance: Any) -> bool: ... + def __subclasscheck__(self, __subclass: type) -> bool: ... @classmethod - def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, Any]: ... + def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, object]: ... if sys.version_info >= (3, 10): - def __or__(self, t: Any) -> types.Union: ... + def __or__(self, __t: Any) -> types.UnionType: ... + def __ror__(self, __t: Any) -> types.UnionType: ... class super(object): @overload - def __init__(self, t: Any, obj: Any) -> None: ... + def __init__(self, __t: Any, __obj: Any) -> None: ... @overload - def __init__(self, t: Any) -> None: ... + def __init__(self, __t: Any) -> None: ... @overload def __init__(self) -> None: ... +_PositiveInteger = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] +_NegativeInteger = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20] + class int: @overload - def __new__(cls: Type[_T], x: Union[str, bytes, SupportsInt, SupportsIndex, _SupportsTrunc] = ...) -> _T: ... + def __new__(cls: Type[_T], __x: str | bytes | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> _T: ... @overload - def __new__(cls: Type[_T], x: Union[str, bytes, bytearray], base: int) -> _T: ... + def __new__(cls: Type[_T], __x: str | bytes | bytearray, base: SupportsIndex) -> _T: ... if sys.version_info >= (3, 8): - def as_integer_ratio(self) -> Tuple[int, Literal[1]]: ... + def as_integer_ratio(self) -> tuple[int, Literal[1]]: ... @property def real(self) -> int: ... @property @@ -184,54 +196,62 @@ class int: def bit_length(self) -> int: ... if sys.version_info >= (3, 10): def bit_count(self) -> int: ... - def to_bytes(self, length: int, byteorder: str, *, signed: bool = ...) -> bytes: ... + def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = ...) -> bytes: ... @classmethod def from_bytes( - cls, bytes: Union[Iterable[int], SupportsBytes], byteorder: str, *, signed: bool = ... + cls, bytes: Iterable[SupportsIndex] | SupportsBytes, byteorder: Literal["little", "big"], *, signed: bool = ... ) -> int: ... # TODO buffer object argument - def __add__(self, x: int) -> int: ... - def __sub__(self, x: int) -> int: ... - def __mul__(self, x: int) -> int: ... - def __floordiv__(self, x: int) -> int: ... - def __truediv__(self, x: int) -> float: ... - def __mod__(self, x: int) -> int: ... - def __divmod__(self, x: int) -> Tuple[int, int]: ... - def __radd__(self, x: int) -> int: ... - def __rsub__(self, x: int) -> int: ... - def __rmul__(self, x: int) -> int: ... - def __rfloordiv__(self, x: int) -> int: ... - def __rtruediv__(self, x: int) -> float: ... - def __rmod__(self, x: int) -> int: ... - def __rdivmod__(self, x: int) -> Tuple[int, int]: ... - @overload - def __pow__(self, __x: Literal[2], __modulo: Optional[int] = ...) -> int: ... - @overload - def __pow__(self, __x: int, __modulo: Optional[int] = ...) -> Any: ... # Return type can be int or float, depending on x. - def __rpow__(self, x: int, mod: Optional[int] = ...) -> Any: ... - def __and__(self, n: int) -> int: ... - def __or__(self, n: int) -> int: ... - def __xor__(self, n: int) -> int: ... - def __lshift__(self, n: int) -> int: ... - def __rshift__(self, n: int) -> int: ... - def __rand__(self, n: int) -> int: ... - def __ror__(self, n: int) -> int: ... - def __rxor__(self, n: int) -> int: ... - def __rlshift__(self, n: int) -> int: ... - def __rrshift__(self, n: int) -> int: ... + def __add__(self, __x: int) -> int: ... + def __sub__(self, __x: int) -> int: ... + def __mul__(self, __x: int) -> int: ... + def __floordiv__(self, __x: int) -> int: ... + def __truediv__(self, __x: int) -> float: ... + def __mod__(self, __x: int) -> int: ... + def __divmod__(self, __x: int) -> tuple[int, int]: ... + def __radd__(self, __x: int) -> int: ... + def __rsub__(self, __x: int) -> int: ... + def __rmul__(self, __x: int) -> int: ... + def __rfloordiv__(self, __x: int) -> int: ... + def __rtruediv__(self, __x: int) -> float: ... + def __rmod__(self, __x: int) -> int: ... + def __rdivmod__(self, __x: int) -> tuple[int, int]: ... + @overload + def __pow__(self, __x: int, __modulo: Literal[0]) -> NoReturn: ... + @overload + def __pow__(self, __x: int, __modulo: int) -> int: ... + @overload + def __pow__(self, __x: _PositiveInteger, __modulo: None = ...) -> int: ... + @overload + def __pow__(self, __x: _NegativeInteger, __modulo: None = ...) -> float: ... + # positive x -> int; negative x -> float + # return type must be Any as `int | float` causes too many false-positive errors + @overload + def __pow__(self, __x: int, __modulo: None = ...) -> Any: ... + def __rpow__(self, __x: int, __mod: int | None = ...) -> Any: ... + def __and__(self, __n: int) -> int: ... + def __or__(self, __n: int) -> int: ... + def __xor__(self, __n: int) -> int: ... + def __lshift__(self, __n: int) -> int: ... + def __rshift__(self, __n: int) -> int: ... + def __rand__(self, __n: int) -> int: ... + def __ror__(self, __n: int) -> int: ... + def __rxor__(self, __n: int) -> int: ... + def __rlshift__(self, __n: int) -> int: ... + def __rrshift__(self, __n: int) -> int: ... def __neg__(self) -> int: ... def __pos__(self) -> int: ... def __invert__(self) -> int: ... def __trunc__(self) -> int: ... def __ceil__(self) -> int: ... def __floor__(self) -> int: ... - def __round__(self, ndigits: Optional[int] = ...) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... - def __eq__(self, x: object) -> bool: ... - def __ne__(self, x: object) -> bool: ... - def __lt__(self, x: int) -> bool: ... - def __le__(self, x: int) -> bool: ... - def __gt__(self, x: int) -> bool: ... - def __ge__(self, x: int) -> bool: ... + def __round__(self, __ndigits: SupportsIndex = ...) -> int: ... + def __getnewargs__(self) -> tuple[int]: ... + def __eq__(self, __x: object) -> bool: ... + def __ne__(self, __x: object) -> bool: ... + def __lt__(self, __x: int) -> bool: ... + def __le__(self, __x: int) -> bool: ... + def __gt__(self, __x: int) -> bool: ... + def __ge__(self, __x: int) -> bool: ... def __str__(self) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... @@ -241,8 +261,8 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: Union[SupportsFloat, SupportsIndex, str, bytes, bytearray] = ...) -> _T: ... - def as_integer_ratio(self) -> Tuple[int, int]: ... + def __new__(cls: Type[_T], x: SupportsFloat | SupportsIndex | str | bytes | bytearray = ...) -> _T: ... + def as_integer_ratio(self) -> tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @classmethod @@ -252,39 +272,42 @@ class float: @property def imag(self) -> float: ... def conjugate(self) -> float: ... - def __add__(self, x: float) -> float: ... - def __sub__(self, x: float) -> float: ... - def __mul__(self, x: float) -> float: ... - def __floordiv__(self, x: float) -> float: ... - def __truediv__(self, x: float) -> float: ... - def __mod__(self, x: float) -> float: ... - def __divmod__(self, x: float) -> Tuple[float, float]: ... - def __pow__( - self, x: float, mod: None = ... - ) -> float: ... # In Python 3, returns complex if self is negative and x is not whole - def __radd__(self, x: float) -> float: ... - def __rsub__(self, x: float) -> float: ... - def __rmul__(self, x: float) -> float: ... - def __rfloordiv__(self, x: float) -> float: ... - def __rtruediv__(self, x: float) -> float: ... - def __rmod__(self, x: float) -> float: ... - def __rdivmod__(self, x: float) -> Tuple[float, float]: ... - def __rpow__(self, x: float, mod: None = ...) -> float: ... - def __getnewargs__(self) -> Tuple[float]: ... + def __add__(self, __x: float) -> float: ... + def __sub__(self, __x: float) -> float: ... + def __mul__(self, __x: float) -> float: ... + def __floordiv__(self, __x: float) -> float: ... + def __truediv__(self, __x: float) -> float: ... + def __mod__(self, __x: float) -> float: ... + def __divmod__(self, __x: float) -> tuple[float, float]: ... + @overload + def __pow__(self, __x: int, __mod: None = ...) -> float: ... + # positive x -> float; negative x -> complex + # return type must be Any as `float | complex` causes too many false-positive errors + @overload + def __pow__(self, __x: float, __mod: None = ...) -> Any: ... + def __radd__(self, __x: float) -> float: ... + def __rsub__(self, __x: float) -> float: ... + def __rmul__(self, __x: float) -> float: ... + def __rfloordiv__(self, __x: float) -> float: ... + def __rtruediv__(self, __x: float) -> float: ... + def __rmod__(self, __x: float) -> float: ... + def __rdivmod__(self, __x: float) -> tuple[float, float]: ... + def __rpow__(self, __x: float, __mod: None = ...) -> float: ... + def __getnewargs__(self) -> tuple[float]: ... def __trunc__(self) -> int: ... if sys.version_info >= (3, 9): def __ceil__(self) -> int: ... def __floor__(self) -> int: ... @overload - def __round__(self, ndigits: None = ...) -> int: ... + def __round__(self, __ndigits: None = ...) -> int: ... @overload - def __round__(self, ndigits: int) -> float: ... - def __eq__(self, x: object) -> bool: ... - def __ne__(self, x: object) -> bool: ... - def __lt__(self, x: float) -> bool: ... - def __le__(self, x: float) -> bool: ... - def __gt__(self, x: float) -> bool: ... - def __ge__(self, x: float) -> bool: ... + def __round__(self, __ndigits: SupportsIndex) -> float: ... + def __eq__(self, __x: object) -> bool: ... + def __ne__(self, __x: object) -> bool: ... + def __lt__(self, __x: float) -> bool: ... + def __le__(self, __x: float) -> bool: ... + def __gt__(self, __x: float) -> bool: ... + def __ge__(self, __x: float) -> bool: ... def __neg__(self) -> float: ... def __pos__(self) -> float: ... def __str__(self) -> str: ... @@ -298,24 +321,24 @@ class complex: @overload def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... @overload - def __new__(cls: Type[_T], real: Union[str, SupportsComplex, SupportsIndex]) -> _T: ... + def __new__(cls: Type[_T], real: str | SupportsComplex | SupportsIndex | complex) -> _T: ... @property def real(self) -> float: ... @property def imag(self) -> float: ... def conjugate(self) -> complex: ... - def __add__(self, x: complex) -> complex: ... - def __sub__(self, x: complex) -> complex: ... - def __mul__(self, x: complex) -> complex: ... - def __pow__(self, x: complex, mod: None = ...) -> complex: ... - def __truediv__(self, x: complex) -> complex: ... - def __radd__(self, x: complex) -> complex: ... - def __rsub__(self, x: complex) -> complex: ... - def __rmul__(self, x: complex) -> complex: ... - def __rpow__(self, x: complex, mod: None = ...) -> complex: ... - def __rtruediv__(self, x: complex) -> complex: ... - def __eq__(self, x: object) -> bool: ... - def __ne__(self, x: object) -> bool: ... + def __add__(self, __x: complex) -> complex: ... + def __sub__(self, __x: complex) -> complex: ... + def __mul__(self, __x: complex) -> complex: ... + def __pow__(self, __x: complex, mod: None = ...) -> complex: ... + def __truediv__(self, __x: complex) -> complex: ... + def __radd__(self, __x: complex) -> complex: ... + def __rsub__(self, __x: complex) -> complex: ... + def __rmul__(self, __x: complex) -> complex: ... + def __rpow__(self, __x: complex, __mod: None = ...) -> complex: ... + def __rtruediv__(self, __x: complex) -> complex: ... + def __eq__(self, __x: object) -> bool: ... + def __ne__(self, __x: object) -> bool: ... def __neg__(self) -> complex: ... def __pos__(self) -> complex: ... def __str__(self) -> str: ... @@ -328,22 +351,25 @@ class _FormatMapMapping(Protocol): class str(Sequence[str]): @overload - def __new__(cls: Type[_T], o: object = ...) -> _T: ... + def __new__(cls: Type[_T], object: object = ...) -> _T: ... @overload def __new__(cls: Type[_T], o: bytes, encoding: str = ..., errors: str = ...) -> _T: ... def capitalize(self) -> str: ... def casefold(self) -> str: ... - def center(self, __width: int, __fillchar: str = ...) -> str: ... - def count(self, x: str, __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ...) -> int: ... + def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... + def count(self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def encode(self, encoding: str = ..., errors: str = ...) -> bytes: ... def endswith( - self, __suffix: Union[str, Tuple[str, ...]], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __suffix: str | Tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def expandtabs(self, tabsize: int = ...) -> str: ... - def find(self, __sub: str, __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ...) -> int: ... + if sys.version_info >= (3, 8): + def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... + else: + def expandtabs(self, tabsize: int = ...) -> str: ... + def find(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... def format_map(self, map: _FormatMapMapping) -> str: ... - def index(self, __sub: str, __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ...) -> int: ... + def index(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... if sys.version_info >= (3, 7): @@ -358,90 +384,90 @@ class str(Sequence[str]): def istitle(self) -> bool: ... def isupper(self) -> bool: ... def join(self, __iterable: Iterable[str]) -> str: ... - def ljust(self, __width: int, __fillchar: str = ...) -> str: ... + def ljust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... def lower(self) -> str: ... - def lstrip(self, __chars: Optional[str] = ...) -> str: ... - def partition(self, __sep: str) -> Tuple[str, str, str]: ... - def replace(self, __old: str, __new: str, __count: int = ...) -> str: ... + def lstrip(self, __chars: str | None = ...) -> str: ... + def partition(self, __sep: str) -> tuple[str, str, str]: ... + def replace(self, __old: str, __new: str, __count: SupportsIndex = ...) -> str: ... if sys.version_info >= (3, 9): def removeprefix(self, __prefix: str) -> str: ... def removesuffix(self, __suffix: str) -> str: ... - def rfind(self, __sub: str, __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ...) -> int: ... - def rindex(self, __sub: str, __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ...) -> int: ... - def rjust(self, __width: int, __fillchar: str = ...) -> str: ... - def rpartition(self, __sep: str) -> Tuple[str, str, str]: ... - def rsplit(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... - def rstrip(self, __chars: Optional[str] = ...) -> str: ... - def split(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... - def splitlines(self, keepends: bool = ...) -> List[str]: ... + def rfind(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... + def rindex(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... + def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... + def rpartition(self, __sep: str) -> tuple[str, str, str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... + def rstrip(self, __chars: str | None = ...) -> str: ... + def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... + def splitlines(self, keepends: bool = ...) -> list[str]: ... def startswith( - self, __prefix: Union[str, Tuple[str, ...]], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __prefix: str | Tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def strip(self, __chars: Optional[str] = ...) -> str: ... + def strip(self, __chars: str | None = ...) -> str: ... def swapcase(self) -> str: ... def title(self) -> str: ... - def translate(self, __table: Union[Mapping[int, Union[int, str, None]], Sequence[Union[int, str, None]]]) -> str: ... + def translate(self, __table: Mapping[int, int | str | None] | Sequence[int | str | None]) -> str: ... def upper(self) -> str: ... - def zfill(self, __width: int) -> str: ... + def zfill(self, __width: SupportsIndex) -> str: ... @staticmethod @overload - def maketrans(__x: Union[Dict[int, _T], Dict[str, _T], Dict[Union[str, int], _T]]) -> Dict[int, _T]: ... + def maketrans(__x: dict[int, _T] | dict[str, _T] | dict[str | int, _T]) -> dict[int, _T]: ... @staticmethod @overload - def maketrans(__x: str, __y: str, __z: Optional[str] = ...) -> Dict[int, Union[int, None]]: ... - def __add__(self, s: str) -> str: ... + def maketrans(__x: str, __y: str, __z: str | None = ...) -> dict[int, int | None]: ... + def __add__(self, __s: str) -> str: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: str) -> bool: ... # type: ignore - def __eq__(self, x: object) -> bool: ... - def __ge__(self, x: str) -> bool: ... - def __getitem__(self, i: Union[int, slice]) -> str: ... - def __gt__(self, x: str) -> bool: ... + def __contains__(self, __o: str) -> bool: ... # type: ignore[override] + def __eq__(self, __x: object) -> bool: ... + def __ge__(self, __x: str) -> bool: ... + def __getitem__(self, __i: int | slice) -> str: ... + def __gt__(self, __x: str) -> bool: ... def __hash__(self) -> int: ... def __iter__(self) -> Iterator[str]: ... - def __le__(self, x: str) -> bool: ... + def __le__(self, __x: str) -> bool: ... def __len__(self) -> int: ... - def __lt__(self, x: str) -> bool: ... - def __mod__(self, x: Any) -> str: ... - def __mul__(self, n: int) -> str: ... - def __ne__(self, x: object) -> bool: ... + def __lt__(self, __x: str) -> bool: ... + def __mod__(self, __x: Any) -> str: ... + def __mul__(self, __n: SupportsIndex) -> str: ... + def __ne__(self, __x: object) -> bool: ... def __repr__(self) -> str: ... - def __rmul__(self, n: int) -> str: ... + def __rmul__(self, n: SupportsIndex) -> str: ... def __str__(self) -> str: ... - def __getnewargs__(self) -> Tuple[str]: ... + def __getnewargs__(self) -> tuple[str]: ... class bytes(ByteString): @overload - def __new__(cls: Type[_T], ints: Iterable[int]) -> _T: ... + def __new__(cls: Type[_T], __ints: Iterable[SupportsIndex]) -> _T: ... @overload - def __new__(cls: Type[_T], string: str, encoding: str, errors: str = ...) -> _T: ... + def __new__(cls: Type[_T], __string: str, encoding: str, errors: str = ...) -> _T: ... @overload - def __new__(cls: Type[_T], length: int) -> _T: ... + def __new__(cls: Type[_T], __length: SupportsIndex) -> _T: ... @overload def __new__(cls: Type[_T]) -> _T: ... @overload - def __new__(cls: Type[_T], o: SupportsBytes) -> _T: ... + def __new__(cls: Type[_T], __o: SupportsBytes) -> _T: ... def capitalize(self) -> bytes: ... - def center(self, __width: int, __fillchar: bytes = ...) -> bytes: ... + def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... def count( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, - __suffix: Union[bytes, Tuple[bytes, ...]], - __start: Optional[SupportsIndex] = ..., - __end: Optional[SupportsIndex] = ..., + self, __suffix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def expandtabs(self, tabsize: int = ...) -> bytes: ... + if sys.version_info >= (3, 8): + def expandtabs(self, tabsize: SupportsIndex = ...) -> bytes: ... + else: + def expandtabs(self, tabsize: int = ...) -> bytes: ... def find( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... if sys.version_info >= (3, 8): - def hex(self, sep: Union[str, bytes] = ..., bytes_per_sep: int = ...) -> str: ... + def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... else: def hex(self) -> str: ... def index( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... @@ -452,41 +478,38 @@ class bytes(ByteString): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - def join(self, __iterable_of_bytes: Iterable[Union[ByteString, memoryview]]) -> bytes: ... - def ljust(self, __width: int, __fillchar: bytes = ...) -> bytes: ... + def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytes: ... + def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... def lower(self) -> bytes: ... - def lstrip(self, __bytes: Optional[bytes] = ...) -> bytes: ... - def partition(self, __sep: bytes) -> Tuple[bytes, bytes, bytes]: ... - def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytes: ... + def lstrip(self, __bytes: bytes | None = ...) -> bytes: ... + def partition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ... + def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytes: ... if sys.version_info >= (3, 9): def removeprefix(self, __prefix: bytes) -> bytes: ... def removesuffix(self, __suffix: bytes) -> bytes: ... def rfind( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def rindex( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... - def rjust(self, __width: int, __fillchar: bytes = ...) -> bytes: ... - def rpartition(self, __sep: bytes) -> Tuple[bytes, bytes, bytes]: ... - def rsplit(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytes]: ... - def rstrip(self, __bytes: Optional[bytes] = ...) -> bytes: ... - def split(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytes]: ... - def splitlines(self, keepends: bool = ...) -> List[bytes]: ... + def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... + def rpartition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... + def rstrip(self, __bytes: bytes | None = ...) -> bytes: ... + def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... + def splitlines(self, keepends: bool = ...) -> list[bytes]: ... def startswith( - self, - __prefix: Union[bytes, Tuple[bytes, ...]], - __start: Optional[SupportsIndex] = ..., - __end: Optional[SupportsIndex] = ..., + self, __prefix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def strip(self, __bytes: Optional[bytes] = ...) -> bytes: ... + def strip(self, __bytes: bytes | None = ...) -> bytes: ... def swapcase(self) -> bytes: ... def title(self) -> bytes: ... - def translate(self, __table: Optional[bytes], delete: bytes = ...) -> bytes: ... + def translate(self, __table: bytes | None, delete: bytes = ...) -> bytes: ... def upper(self) -> bytes: ... - def zfill(self, __width: int) -> bytes: ... + def zfill(self, __width: SupportsIndex) -> bytes: ... @classmethod - def fromhex(cls, __s: str) -> bytes: ... + def fromhex(cls: Type[_T], __s: str) -> _T: ... @staticmethod def maketrans(__frm: bytes, __to: bytes) -> bytes: ... def __len__(self) -> int: ... @@ -495,59 +518,59 @@ class bytes(ByteString): def __repr__(self) -> str: ... def __hash__(self) -> int: ... @overload - def __getitem__(self, i: int) -> int: ... + def __getitem__(self, __i: SupportsIndex) -> int: ... @overload - def __getitem__(self, s: slice) -> bytes: ... - def __add__(self, s: bytes) -> bytes: ... - def __mul__(self, n: int) -> bytes: ... - def __rmul__(self, n: int) -> bytes: ... - def __mod__(self, value: Any) -> bytes: ... + def __getitem__(self, __s: slice) -> bytes: ... + def __add__(self, __s: bytes) -> bytes: ... + def __mul__(self, __n: SupportsIndex) -> bytes: ... + def __rmul__(self, __n: SupportsIndex) -> bytes: ... + def __mod__(self, __value: Any) -> bytes: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[int, bytes]) -> bool: ... # type: ignore - def __eq__(self, x: object) -> bool: ... - def __ne__(self, x: object) -> bool: ... - def __lt__(self, x: bytes) -> bool: ... - def __le__(self, x: bytes) -> bool: ... - def __gt__(self, x: bytes) -> bool: ... - def __ge__(self, x: bytes) -> bool: ... - def __getnewargs__(self) -> Tuple[bytes]: ... + def __contains__(self, __o: SupportsIndex | bytes) -> bool: ... # type: ignore[override] + def __eq__(self, __x: object) -> bool: ... + def __ne__(self, __x: object) -> bool: ... + def __lt__(self, __x: bytes) -> bool: ... + def __le__(self, __x: bytes) -> bool: ... + def __gt__(self, __x: bytes) -> bool: ... + def __ge__(self, __x: bytes) -> bool: ... + def __getnewargs__(self) -> tuple[bytes]: ... class bytearray(MutableSequence[int], ByteString): @overload def __init__(self) -> None: ... @overload - def __init__(self, ints: Iterable[int]) -> None: ... + def __init__(self, __ints: Iterable[SupportsIndex]) -> None: ... @overload - def __init__(self, string: str, encoding: str, errors: str = ...) -> None: ... + def __init__(self, __string: str, encoding: str, errors: str = ...) -> None: ... @overload - def __init__(self, length: int) -> None: ... - def append(self, __item: int) -> None: ... + def __init__(self, __length: SupportsIndex) -> None: ... + def append(self, __item: SupportsIndex) -> None: ... def capitalize(self) -> bytearray: ... - def center(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... + def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... def count( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def copy(self) -> bytearray: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, - __suffix: Union[bytes, Tuple[bytes, ...]], - __start: Optional[SupportsIndex] = ..., - __end: Optional[SupportsIndex] = ..., + self, __suffix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def expandtabs(self, tabsize: int = ...) -> bytearray: ... - def extend(self, __iterable_of_ints: Iterable[int]) -> None: ... + if sys.version_info >= (3, 8): + def expandtabs(self, tabsize: SupportsIndex = ...) -> bytearray: ... + else: + def expandtabs(self, tabsize: int = ...) -> bytearray: ... + def extend(self, __iterable_of_ints: Iterable[SupportsIndex]) -> None: ... def find( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... if sys.version_info >= (3, 8): - def hex(self, sep: Union[str, bytes] = ..., bytes_per_sep: int = ...) -> str: ... + def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... else: def hex(self) -> str: ... def index( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... - def insert(self, __index: int, __item: int) -> None: ... + def insert(self, __index: SupportsIndex, __item: SupportsIndex) -> None: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... if sys.version_info >= (3, 7): @@ -557,39 +580,36 @@ class bytearray(MutableSequence[int], ByteString): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - def join(self, __iterable_of_bytes: Iterable[Union[ByteString, memoryview]]) -> bytearray: ... - def ljust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... + def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytearray: ... + def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... def lower(self) -> bytearray: ... - def lstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... - def partition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... + def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... + def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... if sys.version_info >= (3, 9): def removeprefix(self, __prefix: bytes) -> bytearray: ... def removesuffix(self, __suffix: bytes) -> bytearray: ... - def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytearray: ... + def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytearray: ... def rfind( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def rindex( - self, __sub: Union[bytes, int], __start: Optional[SupportsIndex] = ..., __end: Optional[SupportsIndex] = ... + self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... - def rjust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... - def rpartition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... - def rstrip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... - def split(self, sep: Optional[bytes] = ..., maxsplit: int = ...) -> List[bytearray]: ... - def splitlines(self, keepends: bool = ...) -> List[bytearray]: ... + def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... + def rpartition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... + def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... + def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... + def splitlines(self, keepends: bool = ...) -> list[bytearray]: ... def startswith( - self, - __prefix: Union[bytes, Tuple[bytes, ...]], - __start: Optional[SupportsIndex] = ..., - __end: Optional[SupportsIndex] = ..., + self, __prefix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def strip(self, __bytes: Optional[bytes] = ...) -> bytearray: ... + def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... - def translate(self, __table: Optional[bytes], delete: bytes = ...) -> bytearray: ... + def translate(self, __table: bytes | None, delete: bytes = ...) -> bytearray: ... def upper(self) -> bytearray: ... - def zfill(self, __width: int) -> bytearray: ... + def zfill(self, __width: SupportsIndex) -> bytearray: ... @classmethod def fromhex(cls, __string: str) -> bytearray: ... @staticmethod @@ -598,72 +618,73 @@ class bytearray(MutableSequence[int], ByteString): def __iter__(self) -> Iterator[int]: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... - __hash__: None # type: ignore + __hash__: None # type: ignore[assignment] @overload - def __getitem__(self, i: int) -> int: ... + def __getitem__(self, __i: SupportsIndex) -> int: ... @overload - def __getitem__(self, s: slice) -> bytearray: ... + def __getitem__(self, __s: slice) -> bytearray: ... @overload - def __setitem__(self, i: int, x: int) -> None: ... + def __setitem__(self, __i: SupportsIndex, x: SupportsIndex) -> None: ... @overload - def __setitem__(self, s: slice, x: Union[Iterable[int], bytes]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... - def __add__(self, s: bytes) -> bytearray: ... - def __iadd__(self, s: Iterable[int]) -> bytearray: ... - def __mul__(self, n: int) -> bytearray: ... - def __rmul__(self, n: int) -> bytearray: ... - def __imul__(self, n: int) -> bytearray: ... - def __mod__(self, value: Any) -> bytes: ... + def __setitem__(self, __s: slice, __x: Iterable[SupportsIndex] | bytes) -> None: ... + def __delitem__(self, __i: SupportsIndex | slice) -> None: ... + def __add__(self, __s: bytes) -> bytearray: ... + def __iadd__(self, __s: Iterable[int]) -> bytearray: ... + def __mul__(self, __n: SupportsIndex) -> bytearray: ... + def __rmul__(self, __n: SupportsIndex) -> bytearray: ... + def __imul__(self, __n: SupportsIndex) -> bytearray: ... + def __mod__(self, __value: Any) -> bytes: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: Union[int, bytes]) -> bool: ... # type: ignore - def __eq__(self, x: object) -> bool: ... - def __ne__(self, x: object) -> bool: ... - def __lt__(self, x: bytes) -> bool: ... - def __le__(self, x: bytes) -> bool: ... - def __gt__(self, x: bytes) -> bool: ... - def __ge__(self, x: bytes) -> bool: ... + def __contains__(self, __o: SupportsIndex | bytes) -> bool: ... # type: ignore[override] + def __eq__(self, __x: object) -> bool: ... + def __ne__(self, __x: object) -> bool: ... + def __lt__(self, __x: bytes) -> bool: ... + def __le__(self, __x: bytes) -> bool: ... + def __gt__(self, __x: bytes) -> bool: ... + def __ge__(self, __x: bytes) -> bool: ... +@final class memoryview(Sized, Sequence[int]): format: str itemsize: int - shape: Optional[Tuple[int, ...]] - strides: Optional[Tuple[int, ...]] - suboffsets: Optional[Tuple[int, ...]] + shape: Tuple[int, ...] | None + strides: Tuple[int, ...] | None + suboffsets: Tuple[int, ...] | None readonly: bool ndim: int - obj: Union[bytes, bytearray] + obj: bytes | bytearray c_contiguous: bool f_contiguous: bool contiguous: bool nbytes: int def __init__(self, obj: ReadableBuffer) -> None: ... - def __enter__(self) -> memoryview: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, __exc_type: Type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None ) -> None: ... - def cast(self, format: str, shape: Union[List[int], Tuple[int]] = ...) -> memoryview: ... + def cast(self, format: str, shape: list[int] | Tuple[int, ...] = ...) -> memoryview: ... @overload - def __getitem__(self, i: int) -> int: ... + def __getitem__(self, __i: SupportsIndex) -> int: ... @overload - def __getitem__(self, s: slice) -> memoryview: ... - def __contains__(self, x: object) -> bool: ... + def __getitem__(self, __s: slice) -> memoryview: ... + def __contains__(self, __x: object) -> bool: ... def __iter__(self) -> Iterator[int]: ... def __len__(self) -> int: ... @overload - def __setitem__(self, s: slice, o: bytes) -> None: ... + def __setitem__(self, __s: slice, __o: bytes) -> None: ... @overload - def __setitem__(self, i: int, o: int) -> None: ... + def __setitem__(self, __i: SupportsIndex, __o: SupportsIndex) -> None: ... if sys.version_info >= (3, 8): - def tobytes(self, order: Optional[Literal["C", "F", "A"]] = ...) -> bytes: ... + def tobytes(self, order: Literal["C", "F", "A"] | None = ...) -> bytes: ... else: def tobytes(self) -> bytes: ... - def tolist(self) -> List[int]: ... + def tolist(self) -> list[int]: ... if sys.version_info >= (3, 8): def toreadonly(self) -> memoryview: ... def release(self) -> None: ... if sys.version_info >= (3, 8): - def hex(self, sep: Union[str, bytes] = ..., bytes_per_sep: int = ...) -> str: ... + def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... else: def hex(self) -> str: ... @@ -671,65 +692,66 @@ class memoryview(Sized, Sequence[int]): class bool(int): def __new__(cls: Type[_T], __o: object = ...) -> _T: ... @overload - def __and__(self, x: bool) -> bool: ... + def __and__(self, __x: bool) -> bool: ... @overload - def __and__(self, x: int) -> int: ... + def __and__(self, __x: int) -> int: ... @overload - def __or__(self, x: bool) -> bool: ... + def __or__(self, __x: bool) -> bool: ... @overload - def __or__(self, x: int) -> int: ... + def __or__(self, __x: int) -> int: ... @overload - def __xor__(self, x: bool) -> bool: ... + def __xor__(self, __x: bool) -> bool: ... @overload - def __xor__(self, x: int) -> int: ... + def __xor__(self, __x: int) -> int: ... @overload - def __rand__(self, x: bool) -> bool: ... + def __rand__(self, __x: bool) -> bool: ... @overload - def __rand__(self, x: int) -> int: ... + def __rand__(self, __x: int) -> int: ... @overload - def __ror__(self, x: bool) -> bool: ... + def __ror__(self, __x: bool) -> bool: ... @overload - def __ror__(self, x: int) -> int: ... + def __ror__(self, __x: int) -> int: ... @overload - def __rxor__(self, x: bool) -> bool: ... + def __rxor__(self, __x: bool) -> bool: ... @overload - def __rxor__(self, x: int) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... + def __rxor__(self, __x: int) -> int: ... + def __getnewargs__(self) -> tuple[int]: ... +@final class slice(object): start: Any step: Any stop: Any @overload - def __init__(self, stop: Any) -> None: ... + def __init__(self, __stop: Any) -> None: ... @overload - def __init__(self, start: Any, stop: Any, step: Any = ...) -> None: ... - __hash__: None # type: ignore - def indices(self, len: int) -> Tuple[int, int, int]: ... + def __init__(self, __start: Any, __stop: Any, __step: Any = ...) -> None: ... + __hash__: None # type: ignore[assignment] + def indices(self, __len: SupportsIndex) -> tuple[int, int, int]: ... class tuple(Sequence[_T_co], Generic[_T_co]): - def __new__(cls: Type[_T], iterable: Iterable[_T_co] = ...) -> _T: ... + def __new__(cls: Type[_T], __iterable: Iterable[_T_co] = ...) -> _T: ... def __len__(self) -> int: ... - def __contains__(self, x: object) -> bool: ... + def __contains__(self, __x: object) -> bool: ... @overload - def __getitem__(self, x: int) -> _T_co: ... + def __getitem__(self, __x: int) -> _T_co: ... @overload - def __getitem__(self, x: slice) -> Tuple[_T_co, ...]: ... + def __getitem__(self, __x: slice) -> Tuple[_T_co, ...]: ... def __iter__(self) -> Iterator[_T_co]: ... - def __lt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __le__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __gt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __ge__(self, x: Tuple[_T_co, ...]) -> bool: ... + def __lt__(self, __x: Tuple[_T_co, ...]) -> bool: ... + def __le__(self, __x: Tuple[_T_co, ...]) -> bool: ... + def __gt__(self, __x: Tuple[_T_co, ...]) -> bool: ... + def __ge__(self, __x: Tuple[_T_co, ...]) -> bool: ... @overload - def __add__(self, x: Tuple[_T_co, ...]) -> Tuple[_T_co, ...]: ... + def __add__(self, __x: Tuple[_T_co, ...]) -> Tuple[_T_co, ...]: ... @overload - def __add__(self, x: Tuple[Any, ...]) -> Tuple[Any, ...]: ... - def __mul__(self, n: int) -> Tuple[_T_co, ...]: ... - def __rmul__(self, n: int) -> Tuple[_T_co, ...]: ... + def __add__(self, __x: Tuple[_T, ...]) -> Tuple[_T_co | _T, ...]: ... + def __mul__(self, __n: SupportsIndex) -> Tuple[_T_co, ...]: ... + def __rmul__(self, __n: SupportsIndex) -> Tuple[_T_co, ...]: ... def count(self, __value: Any) -> int: ... - def index(self, __value: Any, __start: int = ..., __stop: int = ...) -> int: ... + def index(self, __value: Any, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class function: # TODO not defined in builtins! @@ -737,211 +759,217 @@ class function: __module__: str __code__: CodeType __qualname__: str - __annotations__: Dict[str, Any] + __annotations__: dict[str, Any] class list(MutableSequence[_T], Generic[_T]): @overload def __init__(self) -> None: ... @overload - def __init__(self, iterable: Iterable[_T]) -> None: ... + def __init__(self, __iterable: Iterable[_T]) -> None: ... def clear(self) -> None: ... - def copy(self) -> List[_T]: ... + def copy(self) -> list[_T]: ... def append(self, __object: _T) -> None: ... def extend(self, __iterable: Iterable[_T]) -> None: ... - def pop(self, __index: int = ...) -> _T: ... - def index(self, __value: _T, __start: int = ..., __stop: int = ...) -> int: ... + def pop(self, __index: SupportsIndex = ...) -> _T: ... + def index(self, __value: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... def count(self, __value: _T) -> int: ... - def insert(self, __index: int, __object: _T) -> None: ... + def insert(self, __index: SupportsIndex, __object: _T) -> None: ... def remove(self, __value: _T) -> None: ... def reverse(self) -> None: ... @overload - def sort(self: List[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> None: ... + def sort(self: list[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> None: ... @overload - def sort(self, *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> None: ... + def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: None # type: ignore[assignment] @overload - def __getitem__(self, i: SupportsIndex) -> _T: ... + def __getitem__(self, __i: SupportsIndex) -> _T: ... @overload - def __getitem__(self, s: slice) -> List[_T]: ... + def __getitem__(self, __s: slice) -> list[_T]: ... @overload - def __setitem__(self, i: SupportsIndex, o: _T) -> None: ... + def __setitem__(self, __i: SupportsIndex, __o: _T) -> None: ... @overload - def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: Union[SupportsIndex, slice]) -> None: ... - def __add__(self, x: List[_T]) -> List[_T]: ... - def __iadd__(self: _S, x: Iterable[_T]) -> _S: ... - def __mul__(self, n: int) -> List[_T]: ... - def __rmul__(self, n: int) -> List[_T]: ... - def __imul__(self: _S, n: int) -> _S: ... - def __contains__(self, o: object) -> bool: ... + def __setitem__(self, __s: slice, __o: Iterable[_T]) -> None: ... + def __delitem__(self, __i: SupportsIndex | slice) -> None: ... + def __add__(self, __x: list[_T]) -> list[_T]: ... + def __iadd__(self: _S, __x: Iterable[_T]) -> _S: ... + def __mul__(self, __n: SupportsIndex) -> list[_T]: ... + def __rmul__(self, __n: SupportsIndex) -> list[_T]: ... + def __imul__(self: _S, __n: SupportsIndex) -> _S: ... + def __contains__(self, __o: object) -> bool: ... def __reversed__(self) -> Iterator[_T]: ... - def __gt__(self, x: List[_T]) -> bool: ... - def __ge__(self, x: List[_T]) -> bool: ... - def __lt__(self, x: List[_T]) -> bool: ... - def __le__(self, x: List[_T]) -> bool: ... + def __gt__(self, __x: list[_T]) -> bool: ... + def __ge__(self, __x: list[_T]) -> bool: ... + def __lt__(self, __x: list[_T]) -> bool: ... + def __le__(self, __x: list[_T]) -> bool: ... if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @overload - def __init__(self: Dict[_KT, _VT]) -> None: ... + def __init__(self: dict[_KT, _VT]) -> None: ... + @overload + def __init__(self: dict[str, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self: Dict[str, _VT], **kwargs: _VT) -> None: ... + def __init__(self, __map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... + def __init__(self, __iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + # Next overload is for dict(string.split(sep) for string in iterable) + # Cannot be Iterable[Sequence[_T]] or otherwise dict(["foo", "bar", "baz"]) is not an error @overload - def __init__(self, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __init__(self: dict[str, str], __iterable: Iterable[list[str]]) -> None: ... def __new__(cls: Type[_T1], *args: Any, **kwargs: Any) -> _T1: ... def clear(self) -> None: ... - def copy(self) -> Dict[_KT, _VT]: ... - def popitem(self) -> Tuple[_KT, _VT]: ... + def copy(self) -> dict[_KT, _VT]: ... + def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... @overload def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload def update(self, **kwargs: _VT) -> None: ... - def keys(self) -> KeysView[_KT]: ... - def values(self) -> ValuesView[_VT]: ... - def items(self) -> ItemsView[_KT, _VT]: ... + def keys(self) -> dict_keys[_KT, _VT]: ... + def values(self) -> dict_values[_KT, _VT]: ... + def items(self) -> dict_items[_KT, _VT]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T]) -> Dict[_T, Any]: ... + def fromkeys(cls, __iterable: Iterable[_T], __value: None = ...) -> dict[_T, Any | None]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> Dict[_T, _S]: ... + def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> dict[_T, _S]: ... def __len__(self) -> int: ... - def __getitem__(self, k: _KT) -> _VT: ... - def __setitem__(self, k: _KT, v: _VT) -> None: ... - def __delitem__(self, v: _KT) -> None: ... + def __getitem__(self, __k: _KT) -> _VT: ... + def __setitem__(self, __k: _KT, v: _VT) -> None: ... + def __delitem__(self, __v: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[_KT]: ... def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: None # type: ignore[assignment] if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... - def __or__(self, __value: Mapping[_KT, _VT]) -> Dict[_KT, _VT]: ... - def __ror__(self, __value: Mapping[_KT, _VT]) -> Dict[_KT, _VT]: ... - def __ior__(self, __value: Mapping[_KT, _VT]) -> Dict[_KT, _VT]: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... + def __or__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT | _T2]: ... + def __ror__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT | _T2]: ... + def __ior__(self, __value: Mapping[_KT, _VT]) -> dict[_KT, _VT]: ... # type: ignore[misc] class set(MutableSet[_T], Generic[_T]): - def __init__(self, iterable: Iterable[_T] = ...) -> None: ... - def add(self, element: _T) -> None: ... + def __init__(self, __iterable: Iterable[_T] = ...) -> None: ... + def add(self, __element: _T) -> None: ... def clear(self) -> None: ... - def copy(self) -> Set[_T]: ... - def difference(self, *s: Iterable[Any]) -> Set[_T]: ... + def copy(self) -> set[_T]: ... + def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... - def discard(self, element: _T) -> None: ... - def intersection(self, *s: Iterable[Any]) -> Set[_T]: ... + def discard(self, __element: _T) -> None: ... + def intersection(self, *s: Iterable[Any]) -> set[_T]: ... def intersection_update(self, *s: Iterable[Any]) -> None: ... - def isdisjoint(self, s: Iterable[Any]) -> bool: ... - def issubset(self, s: Iterable[Any]) -> bool: ... - def issuperset(self, s: Iterable[Any]) -> bool: ... + def isdisjoint(self, __s: Iterable[Any]) -> bool: ... + def issubset(self, __s: Iterable[Any]) -> bool: ... + def issuperset(self, __s: Iterable[Any]) -> bool: ... def pop(self) -> _T: ... - def remove(self, element: _T) -> None: ... - def symmetric_difference(self, s: Iterable[_T]) -> Set[_T]: ... - def symmetric_difference_update(self, s: Iterable[_T]) -> None: ... - def union(self, *s: Iterable[_T]) -> Set[_T]: ... + def remove(self, __element: _T) -> None: ... + def symmetric_difference(self, __s: Iterable[_T]) -> set[_T]: ... + def symmetric_difference_update(self, __s: Iterable[_T]) -> None: ... + def union(self, *s: Iterable[_S]) -> set[_T | _S]: ... def update(self, *s: Iterable[_T]) -> None: ... def __len__(self) -> int: ... - def __contains__(self, o: object) -> bool: ... + def __contains__(self, __o: object) -> bool: ... def __iter__(self) -> Iterator[_T]: ... def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __iand__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __or__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ior__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __sub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... - def __isub__(self, s: AbstractSet[Optional[_T]]) -> Set[_T]: ... - def __xor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __ixor__(self, s: AbstractSet[_S]) -> Set[Union[_T, _S]]: ... - def __le__(self, s: AbstractSet[object]) -> bool: ... - def __lt__(self, s: AbstractSet[object]) -> bool: ... - def __ge__(self, s: AbstractSet[object]) -> bool: ... - def __gt__(self, s: AbstractSet[object]) -> bool: ... - __hash__: None # type: ignore + def __and__(self, __s: AbstractSet[object]) -> set[_T]: ... + def __iand__(self, __s: AbstractSet[object]) -> set[_T]: ... + def __or__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ior__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __sub__(self, __s: AbstractSet[_T | None]) -> set[_T]: ... + def __isub__(self, __s: AbstractSet[_T | None]) -> set[_T]: ... + def __xor__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ixor__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __le__(self, __s: AbstractSet[object]) -> bool: ... + def __lt__(self, __s: AbstractSet[object]) -> bool: ... + def __ge__(self, __s: AbstractSet[object]) -> bool: ... + def __gt__(self, __s: AbstractSet[object]) -> bool: ... + __hash__: None # type: ignore[assignment] if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class frozenset(AbstractSet[_T_co], Generic[_T_co]): - def __init__(self, iterable: Iterable[_T_co] = ...) -> None: ... - def copy(self) -> FrozenSet[_T_co]: ... - def difference(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... - def intersection(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... - def isdisjoint(self, s: Iterable[_T_co]) -> bool: ... - def issubset(self, s: Iterable[object]) -> bool: ... - def issuperset(self, s: Iterable[object]) -> bool: ... - def symmetric_difference(self, s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... - def union(self, *s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... + def __init__(self, __iterable: Iterable[_T_co] = ...) -> None: ... + def copy(self) -> frozenset[_T_co]: ... + def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ... + def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ... + def isdisjoint(self, __s: Iterable[_T_co]) -> bool: ... + def issubset(self, __s: Iterable[object]) -> bool: ... + def issuperset(self, __s: Iterable[object]) -> bool: ... + def symmetric_difference(self, __s: Iterable[_T_co]) -> frozenset[_T_co]: ... + def union(self, *s: Iterable[_S]) -> frozenset[_T_co | _S]: ... def __len__(self) -> int: ... - def __contains__(self, o: object) -> bool: ... + def __contains__(self, __o: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __or__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... - def __sub__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[Union[_T_co, _S]]: ... - def __le__(self, s: AbstractSet[object]) -> bool: ... - def __lt__(self, s: AbstractSet[object]) -> bool: ... - def __ge__(self, s: AbstractSet[object]) -> bool: ... - def __gt__(self, s: AbstractSet[object]) -> bool: ... + def __and__(self, __s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __or__(self, __s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... + def __sub__(self, __s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __xor__(self, __s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... + def __le__(self, __s: AbstractSet[object]) -> bool: ... + def __lt__(self, __s: AbstractSet[object]) -> bool: ... + def __ge__(self, __s: AbstractSet[object]) -> bool: ... + def __gt__(self, __s: AbstractSet[object]) -> bool: ... if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class enumerate(Iterator[Tuple[int, _T]], Generic[_T]): def __init__(self, iterable: Iterable[_T], start: int = ...) -> None: ... - def __iter__(self) -> Iterator[Tuple[int, _T]]: ... - def __next__(self) -> Tuple[int, _T]: ... + def __iter__(self) -> Iterator[tuple[int, _T]]: ... + def __next__(self) -> tuple[int, _T]: ... if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... +@final class range(Sequence[int]): start: int stop: int step: int @overload - def __init__(self, stop: SupportsIndex) -> None: ... + def __init__(self, __stop: SupportsIndex) -> None: ... @overload - def __init__(self, start: SupportsIndex, stop: SupportsIndex, step: SupportsIndex = ...) -> None: ... - def count(self, value: int) -> int: ... - def index(self, value: int) -> int: ... # type: ignore + def __init__(self, __start: SupportsIndex, __stop: SupportsIndex, __step: SupportsIndex = ...) -> None: ... + def count(self, __value: int) -> int: ... + def index(self, __value: int) -> int: ... # type: ignore[override] def __len__(self) -> int: ... - def __contains__(self, o: object) -> bool: ... + def __contains__(self, __o: object) -> bool: ... def __iter__(self) -> Iterator[int]: ... @overload - def __getitem__(self, i: SupportsIndex) -> int: ... + def __getitem__(self, __i: SupportsIndex) -> int: ... @overload - def __getitem__(self, s: slice) -> range: ... + def __getitem__(self, __s: slice) -> range: ... def __repr__(self) -> str: ... def __reversed__(self) -> Iterator[int]: ... class property(object): - fget: Optional[Callable[[Any], Any]] - fset: Optional[Callable[[Any, Any], None]] - fdel: Optional[Callable[[Any], None]] + fget: Callable[[Any], Any] | None + fset: Callable[[Any, Any], None] | None + fdel: Callable[[Any], None] | None def __init__( self, - fget: Optional[Callable[[Any], Any]] = ..., - fset: Optional[Callable[[Any, Any], None]] = ..., - fdel: Optional[Callable[[Any], None]] = ..., - doc: Optional[str] = ..., + fget: Callable[[Any], Any] | None = ..., + fset: Callable[[Any, Any], None] | None = ..., + fdel: Callable[[Any], None] | None = ..., + doc: str | None = ..., ) -> None: ... - def getter(self, fget: Callable[[Any], Any]) -> property: ... - def setter(self, fset: Callable[[Any, Any], None]) -> property: ... - def deleter(self, fdel: Callable[[Any], None]) -> property: ... - def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ... - def __set__(self, obj: Any, value: Any) -> None: ... - def __delete__(self, obj: Any) -> None: ... - -class _NotImplementedType(Any): # type: ignore + def getter(self, __fget: Callable[[Any], Any]) -> property: ... + def setter(self, __fset: Callable[[Any, Any], None]) -> property: ... + def deleter(self, __fdel: Callable[[Any], None]) -> property: ... + def __get__(self, __obj: Any, __type: type | None = ...) -> Any: ... + def __set__(self, __obj: Any, __value: Any) -> None: ... + def __delete__(self, __obj: Any) -> None: ... + +@final +class _NotImplementedType(Any): # type: ignore[misc] # A little weird, but typing the __call__ as NotImplemented makes the error message # for NotImplemented() much better - __call__: NotImplemented # type: ignore + __call__: NotImplemented # type: ignore[valid-type] NotImplemented: _NotImplementedType @@ -949,12 +977,12 @@ def abs(__x: SupportsAbs[_T]) -> _T: ... def all(__iterable: Iterable[object]) -> bool: ... def any(__iterable: Iterable[object]) -> bool: ... def ascii(__obj: object) -> str: ... -def bin(__number: Union[int, SupportsIndex]) -> str: ... +def bin(__number: int | SupportsIndex) -> str: ... if sys.version_info >= (3, 7): def breakpoint(*args: Any, **kws: Any) -> None: ... -def callable(__obj: object) -> bool: ... +def callable(__obj: object) -> TypeGuard[Callable[..., object]]: ... def chr(__i: int) -> str: ... # We define this here instead of using os.PathLike to avoid import cycle issues. @@ -967,14 +995,15 @@ class _PathLike(Protocol[_AnyStr_co]): if sys.version_info >= (3, 10): def aiter(__iterable: AsyncIterable[_T]) -> AsyncIterator[_T]: ... @overload - async def anext(__i: AsyncIterator[_T]) -> _T: ... + async def anext(__i: SupportsAnext[_T]) -> _T: ... @overload - async def anext(__i: AsyncIterator[_T], default: _VT) -> Union[_T, _VT]: ... + async def anext(__i: SupportsAnext[_T], default: _VT) -> _T | _VT: ... +# TODO: `compile` has a more precise return type in reality; work on a way of expressing that? if sys.version_info >= (3, 8): def compile( - source: Union[str, bytes, mod, AST], - filename: Union[str, bytes, _PathLike[Any]], + source: str | bytes | AST, + filename: str | bytes | _PathLike[Any], mode: str, flags: int = ..., dont_inherit: int = ..., @@ -985,8 +1014,8 @@ if sys.version_info >= (3, 8): else: def compile( - source: Union[str, bytes, mod, AST], - filename: Union[str, bytes, _PathLike[Any]], + source: str | bytes | AST, + filename: str | bytes | _PathLike[Any], mode: str, flags: int = ..., dont_inherit: int = ..., @@ -995,48 +1024,80 @@ else: def copyright() -> None: ... def credits() -> None: ... -def delattr(__obj: Any, __name: str) -> None: ... -def dir(__o: object = ...) -> List[str]: ... +def delattr(__obj: object, __name: str) -> None: ... +def dir(__o: object = ...) -> list[str]: ... @overload def divmod(__x: SupportsDivMod[_T_contra, _T_co], __y: _T_contra) -> _T_co: ... @overload def divmod(__x: _T_contra, __y: SupportsRDivMod[_T_contra, _T_co]) -> _T_co: ... + +# The `globals` argument to `eval` has to be `dict[str, Any]` rather than `dict[str, object]` due to invariance. +# (The `globals` argument has to be a "real dict", rather than any old mapping, unlike the `locals` argument.) def eval( - __source: Union[str, bytes, CodeType], __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Mapping[str, Any]] = ... + __source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... ) -> Any: ... + +# Comment above regarding `eval` applies to `exec` as well def exec( - __source: Union[str, bytes, CodeType], __globals: Optional[Dict[str, Any]] = ..., __locals: Optional[Mapping[str, Any]] = ... -) -> Any: ... + __source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... +) -> None: ... def exit(code: object = ...) -> NoReturn: ... class filter(Iterator[_T], Generic[_T]): @overload - def __init__(self, __function: None, __iterable: Iterable[Optional[_T]]) -> None: ... + def __init__(self, __function: None, __iterable: Iterable[_T | None]) -> None: ... @overload def __init__(self, __function: Callable[[_T], Any], __iterable: Iterable[_T]) -> None: ... def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode -def getattr(__o: Any, name: str, __default: Any = ...) -> Any: ... -def globals() -> Dict[str, Any]: ... -def hasattr(__obj: Any, __name: str) -> bool: ... +@overload +def getattr(__o: object, __name: str) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None, bool +# and basic containers help mypy out in some tricky situations involving type context +# (aka bidirectional inference) +@overload +def getattr(__o: object, __name: str, __default: None) -> Any | None: ... +@overload +def getattr(__o: object, __name: str, __default: bool) -> Any | bool: ... +@overload +def getattr(__o: object, name: str, __default: list[Any]) -> Any | list[Any]: ... +@overload +def getattr(__o: object, name: str, __default: dict[Any, Any]) -> Any | dict[Any, Any]: ... +@overload +def getattr(__o: object, __name: str, __default: _T) -> Any | _T: ... +def globals() -> dict[str, Any]: ... +def hasattr(__obj: object, __name: str) -> bool: ... def hash(__obj: object) -> int: ... def help(*args: Any, **kwds: Any) -> None: ... -def hex(__number: Union[int, SupportsIndex]) -> str: ... +def hex(__number: int | SupportsIndex) -> str: ... def id(__obj: object) -> int: ... -def input(__prompt: Any = ...) -> str: ... +def input(__prompt: object = ...) -> str: ... @overload def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... @overload -def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ... +def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload -def iter(__function: Callable[[], _T], __sentinel: Any) -> Iterator[_T]: ... -def isinstance(__obj: object, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... -def issubclass(__cls: type, __class_or_tuple: Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]) -> bool: ... +def iter(__function: Callable[[], _T], __sentinel: object) -> Iterator[_T]: ... + +# We need recursive types to express the type of the second argument to `isinstance` properly, hence the use of `Any` +if sys.version_info >= (3, 10): + def isinstance( + __obj: object, __class_or_tuple: type | types.UnionType | Tuple[type | types.UnionType | Tuple[Any, ...], ...] + ) -> bool: ... + def issubclass( + __cls: type, __class_or_tuple: type | types.UnionType | Tuple[type | types.UnionType | Tuple[Any, ...], ...] + ) -> bool: ... + +else: + def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... + def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... + def len(__obj: Sized) -> int: ... def license() -> None: ... -def locals() -> Dict[str, Any]: ... +def locals() -> dict[str, Any]: ... class map(Iterator[_S], Generic[_S]): @overload @@ -1083,39 +1144,39 @@ class map(Iterator[_S], Generic[_S]): @overload def max( - __arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ... -) -> SupportsLessThanT: ... + __arg1: SupportsRichComparisonT, __arg2: SupportsRichComparisonT, *_args: SupportsRichComparisonT, key: None = ... +) -> SupportsRichComparisonT: ... @overload -def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThan]) -> _T: ... +def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsRichComparison]) -> _T: ... @overload -def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ... +def max(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ...) -> SupportsRichComparisonT: ... @overload -def max(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThan]) -> _T: ... +def max(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison]) -> _T: ... @overload -def max(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ... +def max(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ..., default: _T) -> SupportsRichComparisonT | _T: ... @overload -def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThan], default: _T2) -> Union[_T1, _T2]: ... +def max(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsRichComparison], default: _T2) -> _T1 | _T2: ... @overload def min( - __arg1: SupportsLessThanT, __arg2: SupportsLessThanT, *_args: SupportsLessThanT, key: None = ... -) -> SupportsLessThanT: ... + __arg1: SupportsRichComparisonT, __arg2: SupportsRichComparisonT, *_args: SupportsRichComparisonT, key: None = ... +) -> SupportsRichComparisonT: ... @overload -def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThan]) -> _T: ... +def min(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsRichComparison]) -> _T: ... @overload -def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ...) -> SupportsLessThanT: ... +def min(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ...) -> SupportsRichComparisonT: ... @overload -def min(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThan]) -> _T: ... +def min(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison]) -> _T: ... @overload -def min(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., default: _T) -> Union[SupportsLessThanT, _T]: ... +def min(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ..., default: _T) -> SupportsRichComparisonT | _T: ... @overload -def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsLessThan], default: _T2) -> Union[_T1, _T2]: ... +def min(__iterable: Iterable[_T1], *, key: Callable[[_T1], SupportsRichComparison], default: _T2) -> _T1 | _T2: ... @overload -def next(__i: Iterator[_T]) -> _T: ... +def next(__i: SupportsNext[_T]) -> _T: ... @overload -def next(__i: Iterator[_T], default: _VT) -> Union[_T, _VT]: ... -def oct(__number: Union[int, SupportsIndex]) -> str: ... +def next(__i: SupportsNext[_T], __default: _VT) -> _T | _VT: ... +def oct(__number: int | SupportsIndex) -> str: ... -_OpenFile = Union[AnyPath, int] +_OpenFile = Union[StrOrBytesPath, int] _Opener = Callable[[str, int], int] # Text mode: always returns a TextIOWrapper @@ -1124,11 +1185,11 @@ def open( file: _OpenFile, mode: OpenTextMode = ..., buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> TextIOWrapper: ... # Unbuffered binary mode: returns a FileIO @@ -1141,7 +1202,7 @@ def open( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> FileIO: ... # Buffering is on: return BufferedRandom, BufferedReader, or BufferedWriter @@ -1154,7 +1215,7 @@ def open( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedRandom: ... @overload def open( @@ -1165,7 +1226,7 @@ def open( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedWriter: ... @overload def open( @@ -1176,7 +1237,7 @@ def open( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedReader: ... # Buffering cannot be determined: fall back to BinaryIO @@ -1189,7 +1250,7 @@ def open( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BinaryIO: ... # Fallback if mode is not specified @@ -1198,19 +1259,28 @@ def open( file: _OpenFile, mode: str, buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> IO[Any]: ... -def ord(__c: Union[str, bytes]) -> int: ... +def ord(__c: str | bytes) -> int: ... + +class _SupportsWriteAndFlush(SupportsWrite[_T_contra], Protocol[_T_contra]): + def flush(self) -> None: ... + +@overload def print( *values: object, - sep: Optional[str] = ..., - end: Optional[str] = ..., - file: Optional[SupportsWrite[str]] = ..., - flush: bool = ..., + sep: str | None = ..., + end: str | None = ..., + file: SupportsWrite[str] | None = ..., + flush: Literal[False] = ..., +) -> None: ... +@overload +def print( + *values: object, sep: str | None = ..., end: str | None = ..., file: _SupportsWriteAndFlush[str] | None = ..., flush: bool ) -> None: ... _E = TypeVar("_E", contravariant=True) @@ -1219,42 +1289,82 @@ _M = TypeVar("_M", contravariant=True) class _SupportsPow2(Protocol[_E, _T_co]): def __pow__(self, __other: _E) -> _T_co: ... +class _SupportsPow3NoneOnly(Protocol[_E, _T_co]): + def __pow__(self, __other: _E, __modulo: None = ...) -> _T_co: ... + class _SupportsPow3(Protocol[_E, _M, _T_co]): def __pow__(self, __other: _E, __modulo: _M) -> _T_co: ... +_SupportsSomeKindOfPow = Union[_SupportsPow2[Any, Any], _SupportsPow3NoneOnly[Any, Any], _SupportsPow3[Any, Any, Any]] + if sys.version_info >= (3, 8): @overload - def pow(base: int, exp: int, mod: None = ...) -> Any: ... # returns int or float depending on whether exp is non-negative + def pow(base: int, exp: int, mod: Literal[0]) -> NoReturn: ... @overload def pow(base: int, exp: int, mod: int) -> int: ... @overload - def pow(base: float, exp: float, mod: None = ...) -> float: ... + def pow(base: int, exp: _PositiveInteger, mod: None = ...) -> int: ... # type: ignore[misc] + @overload + def pow(base: int, exp: _NegativeInteger, mod: None = ...) -> float: ... # type: ignore[misc] + # int base & positive-int exp -> int; int base & negative-int exp -> float + # return type must be Any as `int | float` causes too many false-positive errors + @overload + def pow(base: int, exp: int, mod: None = ...) -> Any: ... + @overload + def pow(base: float, exp: int, mod: None = ...) -> float: ... + # float base & float exp could return float or complex + # return type must be Any (same as complex base, complex exp), + # as `float | complex` causes too many false-positive errors + @overload + def pow(base: float, exp: complex | _SupportsSomeKindOfPow, mod: None = ...) -> Any: ... + @overload + def pow(base: complex, exp: complex | _SupportsSomeKindOfPow, mod: None = ...) -> complex: ... + @overload + def pow(base: _SupportsPow2[_E, _T_co], exp: _E, mod: None = ...) -> _T_co: ... + @overload + def pow(base: _SupportsPow3NoneOnly[_E, _T_co], exp: _E, mod: None = ...) -> _T_co: ... + @overload + def pow(base: _SupportsPow3[_E, _M, _T_co], exp: _E, mod: _M = ...) -> _T_co: ... @overload - def pow(base: _SupportsPow2[_E, _T_co], exp: _E) -> _T_co: ... + def pow(base: _SupportsSomeKindOfPow, exp: float, mod: None = ...) -> Any: ... @overload - def pow(base: _SupportsPow3[_E, _M, _T_co], exp: _E, mod: _M) -> _T_co: ... + def pow(base: _SupportsSomeKindOfPow, exp: complex, mod: None = ...) -> complex: ... else: @overload - def pow( - __base: int, __exp: int, __mod: None = ... - ) -> Any: ... # returns int or float depending on whether exp is non-negative + def pow(__base: int, __exp: int, __mod: Literal[0]) -> NoReturn: ... @overload def pow(__base: int, __exp: int, __mod: int) -> int: ... @overload - def pow(__base: float, __exp: float, __mod: None = ...) -> float: ... + def pow(__base: int, __exp: _PositiveInteger, __mod: None = ...) -> int: ... # type: ignore[misc] @overload - def pow(__base: _SupportsPow2[_E, _T_co], __exp: _E) -> _T_co: ... + def pow(__base: int, __exp: _NegativeInteger, __mod: None = ...) -> float: ... # type: ignore[misc] @overload - def pow(__base: _SupportsPow3[_E, _M, _T_co], __exp: _E, __mod: _M) -> _T_co: ... + def pow(__base: int, __exp: int, __mod: None = ...) -> Any: ... + @overload + def pow(__base: float, __exp: int, __mod: None = ...) -> float: ... + @overload + def pow(__base: float, __exp: complex | _SupportsSomeKindOfPow, __mod: None = ...) -> Any: ... + @overload + def pow(__base: complex, __exp: complex | _SupportsSomeKindOfPow, __mod: None = ...) -> complex: ... + @overload + def pow(__base: _SupportsPow2[_E, _T_co], __exp: _E, __mod: None = ...) -> _T_co: ... + @overload + def pow(__base: _SupportsPow3NoneOnly[_E, _T_co], __exp: _E, __mod: None = ...) -> _T_co: ... + @overload + def pow(__base: _SupportsPow3[_E, _M, _T_co], __exp: _E, __mod: _M = ...) -> _T_co: ... + @overload + def pow(__base: _SupportsSomeKindOfPow, __exp: float, __mod: None = ...) -> Any: ... + @overload + def pow(__base: _SupportsSomeKindOfPow, __exp: complex, __mod: None = ...) -> complex: ... def quit(code: object = ...) -> NoReturn: ... class reversed(Iterator[_T], Generic[_T]): - @overload - def __init__(self, __sequence: Sequence[_T]) -> None: ... @overload def __init__(self, __sequence: Reversible[_T]) -> None: ... + @overload + def __init__(self, __sequence: SupportsLenAndGetItem[_T]) -> None: ... def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... @@ -1264,85 +1374,136 @@ def round(number: SupportsRound[Any]) -> int: ... @overload def round(number: SupportsRound[Any], ndigits: None) -> int: ... @overload -def round(number: SupportsRound[_T], ndigits: int) -> _T: ... -def setattr(__obj: Any, __name: str, __value: Any) -> None: ... +def round(number: SupportsRound[_T], ndigits: SupportsIndex) -> _T: ... + +# See https://github.com/python/typeshed/pull/6292#discussion_r748875189 +# for why arg 3 of `setattr` should be annotated with `Any` and not `object` +def setattr(__obj: object, __name: str, __value: Any) -> None: ... @overload -def sorted(__iterable: Iterable[SupportsLessThanT], *, key: None = ..., reverse: bool = ...) -> List[SupportsLessThanT]: ... +def sorted(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> list[SupportsRichComparisonT]: ... @overload -def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsLessThan], reverse: bool = ...) -> List[_T]: ... +def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> list[_T]: ... if sys.version_info >= (3, 8): @overload - def sum(__iterable: Iterable[_T]) -> Union[_T, int]: ... + def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload - def sum(__iterable: Iterable[_T], start: _S) -> Union[_T, _S]: ... + def sum(__iterable: Iterable[_T], start: _S) -> _T | _S: ... else: @overload - def sum(__iterable: Iterable[_T]) -> Union[_T, int]: ... + def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload - def sum(__iterable: Iterable[_T], __start: _S) -> Union[_T, _S]: ... + def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... -def vars(__object: Any = ...) -> Dict[str, Any]: ... +# The argument to `vars()` has to have a `__dict__` attribute, so can't be annotated with `object` +# (A "SupportsDunderDict" protocol doesn't work) +def vars(__object: Any = ...) -> dict[str, Any]: ... class zip(Iterator[_T_co], Generic[_T_co]): - @overload - def __new__(cls, __iter1: Iterable[_T1]) -> zip[Tuple[_T1]]: ... - @overload - def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> zip[Tuple[_T1, _T2]]: ... - @overload - def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> zip[Tuple[_T1, _T2, _T3]]: ... - @overload - def __new__( - cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] - ) -> zip[Tuple[_T1, _T2, _T3, _T4]]: ... - @overload - def __new__( - cls, - __iter1: Iterable[_T1], - __iter2: Iterable[_T2], - __iter3: Iterable[_T3], - __iter4: Iterable[_T4], - __iter5: Iterable[_T5], - ) -> zip[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... - @overload - def __new__( - cls, - __iter1: Iterable[Any], - __iter2: Iterable[Any], - __iter3: Iterable[Any], - __iter4: Iterable[Any], - __iter5: Iterable[Any], - __iter6: Iterable[Any], - *iterables: Iterable[Any], - ) -> zip[Tuple[Any, ...]]: ... + if sys.version_info >= (3, 10): + @overload + def __new__(cls, __iter1: Iterable[_T1], *, strict: bool = ...) -> zip[tuple[_T1]]: ... + @overload + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], *, strict: bool = ...) -> zip[tuple[_T1, _T2]]: ... + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], *, strict: bool = ... + ) -> zip[tuple[_T1, _T2, _T3]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[_T1], + __iter2: Iterable[_T2], + __iter3: Iterable[_T3], + __iter4: Iterable[_T4], + *, + strict: bool = ..., + ) -> zip[tuple[_T1, _T2, _T3, _T4]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[_T1], + __iter2: Iterable[_T2], + __iter3: Iterable[_T3], + __iter4: Iterable[_T4], + __iter5: Iterable[_T5], + *, + strict: bool = ..., + ) -> zip[tuple[_T1, _T2, _T3, _T4, _T5]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[Any], + __iter2: Iterable[Any], + __iter3: Iterable[Any], + __iter4: Iterable[Any], + __iter5: Iterable[Any], + __iter6: Iterable[Any], + *iterables: Iterable[Any], + strict: bool = ..., + ) -> zip[Tuple[Any, ...]]: ... + else: + @overload + def __new__(cls, __iter1: Iterable[_T1]) -> zip[tuple[_T1]]: ... + @overload + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> zip[tuple[_T1, _T2]]: ... + @overload + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> zip[tuple[_T1, _T2, _T3]]: ... + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] + ) -> zip[tuple[_T1, _T2, _T3, _T4]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[_T1], + __iter2: Iterable[_T2], + __iter3: Iterable[_T3], + __iter4: Iterable[_T4], + __iter5: Iterable[_T5], + ) -> zip[tuple[_T1, _T2, _T3, _T4, _T5]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[Any], + __iter2: Iterable[Any], + __iter3: Iterable[Any], + __iter4: Iterable[Any], + __iter5: Iterable[Any], + __iter6: Iterable[Any], + *iterables: Iterable[Any], + ) -> zip[Tuple[Any, ...]]: ... def __iter__(self) -> Iterator[_T_co]: ... def __next__(self) -> _T_co: ... +# Signature of `builtins.__import__` should be kept identical to `importlib.__import__` +# Return type of `__import__` should be kept the same as return type of `importlib.import_module` def __import__( name: str, - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, object] | None = ..., + locals: Mapping[str, object] | None = ..., fromlist: Sequence[str] = ..., level: int = ..., -) -> Any: ... +) -> types.ModuleType: ... # Actually the type of Ellipsis is , but since it's # not exposed anywhere under that name, we make it private here. +@final class ellipsis: ... Ellipsis: ellipsis class BaseException(object): args: Tuple[Any, ...] - __cause__: Optional[BaseException] - __context__: Optional[BaseException] + __cause__: BaseException | None + __context__: BaseException | None __suppress_context__: bool - __traceback__: Optional[TracebackType] + __traceback__: TracebackType | None def __init__(self, *args: object) -> None: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... - def with_traceback(self: _TBE, tb: Optional[TracebackType]) -> _TBE: ... + def with_traceback(self: _TBE, __tb: TracebackType | None) -> _TBE: ... class GeneratorExit(BaseException): ... class KeyboardInterrupt(BaseException): ... @@ -1360,7 +1521,7 @@ _StandardError = Exception class OSError(Exception): errno: int strerror: str - # filename, filename2 are actually Union[str, bytes, None] + # filename, filename2 are actually str | bytes | None filename: Any filename2: Any if sys.platform == "win32": @@ -1383,9 +1544,9 @@ class BufferError(_StandardError): ... class EOFError(_StandardError): ... class ImportError(_StandardError): - def __init__(self, *args: object, name: Optional[str] = ..., path: Optional[str] = ...) -> None: ... - name: Optional[str] - path: Optional[str] + def __init__(self, *args: object, name: str | None = ..., path: str | None = ...) -> None: ... + name: str | None + path: str | None msg: str # undocumented class LookupError(_StandardError): ... @@ -1403,13 +1564,13 @@ class StopAsyncIteration(Exception): class SyntaxError(_StandardError): msg: str - lineno: Optional[int] - offset: Optional[int] - text: Optional[str] - filename: Optional[str] + lineno: int | None + offset: int | None + text: str | None + filename: str | None if sys.version_info >= (3, 10): - end_lineno: Optional[int] - end_offset: Optional[int] + end_lineno: int | None + end_offset: int | None class SystemError(_StandardError): ... class TypeError(_StandardError): ... diff --git a/mypy/typeshed/stdlib/bz2.pyi b/mypy/typeshed/stdlib/bz2.pyi index dfc1876bf43e..c49832759fa8 100644 --- a/mypy/typeshed/stdlib/bz2.pyi +++ b/mypy/typeshed/stdlib/bz2.pyi @@ -1,78 +1,135 @@ -import io +import _compression import sys -from _typeshed import AnyPath, ReadableBuffer, WriteableBuffer -from typing import IO, Any, Iterable, List, Optional, TextIO, TypeVar, Union, overload -from typing_extensions import Literal, SupportsIndex +from _compression import BaseStream +from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer +from typing import IO, Any, Iterable, Protocol, TextIO, TypeVar, overload +from typing_extensions import Literal, SupportsIndex, final + +# The following attributes and methods are optional: +# def fileno(self) -> int: ... +# def close(self) -> object: ... +class _ReadableFileobj(_compression._Reader, Protocol): ... + +class _WritableFileobj(Protocol): + def write(self, __b: bytes) -> object: ... + # The following attributes and methods are optional: + # def fileno(self) -> int: ... + # def close(self) -> object: ... -_PathOrFile = Union[AnyPath, IO[bytes]] _T = TypeVar("_T") def compress(data: bytes, compresslevel: int = ...) -> bytes: ... def decompress(data: bytes) -> bytes: ... -if sys.version_info >= (3, 3): - _OpenBinaryMode = Literal["r", "rb", "w", "wb", "x", "xb", "a", "ab"] - _OpenTextMode = Literal["rt", "wt", "xt", "at"] - @overload - def open( - filename: _PathOrFile, - mode: _OpenBinaryMode = ..., - compresslevel: int = ..., - encoding: None = ..., - errors: None = ..., - newline: None = ..., - ) -> BZ2File: ... - @overload - def open( - filename: AnyPath, - mode: _OpenTextMode, - compresslevel: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., - ) -> TextIO: ... - @overload - def open( - filename: _PathOrFile, - mode: str, - compresslevel: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., - ) -> Union[BZ2File, TextIO]: ... +_ReadBinaryMode = Literal["", "r", "rb"] +_WriteBinaryMode = Literal["w", "wb", "x", "xb", "a", "ab"] +_ReadTextMode = Literal["rt"] +_WriteTextMode = Literal["wt", "xt", "at"] + +@overload +def open( + filename: _ReadableFileobj, + mode: _ReadBinaryMode = ..., + compresslevel: int = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., +) -> BZ2File: ... +@overload +def open( + filename: _ReadableFileobj, + mode: _ReadTextMode, + compresslevel: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> TextIO: ... +@overload +def open( + filename: _WritableFileobj, + mode: _WriteBinaryMode, + compresslevel: int = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., +) -> BZ2File: ... +@overload +def open( + filename: _WritableFileobj, + mode: _WriteTextMode, + compresslevel: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> TextIO: ... +@overload +def open( + filename: StrOrBytesPath, + mode: _ReadBinaryMode | _WriteBinaryMode = ..., + compresslevel: int = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., +) -> BZ2File: ... +@overload +def open( + filename: StrOrBytesPath, + mode: _ReadTextMode | _WriteTextMode, + compresslevel: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> TextIO: ... -class BZ2File(io.BufferedIOBase, IO[bytes]): - def __enter__(self: _T) -> _T: ... +class BZ2File(BaseStream, IO[bytes]): + def __enter__(self: Self) -> Self: ... if sys.version_info >= (3, 9): - def __init__(self, filename: _PathOrFile, mode: str = ..., *, compresslevel: int = ...) -> None: ... + @overload + def __init__(self, filename: _WritableFileobj, mode: _WriteBinaryMode, *, compresslevel: int = ...) -> None: ... + @overload + def __init__(self, filename: _ReadableFileobj, mode: _ReadBinaryMode = ..., *, compresslevel: int = ...) -> None: ... + @overload + def __init__( + self, filename: StrOrBytesPath, mode: _ReadBinaryMode | _WriteBinaryMode = ..., *, compresslevel: int = ... + ) -> None: ... else: + @overload + def __init__( + self, filename: _WritableFileobj, mode: _WriteBinaryMode, buffering: Any | None = ..., compresslevel: int = ... + ) -> None: ... + @overload + def __init__( + self, filename: _ReadableFileobj, mode: _ReadBinaryMode = ..., buffering: Any | None = ..., compresslevel: int = ... + ) -> None: ... + @overload def __init__( - self, filename: _PathOrFile, mode: str = ..., buffering: Optional[Any] = ..., compresslevel: int = ... + self, + filename: StrOrBytesPath, + mode: _ReadBinaryMode | _WriteBinaryMode = ..., + buffering: Any | None = ..., + compresslevel: int = ..., ) -> None: ... - def read(self, size: Optional[int] = ...) -> bytes: ... + def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore def readinto(self, b: WriteableBuffer) -> int: ... - def readlines(self, size: SupportsIndex = ...) -> List[bytes]: ... + def readlines(self, size: SupportsIndex = ...) -> list[bytes]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def write(self, data: ReadableBuffer) -> int: ... def writelines(self, seq: Iterable[ReadableBuffer]) -> None: ... +@final class BZ2Compressor(object): def __init__(self, compresslevel: int = ...) -> None: ... def compress(self, __data: bytes) -> bytes: ... def flush(self) -> bytes: ... +@final class BZ2Decompressor(object): - if sys.version_info >= (3, 5): - def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... - else: - def decompress(self, data: bytes) -> bytes: ... - if sys.version_info >= (3, 3): - @property - def eof(self) -> bool: ... - if sys.version_info >= (3, 5): - @property - def needs_input(self) -> bool: ... + def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... + @property + def eof(self) -> bool: ... + @property + def needs_input(self) -> bool: ... @property def unused_data(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/cProfile.pyi b/mypy/typeshed/stdlib/cProfile.pyi index 638a2a79f2e5..f4a7ab50cc11 100644 --- a/mypy/typeshed/stdlib/cProfile.pyi +++ b/mypy/typeshed/stdlib/cProfile.pyi @@ -1,14 +1,13 @@ import sys -from _typeshed import AnyPath +from _typeshed import Self, StrOrBytesPath from types import CodeType -from typing import Any, Callable, Dict, Optional, Tuple, TypeVar, Union +from typing import Any, Callable, Tuple, TypeVar -def run(statement: str, filename: Optional[str] = ..., sort: Union[str, int] = ...) -> None: ... +def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( - statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: Optional[str] = ..., sort: Union[str, int] = ... + statement: str, globals: dict[str, Any], locals: dict[str, Any], filename: str | None = ..., sort: str | int = ... ) -> None: ... -_SelfT = TypeVar("_SelfT", bound=Profile) _T = TypeVar("_T") _Label = Tuple[str, int, str] @@ -19,15 +18,15 @@ class Profile: ) -> None: ... def enable(self) -> None: ... def disable(self) -> None: ... - def print_stats(self, sort: Union[str, int] = ...) -> None: ... - def dump_stats(self, file: AnyPath) -> None: ... + def print_stats(self, sort: str | int = ...) -> None: ... + def dump_stats(self, file: StrOrBytesPath) -> None: ... def create_stats(self) -> None: ... def snapshot_stats(self) -> None: ... - def run(self: _SelfT, cmd: str) -> _SelfT: ... - def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... + def run(self: Self, cmd: str) -> Self: ... + def runctx(self: Self, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> Self: ... def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... if sys.version_info >= (3, 8): - def __enter__(self: _SelfT) -> _SelfT: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *exc_info: Any) -> None: ... -def label(code: Union[str, CodeType]) -> _Label: ... # undocumented +def label(code: str | CodeType) -> _Label: ... # undocumented diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index ad73132b4595..26073fb7281b 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -1,7 +1,7 @@ import datetime import sys from time import struct_time -from typing import Any, Iterable, List, Optional, Sequence, Tuple, Union +from typing import Any, Iterable, Optional, Sequence, Tuple _LocaleType = Tuple[Optional[str], Optional[str]] @@ -16,7 +16,7 @@ class IllegalWeekdayError(ValueError): def isleap(year: int) -> bool: ... def leapdays(y1: int, y2: int) -> int: ... def weekday(year: int, month: int, day: int) -> int: ... -def monthrange(year: int, month: int) -> Tuple[int, int]: ... +def monthrange(year: int, month: int) -> tuple[int, int]: ... class Calendar: firstweekday: int @@ -25,17 +25,17 @@ class Calendar: def setfirstweekday(self, firstweekday: int) -> None: ... def iterweekdays(self) -> Iterable[int]: ... def itermonthdates(self, year: int, month: int) -> Iterable[datetime.date]: ... - def itermonthdays2(self, year: int, month: int) -> Iterable[Tuple[int, int]]: ... + def itermonthdays2(self, year: int, month: int) -> Iterable[tuple[int, int]]: ... def itermonthdays(self, year: int, month: int) -> Iterable[int]: ... - def monthdatescalendar(self, year: int, month: int) -> List[List[datetime.date]]: ... - def monthdays2calendar(self, year: int, month: int) -> List[List[Tuple[int, int]]]: ... - def monthdayscalendar(self, year: int, month: int) -> List[List[int]]: ... - def yeardatescalendar(self, year: int, width: int = ...) -> List[List[int]]: ... - def yeardays2calendar(self, year: int, width: int = ...) -> List[List[Tuple[int, int]]]: ... - def yeardayscalendar(self, year: int, width: int = ...) -> List[List[int]]: ... + def monthdatescalendar(self, year: int, month: int) -> list[list[datetime.date]]: ... + def monthdays2calendar(self, year: int, month: int) -> list[list[tuple[int, int]]]: ... + def monthdayscalendar(self, year: int, month: int) -> list[list[int]]: ... + def yeardatescalendar(self, year: int, width: int = ...) -> list[list[int]]: ... + def yeardays2calendar(self, year: int, width: int = ...) -> list[list[tuple[int, int]]]: ... + def yeardayscalendar(self, year: int, width: int = ...) -> list[list[int]]: ... if sys.version_info >= (3, 7): - def itermonthdays3(self, year: int, month: int) -> Iterable[Tuple[int, int, int]]: ... - def itermonthdays4(self, year: int, month: int) -> Iterable[Tuple[int, int, int, int]]: ... + def itermonthdays3(self, year: int, month: int) -> Iterable[tuple[int, int, int]]: ... + def itermonthdays4(self, year: int, month: int) -> Iterable[tuple[int, int, int, int]]: ... class TextCalendar(Calendar): def prweek(self, theweek: int, width: int) -> None: ... @@ -50,7 +50,7 @@ class TextCalendar(Calendar): def pryear(self, theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> None: ... def firstweekday() -> int: ... -def monthcalendar(year: int, month: int) -> List[List[int]]: ... +def monthcalendar(year: int, month: int) -> list[list[int]]: ... def prweek(theweek: int, width: int) -> None: ... def week(theweek: int, width: int) -> str: ... def weekheader(width: int) -> str: ... @@ -67,35 +67,28 @@ class HTMLCalendar(Calendar): def formatmonthname(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... def formatmonth(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... def formatyear(self, theyear: int, width: int = ...) -> str: ... - def formatyearpage(self, theyear: int, width: int = ..., css: Optional[str] = ..., encoding: Optional[str] = ...) -> str: ... + def formatyearpage(self, theyear: int, width: int = ..., css: str | None = ..., encoding: str | None = ...) -> str: ... if sys.version_info >= (3, 7): - cssclasses: List[str] + cssclasses: list[str] cssclass_noday: str - cssclasses_weekday_head: List[str] + cssclasses_weekday_head: list[str] cssclass_month_head: str cssclass_month: str cssclass_year: str cssclass_year_head: str -if sys.version_info >= (3, 0): - class different_locale: - def __init__(self, locale: _LocaleType) -> None: ... - def __enter__(self) -> _LocaleType: ... - def __exit__(self, *args: Any) -> None: ... - -else: - class TimeEncoding: - def __init__(self, locale: _LocaleType) -> None: ... - def __enter__(self) -> _LocaleType: ... - def __exit__(self, *args: Any) -> None: ... +class different_locale: + def __init__(self, locale: _LocaleType) -> None: ... + def __enter__(self) -> _LocaleType: ... + def __exit__(self, *args: Any) -> None: ... class LocaleTextCalendar(TextCalendar): - def __init__(self, firstweekday: int = ..., locale: Optional[_LocaleType] = ...) -> None: ... + def __init__(self, firstweekday: int = ..., locale: _LocaleType | None = ...) -> None: ... def formatweekday(self, day: int, width: int) -> str: ... def formatmonthname(self, theyear: int, themonth: int, width: int, withyear: bool = ...) -> str: ... class LocaleHTMLCalendar(HTMLCalendar): - def __init__(self, firstweekday: int = ..., locale: Optional[_LocaleType] = ...) -> None: ... + def __init__(self, firstweekday: int = ..., locale: _LocaleType | None = ...) -> None: ... def formatweekday(self, day: int) -> str: ... def formatmonthname(self, theyear: int, themonth: int, withyear: bool = ...) -> str: ... @@ -104,7 +97,7 @@ c: TextCalendar def setfirstweekday(firstweekday: int) -> None: ... def format(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... def formatstring(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... -def timegm(tuple: Union[Tuple[int, ...], struct_time]) -> int: ... +def timegm(tuple: Tuple[int, ...] | struct_time) -> int: ... # Data attributes day_name: Sequence[str] diff --git a/mypy/typeshed/stdlib/cgi.pyi b/mypy/typeshed/stdlib/cgi.pyi index da3a4d43c563..3821de46ed75 100644 --- a/mypy/typeshed/stdlib/cgi.pyi +++ b/mypy/typeshed/stdlib/cgi.pyi @@ -2,12 +2,12 @@ import sys from _typeshed import SupportsGetItem, SupportsItemAccess from builtins import type as _type from collections.abc import Iterable, Iterator, Mapping -from typing import IO, Any, Optional, Protocol, TypeVar, Union +from typing import IO, Any, Protocol, TypeVar _T = TypeVar("_T", bound=FieldStorage) def parse( - fp: Optional[IO[Any]] = ..., + fp: IO[Any] | None = ..., environ: SupportsItemAccess[str, str] = ..., keep_blank_values: bool = ..., strict_parsing: bool = ..., @@ -38,14 +38,14 @@ def print_directory() -> None: ... def print_environ_usage() -> None: ... if sys.version_info < (3, 8): - def escape(s: str, quote: Optional[bool] = ...) -> str: ... + def escape(s: str, quote: bool | None = ...) -> str: ... class MiniFieldStorage: # The first five "Any" attributes here are always None, but mypy doesn't support that filename: Any list: Any type: Any - file: Optional[IO[bytes]] + file: IO[bytes] | None type_options: dict[Any, Any] disposition: Any disposition_options: dict[Any, Any] @@ -58,40 +58,40 @@ class MiniFieldStorage: _list = list class FieldStorage(object): - FieldStorageClass: Optional[_type] + FieldStorageClass: _type | None keep_blank_values: int strict_parsing: int - qs_on_post: Optional[str] + qs_on_post: str | None headers: Mapping[str, str] fp: IO[bytes] encoding: str errors: str outerboundary: bytes bytes_read: int - limit: Optional[int] + limit: int | None disposition: str disposition_options: dict[str, str] - filename: Optional[str] - file: Optional[IO[bytes]] + filename: str | None + file: IO[bytes] | None type: str type_options: dict[str, str] innerboundary: bytes length: int done: int - list: Optional[_list[Any]] - value: Union[None, bytes, _list[Any]] + list: _list[Any] | None + value: None | bytes | _list[Any] def __init__( self, - fp: Optional[IO[Any]] = ..., - headers: Optional[Mapping[str, str]] = ..., + fp: IO[Any] | None = ..., + headers: Mapping[str, str] | None = ..., outerboundary: bytes = ..., environ: SupportsGetItem[str, str] = ..., keep_blank_values: int = ..., strict_parsing: int = ..., - limit: Optional[int] = ..., + limit: int | None = ..., encoding: str = ..., errors: str = ..., - max_num_fields: Optional[int] = ..., + max_num_fields: int | None = ..., separator: str = ..., ) -> None: ... def __enter__(self: _T) -> _T: ... diff --git a/mypy/typeshed/stdlib/cgitb.pyi b/mypy/typeshed/stdlib/cgitb.pyi index 7603ecd9afbe..7576740fc1c0 100644 --- a/mypy/typeshed/stdlib/cgitb.pyi +++ b/mypy/typeshed/stdlib/cgitb.pyi @@ -1,6 +1,6 @@ -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from types import FrameType, TracebackType -from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Type +from typing import IO, Any, Callable, Optional, Tuple, Type _ExcInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] @@ -8,10 +8,10 @@ def reset() -> str: ... # undocumented def small(text: str) -> str: ... # undocumented def strong(text: str) -> str: ... # undocumented def grey(text: str) -> str: ... # undocumented -def lookup(name: str, frame: FrameType, locals: Dict[str, Any]) -> Tuple[Optional[str], Any]: ... # undocumented +def lookup(name: str, frame: FrameType, locals: dict[str, Any]) -> tuple[str | None, Any]: ... # undocumented def scanvars( - reader: Callable[[], bytes], frame: FrameType, locals: Dict[str, Any] -) -> List[Tuple[str, Optional[str], Any]]: ... # undocumented + reader: Callable[[], bytes], frame: FrameType, locals: dict[str, Any] +) -> list[tuple[str, str | None, Any]]: ... # undocumented def html(einfo: _ExcInfo, context: int = ...) -> str: ... def text(einfo: _ExcInfo, context: int = ...) -> str: ... @@ -19,15 +19,13 @@ class Hook: # undocumented def __init__( self, display: int = ..., - logdir: Optional[AnyPath] = ..., + logdir: StrOrBytesPath | None = ..., context: int = ..., - file: Optional[IO[str]] = ..., + file: IO[str] | None = ..., format: str = ..., ) -> None: ... - def __call__( - self, etype: Optional[Type[BaseException]], evalue: Optional[BaseException], etb: Optional[TracebackType] - ) -> None: ... - def handle(self, info: Optional[_ExcInfo] = ...) -> None: ... + def __call__(self, etype: Type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... + def handle(self, info: _ExcInfo | None = ...) -> None: ... -def handler(info: Optional[_ExcInfo] = ...) -> None: ... -def enable(display: int = ..., logdir: Optional[AnyPath] = ..., context: int = ..., format: str = ...) -> None: ... +def handler(info: _ExcInfo | None = ...) -> None: ... +def enable(display: int = ..., logdir: StrOrBytesPath | None = ..., context: int = ..., format: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/cmath.pyi b/mypy/typeshed/stdlib/cmath.pyi index eaa62eafcb33..04c2b632d411 100644 --- a/mypy/typeshed/stdlib/cmath.pyi +++ b/mypy/typeshed/stdlib/cmath.pyi @@ -1,16 +1,21 @@ import sys -from typing import SupportsComplex, SupportsFloat, Tuple, Union +from typing import SupportsComplex, SupportsFloat, Union + +if sys.version_info >= (3, 8): + from typing import SupportsIndex e: float pi: float -if sys.version_info >= (3, 6): - inf: float - infj: complex - nan: float - nanj: complex - tau: float +inf: float +infj: complex +nan: float +nanj: complex +tau: float -_C = Union[SupportsFloat, SupportsComplex, complex] +if sys.version_info >= (3, 8): + _C = Union[SupportsFloat, SupportsComplex, SupportsIndex, complex] +else: + _C = Union[SupportsFloat, SupportsComplex, complex] def acos(__z: _C) -> complex: ... def acosh(__z: _C) -> complex: ... @@ -21,22 +26,17 @@ def atanh(__z: _C) -> complex: ... def cos(__z: _C) -> complex: ... def cosh(__z: _C) -> complex: ... def exp(__z: _C) -> complex: ... - -if sys.version_info >= (3, 5): - def isclose(a: _C, b: _C, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ...) -> bool: ... - +def isclose(a: _C, b: _C, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ...) -> bool: ... def isinf(__z: _C) -> bool: ... def isnan(__z: _C) -> bool: ... def log(__x: _C, __y_obj: _C = ...) -> complex: ... def log10(__z: _C) -> complex: ... def phase(__z: _C) -> float: ... -def polar(__z: _C) -> Tuple[float, float]: ... +def polar(__z: _C) -> tuple[float, float]: ... def rect(__r: float, __phi: float) -> complex: ... def sin(__z: _C) -> complex: ... def sinh(__z: _C) -> complex: ... def sqrt(__z: _C) -> complex: ... def tan(__z: _C) -> complex: ... def tanh(__z: _C) -> complex: ... - -if sys.version_info >= (3,): - def isfinite(__z: _C) -> bool: ... +def isfinite(__z: _C) -> bool: ... diff --git a/mypy/typeshed/stdlib/cmd.pyi b/mypy/typeshed/stdlib/cmd.pyi index 0b7a7f704a9b..f6d818591a4e 100644 --- a/mypy/typeshed/stdlib/cmd.pyi +++ b/mypy/typeshed/stdlib/cmd.pyi @@ -1,11 +1,11 @@ -from typing import IO, Any, Callable, List, Optional, Tuple +from typing import IO, Any, Callable class Cmd: prompt: str identchars: str ruler: str lastcmd: str - intro: Optional[Any] + intro: Any | None doc_leader: str doc_header: str misc_header: str @@ -14,26 +14,26 @@ class Cmd: use_rawinput: bool stdin: IO[str] stdout: IO[str] - cmdqueue: List[str] + cmdqueue: list[str] completekey: str - def __init__(self, completekey: str = ..., stdin: Optional[IO[str]] = ..., stdout: Optional[IO[str]] = ...) -> None: ... - old_completer: Optional[Callable[[str, int], Optional[str]]] - def cmdloop(self, intro: Optional[Any] = ...) -> None: ... + def __init__(self, completekey: str = ..., stdin: IO[str] | None = ..., stdout: IO[str] | None = ...) -> None: ... + old_completer: Callable[[str, int], str | None] | None + def cmdloop(self, intro: Any | None = ...) -> None: ... def precmd(self, line: str) -> str: ... def postcmd(self, stop: bool, line: str) -> bool: ... def preloop(self) -> None: ... def postloop(self) -> None: ... - def parseline(self, line: str) -> Tuple[Optional[str], Optional[str], str]: ... + def parseline(self, line: str) -> tuple[str | None, str | None, str]: ... def onecmd(self, line: str) -> bool: ... def emptyline(self) -> bool: ... def default(self, line: str) -> bool: ... - def completedefault(self, *ignored: Any) -> List[str]: ... - def completenames(self, text: str, *ignored: Any) -> List[str]: ... - completion_matches: Optional[List[str]] - def complete(self, text: str, state: int) -> Optional[List[str]]: ... - def get_names(self) -> List[str]: ... + def completedefault(self, *ignored: Any) -> list[str]: ... + def completenames(self, text: str, *ignored: Any) -> list[str]: ... + completion_matches: list[str] | None + def complete(self, text: str, state: int) -> list[str] | None: ... + def get_names(self) -> list[str]: ... # Only the first element of args matters. - def complete_help(self, *args: Any) -> List[str]: ... - def do_help(self, arg: str) -> Optional[bool]: ... - def print_topics(self, header: str, cmds: Optional[List[str]], cmdlen: Any, maxcol: int) -> None: ... - def columnize(self, list: Optional[List[str]], displaywidth: int = ...) -> None: ... + def complete_help(self, *args: Any) -> list[str]: ... + def do_help(self, arg: str) -> bool | None: ... + def print_topics(self, header: str, cmds: list[str] | None, cmdlen: Any, maxcol: int) -> None: ... + def columnize(self, list: list[str] | None, displaywidth: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/code.pyi b/mypy/typeshed/stdlib/code.pyi index 16c2b129dd1e..ed00eaf96a5c 100644 --- a/mypy/typeshed/stdlib/code.pyi +++ b/mypy/typeshed/stdlib/code.pyi @@ -1,36 +1,30 @@ -import sys +from codeop import CommandCompiler from types import CodeType -from typing import Any, Callable, Mapping, Optional +from typing import Any, Callable, Mapping class InteractiveInterpreter: - def __init__(self, locals: Optional[Mapping[str, Any]] = ...) -> None: ... + locals: Mapping[str, Any] # undocumented + compile: CommandCompiler # undocumented + def __init__(self, locals: Mapping[str, Any] | None = ...) -> None: ... def runsource(self, source: str, filename: str = ..., symbol: str = ...) -> bool: ... def runcode(self, code: CodeType) -> None: ... - def showsyntaxerror(self, filename: Optional[str] = ...) -> None: ... + def showsyntaxerror(self, filename: str | None = ...) -> None: ... def showtraceback(self) -> None: ... def write(self, data: str) -> None: ... class InteractiveConsole(InteractiveInterpreter): - def __init__(self, locals: Optional[Mapping[str, Any]] = ..., filename: str = ...) -> None: ... - if sys.version_info >= (3, 6): - def interact(self, banner: Optional[str] = ..., exitmsg: Optional[str] = ...) -> None: ... - else: - def interact(self, banner: Optional[str] = ...) -> None: ... + buffer: list[str] # undocumented + filename: str # undocumented + def __init__(self, locals: Mapping[str, Any] | None = ..., filename: str = ...) -> None: ... + def interact(self, banner: str | None = ..., exitmsg: str | None = ...) -> None: ... def push(self, line: str) -> bool: ... def resetbuffer(self) -> None: ... def raw_input(self, prompt: str = ...) -> str: ... -if sys.version_info >= (3, 6): - def interact( - banner: Optional[str] = ..., - readfunc: Optional[Callable[[str], str]] = ..., - local: Optional[Mapping[str, Any]] = ..., - exitmsg: Optional[str] = ..., - ) -> None: ... - -else: - def interact( - banner: Optional[str] = ..., readfunc: Optional[Callable[[str], str]] = ..., local: Optional[Mapping[str, Any]] = ... - ) -> None: ... - -def compile_command(source: str, filename: str = ..., symbol: str = ...) -> Optional[CodeType]: ... +def interact( + banner: str | None = ..., + readfunc: Callable[[str], str] | None = ..., + local: Mapping[str, Any] | None = ..., + exitmsg: str | None = ..., +) -> None: ... +def compile_command(source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... diff --git a/mypy/typeshed/stdlib/codecs.pyi b/mypy/typeshed/stdlib/codecs.pyi index 79be8e254c4c..ebd6911c3e63 100644 --- a/mypy/typeshed/stdlib/codecs.pyi +++ b/mypy/typeshed/stdlib/codecs.pyi @@ -1,47 +1,27 @@ import sys import types +from _typeshed import Self from abc import abstractmethod -from typing import ( - IO, - Any, - BinaryIO, - Callable, - Generator, - Iterable, - Iterator, - List, - Optional, - Protocol, - Text, - TextIO, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, Tuple, Type, TypeVar, overload from typing_extensions import Literal # TODO: this only satisfies the most common interface, where -# bytes (py2 str) is the raw form and str (py2 unicode) is the cooked form. +# bytes is the raw form and str is the cooked form. # In the long run, both should become template parameters maybe? # There *are* bytes->bytes and str->str encodings in the standard library. # They are much more common in Python 2 than in Python 3. -_Decoded = Text -_Encoded = bytes - class _Encoder(Protocol): - def __call__(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... # signature of Codec().encode + def __call__(self, input: str, errors: str = ...) -> tuple[bytes, int]: ... # signature of Codec().encode class _Decoder(Protocol): - def __call__(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... # signature of Codec().decode + def __call__(self, input: bytes, errors: str = ...) -> tuple[str, int]: ... # signature of Codec().decode class _StreamReader(Protocol): - def __call__(self, stream: IO[_Encoded], errors: str = ...) -> StreamReader: ... + def __call__(self, stream: IO[bytes], errors: str = ...) -> StreamReader: ... class _StreamWriter(Protocol): - def __call__(self, stream: IO[_Encoded], errors: str = ...) -> StreamWriter: ... + def __call__(self, stream: IO[bytes], errors: str = ...) -> StreamWriter: ... class _IncrementalEncoder(Protocol): def __call__(self, errors: str = ...) -> IncrementalEncoder: ... @@ -75,18 +55,16 @@ def encode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> b @overload def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore @overload -def encode(obj: _Decoded, encoding: str = ..., errors: str = ...) -> _Encoded: ... +def encode(obj: str, encoding: str = ..., errors: str = ...) -> bytes: ... @overload def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore @overload -def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> Text: ... +def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... @overload -def decode(obj: _Encoded, encoding: str = ..., errors: str = ...) -> _Decoded: ... +def decode(obj: bytes, encoding: str = ..., errors: str = ...) -> str: ... def lookup(__encoding: str) -> CodecInfo: ... -def utf_16_be_decode( - __data: _Encoded, __errors: Optional[str] = ..., __final: bool = ... -) -> Tuple[_Decoded, int]: ... # undocumented -def utf_16_be_encode(__str: _Decoded, __errors: Optional[str] = ...) -> Tuple[_Encoded, int]: ... # undocumented +def utf_16_be_decode(__data: bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... # undocumented +def utf_16_be_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... # undocumented class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): @property @@ -106,13 +84,13 @@ class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): cls, encode: _Encoder, decode: _Decoder, - streamreader: Optional[_StreamReader] = ..., - streamwriter: Optional[_StreamWriter] = ..., - incrementalencoder: Optional[_IncrementalEncoder] = ..., - incrementaldecoder: Optional[_IncrementalDecoder] = ..., - name: Optional[str] = ..., + streamreader: _StreamReader | None = ..., + streamwriter: _StreamWriter | None = ..., + incrementalencoder: _IncrementalEncoder | None = ..., + incrementaldecoder: _IncrementalDecoder | None = ..., + name: str | None = ..., *, - _is_text_encoding: Optional[bool] = ..., + _is_text_encoding: bool | None = ..., ) -> CodecInfo: ... def getencoder(encoding: str) -> _Encoder: ... @@ -121,15 +99,16 @@ def getincrementalencoder(encoding: str) -> _IncrementalEncoder: ... def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... -def register(__search_function: Callable[[str], Optional[CodecInfo]]) -> None: ... +def register(__search_function: Callable[[str], CodecInfo | None]) -> None: ... def open( - filename: str, mode: str = ..., encoding: Optional[str] = ..., errors: str = ..., buffering: int = ... + filename: str, mode: str = ..., encoding: str | None = ..., errors: str = ..., buffering: int = ... ) -> StreamReaderWriter: ... -def EncodedFile( - file: IO[_Encoded], data_encoding: str, file_encoding: Optional[str] = ..., errors: str = ... -) -> StreamRecoder: ... -def iterencode(iterator: Iterable[_Decoded], encoding: str, errors: str = ...) -> Generator[_Encoded, None, None]: ... -def iterdecode(iterator: Iterable[_Encoded], encoding: str, errors: str = ...) -> Generator[_Decoded, None, None]: ... +def EncodedFile(file: IO[bytes], data_encoding: str, file_encoding: str | None = ..., errors: str = ...) -> StreamRecoder: ... +def iterencode(iterator: Iterable[str], encoding: str, errors: str = ...) -> Generator[bytes, None, None]: ... +def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = ...) -> Generator[str, None, None]: ... + +if sys.version_info >= (3, 10): + def unregister(__search_function: Callable[[str], CodecInfo | None]) -> None: ... BOM: bytes BOM_BE: bytes @@ -145,84 +124,76 @@ BOM_UTF32_LE: bytes # It is expected that different actions be taken depending on which of the # three subclasses of `UnicodeError` is actually ...ed. However, the Union # is still needed for at least one of the cases. -def register_error(__errors: str, __handler: Callable[[UnicodeError], Tuple[Union[str, bytes], int]]) -> None: ... -def lookup_error(__name: str) -> Callable[[UnicodeError], Tuple[Union[str, bytes], int]]: ... -def strict_errors(exception: UnicodeError) -> Tuple[Union[str, bytes], int]: ... -def replace_errors(exception: UnicodeError) -> Tuple[Union[str, bytes], int]: ... -def ignore_errors(exception: UnicodeError) -> Tuple[Union[str, bytes], int]: ... -def xmlcharrefreplace_errors(exception: UnicodeError) -> Tuple[Union[str, bytes], int]: ... -def backslashreplace_errors(exception: UnicodeError) -> Tuple[Union[str, bytes], int]: ... +def register_error(__errors: str, __handler: Callable[[UnicodeError], tuple[str | bytes, int]]) -> None: ... +def lookup_error(__name: str) -> Callable[[UnicodeError], tuple[str | bytes, int]]: ... +def strict_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def replace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def ignore_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def xmlcharrefreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def backslashreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... class Codec: # These are sort of @abstractmethod but sort of not. # The StreamReader and StreamWriter subclasses only implement one. - def encode(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... - def decode(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... + def encode(self, input: str, errors: str = ...) -> tuple[bytes, int]: ... + def decode(self, input: bytes, errors: str = ...) -> tuple[str, int]: ... class IncrementalEncoder: errors: str def __init__(self, errors: str = ...) -> None: ... @abstractmethod - def encode(self, input: _Decoded, final: bool = ...) -> _Encoded: ... + def encode(self, input: str, final: bool = ...) -> bytes: ... def reset(self) -> None: ... # documentation says int but str is needed for the subclass. - def getstate(self) -> Union[int, _Decoded]: ... - def setstate(self, state: Union[int, _Decoded]) -> None: ... + def getstate(self) -> int | str: ... + def setstate(self, state: int | str) -> None: ... class IncrementalDecoder: errors: str def __init__(self, errors: str = ...) -> None: ... @abstractmethod - def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... + def decode(self, input: bytes, final: bool = ...) -> str: ... def reset(self) -> None: ... - def getstate(self) -> Tuple[_Encoded, int]: ... - def setstate(self, state: Tuple[_Encoded, int]) -> None: ... + def getstate(self) -> tuple[bytes, int]: ... + def setstate(self, state: tuple[bytes, int]) -> None: ... # These are not documented but used in encodings/*.py implementations. class BufferedIncrementalEncoder(IncrementalEncoder): buffer: str def __init__(self, errors: str = ...) -> None: ... @abstractmethod - def _buffer_encode(self, input: _Decoded, errors: str, final: bool) -> _Encoded: ... - def encode(self, input: _Decoded, final: bool = ...) -> _Encoded: ... + def _buffer_encode(self, input: str, errors: str, final: bool) -> bytes: ... + def encode(self, input: str, final: bool = ...) -> bytes: ... class BufferedIncrementalDecoder(IncrementalDecoder): buffer: bytes def __init__(self, errors: str = ...) -> None: ... @abstractmethod - def _buffer_decode(self, input: _Encoded, errors: str, final: bool) -> Tuple[_Decoded, int]: ... - def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... - -_SW = TypeVar("_SW", bound=StreamWriter) + def _buffer_decode(self, input: bytes, errors: str, final: bool) -> tuple[str, int]: ... + def decode(self, input: bytes, final: bool = ...) -> str: ... # TODO: it is not possible to specify the requirement that all other # attributes and methods are passed-through from the stream. class StreamWriter(Codec): errors: str - def __init__(self, stream: IO[_Encoded], errors: str = ...) -> None: ... - def write(self, object: _Decoded) -> None: ... - def writelines(self, list: Iterable[_Decoded]) -> None: ... + def __init__(self, stream: IO[bytes], errors: str = ...) -> None: ... + def write(self, object: str) -> None: ... + def writelines(self, list: Iterable[str]) -> None: ... def reset(self) -> None: ... - def __enter__(self: _SW) -> _SW: ... - def __exit__( - self, typ: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[types.TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -_SR = TypeVar("_SR", bound=StreamReader) - class StreamReader(Codec): errors: str - def __init__(self, stream: IO[_Encoded], errors: str = ...) -> None: ... - def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> _Decoded: ... - def readline(self, size: Optional[int] = ..., keepends: bool = ...) -> _Decoded: ... - def readlines(self, sizehint: Optional[int] = ..., keepends: bool = ...) -> List[_Decoded]: ... + def __init__(self, stream: IO[bytes], errors: str = ...) -> None: ... + def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> str: ... + def readline(self, size: int | None = ..., keepends: bool = ...) -> str: ... + def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> list[str]: ... def reset(self) -> None: ... - def __enter__(self: _SR) -> _SR: ... - def __exit__( - self, typ: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[types.TracebackType] - ) -> None: ... - def __iter__(self) -> Iterator[_Decoded]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __iter__(self) -> Iterator[str]: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... _T = TypeVar("_T", bound=StreamReaderWriter) @@ -230,25 +201,20 @@ _T = TypeVar("_T", bound=StreamReaderWriter) # Doesn't actually inherit from TextIO, but wraps a BinaryIO to provide text reading and writing # and delegates attributes to the underlying binary stream with __getattr__. class StreamReaderWriter(TextIO): - def __init__(self, stream: IO[_Encoded], Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... - def read(self, size: int = ...) -> _Decoded: ... - def readline(self, size: Optional[int] = ...) -> _Decoded: ... - def readlines(self, sizehint: Optional[int] = ...) -> List[_Decoded]: ... - if sys.version_info >= (3,): - def __next__(self) -> Text: ... - else: - def next(self) -> Text: ... + def __init__(self, stream: IO[bytes], Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... + def read(self, size: int = ...) -> str: ... + def readline(self, size: int | None = ...) -> str: ... + def readlines(self, sizehint: int | None = ...) -> list[str]: ... + def __next__(self) -> str: ... def __iter__(self: _T) -> _T: ... # This actually returns None, but that's incompatible with the supertype - def write(self, data: _Decoded) -> int: ... - def writelines(self, list: Iterable[_Decoded]) -> None: ... + def write(self, data: str) -> int: ... + def writelines(self, list: Iterable[str]) -> None: ... def reset(self) -> None: ... # Same as write() def seek(self, offset: int, whence: int = ...) -> int: ... - def __enter__(self: _T) -> _T: ... - def __exit__( - self, typ: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[types.TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str) -> Any: ... # These methods don't actually exist directly, but they are needed to satisfy the TextIO # interface. At runtime, they are delegated through __getattr__. @@ -257,7 +223,7 @@ class StreamReaderWriter(TextIO): def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def writable(self) -> bool: ... @@ -267,7 +233,7 @@ _SRT = TypeVar("_SRT", bound=StreamRecoder) class StreamRecoder(BinaryIO): def __init__( self, - stream: IO[_Encoded], + stream: IO[bytes], encode: _Encoder, decode: _Decoder, Reader: _StreamReader, @@ -275,21 +241,16 @@ class StreamRecoder(BinaryIO): errors: str = ..., ) -> None: ... def read(self, size: int = ...) -> bytes: ... - def readline(self, size: Optional[int] = ...) -> bytes: ... - def readlines(self, sizehint: Optional[int] = ...) -> List[bytes]: ... - if sys.version_info >= (3,): - def __next__(self) -> bytes: ... - else: - def next(self) -> bytes: ... + def readline(self, size: int | None = ...) -> bytes: ... + def readlines(self, sizehint: int | None = ...) -> list[bytes]: ... + def __next__(self) -> bytes: ... def __iter__(self: _SRT) -> _SRT: ... def write(self, data: bytes) -> int: ... def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore # it's supposed to return None def reset(self) -> None: ... def __getattr__(self, name: str) -> Any: ... - def __enter__(self: _SRT) -> _SRT: ... - def __exit__( - self, type: Optional[Type[BaseException]], value: Optional[BaseException], tb: Optional[types.TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, type: Type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... # These methods don't actually exist directly, but they are needed to satisfy the BinaryIO # interface. At runtime, they are delegated through __getattr__. def seek(self, offset: int, whence: int = ...) -> int: ... @@ -298,7 +259,7 @@ class StreamRecoder(BinaryIO): def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... def writable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/codeop.pyi b/mypy/typeshed/stdlib/codeop.pyi index f3d6c2819ec6..8ed5710c9891 100644 --- a/mypy/typeshed/stdlib/codeop.pyi +++ b/mypy/typeshed/stdlib/codeop.pyi @@ -1,7 +1,6 @@ from types import CodeType -from typing import Optional -def compile_command(source: str, filename: str = ..., symbol: str = ...) -> Optional[CodeType]: ... +def compile_command(source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... class Compile: flags: int @@ -11,4 +10,4 @@ class Compile: class CommandCompiler: compiler: Compile def __init__(self) -> None: ... - def __call__(self, source: str, filename: str = ..., symbol: str = ...) -> Optional[CodeType]: ... + def __call__(self, source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... diff --git a/mypy/typeshed/stdlib/collections/__init__.pyi b/mypy/typeshed/stdlib/collections/__init__.pyi index 635d32ebd294..66a76941beee 100644 --- a/mypy/typeshed/stdlib/collections/__init__.pyi +++ b/mypy/typeshed/stdlib/collections/__init__.pyi @@ -1,20 +1,11 @@ import sys -from typing import Any, Dict, Generic, List, NoReturn, Optional, Tuple, Type, TypeVar, Union, overload +from _collections_abc import dict_items, dict_keys, dict_values +from _typeshed import Self +from typing import Any, Dict, Generic, NoReturn, Tuple, Type, TypeVar, overload +from typing_extensions import final if sys.version_info >= (3, 10): - from typing import ( - Callable, - ItemsView, - Iterable, - Iterator, - KeysView, - Mapping, - MutableMapping, - MutableSequence, - Reversible, - Sequence, - ValuesView, - ) + from typing import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Reversible, Sequence else: from _collections_abc import * @@ -22,44 +13,41 @@ _S = TypeVar("_S") _T = TypeVar("_T") _KT = TypeVar("_KT") _VT = TypeVar("_VT") +_KT_co = TypeVar("_KT_co", covariant=True) +_VT_co = TypeVar("_VT_co", covariant=True) # namedtuple is special-cased in the type checker; the initializer is ignored. if sys.version_info >= (3, 7): def namedtuple( typename: str, - field_names: Union[str, Iterable[str]], + field_names: str | Iterable[str], *, rename: bool = ..., - module: Optional[str] = ..., - defaults: Optional[Iterable[Any]] = ..., + module: str | None = ..., + defaults: Iterable[Any] | None = ..., ) -> Type[Tuple[Any, ...]]: ... else: def namedtuple( - typename: str, - field_names: Union[str, Iterable[str]], - *, - verbose: bool = ..., - rename: bool = ..., - module: Optional[str] = ..., + typename: str, field_names: str | Iterable[str], *, verbose: bool = ..., rename: bool = ..., module: str | None = ... ) -> Type[Tuple[Any, ...]]: ... class UserDict(MutableMapping[_KT, _VT]): - data: Dict[_KT, _VT] - def __init__(self, __dict: Optional[Mapping[_KT, _VT]] = ..., **kwargs: _VT) -> None: ... + data: dict[_KT, _VT] + def __init__(self, __dict: Mapping[_KT, _VT] | None = ..., **kwargs: _VT) -> None: ... def __len__(self) -> int: ... def __getitem__(self, key: _KT) -> _VT: ... def __setitem__(self, key: _KT, item: _VT) -> None: ... def __delitem__(self, key: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... def __contains__(self, key: object) -> bool: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... @classmethod - def fromkeys(cls: Type[_S], iterable: Iterable[_KT], value: Optional[_VT] = ...) -> _S: ... + def fromkeys(cls: Type[Self], iterable: Iterable[_KT], value: _VT | None = ...) -> Self: ... class UserList(MutableSequence[_T]): - data: List[_T] - def __init__(self, initlist: Optional[Iterable[_T]] = ...) -> None: ... + data: list[_T] + def __init__(self, initlist: Iterable[_T] | None = ...) -> None: ... def __lt__(self, other: object) -> bool: ... def __le__(self, other: object) -> bool: ... def __gt__(self, other: object) -> bool: ... @@ -69,12 +57,12 @@ class UserList(MutableSequence[_T]): @overload def __getitem__(self, i: int) -> _T: ... @overload - def __getitem__(self, i: slice) -> MutableSequence[_T]: ... + def __getitem__(self: Self, i: slice) -> Self: ... @overload def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, i: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... def __add__(self: _S, other: Iterable[_T]) -> _S: ... def __iadd__(self: _S, other: Iterable[_T]) -> _S: ... def __mul__(self: _S, n: int) -> _S: ... @@ -99,29 +87,31 @@ class UserString(Sequence[str]): def __int__(self) -> int: ... def __float__(self) -> float: ... def __complex__(self) -> complex: ... - def __getnewargs__(self) -> Tuple[str]: ... - def __lt__(self, string: Union[str, UserString]) -> bool: ... - def __le__(self, string: Union[str, UserString]) -> bool: ... - def __gt__(self, string: Union[str, UserString]) -> bool: ... - def __ge__(self, string: Union[str, UserString]) -> bool: ... + def __getnewargs__(self) -> tuple[str]: ... + def __lt__(self, string: str | UserString) -> bool: ... + def __le__(self, string: str | UserString) -> bool: ... + def __gt__(self, string: str | UserString) -> bool: ... + def __ge__(self, string: str | UserString) -> bool: ... def __contains__(self, char: object) -> bool: ... def __len__(self) -> int: ... # It should return a str to implement Sequence correctly, but it doesn't. - def __getitem__(self: _UserStringT, i: Union[int, slice]) -> _UserStringT: ... # type: ignore + def __getitem__(self: _UserStringT, i: int | slice) -> _UserStringT: ... # type: ignore + def __iter__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore + def __reversed__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore def __add__(self: _UserStringT, other: object) -> _UserStringT: ... def __mul__(self: _UserStringT, n: int) -> _UserStringT: ... def __mod__(self: _UserStringT, args: Any) -> _UserStringT: ... def capitalize(self: _UserStringT) -> _UserStringT: ... def casefold(self: _UserStringT) -> _UserStringT: ... def center(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... - def count(self, sub: Union[str, UserString], start: int = ..., end: int = ...) -> int: ... + def count(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... if sys.version_info >= (3, 8): - def encode(self: UserString, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> bytes: ... + def encode(self: UserString, encoding: str | None = ..., errors: str | None = ...) -> bytes: ... else: - def encode(self: _UserStringT, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> _UserStringT: ... - def endswith(self, suffix: Union[str, Tuple[str, ...]], start: Optional[int] = ..., end: Optional[int] = ...) -> bool: ... + def encode(self: _UserStringT, encoding: str | None = ..., errors: str | None = ...) -> _UserStringT: ... + def endswith(self, suffix: str | Tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... def expandtabs(self: _UserStringT, tabsize: int = ...) -> _UserStringT: ... - def find(self, sub: Union[str, UserString], start: int = ..., end: int = ...) -> int: ... + def find(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... def format(self, *args: Any, **kwds: Any) -> str: ... def format_map(self, mapping: Mapping[str, Any]) -> str: ... def index(self, sub: str, start: int = ..., end: int = ...) -> int: ... @@ -139,30 +129,28 @@ class UserString(Sequence[str]): def join(self, seq: Iterable[str]) -> str: ... def ljust(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... def lower(self: _UserStringT) -> _UserStringT: ... - def lstrip(self: _UserStringT, chars: Optional[str] = ...) -> _UserStringT: ... + def lstrip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... @staticmethod @overload - def maketrans(x: Union[Dict[int, _T], Dict[str, _T], Dict[Union[str, int], _T]]) -> Dict[int, _T]: ... + def maketrans(x: dict[int, _T] | dict[str, _T] | dict[str | int, _T]) -> dict[int, _T]: ... @staticmethod @overload - def maketrans(x: str, y: str, z: str = ...) -> Dict[int, Union[int, None]]: ... - def partition(self, sep: str) -> Tuple[str, str, str]: ... + def maketrans(x: str, y: str, z: str = ...) -> dict[int, int | None]: ... + def partition(self, sep: str) -> tuple[str, str, str]: ... if sys.version_info >= (3, 9): - def removeprefix(self: _UserStringT, __prefix: Union[str, UserString]) -> _UserStringT: ... - def removesuffix(self: _UserStringT, __suffix: Union[str, UserString]) -> _UserStringT: ... - def replace( - self: _UserStringT, old: Union[str, UserString], new: Union[str, UserString], maxsplit: int = ... - ) -> _UserStringT: ... - def rfind(self, sub: Union[str, UserString], start: int = ..., end: int = ...) -> int: ... - def rindex(self, sub: Union[str, UserString], start: int = ..., end: int = ...) -> int: ... + def removeprefix(self: _UserStringT, __prefix: str | UserString) -> _UserStringT: ... + def removesuffix(self: _UserStringT, __suffix: str | UserString) -> _UserStringT: ... + def replace(self: _UserStringT, old: str | UserString, new: str | UserString, maxsplit: int = ...) -> _UserStringT: ... + def rfind(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... + def rindex(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... def rjust(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... - def rpartition(self, sep: str) -> Tuple[str, str, str]: ... - def rstrip(self: _UserStringT, chars: Optional[str] = ...) -> _UserStringT: ... - def split(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... - def rsplit(self, sep: Optional[str] = ..., maxsplit: int = ...) -> List[str]: ... - def splitlines(self, keepends: bool = ...) -> List[str]: ... - def startswith(self, prefix: Union[str, Tuple[str, ...]], start: Optional[int] = ..., end: Optional[int] = ...) -> bool: ... - def strip(self: _UserStringT, chars: Optional[str] = ...) -> _UserStringT: ... + def rpartition(self, sep: str) -> tuple[str, str, str]: ... + def rstrip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... + def split(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... + def splitlines(self, keepends: bool = ...) -> list[str]: ... + def startswith(self, prefix: str | Tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def strip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... def swapcase(self: _UserStringT) -> _UserStringT: ... def title(self: _UserStringT) -> _UserStringT: ... def translate(self: _UserStringT, *args: Any) -> _UserStringT: ... @@ -171,45 +159,47 @@ class UserString(Sequence[str]): class deque(MutableSequence[_T], Generic[_T]): @property - def maxlen(self) -> Optional[int]: ... - def __init__(self, iterable: Iterable[_T] = ..., maxlen: Optional[int] = ...) -> None: ... - def append(self, x: _T) -> None: ... - def appendleft(self, x: _T) -> None: ... + def maxlen(self) -> int | None: ... + def __init__(self, iterable: Iterable[_T] = ..., maxlen: int | None = ...) -> None: ... + def append(self, __x: _T) -> None: ... + def appendleft(self, __x: _T) -> None: ... def clear(self) -> None: ... - def copy(self) -> deque[_T]: ... - def count(self, x: _T) -> int: ... - def extend(self, iterable: Iterable[_T]) -> None: ... - def extendleft(self, iterable: Iterable[_T]) -> None: ... - def insert(self, i: int, x: _T) -> None: ... - def index(self, x: _T, start: int = ..., stop: int = ...) -> int: ... + def copy(self: _S) -> _S: ... + def count(self, __x: _T) -> int: ... + def extend(self, __iterable: Iterable[_T]) -> None: ... + def extendleft(self, __iterable: Iterable[_T]) -> None: ... + def insert(self, __i: int, __x: _T) -> None: ... + def index(self, __x: _T, __start: int = ..., __stop: int = ...) -> int: ... def pop(self) -> _T: ... # type: ignore def popleft(self) -> _T: ... - def remove(self, value: _T) -> None: ... + def remove(self, __value: _T) -> None: ... def reverse(self) -> None: ... - def rotate(self, n: int = ...) -> None: ... + def rotate(self, __n: int = ...) -> None: ... + def __copy__(self: _S) -> _S: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... def __str__(self) -> str: ... # These methods of deque don't really take slices, but we need to # define them as taking a slice to satisfy MutableSequence. @overload - def __getitem__(self, index: int) -> _T: ... + def __getitem__(self, __index: int) -> _T: ... @overload - def __getitem__(self, s: slice) -> MutableSequence[_T]: ... + def __getitem__(self, __s: slice) -> MutableSequence[_T]: ... @overload - def __setitem__(self, i: int, x: _T) -> None: ... + def __setitem__(self, __i: int, __x: _T) -> None: ... @overload - def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... + def __setitem__(self, __s: slice, __o: Iterable[_T]) -> None: ... @overload - def __delitem__(self, i: int) -> None: ... + def __delitem__(self, __i: int) -> None: ... @overload - def __delitem__(self, s: slice) -> None: ... - def __contains__(self, o: object) -> bool: ... + def __delitem__(self, __s: slice) -> None: ... + def __contains__(self, __o: object) -> bool: ... + def __reduce__(self: Self) -> tuple[Type[Self], tuple[()], None, Iterator[_T]]: ... def __reversed__(self) -> Iterator[_T]: ... - def __iadd__(self: _S, iterable: Iterable[_T]) -> _S: ... - def __add__(self, other: deque[_T]) -> deque[_T]: ... - def __mul__(self, other: int) -> deque[_T]: ... - def __imul__(self, other: int) -> None: ... + def __iadd__(self: _S, __iterable: Iterable[_T]) -> _S: ... + def __add__(self: _S, __other: _S) -> _S: ... + def __mul__(self: _S, __other: int) -> _S: ... + def __imul__(self: _S, __other: int) -> _S: ... class Counter(Dict[_T, int], Generic[_T]): @overload @@ -218,11 +208,11 @@ class Counter(Dict[_T, int], Generic[_T]): def __init__(self, __mapping: Mapping[_T, int]) -> None: ... @overload def __init__(self, __iterable: Iterable[_T]) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def elements(self) -> Iterator[_T]: ... - def most_common(self, n: Optional[int] = ...) -> List[Tuple[_T, int]]: ... + def most_common(self, n: int | None = ...) -> list[tuple[_T, int]]: ... @classmethod - def fromkeys(cls, iterable: Any, v: Optional[int] = ...) -> NoReturn: ... # type: ignore + def fromkeys(cls, iterable: Any, v: int | None = ...) -> NoReturn: ... # type: ignore @overload def subtract(self, __iterable: None = ...) -> None: ... @overload @@ -237,7 +227,7 @@ class Counter(Dict[_T, int], Generic[_T]): @overload def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ... @overload - def update(self, __m: Union[Iterable[_T], Iterable[Tuple[_T, int]]], **kwargs: int) -> None: ... + def update(self, __m: Iterable[_T] | Iterable[tuple[_T, int]], **kwargs: int) -> None: ... @overload def update(self, __m: None = ..., **kwargs: int) -> None: ... def __add__(self, other: Counter[_T]) -> Counter[_T]: ... @@ -251,55 +241,63 @@ class Counter(Dict[_T, int], Generic[_T]): def __iand__(self, other: Counter[_T]) -> Counter[_T]: ... def __ior__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore -class _OrderedDictKeysView(KeysView[_KT], Reversible[_KT]): - def __reversed__(self) -> Iterator[_KT]: ... +@final +class _OrderedDictKeysView(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc] + def __reversed__(self) -> Iterator[_KT_co]: ... -class _OrderedDictItemsView(ItemsView[_KT, _VT], Reversible[Tuple[_KT, _VT]]): - def __reversed__(self) -> Iterator[Tuple[_KT, _VT]]: ... +@final +class _OrderedDictItemsView(dict_items[_KT_co, _VT_co], Reversible[Tuple[_KT_co, _VT_co]]): # type: ignore[misc] + def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... -class _OrderedDictValuesView(ValuesView[_VT], Reversible[_VT]): - def __reversed__(self) -> Iterator[_VT]: ... +@final +class _OrderedDictValuesView(dict_values[_KT_co, _VT_co], Reversible[_VT_co], Generic[_KT_co, _VT_co]): # type: ignore[misc] + def __reversed__(self) -> Iterator[_VT_co]: ... class OrderedDict(Dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): - def popitem(self, last: bool = ...) -> Tuple[_KT, _VT]: ... + def popitem(self, last: bool = ...) -> tuple[_KT, _VT]: ... def move_to_end(self, key: _KT, last: bool = ...) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def __reversed__(self) -> Iterator[_KT]: ... - def keys(self) -> _OrderedDictKeysView[_KT]: ... + def keys(self) -> _OrderedDictKeysView[_KT, _VT]: ... def items(self) -> _OrderedDictItemsView[_KT, _VT]: ... - def values(self) -> _OrderedDictValuesView[_VT]: ... + def values(self) -> _OrderedDictValuesView[_KT, _VT]: ... class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): - default_factory: Optional[Callable[[], _VT]] + default_factory: Callable[[], _VT] | None @overload def __init__(self, **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]]) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], **kwargs: _VT) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None, **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], map: Mapping[_KT, _VT]) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None, __map: Mapping[_KT, _VT]) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None, __map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Optional[Callable[[], _VT]], iterable: Iterable[Tuple[_KT, _VT]]) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None, __iterable: Iterable[tuple[_KT, _VT]]) -> None: ... @overload def __init__( - self, default_factory: Optional[Callable[[], _VT]], iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT + self, __default_factory: Callable[[], _VT] | None, __iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT ) -> None: ... - def __missing__(self, key: _KT) -> _VT: ... - # TODO __reversed__ + def __missing__(self, __key: _KT) -> _VT: ... + def __copy__(self: _S) -> _S: ... def copy(self: _S) -> _S: ... class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): - maps: List[Mapping[_KT, _VT]] - def __init__(self, *maps: Mapping[_KT, _VT]) -> None: ... - def new_child(self, m: Optional[Mapping[_KT, _VT]] = ...) -> ChainMap[_KT, _VT]: ... + maps: list[MutableMapping[_KT, _VT]] + def __init__(self, *maps: MutableMapping[_KT, _VT]) -> None: ... + def new_child(self: Self, m: MutableMapping[_KT, _VT] | None = ...) -> Self: ... @property - def parents(self) -> ChainMap[_KT, _VT]: ... + def parents(self: Self) -> Self: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... def __delitem__(self, v: _KT) -> None: ... def __getitem__(self, k: _KT) -> _VT: ... def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... def __missing__(self, key: _KT) -> _VT: ... # undocumented + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... diff --git a/mypy/typeshed/stdlib/colorsys.pyi b/mypy/typeshed/stdlib/colorsys.pyi index 8db2e2c9ab3a..00c5f9d22cb1 100644 --- a/mypy/typeshed/stdlib/colorsys.pyi +++ b/mypy/typeshed/stdlib/colorsys.pyi @@ -1,11 +1,9 @@ -from typing import Tuple - -def rgb_to_yiq(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def yiq_to_rgb(y: float, i: float, q: float) -> Tuple[float, float, float]: ... -def rgb_to_hls(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def hls_to_rgb(h: float, l: float, s: float) -> Tuple[float, float, float]: ... -def rgb_to_hsv(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def hsv_to_rgb(h: float, s: float, v: float) -> Tuple[float, float, float]: ... +def rgb_to_yiq(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def yiq_to_rgb(y: float, i: float, q: float) -> tuple[float, float, float]: ... +def rgb_to_hls(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def hls_to_rgb(h: float, l: float, s: float) -> tuple[float, float, float]: ... +def rgb_to_hsv(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def hsv_to_rgb(h: float, s: float, v: float) -> tuple[float, float, float]: ... # TODO undocumented ONE_SIXTH: float diff --git a/mypy/typeshed/stdlib/compileall.pyi b/mypy/typeshed/stdlib/compileall.pyi index 529568275c8c..64b4dc2bc5f7 100644 --- a/mypy/typeshed/stdlib/compileall.pyi +++ b/mypy/typeshed/stdlib/compileall.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import StrPath -from typing import Any, Optional, Protocol +from typing import Any, Protocol if sys.version_info >= (3, 7): from py_compile import PycInvalidationMode @@ -11,34 +11,34 @@ class _SupportsSearch(Protocol): if sys.version_info >= (3, 9): def compile_dir( dir: StrPath, - maxlevels: Optional[int] = ..., - ddir: Optional[StrPath] = ..., + maxlevels: int | None = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., workers: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., *, - stripdir: Optional[str] = ..., # TODO: change to Optional[StrPath] once https://bugs.python.org/issue40447 is resolved - prependdir: Optional[StrPath] = ..., - limit_sl_dest: Optional[StrPath] = ..., + stripdir: str | None = ..., # TODO: change to StrPath | None once https://bugs.python.org/issue40447 is resolved + prependdir: StrPath | None = ..., + limit_sl_dest: StrPath | None = ..., hardlink_dupes: bool = ..., ) -> int: ... def compile_file( fullname: StrPath, - ddir: Optional[StrPath] = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., *, - stripdir: Optional[str] = ..., # TODO: change to Optional[StrPath] once https://bugs.python.org/issue40447 is resolved - prependdir: Optional[StrPath] = ..., - limit_sl_dest: Optional[StrPath] = ..., + stripdir: str | None = ..., # TODO: change to StrPath | None once https://bugs.python.org/issue40447 is resolved + prependdir: StrPath | None = ..., + limit_sl_dest: StrPath | None = ..., hardlink_dupes: bool = ..., ) -> int: ... @@ -46,33 +46,33 @@ elif sys.version_info >= (3, 7): def compile_dir( dir: StrPath, maxlevels: int = ..., - ddir: Optional[StrPath] = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., workers: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., ) -> int: ... def compile_file( fullname: StrPath, - ddir: Optional[StrPath] = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., ) -> int: ... else: def compile_dir( dir: StrPath, maxlevels: int = ..., - ddir: Optional[StrPath] = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., @@ -80,9 +80,9 @@ else: ) -> int: ... def compile_file( fullname: StrPath, - ddir: Optional[StrPath] = ..., + ddir: StrPath | None = ..., force: bool = ..., - rx: Optional[_SupportsSearch] = ..., + rx: _SupportsSearch | None = ..., quiet: int = ..., legacy: bool = ..., optimize: int = ..., @@ -96,7 +96,7 @@ if sys.version_info >= (3, 7): quiet: int = ..., legacy: bool = ..., optimize: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., ) -> int: ... else: diff --git a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi index ca4087948c3e..fd7333420b39 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi @@ -1,22 +1,10 @@ import sys import threading +from _typeshed import Self from abc import abstractmethod +from collections.abc import Container, Iterable, Iterator, Sequence from logging import Logger -from typing import ( - Any, - Callable, - Container, - Generic, - Iterable, - Iterator, - List, - Optional, - Protocol, - Sequence, - Set, - TypeVar, - overload, -) +from typing import Any, Callable, Generic, Protocol, Set, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -29,6 +17,8 @@ RUNNING: str CANCELLED: str CANCELLED_AND_NOTIFIED: str FINISHED: str +_FUTURE_STATES: list[str] +_STATE_TO_DESCRIPTION_MAP: dict[str, str] LOGGER: Logger class Error(Exception): ... @@ -59,11 +49,11 @@ class Future(Generic[_T]): def running(self) -> bool: ... def done(self) -> bool: ... def add_done_callback(self, fn: Callable[[Future[_T]], Any]) -> None: ... - def result(self, timeout: Optional[float] = ...) -> _T: ... + def result(self, timeout: float | None = ...) -> _T: ... def set_running_or_notify_cancel(self) -> bool: ... def set_result(self, result: _T) -> None: ... - def exception(self, timeout: Optional[float] = ...) -> Optional[BaseException]: ... - def set_exception(self, exception: Optional[BaseException]) -> None: ... + def exception(self, timeout: float | None = ...) -> BaseException | None: ... + def set_exception(self, exception: BaseException | None) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -73,33 +63,33 @@ class Executor: else: def submit(self, fn: Callable[..., _T], *args: Any, **kwargs: Any) -> Future[_T]: ... def map( - self, fn: Callable[..., _T], *iterables: Iterable[Any], timeout: Optional[float] = ..., chunksize: int = ... + self, fn: Callable[..., _T], *iterables: Iterable[Any], timeout: float | None = ..., chunksize: int = ... ) -> Iterator[_T]: ... if sys.version_info >= (3, 9): def shutdown(self, wait: bool = ..., *, cancel_futures: bool = ...) -> None: ... else: def shutdown(self, wait: bool = ...) -> None: ... - def __enter__(self: _T) -> _T: ... - def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Optional[bool]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> bool | None: ... -def as_completed(fs: Iterable[Future[_T]], timeout: Optional[float] = ...) -> Iterator[Future[_T]]: ... +def as_completed(fs: Iterable[Future[_T]], timeout: float | None = ...) -> Iterator[Future[_T]]: ... # Ideally this would be a namedtuple, but mypy doesn't support generic tuple types. See #1976 class DoneAndNotDoneFutures(Sequence[Set[Future[_T]]]): - done: Set[Future[_T]] - not_done: Set[Future[_T]] - def __new__(_cls, done: Set[Future[_T]], not_done: Set[Future[_T]]) -> DoneAndNotDoneFutures[_T]: ... + done: set[Future[_T]] + not_done: set[Future[_T]] + def __new__(_cls, done: set[Future[_T]], not_done: set[Future[_T]]) -> DoneAndNotDoneFutures[_T]: ... def __len__(self) -> int: ... @overload - def __getitem__(self, i: int) -> Set[Future[_T]]: ... + def __getitem__(self, i: int) -> set[Future[_T]]: ... @overload def __getitem__(self, s: slice) -> DoneAndNotDoneFutures[_T]: ... -def wait(fs: Iterable[Future[_T]], timeout: Optional[float] = ..., return_when: str = ...) -> DoneAndNotDoneFutures[_T]: ... +def wait(fs: Iterable[Future[_T]], timeout: float | None = ..., return_when: str = ...) -> DoneAndNotDoneFutures[_T]: ... class _Waiter: event: threading.Event - finished_futures: List[Future[Any]] + finished_futures: list[Future[Any]] def __init__(self) -> None: ... def add_result(self, future: Future[Any]) -> None: ... def add_exception(self, future: Future[Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/process.pyi b/mypy/typeshed/stdlib/concurrent/futures/process.pyi index a66557671ce5..cc48f48f0023 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/process.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/process.pyi @@ -1,9 +1,133 @@ import sys -from typing import Any, Callable, Optional, Tuple +from collections.abc import Generator, Iterable, Mapping, MutableMapping, MutableSequence +from multiprocessing.connection import Connection +from multiprocessing.context import BaseContext, Process +from multiprocessing.queues import Queue, SimpleQueue +from threading import Lock, Semaphore, Thread +from types import TracebackType +from typing import Any, Callable, Generic, Tuple, TypeVar +from weakref import ref -from ._base import Executor +from ._base import Executor, Future -EXTRA_QUEUED_CALLS: Any +_threads_wakeups: MutableMapping[Any, Any] +_global_shutdown: bool + +class _ThreadWakeup: + _closed: bool + _reader: Connection + _writer: Connection + def __init__(self) -> None: ... + def close(self) -> None: ... + def wakeup(self) -> None: ... + def clear(self) -> None: ... + +def _python_exit() -> None: ... + +EXTRA_QUEUED_CALLS: int + +_MAX_WINDOWS_WORKERS: int + +class _RemoteTraceback(Exception): + tb: str + def __init__(self, tb: TracebackType) -> None: ... + def __str__(self) -> str: ... + +class _ExceptionWithTraceback: + exc: BaseException + tb: TracebackType + def __init__(self, exc: BaseException, tb: TracebackType) -> None: ... + def __reduce__(self) -> str | Tuple[Any, ...]: ... + +def _rebuild_exc(exc: Exception, tb: str) -> Exception: ... + +_S = TypeVar("_S") + +class _WorkItem(Generic[_S]): + future: Future[_S] + fn: Callable[..., _S] + args: Iterable[Any] + kwargs: Mapping[str, Any] + def __init__(self, future: Future[_S], fn: Callable[..., _S], args: Iterable[Any], kwargs: Mapping[str, Any]) -> None: ... + +class _ResultItem: + work_id: int + exception: Exception + result: Any + def __init__(self, work_id: int, exception: Exception | None = ..., result: Any | None = ...) -> None: ... + +class _CallItem: + work_id: int + fn: Callable[..., Any] + args: Iterable[Any] + kwargs: Mapping[str, Any] + def __init__(self, work_id: int, fn: Callable[..., Any], args: Iterable[Any], kwargs: Mapping[str, Any]) -> None: ... + +if sys.version_info >= (3, 7): + class _SafeQueue(Queue[Future[Any]]): + pending_work_items: dict[int, _WorkItem[Any]] + shutdown_lock: Lock + thread_wakeup: _ThreadWakeup + if sys.version_info >= (3, 9): + def __init__( + self, + max_size: int | None = ..., + *, + ctx: BaseContext, + pending_work_items: dict[int, _WorkItem[Any]], + shutdown_lock: Lock, + thread_wakeup: _ThreadWakeup, + ) -> None: ... + else: + def __init__( + self, max_size: int | None = ..., *, ctx: BaseContext, pending_work_items: dict[int, _WorkItem[Any]] + ) -> None: ... + def _on_queue_feeder_error(self, e: Exception, obj: _CallItem) -> None: ... + +def _get_chunks(*iterables: Any, chunksize: int) -> Generator[Tuple[Any, ...], None, None]: ... +def _process_chunk(fn: Callable[..., Any], chunk: tuple[Any, None, None]) -> Generator[Any, None, None]: ... +def _sendback_result( + result_queue: SimpleQueue[_WorkItem[Any]], work_id: int, result: Any | None = ..., exception: Exception | None = ... +) -> None: ... + +if sys.version_info >= (3, 7): + def _process_worker( + call_queue: Queue[_CallItem], + result_queue: SimpleQueue[_ResultItem], + initializer: Callable[..., None] | None, + initargs: Tuple[Any, ...], + ) -> None: ... + +else: + def _process_worker(call_queue: Queue[_CallItem], result_queue: SimpleQueue[_ResultItem]) -> None: ... + +if sys.version_info >= (3, 9): + class _ExecutorManagerThread(Thread): + thread_wakeup: _ThreadWakeup + shutdown_lock: Lock + executor_reference: ref[Any] + processes: MutableMapping[int, Process] + call_queue: Queue[_CallItem] + result_queue: SimpleQueue[_ResultItem] + work_ids_queue: Queue[int] + pending_work_items: dict[int, _WorkItem[Any]] + def __init__(self, executor: ProcessPoolExecutor) -> None: ... + def run(self) -> None: ... + def add_call_item_to_queue(self) -> None: ... + def wait_result_broken_or_wakeup(self) -> tuple[Any, bool, str]: ... + def process_result_item(self, result_item: int | _ResultItem) -> None: ... + def is_shutting_down(self) -> bool: ... + def terminate_broken(self, cause: str) -> None: ... + def flag_executor_shutting_down(self) -> None: ... + def shutdown_workers(self) -> None: ... + def join_executor_internals(self) -> None: ... + def get_n_children_alive(self) -> int: ... + +_system_limits_checked: bool +_system_limited: bool | None + +def _check_system_limits() -> None: ... +def _chain_from_iterable_of_lists(iterable: Iterable[MutableSequence[Any]]) -> Any: ... if sys.version_info >= (3, 7): from ._base import BrokenExecutor @@ -12,17 +136,32 @@ if sys.version_info >= (3, 7): else: class BrokenProcessPool(RuntimeError): ... -if sys.version_info >= (3, 7): - from multiprocessing.context import BaseContext - class ProcessPoolExecutor(Executor): +class ProcessPoolExecutor(Executor): + _mp_context: BaseContext | None = ... + _initializer: Callable[..., None] | None = ... + _initargs: Tuple[Any, ...] = ... + _executor_manager_thread: _ThreadWakeup + _processes: MutableMapping[int, Process] + _shutdown_thread: bool + _shutdown_lock: Lock + _idle_worker_semaphore: Semaphore + _broken: bool + _queue_count: int + _pending_work_items: dict[int, _WorkItem[Any]] + _cancel_pending_futures: bool + _executor_manager_thread_wakeup: _ThreadWakeup + _result_queue: SimpleQueue[Any] + _work_ids: Queue[Any] + if sys.version_info >= (3, 7): def __init__( self, - max_workers: Optional[int] = ..., - mp_context: Optional[BaseContext] = ..., - initializer: Optional[Callable[..., None]] = ..., + max_workers: int | None = ..., + mp_context: BaseContext | None = ..., + initializer: Callable[..., None] | None = ..., initargs: Tuple[Any, ...] = ..., ) -> None: ... - -else: - class ProcessPoolExecutor(Executor): - def __init__(self, max_workers: Optional[int] = ...) -> None: ... + else: + def __init__(self, max_workers: int | None = ...) -> None: ... + if sys.version_info >= (3, 9): + def _start_executor_manager_thread(self) -> None: ... + def _adjust_process_count(self) -> None: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi index aedfe5d05bad..5ad5b65d3bec 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi @@ -1,42 +1,72 @@ import queue import sys -from typing import Any, Callable, Generic, Iterable, Mapping, Optional, Tuple, TypeVar +from collections.abc import Iterable, Mapping, Set # equivalent to typing.AbstractSet, not builtins.set +from threading import Lock, Semaphore, Thread +from typing import Any, Callable, Generic, Tuple, TypeVar +from weakref import ref from ._base import Executor, Future -if sys.version_info >= (3, 7): - from ._base import BrokenExecutor - class BrokenThreadPool(BrokenExecutor): ... +_threads_queues: Mapping[Any, Any] +_shutdown: bool +_global_shutdown_lock: Lock + +def _python_exit() -> None: ... if sys.version_info >= (3, 9): from types import GenericAlias _S = TypeVar("_S") +class _WorkItem(Generic[_S]): + future: Future[_S] + fn: Callable[..., _S] + args: Iterable[Any] + kwargs: Mapping[str, Any] + def __init__(self, future: Future[_S], fn: Callable[..., _S], args: Iterable[Any], kwargs: Mapping[str, Any]) -> None: ... + def run(self) -> None: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... + +if sys.version_info >= (3, 7): + def _worker( + executor_reference: ref[Any], + work_queue: queue.SimpleQueue[Any], + initializer: Callable[..., None], + initargs: Tuple[Any, ...], + ) -> None: ... + +else: + def _worker(executor_reference: ref[Any], work_queue: queue.Queue[Any]) -> None: ... + +if sys.version_info >= (3, 7): + from ._base import BrokenExecutor + class BrokenThreadPool(BrokenExecutor): ... + class ThreadPoolExecutor(Executor): + _max_workers: int + _idle_semaphore: Semaphore + _threads: Set[Thread] + _broken: bool + _shutdown: bool + _shutdown_lock: Lock + _thread_name_prefix: str | None = ... + _initializer: Callable[..., None] | None = ... + _initargs: Tuple[Any, ...] = ... if sys.version_info >= (3, 7): - _work_queue: queue.SimpleQueue[Any] + _work_queue: queue.SimpleQueue[_WorkItem[Any]] else: - _work_queue: queue.Queue[Any] + _work_queue: queue.Queue[_WorkItem[Any]] if sys.version_info >= (3, 7): def __init__( self, - max_workers: Optional[int] = ..., + max_workers: int | None = ..., thread_name_prefix: str = ..., - initializer: Optional[Callable[..., None]] = ..., + initializer: Callable[..., None] | None = ..., initargs: Tuple[Any, ...] = ..., ) -> None: ... - elif sys.version_info >= (3, 6): - def __init__(self, max_workers: Optional[int] = ..., thread_name_prefix: str = ...) -> None: ... else: - def __init__(self, max_workers: Optional[int] = ...) -> None: ... - -class _WorkItem(Generic[_S]): - future: Future[_S] - fn: Callable[..., _S] - args: Iterable[Any] - kwargs: Mapping[str, Any] - def __init__(self, future: Future[_S], fn: Callable[..., _S], args: Iterable[Any], kwargs: Mapping[str, Any]) -> None: ... - def run(self) -> None: ... - if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __init__(self, max_workers: int | None = ..., thread_name_prefix: str = ...) -> None: ... + def _adjust_thread_count(self) -> None: ... + if sys.version_info >= (3, 7): + def _initializer_failed(self) -> None: ... diff --git a/mypy/typeshed/stdlib/configparser.pyi b/mypy/typeshed/stdlib/configparser.pyi index f4a4e889c646..a0efa30416dd 100644 --- a/mypy/typeshed/stdlib/configparser.pyi +++ b/mypy/typeshed/stdlib/configparser.pyi @@ -1,25 +1,7 @@ import sys -from _typeshed import AnyPath, StrPath, SupportsWrite -from typing import ( - AbstractSet, - Any, - Callable, - ClassVar, - Dict, - Iterable, - Iterator, - List, - Mapping, - MutableMapping, - Optional, - Pattern, - Sequence, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from _typeshed import StrOrBytesPath, StrPath, SupportsWrite +from collections.abc import Callable, ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence +from typing import Any, ClassVar, Dict, Optional, Pattern, Type, TypeVar, overload from typing_extensions import Literal # Internal type aliases @@ -30,7 +12,7 @@ _converters = Dict[str, _converter] _T = TypeVar("_T") if sys.version_info >= (3, 7): - _Path = AnyPath + _Path = StrOrBytesPath else: _Path = StrPath @@ -50,47 +32,47 @@ class LegacyInterpolation(Interpolation): def before_get(self, parser: _parser, section: str, option: str, value: str, vars: _section) -> str: ... class RawConfigParser(_parser): - _SECT_TMPL: ClassVar[str] = ... # Undocumented - _OPT_TMPL: ClassVar[str] = ... # Undocumented - _OPT_NV_TMPL: ClassVar[str] = ... # Undocumented + _SECT_TMPL: ClassVar[str] # undocumented + _OPT_TMPL: ClassVar[str] # undocumented + _OPT_NV_TMPL: ClassVar[str] # undocumented - SECTCRE: Pattern[str] = ... - OPTCRE: ClassVar[Pattern[str]] = ... - OPTCRE_NV: ClassVar[Pattern[str]] = ... # Undocumented - NONSPACECRE: ClassVar[Pattern[str]] = ... # Undocumented + SECTCRE: Pattern[str] + OPTCRE: ClassVar[Pattern[str]] + OPTCRE_NV: ClassVar[Pattern[str]] # undocumented + NONSPACECRE: ClassVar[Pattern[str]] # undocumented - BOOLEAN_STATES: ClassVar[Mapping[str, bool]] = ... # Undocumented + BOOLEAN_STATES: ClassVar[Mapping[str, bool]] # undocumented default_section: str @overload def __init__( self, - defaults: Optional[Mapping[str, Optional[str]]] = ..., + defaults: Mapping[str, str | None] | None = ..., dict_type: Type[Mapping[str, str]] = ..., allow_no_value: Literal[True] = ..., *, delimiters: Sequence[str] = ..., comment_prefixes: Sequence[str] = ..., - inline_comment_prefixes: Optional[Sequence[str]] = ..., + inline_comment_prefixes: Sequence[str] | None = ..., strict: bool = ..., empty_lines_in_values: bool = ..., default_section: str = ..., - interpolation: Optional[Interpolation] = ..., + interpolation: Interpolation | None = ..., converters: _converters = ..., ) -> None: ... @overload def __init__( self, - defaults: Optional[_section] = ..., + defaults: _section | None = ..., dict_type: Type[Mapping[str, str]] = ..., allow_no_value: bool = ..., *, delimiters: Sequence[str] = ..., comment_prefixes: Sequence[str] = ..., - inline_comment_prefixes: Optional[Sequence[str]] = ..., + inline_comment_prefixes: Sequence[str] | None = ..., strict: bool = ..., empty_lines_in_values: bool = ..., default_section: str = ..., - interpolation: Optional[Interpolation] = ..., + interpolation: Interpolation | None = ..., converters: _converters = ..., ) -> None: ... def __len__(self) -> int: ... @@ -99,36 +81,36 @@ class RawConfigParser(_parser): def __delitem__(self, section: str) -> None: ... def __iter__(self) -> Iterator[str]: ... def defaults(self) -> _section: ... - def sections(self) -> List[str]: ... + def sections(self) -> list[str]: ... def add_section(self, section: str) -> None: ... def has_section(self, section: str) -> bool: ... - def options(self, section: str) -> List[str]: ... + def options(self, section: str) -> list[str]: ... def has_option(self, section: str, option: str) -> bool: ... - def read(self, filenames: Union[_Path, Iterable[_Path]], encoding: Optional[str] = ...) -> List[str]: ... - def read_file(self, f: Iterable[str], source: Optional[str] = ...) -> None: ... + def read(self, filenames: _Path | Iterable[_Path], encoding: str | None = ...) -> list[str]: ... + def read_file(self, f: Iterable[str], source: str | None = ...) -> None: ... def read_string(self, string: str, source: str = ...) -> None: ... def read_dict(self, dictionary: Mapping[str, Mapping[str, Any]], source: str = ...) -> None: ... - def readfp(self, fp: Iterable[str], filename: Optional[str] = ...) -> None: ... + def readfp(self, fp: Iterable[str], filename: str | None = ...) -> None: ... # These get* methods are partially applied (with the same names) in # SectionProxy; the stubs should be kept updated together @overload - def getint(self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> int: ... + def getint(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ...) -> int: ... @overload def getint( - self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ..., fallback: _T = ... - ) -> Union[int, _T]: ... + self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ..., fallback: _T = ... + ) -> int | _T: ... @overload - def getfloat(self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> float: ... + def getfloat(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ...) -> float: ... @overload def getfloat( - self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ..., fallback: _T = ... - ) -> Union[float, _T]: ... + self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ..., fallback: _T = ... + ) -> float | _T: ... @overload - def getboolean(self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> bool: ... + def getboolean(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ...) -> bool: ... @overload def getboolean( - self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ..., fallback: _T = ... - ) -> Union[bool, _T]: ... + self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ..., fallback: _T = ... + ) -> bool | _T: ... def _get_conv( self, section: str, @@ -136,21 +118,19 @@ class RawConfigParser(_parser): conv: Callable[[str], _T], *, raw: bool = ..., - vars: Optional[_section] = ..., + vars: _section | None = ..., fallback: _T = ..., ) -> _T: ... # This is incompatible with MutableMapping so we ignore the type @overload # type: ignore - def get(self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> str: ... + def get(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ...) -> str: ... @overload - def get( - self, section: str, option: str, *, raw: bool = ..., vars: Optional[_section] = ..., fallback: _T - ) -> Union[str, _T]: ... + def get(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ..., fallback: _T) -> str | _T: ... @overload - def items(self, *, raw: bool = ..., vars: Optional[_section] = ...) -> AbstractSet[Tuple[str, SectionProxy]]: ... + def items(self, *, raw: bool = ..., vars: _section | None = ...) -> ItemsView[str, SectionProxy]: ... @overload - def items(self, section: str, raw: bool = ..., vars: Optional[_section] = ...) -> List[Tuple[str, str]]: ... - def set(self, section: str, option: str, value: Optional[str] = ...) -> None: ... + def items(self, section: str, raw: bool = ..., vars: _section | None = ...) -> list[tuple[str, str]]: ... + def set(self, section: str, option: str, value: str | None = ...) -> None: ... def write(self, fp: SupportsWrite[str], space_around_delimiters: bool = ...) -> None: ... def remove_option(self, section: str, option: str) -> bool: ... def remove_section(self, section: str) -> bool: ... @@ -171,25 +151,21 @@ class SectionProxy(MutableMapping[str, str]): def parser(self) -> RawConfigParser: ... @property def name(self) -> str: ... - def get(self, option: str, fallback: Optional[str] = ..., *, raw: bool = ..., vars: Optional[_section] = ..., _impl: Optional[Any] = ..., **kwargs: Any) -> str: ... # type: ignore + def get(self, option: str, fallback: str | None = ..., *, raw: bool = ..., vars: _section | None = ..., _impl: Any | None = ..., **kwargs: Any) -> str: ... # type: ignore # These are partially-applied version of the methods with the same names in # RawConfigParser; the stubs should be kept updated together @overload - def getint(self, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> int: ... + def getint(self, option: str, *, raw: bool = ..., vars: _section | None = ...) -> int: ... @overload - def getint(self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: Optional[_section] = ...) -> Union[int, _T]: ... + def getint(self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: _section | None = ...) -> int | _T: ... @overload - def getfloat(self, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> float: ... + def getfloat(self, option: str, *, raw: bool = ..., vars: _section | None = ...) -> float: ... @overload - def getfloat( - self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: Optional[_section] = ... - ) -> Union[float, _T]: ... + def getfloat(self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: _section | None = ...) -> float | _T: ... @overload - def getboolean(self, option: str, *, raw: bool = ..., vars: Optional[_section] = ...) -> bool: ... + def getboolean(self, option: str, *, raw: bool = ..., vars: _section | None = ...) -> bool: ... @overload - def getboolean( - self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: Optional[_section] = ... - ) -> Union[bool, _T]: ... + def getboolean(self, option: str, fallback: _T = ..., *, raw: bool = ..., vars: _section | None = ...) -> bool | _T: ... # SectionProxy can have arbitrary attributes when custom converters are used def __getattr__(self, key: str) -> Callable[..., Any]: ... @@ -197,7 +173,7 @@ class ConverterMapping(MutableMapping[str, Optional[_converter]]): GETTERCRE: Pattern[Any] def __init__(self, parser: RawConfigParser) -> None: ... def __getitem__(self, key: str) -> _converter: ... - def __setitem__(self, key: str, value: Optional[_converter]) -> None: ... + def __setitem__(self, key: str, value: _converter | None) -> None: ... def __delitem__(self, key: str) -> None: ... def __iter__(self) -> Iterator[str]: ... def __len__(self) -> int: ... @@ -212,16 +188,16 @@ class NoSectionError(Error): class DuplicateSectionError(Error): section: str - source: Optional[str] - lineno: Optional[int] - def __init__(self, section: str, source: Optional[str] = ..., lineno: Optional[int] = ...) -> None: ... + source: str | None + lineno: int | None + def __init__(self, section: str, source: str | None = ..., lineno: int | None = ...) -> None: ... class DuplicateOptionError(Error): section: str option: str - source: Optional[str] - lineno: Optional[int] - def __init__(self, section: str, option: str, source: Optional[str] = ..., lineno: Optional[int] = ...) -> None: ... + source: str | None + lineno: int | None + def __init__(self, section: str, option: str, source: str | None = ..., lineno: int | None = ...) -> None: ... class NoOptionError(Error): section: str @@ -244,8 +220,8 @@ class InterpolationSyntaxError(InterpolationError): ... class ParsingError(Error): source: str - errors: List[Tuple[int, str]] - def __init__(self, source: Optional[str] = ..., filename: Optional[str] = ...) -> None: ... + errors: list[tuple[int, str]] + def __init__(self, source: str | None = ..., filename: str | None = ...) -> None: ... def append(self, lineno: int, line: str) -> None: ... class MissingSectionHeaderError(ParsingError): diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index 19ef45bed241..9d968e092ca5 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -1,115 +1,136 @@ import sys +from _typeshed import Self, StrOrBytesPath from types import TracebackType -from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Optional, Type, TypeVar, overload -from typing_extensions import Protocol - -if sys.version_info >= (3, 5): - from typing import AsyncContextManager, AsyncIterator - -if sys.version_info >= (3, 6): - AbstractContextManager = ContextManager +from typing import ( + IO, + Any, + AsyncIterator, + Awaitable, + Callable, + ContextManager, + Generic, + Iterator, + Optional, + Type, + TypeVar, + overload, +) +from typing_extensions import ParamSpec, Protocol + +AbstractContextManager = ContextManager if sys.version_info >= (3, 7): + from typing import AsyncContextManager + AbstractAsyncContextManager = AsyncContextManager _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _T_io = TypeVar("_T_io", bound=Optional[IO[str]]) _F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") _ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] -_CM_EF = TypeVar("_CM_EF", ContextManager[Any], _ExitFunc) +_CM_EF = TypeVar("_CM_EF", AbstractContextManager[Any], _ExitFunc) -if sys.version_info >= (3, 2): - class _GeneratorContextManager(ContextManager[_T_co]): - def __call__(self, func: _F) -> _F: ... - def contextmanager(func: Callable[..., Iterator[_T]]) -> Callable[..., _GeneratorContextManager[_T]]: ... +class _GeneratorContextManager(AbstractContextManager[_T_co]): + def __call__(self, func: _F) -> _F: ... -else: - class GeneratorContextManager(ContextManager[_T_co]): - def __call__(self, func: _F) -> _F: ... - def contextmanager(func: Callable[..., Iterator[_T]]) -> Callable[..., ContextManager[_T]]: ... +# type ignore to deal with incomplete ParamSpec support in mypy +def contextmanager(func: Callable[_P, Iterator[_T]]) -> Callable[_P, _GeneratorContextManager[_T]]: ... # type: ignore if sys.version_info >= (3, 7): - def asynccontextmanager(func: Callable[..., AsyncIterator[_T]]) -> Callable[..., AsyncContextManager[_T]]: ... - -if sys.version_info < (3,): - def nested(*mgr: ContextManager[Any]) -> ContextManager[Iterable[Any]]: ... + def asynccontextmanager(func: Callable[_P, AsyncIterator[_T]]) -> Callable[_P, AbstractAsyncContextManager[_T]]: ... # type: ignore class _SupportsClose(Protocol): - def close(self) -> None: ... + def close(self) -> object: ... _SupportsCloseT = TypeVar("_SupportsCloseT", bound=_SupportsClose) -class closing(ContextManager[_SupportsCloseT]): +class closing(AbstractContextManager[_SupportsCloseT]): def __init__(self, thing: _SupportsCloseT) -> None: ... if sys.version_info >= (3, 10): class _SupportsAclose(Protocol): - async def aclose(self) -> None: ... + def aclose(self) -> Awaitable[object]: ... _SupportsAcloseT = TypeVar("_SupportsAcloseT", bound=_SupportsAclose) - class aclosing(AsyncContextManager[_SupportsAcloseT]): + class aclosing(AbstractAsyncContextManager[_SupportsAcloseT]): def __init__(self, thing: _SupportsAcloseT) -> None: ... - -if sys.version_info >= (3, 4): - class suppress(ContextManager[None]): - def __init__(self, *exceptions: Type[BaseException]) -> None: ... - def __exit__( - self, exctype: Optional[Type[BaseException]], excinst: Optional[BaseException], exctb: Optional[TracebackType] - ) -> bool: ... - class redirect_stdout(ContextManager[_T_io]): - def __init__(self, new_target: _T_io) -> None: ... - -if sys.version_info >= (3, 5): - class redirect_stderr(ContextManager[_T_io]): - def __init__(self, new_target: _T_io) -> None: ... - -if sys.version_info >= (3,): - class ContextDecorator: - def __call__(self, func: _F) -> _F: ... - _U = TypeVar("_U", bound=ExitStack) - class ExitStack(ContextManager[ExitStack]): - def __init__(self) -> None: ... - def enter_context(self, cm: ContextManager[_T]) -> _T: ... - def push(self, exit: _CM_EF) -> _CM_EF: ... - def callback(self, callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... - def pop_all(self: _U) -> _U: ... - def close(self) -> None: ... - def __enter__(self: _U) -> _U: ... - def __exit__( - self, - __exc_type: Optional[Type[BaseException]], - __exc_value: Optional[BaseException], - __traceback: Optional[TracebackType], - ) -> bool: ... + _AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]]) + class AsyncContextDecorator: + def __call__(self, func: _AF) -> _AF: ... + +class suppress(AbstractContextManager[None]): + def __init__(self, *exceptions: Type[BaseException]) -> None: ... + def __exit__( + self, exctype: Type[BaseException] | None, excinst: BaseException | None, exctb: TracebackType | None + ) -> bool: ... + +class redirect_stdout(AbstractContextManager[_T_io]): + def __init__(self, new_target: _T_io) -> None: ... + +class redirect_stderr(AbstractContextManager[_T_io]): + def __init__(self, new_target: _T_io) -> None: ... + +class ContextDecorator: + def __call__(self, func: _F) -> _F: ... + +class ExitStack(AbstractContextManager[ExitStack]): + def __init__(self) -> None: ... + def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... + def push(self, exit: _CM_EF) -> _CM_EF: ... + def callback(self, __callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... + def pop_all(self: Self) -> Self: ... + def close(self) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> bool: ... if sys.version_info >= (3, 7): - from typing import Awaitable - - _S = TypeVar("_S", bound=AsyncExitStack) - _ExitCoroFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], Awaitable[bool]] _CallbackCoroFunc = Callable[..., Awaitable[Any]] - _ACM_EF = TypeVar("_ACM_EF", AsyncContextManager[Any], _ExitCoroFunc) - class AsyncExitStack(AsyncContextManager[AsyncExitStack]): + _ACM_EF = TypeVar("_ACM_EF", AbstractAsyncContextManager[Any], _ExitCoroFunc) + class AsyncExitStack(AbstractAsyncContextManager[AsyncExitStack]): def __init__(self) -> None: ... - def enter_context(self, cm: ContextManager[_T]) -> _T: ... - def enter_async_context(self, cm: AsyncContextManager[_T]) -> Awaitable[_T]: ... + def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... + def enter_async_context(self, cm: AbstractAsyncContextManager[_T]) -> Awaitable[_T]: ... def push(self, exit: _CM_EF) -> _CM_EF: ... def push_async_exit(self, exit: _ACM_EF) -> _ACM_EF: ... - def callback(self, callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... - def push_async_callback(self, callback: _CallbackCoroFunc, *args: Any, **kwds: Any) -> _CallbackCoroFunc: ... - def pop_all(self: _S) -> _S: ... + def callback(self, __callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... + def push_async_callback(self, __callback: _CallbackCoroFunc, *args: Any, **kwds: Any) -> _CallbackCoroFunc: ... + def pop_all(self: Self) -> Self: ... def aclose(self) -> Awaitable[None]: ... - def __aenter__(self: _S) -> Awaitable[_S]: ... + def __aenter__(self: Self) -> Awaitable[Self]: ... def __aexit__( - self, - __exc_type: Optional[Type[BaseException]], - __exc_value: Optional[BaseException], - __traceback: Optional[TracebackType], + self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None ) -> Awaitable[bool]: ... -if sys.version_info >= (3, 7): - @overload - def nullcontext(enter_result: _T) -> ContextManager[_T]: ... - @overload - def nullcontext() -> ContextManager[None]: ... +if sys.version_info >= (3, 10): + class nullcontext(AbstractContextManager[_T], AbstractAsyncContextManager[_T]): + enter_result: _T + @overload + def __init__(self: nullcontext[None], enter_result: None = ...) -> None: ... + @overload + def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... + def __enter__(self) -> _T: ... + def __exit__(self, *exctype: Any) -> None: ... + async def __aenter__(self) -> _T: ... + async def __aexit__(self, *exctype: Any) -> None: ... + +elif sys.version_info >= (3, 7): + class nullcontext(AbstractContextManager[_T]): + enter_result: _T + @overload + def __init__(self: nullcontext[None], enter_result: None = ...) -> None: ... + @overload + def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... + def __enter__(self) -> _T: ... + def __exit__(self, *exctype: Any) -> None: ... + +if sys.version_info >= (3, 11): + _T_fd_or_any_path = TypeVar("_T_fd_or_any_path", bound=int | StrOrBytesPath) + class chdir(AbstractContextManager[None], Generic[_T_fd_or_any_path]): + path: _T_fd_or_any_path + def __init__(self, path: _T_fd_or_any_path) -> None: ... + def __enter__(self) -> None: ... + def __exit__(self, *excinfo: object) -> None: ... diff --git a/mypy/typeshed/stdlib/contextvars.pyi b/mypy/typeshed/stdlib/contextvars.pyi index 069a6786688e..e97f62188dcb 100644 --- a/mypy/typeshed/stdlib/contextvars.pyi +++ b/mypy/typeshed/stdlib/contextvars.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Callable, ClassVar, Generic, Iterator, Mapping, Optional, TypeVar, Union, overload +from typing import Any, Callable, ClassVar, Generic, Iterator, Mapping, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -14,7 +14,7 @@ class ContextVar(Generic[_T]): @overload def get(self) -> _T: ... @overload - def get(self, default: Union[_D, _T]) -> Union[_D, _T]: ... + def get(self, default: _D | _T) -> _D | _T: ... def set(self, value: _T) -> Token[_T]: ... def reset(self, token: Token[_T]) -> None: ... if sys.version_info >= (3, 9): @@ -36,9 +36,9 @@ def copy_context() -> Context: ... class Context(Mapping[ContextVar[Any], Any]): def __init__(self) -> None: ... @overload - def get(self, __key: ContextVar[Any]) -> Optional[Any]: ... + def get(self, __key: ContextVar[Any]) -> Any | None: ... @overload - def get(self, __key: ContextVar[Any], __default: Optional[Any]) -> Any: ... + def get(self, __key: ContextVar[Any], __default: Any | None) -> Any: ... def run(self, callable: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ... def copy(self) -> Context: ... def __getitem__(self, key: ContextVar[Any]) -> Any: ... diff --git a/mypy/typeshed/stdlib/copy.pyi b/mypy/typeshed/stdlib/copy.pyi index b51c79c66c6a..a5f9420e3811 100644 --- a/mypy/typeshed/stdlib/copy.pyi +++ b/mypy/typeshed/stdlib/copy.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, TypeVar +from typing import Any, TypeVar _T = TypeVar("_T") @@ -6,7 +6,7 @@ _T = TypeVar("_T") PyStringMap: Any # Note: memo and _nil are internal kwargs. -def deepcopy(x: _T, memo: Optional[Dict[int, Any]] = ..., _nil: Any = ...) -> _T: ... +def deepcopy(x: _T, memo: dict[int, Any] | None = ..., _nil: Any = ...) -> _T: ... def copy(x: _T) -> _T: ... class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/copyreg.pyi b/mypy/typeshed/stdlib/copyreg.pyi index ea07ba410b6d..320097b3a204 100644 --- a/mypy/typeshed/stdlib/copyreg.pyi +++ b/mypy/typeshed/stdlib/copyreg.pyi @@ -1,16 +1,18 @@ -from typing import Any, Callable, Hashable, List, Optional, SupportsInt, Tuple, TypeVar, Union +from typing import Any, Callable, Hashable, Optional, SupportsInt, Tuple, TypeVar, Union _TypeT = TypeVar("_TypeT", bound=type) _Reduce = Union[Tuple[Callable[..., _TypeT], Tuple[Any, ...]], Tuple[Callable[..., _TypeT], Tuple[Any, ...], Optional[Any]]] -__all__: List[str] +__all__: list[str] def pickle( ob_type: _TypeT, - pickle_function: Callable[[_TypeT], Union[str, _Reduce[_TypeT]]], - constructor_ob: Optional[Callable[[_Reduce[_TypeT]], _TypeT]] = ..., + pickle_function: Callable[[_TypeT], str | _Reduce[_TypeT]], + constructor_ob: Callable[[_Reduce[_TypeT]], _TypeT] | None = ..., ) -> None: ... def constructor(object: Callable[[_Reduce[_TypeT]], _TypeT]) -> None: ... def add_extension(module: Hashable, name: Hashable, code: SupportsInt) -> None: ... def remove_extension(module: Hashable, name: Hashable, code: int) -> None: ... def clear_extension_cache() -> None: ... + +dispatch_table: dict[type, Callable[[type], str | _Reduce[type]]] # undocumented diff --git a/mypy/typeshed/stdlib/crypt.pyi b/mypy/typeshed/stdlib/crypt.pyi index 18893721a11f..27e30433f702 100644 --- a/mypy/typeshed/stdlib/crypt.pyi +++ b/mypy/typeshed/stdlib/crypt.pyi @@ -1,22 +1,20 @@ import sys -from typing import List, Optional, Union -if sys.version_info >= (3, 3): - class _Method: ... - METHOD_CRYPT: _Method - METHOD_MD5: _Method - METHOD_SHA256: _Method - METHOD_SHA512: _Method - if sys.version_info >= (3, 7): - METHOD_BLOWFISH: _Method +class _Method: ... - methods: List[_Method] +METHOD_CRYPT: _Method +METHOD_MD5: _Method +METHOD_SHA256: _Method +METHOD_SHA512: _Method +if sys.version_info >= (3, 7): + METHOD_BLOWFISH: _Method - if sys.version_info >= (3, 7): - def mksalt(method: Optional[_Method] = ..., *, rounds: Optional[int] = ...) -> str: ... - else: - def mksalt(method: Optional[_Method] = ...) -> str: ... - def crypt(word: str, salt: Optional[Union[str, _Method]] = ...) -> str: ... +methods: list[_Method] + +if sys.version_info >= (3, 7): + def mksalt(method: _Method | None = ..., *, rounds: int | None = ...) -> str: ... else: - def crypt(word: str, salt: str) -> str: ... + def mksalt(method: _Method | None = ...) -> str: ... + +def crypt(word: str, salt: str | _Method | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/csv.pyi b/mypy/typeshed/stdlib/csv.pyi index db48e9e6c78a..0b69cb2272d3 100644 --- a/mypy/typeshed/stdlib/csv.pyi +++ b/mypy/typeshed/stdlib/csv.pyi @@ -17,9 +17,10 @@ from _csv import ( unregister_dialect as unregister_dialect, writer as writer, ) -from typing import Any, Generic, Iterable, Iterator, List, Mapping, Optional, Sequence, Text, Type, TypeVar, overload +from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence +from typing import Any, Generic, Type, TypeVar, overload -if sys.version_info >= (3, 8) or sys.version_info < (3, 6): +if sys.version_info >= (3, 8): from typing import Dict as _DictReadMapping else: from collections import OrderedDict as _DictReadMapping @@ -37,29 +38,28 @@ class excel(Dialect): class excel_tab(excel): delimiter: str -if sys.version_info >= (3,): - class unix_dialect(Dialect): - delimiter: str - quotechar: str - doublequote: bool - skipinitialspace: bool - lineterminator: str - quoting: int +class unix_dialect(Dialect): + delimiter: str + quotechar: str + doublequote: bool + skipinitialspace: bool + lineterminator: str + quoting: int class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): - fieldnames: Optional[Sequence[_T]] - restkey: Optional[str] - restval: Optional[str] + fieldnames: Sequence[_T] | None + restkey: str | None + restval: str | None reader: _reader dialect: _DialectLike line_num: int @overload def __init__( self, - f: Iterable[Text], + f: Iterable[str], fieldnames: Sequence[_T], - restkey: Optional[str] = ..., - restval: Optional[str] = ..., + restkey: str | None = ..., + restval: str | None = ..., dialect: _DialectLike = ..., *args: Any, **kwds: Any, @@ -67,30 +67,27 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): @overload def __init__( self: DictReader[str], - f: Iterable[Text], - fieldnames: Optional[Sequence[str]] = ..., - restkey: Optional[str] = ..., - restval: Optional[str] = ..., + f: Iterable[str], + fieldnames: Sequence[str] | None = ..., + restkey: str | None = ..., + restval: str | None = ..., dialect: _DialectLike = ..., *args: Any, **kwds: Any, ) -> None: ... def __iter__(self) -> DictReader[_T]: ... - if sys.version_info >= (3,): - def __next__(self) -> _DictReadMapping[_T, str]: ... - else: - def next(self) -> _DictReadMapping[_T, str]: ... + def __next__(self) -> _DictReadMapping[_T, str]: ... class DictWriter(Generic[_T]): - fieldnames: Sequence[_T] - restval: Optional[Any] + fieldnames: Collection[_T] + restval: Any | None extrasaction: str writer: _writer def __init__( self, f: Any, - fieldnames: Sequence[_T], - restval: Optional[Any] = ..., + fieldnames: Collection[_T], + restval: Any | None = ..., extrasaction: str = ..., dialect: _DialectLike = ..., *args: Any, @@ -104,7 +101,7 @@ class DictWriter(Generic[_T]): def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... class Sniffer(object): - preferred: List[str] + preferred: list[str] def __init__(self) -> None: ... - def sniff(self, sample: str, delimiters: Optional[str] = ...) -> Type[Dialect]: ... + def sniff(self, sample: str, delimiters: str | None = ...) -> Type[Dialect]: ... def has_header(self, sample: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/ctypes/__init__.pyi b/mypy/typeshed/stdlib/ctypes/__init__.pyi index 299672ad0629..bbe083f5d4c4 100644 --- a/mypy/typeshed/stdlib/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/ctypes/__init__.pyi @@ -1,5 +1,5 @@ import sys -from array import array +from _typeshed import ReadableBuffer, WriteableBuffer from typing import ( Any, Callable, @@ -7,11 +7,9 @@ from typing import ( Generic, Iterable, Iterator, - List, Mapping, Optional, Sequence, - Text, Tuple, Type, TypeVar, @@ -26,34 +24,29 @@ _T = TypeVar("_T") _DLLT = TypeVar("_DLLT", bound=CDLL) _CT = TypeVar("_CT", bound=_CData) -RTLD_GLOBAL: int = ... -RTLD_LOCAL: int = ... -DEFAULT_MODE: int = ... +RTLD_GLOBAL: int +RTLD_LOCAL: int +DEFAULT_MODE: int class CDLL(object): - _func_flags_: ClassVar[int] = ... - _func_restype_: ClassVar[_CData] = ... - _name: str = ... - _handle: int = ... - _FuncPtr: Type[_FuncPointer] = ... + _func_flags_: ClassVar[int] + _func_restype_: ClassVar[_CData] + _name: str + _handle: int + _FuncPtr: Type[_FuncPointer] if sys.version_info >= (3, 8): def __init__( self, - name: Optional[str], + name: str | None, mode: int = ..., - handle: Optional[int] = ..., + handle: int | None = ..., use_errno: bool = ..., use_last_error: bool = ..., - winmode: Optional[int] = ..., + winmode: int | None = ..., ) -> None: ... else: def __init__( - self, - name: Optional[str], - mode: int = ..., - handle: Optional[int] = ..., - use_errno: bool = ..., - use_last_error: bool = ..., + self, name: str | None, mode: int = ..., handle: int | None = ..., use_errno: bool = ..., use_last_error: bool = ... ) -> None: ... def __getattr__(self, name: str) -> _NamedFuncPointer: ... def __getitem__(self, name: str) -> _NamedFuncPointer: ... @@ -72,19 +65,12 @@ class LibraryLoader(Generic[_DLLT]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -cdll: LibraryLoader[CDLL] = ... +cdll: LibraryLoader[CDLL] if sys.platform == "win32": - windll: LibraryLoader[WinDLL] = ... - oledll: LibraryLoader[OleDLL] = ... -pydll: LibraryLoader[PyDLL] = ... -pythonapi: PyDLL = ... - -# Anything that implements the read-write buffer interface. -# The buffer interface is defined purely on the C level, so we cannot define a normal Protocol -# for it. Instead we have to list the most common stdlib buffer classes in a Union. -_WritableBuffer = _UnionT[bytearray, memoryview, array[Any], _CData] -# Same as _WritableBuffer, but also includes read-only buffer types (like bytes). -_ReadOnlyBuffer = _UnionT[_WritableBuffer, bytes] + windll: LibraryLoader[WinDLL] + oledll: LibraryLoader[OleDLL] +pydll: LibraryLoader[PyDLL] +pythonapi: PyDLL class _CDataMeta(type): # By default mypy complains about the following two methods, because strictly speaking cls @@ -94,17 +80,17 @@ class _CDataMeta(type): def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore class _CData(metaclass=_CDataMeta): - _b_base: int = ... - _b_needsfree_: bool = ... - _objects: Optional[Mapping[Any, int]] = ... + _b_base: int + _b_needsfree_: bool + _objects: Mapping[Any, int] | None @classmethod - def from_buffer(cls: Type[_CT], source: _WritableBuffer, offset: int = ...) -> _CT: ... + def from_buffer(cls: Type[_CT], source: WriteableBuffer, offset: int = ...) -> _CT: ... @classmethod - def from_buffer_copy(cls: Type[_CT], source: _ReadOnlyBuffer, offset: int = ...) -> _CT: ... + def from_buffer_copy(cls: Type[_CT], source: ReadableBuffer, offset: int = ...) -> _CT: ... @classmethod def from_address(cls: Type[_CT], address: int) -> _CT: ... @classmethod - def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _CArgObject]: ... + def from_param(cls: Type[_CT], obj: Any) -> _CT | _CArgObject: ... @classmethod def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... @@ -115,15 +101,15 @@ _ECT = Callable[[Optional[Type[_CData]], _FuncPointer, Tuple[_CData, ...]], _CDa _PF = _UnionT[Tuple[int], Tuple[int, str], Tuple[int, str, Any]] class _FuncPointer(_PointerLike, _CData): - restype: _UnionT[Type[_CData], Callable[[int], Any], None] = ... - argtypes: Sequence[Type[_CData]] = ... - errcheck: _ECT = ... + restype: Type[_CData] | Callable[[int], Any] | None + argtypes: Sequence[Type[_CData]] + errcheck: _ECT @overload def __init__(self, address: int) -> None: ... @overload def __init__(self, callable: Callable[..., Any]) -> None: ... @overload - def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... + def __init__(self, func_spec: tuple[str | int, CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... @overload def __init__(self, vtlb_index: int, name: str, paramflags: Tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... @@ -134,15 +120,15 @@ class _NamedFuncPointer(_FuncPointer): class ArgumentError(Exception): ... def CFUNCTYPE( - restype: Optional[Type[_CData]], *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... + restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... ) -> Type[_FuncPointer]: ... if sys.platform == "win32": def WINFUNCTYPE( - restype: Optional[Type[_CData]], *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... + restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... ) -> Type[_FuncPointer]: ... -def PYFUNCTYPE(restype: Optional[Type[_CData]], *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... +def PYFUNCTYPE(restype: Type[_CData] | None, *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... class _CArgObject: ... @@ -156,17 +142,17 @@ _CVoidPLike = _UnionT[_PointerLike, Array[Any], _CArgObject, int] _CVoidConstPLike = _UnionT[_CVoidPLike, bytes] def addressof(obj: _CData) -> int: ... -def alignment(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def alignment(obj_or_type: _CData | Type[_CData]) -> int: ... def byref(obj: _CData, offset: int = ...) -> _CArgObject: ... _CastT = TypeVar("_CastT", bound=_CanCastTo) -def cast(obj: _UnionT[_CData, _CArgObject, int], typ: Type[_CastT]) -> _CastT: ... -def create_string_buffer(init: _UnionT[int, bytes], size: Optional[int] = ...) -> Array[c_char]: ... +def cast(obj: _CData | _CArgObject | int, typ: Type[_CastT]) -> _CastT: ... +def create_string_buffer(init: int | bytes, size: int | None = ...) -> Array[c_char]: ... c_buffer = create_string_buffer -def create_unicode_buffer(init: _UnionT[int, Text], size: Optional[int] = ...) -> Array[c_wchar]: ... +def create_unicode_buffer(init: int | str, size: int | None = ...) -> Array[c_wchar]: ... if sys.platform == "win32": def DllCanUnloadNow() -> int: ... @@ -187,47 +173,43 @@ def POINTER(type: Type[_CT]) -> Type[pointer[_CT]]: ... # ctypes._Pointer in that it is the base class for all pointer types. Unlike the real _Pointer, # it can be instantiated directly (to mimic the behavior of the real pointer function). class pointer(Generic[_CT], _PointerLike, _CData): - _type_: ClassVar[Type[_CT]] = ... - contents: _CT = ... + _type_: Type[_CT] + contents: _CT def __init__(self, arg: _CT = ...) -> None: ... @overload def __getitem__(self, i: int) -> _CT: ... @overload - def __getitem__(self, s: slice) -> List[_CT]: ... + def __getitem__(self, s: slice) -> list[_CT]: ... @overload def __setitem__(self, i: int, o: _CT) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_CT]) -> None: ... def resize(obj: _CData, size: int) -> None: ... - -if sys.version_info < (3,): - def set_conversion_mode(encoding: str, errors: str) -> Tuple[str, str]: ... - def set_errno(value: int) -> int: ... if sys.platform == "win32": def set_last_error(value: int) -> int: ... -def sizeof(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def sizeof(obj_or_type: _CData | Type[_CData]) -> int: ... def string_at(address: _CVoidConstPLike, size: int = ...) -> bytes: ... if sys.platform == "win32": - def WinError(code: Optional[int] = ..., descr: Optional[str] = ...) -> OSError: ... + def WinError(code: int | None = ..., descr: str | None = ...) -> OSError: ... def wstring_at(address: _CVoidConstPLike, size: int = ...) -> str: ... class _SimpleCData(Generic[_T], _CData): - value: _T = ... + value: _T def __init__(self, value: _T = ...) -> None: ... class c_byte(_SimpleCData[int]): ... class c_char(_SimpleCData[bytes]): - def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ... + def __init__(self, value: int | bytes = ...) -> None: ... class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): - def __init__(self, value: Optional[_UnionT[int, bytes]] = ...) -> None: ... + def __init__(self, value: int | bytes | None = ...) -> None: ... class c_double(_SimpleCData[float]): ... class c_longdouble(_SimpleCData[float]): ... @@ -252,10 +234,10 @@ class c_ulong(_SimpleCData[int]): ... class c_ulonglong(_SimpleCData[int]): ... class c_ushort(_SimpleCData[int]): ... class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... -class c_wchar(_SimpleCData[Text]): ... +class c_wchar(_SimpleCData[str]): ... -class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]): - def __init__(self, value: Optional[_UnionT[int, Text]] = ...) -> None: ... +class c_wchar_p(_PointerLike, _SimpleCData[Optional[str]]): + def __init__(self, value: int | str | None = ...) -> None: ... class c_bool(_SimpleCData[bool]): def __init__(self, value: bool = ...) -> None: ... @@ -266,13 +248,13 @@ if sys.platform == "win32": class py_object(_CanCastTo, _SimpleCData[_T]): ... class _CField: - offset: int = ... - size: int = ... + offset: int + size: int class _StructUnionMeta(_CDataMeta): - _fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... - _pack_: int = ... - _anonymous_: Sequence[str] = ... + _fields_: Sequence[tuple[str, Type[_CData]] | tuple[str, Type[_CData], int]] + _pack_: int + _anonymous_: Sequence[str] def __getattr__(self, name: str) -> _CField: ... class _StructUnionBase(_CData, metaclass=_StructUnionMeta): @@ -286,10 +268,10 @@ class BigEndianStructure(Structure): ... class LittleEndianStructure(Structure): ... class Array(Generic[_CT], _CData): - _length_: ClassVar[int] = ... - _type_: ClassVar[Type[_CT]] = ... - raw: bytes = ... # Note: only available if _CT == c_char - value: Any = ... # Note: bytes if _CT == c_char, Text if _CT == c_wchar, unavailable otherwise + _length_: int + _type_: Type[_CT] + raw: bytes # Note: only available if _CT == c_char + value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise # TODO These methods cannot be annotated correctly at the moment. # All of these "Any"s stand for the array's element type, but it's not possible to use _CT # here, because of a special feature of ctypes. @@ -306,7 +288,7 @@ class Array(Generic[_CT], _CData): @overload def __getitem__(self, i: int) -> Any: ... @overload - def __getitem__(self, s: slice) -> List[Any]: ... + def __getitem__(self, s: slice) -> list[Any]: ... @overload def __setitem__(self, i: int, o: Any) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/ctypes/util.pyi b/mypy/typeshed/stdlib/ctypes/util.pyi index 20914c70a05c..c0274f5e539b 100644 --- a/mypy/typeshed/stdlib/ctypes/util.pyi +++ b/mypy/typeshed/stdlib/ctypes/util.pyi @@ -1,7 +1,6 @@ import sys -from typing import Optional -def find_library(name: str) -> Optional[str]: ... +def find_library(name: str) -> str | None: ... if sys.platform == "win32": - def find_msvcrt() -> Optional[str]: ... + def find_msvcrt() -> str | None: ... diff --git a/mypy/typeshed/stdlib/curses/ascii.pyi b/mypy/typeshed/stdlib/curses/ascii.pyi index 10bab853adcf..66efbe36a7df 100644 --- a/mypy/typeshed/stdlib/curses/ascii.pyi +++ b/mypy/typeshed/stdlib/curses/ascii.pyi @@ -1,4 +1,4 @@ -from typing import List, TypeVar, Union +from typing import TypeVar _CharT = TypeVar("_CharT", str, int) @@ -39,24 +39,24 @@ US: int SP: int DEL: int -controlnames: List[int] +controlnames: list[int] -def isalnum(c: Union[str, int]) -> bool: ... -def isalpha(c: Union[str, int]) -> bool: ... -def isascii(c: Union[str, int]) -> bool: ... -def isblank(c: Union[str, int]) -> bool: ... -def iscntrl(c: Union[str, int]) -> bool: ... -def isdigit(c: Union[str, int]) -> bool: ... -def isgraph(c: Union[str, int]) -> bool: ... -def islower(c: Union[str, int]) -> bool: ... -def isprint(c: Union[str, int]) -> bool: ... -def ispunct(c: Union[str, int]) -> bool: ... -def isspace(c: Union[str, int]) -> bool: ... -def isupper(c: Union[str, int]) -> bool: ... -def isxdigit(c: Union[str, int]) -> bool: ... -def isctrl(c: Union[str, int]) -> bool: ... -def ismeta(c: Union[str, int]) -> bool: ... +def isalnum(c: str | int) -> bool: ... +def isalpha(c: str | int) -> bool: ... +def isascii(c: str | int) -> bool: ... +def isblank(c: str | int) -> bool: ... +def iscntrl(c: str | int) -> bool: ... +def isdigit(c: str | int) -> bool: ... +def isgraph(c: str | int) -> bool: ... +def islower(c: str | int) -> bool: ... +def isprint(c: str | int) -> bool: ... +def ispunct(c: str | int) -> bool: ... +def isspace(c: str | int) -> bool: ... +def isupper(c: str | int) -> bool: ... +def isxdigit(c: str | int) -> bool: ... +def isctrl(c: str | int) -> bool: ... +def ismeta(c: str | int) -> bool: ... def ascii(c: _CharT) -> _CharT: ... def ctrl(c: _CharT) -> _CharT: ... def alt(c: _CharT) -> _CharT: ... -def unctrl(c: Union[str, int]) -> str: ... +def unctrl(c: str | int) -> str: ... diff --git a/mypy/typeshed/stdlib/curses/textpad.pyi b/mypy/typeshed/stdlib/curses/textpad.pyi index d2b5766fda26..578a579fda38 100644 --- a/mypy/typeshed/stdlib/curses/textpad.pyi +++ b/mypy/typeshed/stdlib/curses/textpad.pyi @@ -1,11 +1,11 @@ from _curses import _CursesWindow -from typing import Callable, Optional, Union +from typing import Callable def rectangle(win: _CursesWindow, uly: int, ulx: int, lry: int, lrx: int) -> None: ... class Textbox: stripspaces: bool def __init__(self, win: _CursesWindow, insert_mode: bool = ...) -> None: ... - def edit(self, validate: Optional[Callable[[int], int]] = ...) -> str: ... - def do_command(self, ch: Union[str, int]) -> None: ... + def edit(self, validate: Callable[[int], int] | None = ...) -> str: ... + def do_command(self, ch: str | int) -> None: ... def gather(self) -> str: ... diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index 1e619516f1cc..59efbe77aed6 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -1,26 +1,31 @@ import sys -from typing import Any, Callable, Dict, Generic, Iterable, List, Mapping, Optional, Tuple, Type, TypeVar, Union, overload +import types +from typing import Any, Callable, Generic, Iterable, Mapping, Tuple, Type, TypeVar, overload +from typing_extensions import Protocol if sys.version_info >= (3, 9): from types import GenericAlias _T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) class _MISSING_TYPE: ... MISSING: _MISSING_TYPE +if sys.version_info >= (3, 10): + class KW_ONLY: ... + @overload -def asdict(obj: Any) -> Dict[str, Any]: ... +def asdict(obj: Any) -> dict[str, Any]: ... @overload -def asdict(obj: Any, *, dict_factory: Callable[[List[Tuple[str, Any]]], _T]) -> _T: ... +def asdict(obj: Any, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T: ... @overload def astuple(obj: Any) -> Tuple[Any, ...]: ... @overload -def astuple(obj: Any, *, tuple_factory: Callable[[List[Any]], _T]) -> _T: ... +def astuple(obj: Any, *, tuple_factory: Callable[[list[Any]], _T]) -> _T: ... if sys.version_info >= (3, 10): - # Added match_args @overload def dataclass(__cls: Type[_T]) -> Type[_T]: ... @overload @@ -35,6 +40,8 @@ if sys.version_info >= (3, 10): unsafe_hash: bool = ..., frozen: bool = ..., match_args: bool = ..., + kw_only: bool = ..., + slots: bool = ..., ) -> Callable[[Type[_T]], Type[_T]]: ... elif sys.version_info >= (3, 8): @@ -58,60 +65,114 @@ else: *, init: bool = ..., repr: bool = ..., eq: bool = ..., order: bool = ..., unsafe_hash: bool = ..., frozen: bool = ... ) -> Callable[[Type[_T]], Type[_T]]: ... +# See https://github.com/python/mypy/issues/10750 +class _DefaultFactory(Protocol[_T_co]): + def __call__(self) -> _T_co: ... + class Field(Generic[_T]): name: str type: Type[_T] default: _T - default_factory: Callable[[], _T] + default_factory: _DefaultFactory[_T] repr: bool - hash: Optional[bool] + hash: bool | None init: bool compare: bool - metadata: Mapping[str, Any] - def __init__( - self, - default: _T, - default_factory: Callable[[], _T], - init: bool, - repr: bool, - hash: Optional[bool], - compare: bool, - metadata: Mapping[str, Any], - ) -> None: ... + metadata: types.MappingProxyType[Any, Any] + if sys.version_info >= (3, 10): + kw_only: bool + def __init__( + self, + default: _T, + default_factory: Callable[[], _T], + init: bool, + repr: bool, + hash: bool | None, + compare: bool, + metadata: Mapping[Any, Any], + kw_only: bool, + ) -> None: ... + else: + def __init__( + self, + default: _T, + default_factory: Callable[[], _T], + init: bool, + repr: bool, + hash: bool | None, + compare: bool, + metadata: Mapping[Any, Any], + ) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... # NOTE: Actual return type is 'Field[_T]', but we want to help type checkers # to understand the magic that happens at runtime. -@overload # `default` and `default_factory` are optional and mutually exclusive. -def field( - *, - default: _T, - init: bool = ..., - repr: bool = ..., - hash: Optional[bool] = ..., - compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ..., -) -> _T: ... -@overload -def field( - *, - default_factory: Callable[[], _T], - init: bool = ..., - repr: bool = ..., - hash: Optional[bool] = ..., - compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ..., -) -> _T: ... -@overload -def field( - *, - init: bool = ..., - repr: bool = ..., - hash: Optional[bool] = ..., - compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ..., -) -> Any: ... +if sys.version_info >= (3, 10): + @overload # `default` and `default_factory` are optional and mutually exclusive. + def field( + *, + default: _T, + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + kw_only: bool = ..., + ) -> _T: ... + @overload + def field( + *, + default_factory: Callable[[], _T], + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + kw_only: bool = ..., + ) -> _T: ... + @overload + def field( + *, + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + kw_only: bool = ..., + ) -> Any: ... + +else: + @overload # `default` and `default_factory` are optional and mutually exclusive. + def field( + *, + default: _T, + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + ) -> _T: ... + @overload + def field( + *, + default_factory: Callable[[], _T], + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + ) -> _T: ... + @overload + def field( + *, + init: bool = ..., + repr: bool = ..., + hash: bool | None = ..., + compare: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + ) -> Any: ... + def fields(class_or_instance: Any) -> Tuple[Field[Any], ...]: ... def is_dataclass(obj: Any) -> bool: ... @@ -126,17 +187,36 @@ class InitVar(Generic[_T]): @overload def __class_getitem__(cls, type: Any) -> InitVar[Any]: ... -def make_dataclass( - cls_name: str, - fields: Iterable[Union[str, Tuple[str, type], Tuple[str, type, Field[Any]]]], - *, - bases: Tuple[type, ...] = ..., - namespace: Optional[Dict[str, Any]] = ..., - init: bool = ..., - repr: bool = ..., - eq: bool = ..., - order: bool = ..., - unsafe_hash: bool = ..., - frozen: bool = ..., -) -> type: ... +if sys.version_info >= (3, 10): + def make_dataclass( + cls_name: str, + fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], + *, + bases: Tuple[type, ...] = ..., + namespace: dict[str, Any] | None = ..., + init: bool = ..., + repr: bool = ..., + eq: bool = ..., + order: bool = ..., + unsafe_hash: bool = ..., + frozen: bool = ..., + match_args: bool = ..., + slots: bool = ..., + ) -> type: ... + +else: + def make_dataclass( + cls_name: str, + fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], + *, + bases: Tuple[type, ...] = ..., + namespace: dict[str, Any] | None = ..., + init: bool = ..., + repr: bool = ..., + eq: bool = ..., + order: bool = ..., + unsafe_hash: bool = ..., + frozen: bool = ..., + ) -> type: ... + def replace(__obj: _T, **changes: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index 4692f590b5b3..bd4d47e051ec 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -1,30 +1,30 @@ import sys from time import struct_time -from typing import AnyStr, ClassVar, NamedTuple, Optional, SupportsAbs, Tuple, Type, TypeVar, Union, overload +from typing import ClassVar, NamedTuple, NoReturn, SupportsAbs, Type, TypeVar, overload +from typing_extensions import final _S = TypeVar("_S") - -if sys.version_info >= (3,): - _Text = str -else: - _Text = Union[str, unicode] +_D = TypeVar("_D", bound=date) MINYEAR: int MAXYEAR: int class tzinfo: - def tzname(self, dt: Optional[datetime]) -> Optional[str]: ... - def utcoffset(self, dt: Optional[datetime]) -> Optional[timedelta]: ... - def dst(self, dt: Optional[datetime]) -> Optional[timedelta]: ... - def fromutc(self, dt: datetime) -> datetime: ... + def tzname(self, __dt: datetime | None) -> str | None: ... + def utcoffset(self, __dt: datetime | None) -> timedelta | None: ... + def dst(self, __dt: datetime | None) -> timedelta | None: ... + def fromutc(self, __dt: datetime) -> datetime: ... + +# Alias required to avoid name conflicts with date(time).tzinfo. +_tzinfo = tzinfo -if sys.version_info >= (3, 2): - class timezone(tzinfo): - utc: ClassVar[timezone] - min: ClassVar[timezone] - max: ClassVar[timezone] - def __init__(self, offset: timedelta, name: str = ...) -> None: ... - def __hash__(self) -> int: ... +@final +class timezone(tzinfo): + utc: ClassVar[timezone] + min: ClassVar[timezone] + max: ClassVar[timezone] + def __init__(self, offset: timedelta, name: str = ...) -> None: ... + def __hash__(self) -> int: ... if sys.version_info >= (3, 9): class _IsoCalendarDate(NamedTuple): @@ -32,8 +32,6 @@ if sys.version_info >= (3, 9): week: int weekday: int -_tzinfo = tzinfo - class date: min: ClassVar[date] max: ClassVar[date] @@ -44,10 +42,10 @@ class date: @classmethod def today(cls: Type[_S]) -> _S: ... @classmethod - def fromordinal(cls: Type[_S], n: int) -> _S: ... + def fromordinal(cls: Type[_S], __n: int) -> _S: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], date_string: str) -> _S: ... + def fromisoformat(cls: Type[_S], __date_string: str) -> _S: ... if sys.version_info >= (3, 8): @classmethod def fromisocalendar(cls: Type[_S], year: int, week: int, day: int) -> _S: ... @@ -58,57 +56,57 @@ class date: @property def day(self) -> int: ... def ctime(self) -> str: ... - def strftime(self, fmt: _Text) -> str: ... - if sys.version_info >= (3,): - def __format__(self, fmt: str) -> str: ... - else: - def __format__(self, fmt: AnyStr) -> AnyStr: ... + def strftime(self, fmt: str) -> str: ... + def __format__(self, __fmt: str) -> str: ... def isoformat(self) -> str: ... def timetuple(self) -> struct_time: ... def toordinal(self) -> int: ... def replace(self, year: int = ..., month: int = ..., day: int = ...) -> date: ... - def __le__(self, other: date) -> bool: ... - def __lt__(self, other: date) -> bool: ... - def __ge__(self, other: date) -> bool: ... - def __gt__(self, other: date) -> bool: ... + def __le__(self, __other: date) -> bool: ... + def __lt__(self, __other: date) -> bool: ... + def __ge__(self, __other: date) -> bool: ... + def __gt__(self, __other: date) -> bool: ... if sys.version_info >= (3, 8): - def __add__(self: _S, other: timedelta) -> _S: ... - def __radd__(self: _S, other: timedelta) -> _S: ... + def __add__(self: _S, __other: timedelta) -> _S: ... + def __radd__(self: _S, __other: timedelta) -> _S: ... + @overload + def __sub__(self: _D, __other: timedelta) -> _D: ... + @overload + def __sub__(self, __other: datetime) -> NoReturn: ... + @overload + def __sub__(self: _D, __other: _D) -> timedelta: ... else: - def __add__(self, other: timedelta) -> date: ... - def __radd__(self, other: timedelta) -> date: ... - @overload - def __sub__(self, other: timedelta) -> date: ... - @overload - def __sub__(self, other: date) -> timedelta: ... + # Prior to Python 3.8, arithmetic operations always returned `date`, even in subclasses + def __add__(self, __other: timedelta) -> date: ... + def __radd__(self, __other: timedelta) -> date: ... + @overload + def __sub__(self, __other: timedelta) -> date: ... + @overload + def __sub__(self, __other: datetime) -> NoReturn: ... + @overload + def __sub__(self, __other: date) -> timedelta: ... def __hash__(self) -> int: ... def weekday(self) -> int: ... def isoweekday(self) -> int: ... if sys.version_info >= (3, 9): def isocalendar(self) -> _IsoCalendarDate: ... else: - def isocalendar(self) -> Tuple[int, int, int]: ... + def isocalendar(self) -> tuple[int, int, int]: ... class time: min: ClassVar[time] max: ClassVar[time] resolution: ClassVar[timedelta] - - if sys.version_info >= (3, 6): - def __init__( - self, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - *, - fold: int = ..., - ) -> None: ... - else: - def __init__( - self, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: Optional[_tzinfo] = ... - ) -> None: ... + def __new__( + cls: Type[_S], + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> _S: ... @property def hour(self) -> int: ... @property @@ -118,45 +116,33 @@ class time: @property def microsecond(self) -> int: ... @property - def tzinfo(self) -> Optional[_tzinfo]: ... - if sys.version_info >= (3, 6): - @property - def fold(self) -> int: ... - def __le__(self, other: time) -> bool: ... - def __lt__(self, other: time) -> bool: ... - def __ge__(self, other: time) -> bool: ... - def __gt__(self, other: time) -> bool: ... + def tzinfo(self) -> _tzinfo | None: ... + @property + def fold(self) -> int: ... + def __le__(self, __other: time) -> bool: ... + def __lt__(self, __other: time) -> bool: ... + def __ge__(self, __other: time) -> bool: ... + def __gt__(self, __other: time) -> bool: ... def __hash__(self) -> int: ... - if sys.version_info >= (3, 6): - def isoformat(self, timespec: str = ...) -> str: ... - else: - def isoformat(self) -> str: ... + def isoformat(self, timespec: str = ...) -> str: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], time_string: str) -> _S: ... - def strftime(self, fmt: _Text) -> str: ... - if sys.version_info >= (3,): - def __format__(self, fmt: str) -> str: ... - else: - def __format__(self, fmt: AnyStr) -> AnyStr: ... - def utcoffset(self) -> Optional[timedelta]: ... - def tzname(self) -> Optional[str]: ... - def dst(self) -> Optional[timedelta]: ... - if sys.version_info >= (3, 6): - def replace( - self, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - *, - fold: int = ..., - ) -> time: ... - else: - def replace( - self, hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: Optional[_tzinfo] = ... - ) -> time: ... + def fromisoformat(cls: Type[_S], __time_string: str) -> _S: ... + def strftime(self, fmt: str) -> str: ... + def __format__(self, __fmt: str) -> str: ... + def utcoffset(self) -> timedelta | None: ... + def tzname(self) -> str | None: ... + def dst(self) -> timedelta | None: ... + def replace( + self, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> time: ... _date = date _time = time @@ -165,31 +151,16 @@ class timedelta(SupportsAbs[timedelta]): min: ClassVar[timedelta] max: ClassVar[timedelta] resolution: ClassVar[timedelta] - - if sys.version_info >= (3, 6): - def __init__( - self, - days: float = ..., - seconds: float = ..., - microseconds: float = ..., - milliseconds: float = ..., - minutes: float = ..., - hours: float = ..., - weeks: float = ..., - *, - fold: int = ..., - ) -> None: ... - else: - def __init__( - self, - days: float = ..., - seconds: float = ..., - microseconds: float = ..., - milliseconds: float = ..., - minutes: float = ..., - hours: float = ..., - weeks: float = ..., - ) -> None: ... + def __new__( + cls: Type[_S], + days: float = ..., + seconds: float = ..., + microseconds: float = ..., + milliseconds: float = ..., + minutes: float = ..., + hours: float = ..., + weeks: float = ..., + ) -> _S: ... @property def days(self) -> int: ... @property @@ -197,74 +168,49 @@ class timedelta(SupportsAbs[timedelta]): @property def microseconds(self) -> int: ... def total_seconds(self) -> float: ... - def __add__(self, other: timedelta) -> timedelta: ... - def __radd__(self, other: timedelta) -> timedelta: ... - def __sub__(self, other: timedelta) -> timedelta: ... - def __rsub__(self, other: timedelta) -> timedelta: ... + def __add__(self, __other: timedelta) -> timedelta: ... + def __radd__(self, __other: timedelta) -> timedelta: ... + def __sub__(self, __other: timedelta) -> timedelta: ... + def __rsub__(self, __other: timedelta) -> timedelta: ... def __neg__(self) -> timedelta: ... def __pos__(self) -> timedelta: ... def __abs__(self) -> timedelta: ... - def __mul__(self, other: float) -> timedelta: ... - def __rmul__(self, other: float) -> timedelta: ... + def __mul__(self, __other: float) -> timedelta: ... + def __rmul__(self, __other: float) -> timedelta: ... @overload - def __floordiv__(self, other: timedelta) -> int: ... + def __floordiv__(self, __other: timedelta) -> int: ... @overload - def __floordiv__(self, other: int) -> timedelta: ... - if sys.version_info >= (3,): - @overload - def __truediv__(self, other: timedelta) -> float: ... - @overload - def __truediv__(self, other: float) -> timedelta: ... - def __mod__(self, other: timedelta) -> timedelta: ... - def __divmod__(self, other: timedelta) -> Tuple[int, timedelta]: ... - else: - @overload - def __div__(self, other: timedelta) -> float: ... - @overload - def __div__(self, other: float) -> timedelta: ... - def __le__(self, other: timedelta) -> bool: ... - def __lt__(self, other: timedelta) -> bool: ... - def __ge__(self, other: timedelta) -> bool: ... - def __gt__(self, other: timedelta) -> bool: ... + def __floordiv__(self, __other: int) -> timedelta: ... + @overload + def __truediv__(self, __other: timedelta) -> float: ... + @overload + def __truediv__(self, __other: float) -> timedelta: ... + def __mod__(self, __other: timedelta) -> timedelta: ... + def __divmod__(self, __other: timedelta) -> tuple[int, timedelta]: ... + def __le__(self, __other: timedelta) -> bool: ... + def __lt__(self, __other: timedelta) -> bool: ... + def __ge__(self, __other: timedelta) -> bool: ... + def __gt__(self, __other: timedelta) -> bool: ... + def __bool__(self) -> bool: ... def __hash__(self) -> int: ... class datetime(date): min: ClassVar[datetime] max: ClassVar[datetime] resolution: ClassVar[timedelta] - - if sys.version_info >= (3, 6): - def __new__( - cls: Type[_S], - year: int, - month: int, - day: int, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - *, - fold: int = ..., - ) -> _S: ... - else: - def __new__( - cls: Type[_S], - year: int, - month: int, - day: int, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - ) -> _S: ... - @property - def year(self) -> int: ... - @property - def month(self) -> int: ... - @property - def day(self) -> int: ... + def __new__( + cls: Type[_S], + year: int, + month: int, + day: int, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> _S: ... @property def hour(self) -> int: ... @property @@ -274,21 +220,19 @@ class datetime(date): @property def microsecond(self) -> int: ... @property - def tzinfo(self) -> Optional[_tzinfo]: ... - if sys.version_info >= (3, 6): - @property - def fold(self) -> int: ... - @classmethod - def fromtimestamp(cls: Type[_S], t: float, tz: Optional[_tzinfo] = ...) -> _S: ... - @classmethod - def utcfromtimestamp(cls: Type[_S], t: float) -> _S: ... + def tzinfo(self) -> _tzinfo | None: ... + @property + def fold(self) -> int: ... + # The first parameter in `fromtimestamp` is actually positional-or-keyword, + # but it is named "timestamp" in the C implementation and "t" in the Python implementation, + # so it is only truly *safe* to pass it as a positional argument. @classmethod - def today(cls: Type[_S]) -> _S: ... + def fromtimestamp(cls: Type[_S], __timestamp: float, tz: _tzinfo | None = ...) -> _S: ... @classmethod - def fromordinal(cls: Type[_S], n: int) -> _S: ... + def utcfromtimestamp(cls: Type[_S], __t: float) -> _S: ... if sys.version_info >= (3, 8): @classmethod - def now(cls: Type[_S], tz: Optional[_tzinfo] = ...) -> _S: ... + def now(cls: Type[_S], tz: _tzinfo | None = ...) -> _S: ... else: @overload @classmethod @@ -298,88 +242,58 @@ class datetime(date): def now(cls, tz: _tzinfo) -> datetime: ... @classmethod def utcnow(cls: Type[_S]) -> _S: ... - if sys.version_info >= (3, 6): - @classmethod - def combine(cls, date: _date, time: _time, tzinfo: Optional[_tzinfo] = ...) -> datetime: ... - else: - @classmethod - def combine(cls, date: _date, time: _time) -> datetime: ... + @classmethod + def combine(cls, date: _date, time: _time, tzinfo: _tzinfo | None = ...) -> datetime: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], date_string: str) -> _S: ... - def strftime(self, fmt: _Text) -> str: ... - if sys.version_info >= (3,): - def __format__(self, fmt: str) -> str: ... - else: - def __format__(self, fmt: AnyStr) -> AnyStr: ... - def toordinal(self) -> int: ... - def timetuple(self) -> struct_time: ... - if sys.version_info >= (3, 3): - def timestamp(self) -> float: ... + def fromisoformat(cls: Type[_S], __date_string: str) -> _S: ... + def timestamp(self) -> float: ... def utctimetuple(self) -> struct_time: ... def date(self) -> _date: ... def time(self) -> _time: ... def timetz(self) -> _time: ... - if sys.version_info >= (3, 6): - def replace( - self, - year: int = ..., - month: int = ..., - day: int = ..., - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - *, - fold: int = ..., - ) -> datetime: ... - else: - def replace( - self, - year: int = ..., - month: int = ..., - day: int = ..., - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: Optional[_tzinfo] = ..., - ) -> datetime: ... + def replace( + self, + year: int = ..., + month: int = ..., + day: int = ..., + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> datetime: ... if sys.version_info >= (3, 8): - def astimezone(self: _S, tz: Optional[_tzinfo] = ...) -> _S: ... - elif sys.version_info >= (3, 3): - def astimezone(self, tz: Optional[_tzinfo] = ...) -> datetime: ... + def astimezone(self: _S, tz: _tzinfo | None = ...) -> _S: ... else: - def astimezone(self, tz: _tzinfo) -> datetime: ... + def astimezone(self, tz: _tzinfo | None = ...) -> datetime: ... def ctime(self) -> str: ... - if sys.version_info >= (3, 6): - def isoformat(self, sep: str = ..., timespec: str = ...) -> str: ... - else: - def isoformat(self, sep: str = ...) -> str: ... + def isoformat(self, sep: str = ..., timespec: str = ...) -> str: ... @classmethod - def strptime(cls, date_string: _Text, format: _Text) -> datetime: ... - def utcoffset(self) -> Optional[timedelta]: ... - def tzname(self) -> Optional[str]: ... - def dst(self) -> Optional[timedelta]: ... - def __le__(self, other: datetime) -> bool: ... # type: ignore - def __lt__(self, other: datetime) -> bool: ... # type: ignore - def __ge__(self, other: datetime) -> bool: ... # type: ignore - def __gt__(self, other: datetime) -> bool: ... # type: ignore + def strptime(cls, __date_string: str, __format: str) -> datetime: ... + def utcoffset(self) -> timedelta | None: ... + def tzname(self) -> str | None: ... + def dst(self) -> timedelta | None: ... + def __le__(self, __other: datetime) -> bool: ... # type: ignore + def __lt__(self, __other: datetime) -> bool: ... # type: ignore + def __ge__(self, __other: datetime) -> bool: ... # type: ignore + def __gt__(self, __other: datetime) -> bool: ... # type: ignore if sys.version_info >= (3, 8): - def __add__(self: _S, other: timedelta) -> _S: ... - def __radd__(self: _S, other: timedelta) -> _S: ... + @overload # type: ignore[override] + def __sub__(self: _D, __other: timedelta) -> _D: ... + @overload + def __sub__(self: _D, __other: _D) -> timedelta: ... else: - def __add__(self, other: timedelta) -> datetime: ... - def __radd__(self, other: timedelta) -> datetime: ... - @overload # type: ignore - def __sub__(self, other: datetime) -> timedelta: ... - @overload - def __sub__(self, other: timedelta) -> datetime: ... - def __hash__(self) -> int: ... - def weekday(self) -> int: ... - def isoweekday(self) -> int: ... + # Prior to Python 3.8, arithmetic operations always returned `datetime`, even in subclasses + def __add__(self, __other: timedelta) -> datetime: ... + def __radd__(self, __other: timedelta) -> datetime: ... + @overload # type: ignore[override] + def __sub__(self, __other: datetime) -> timedelta: ... + @overload + def __sub__(self, __other: timedelta) -> datetime: ... if sys.version_info >= (3, 9): def isocalendar(self) -> _IsoCalendarDate: ... else: - def isocalendar(self) -> Tuple[int, int, int]: ... + def isocalendar(self) -> tuple[int, int, int]: ... diff --git a/mypy/typeshed/stdlib/dbm/__init__.pyi b/mypy/typeshed/stdlib/dbm/__init__.pyi index edce1ea02861..9b9f92ccaa86 100644 --- a/mypy/typeshed/stdlib/dbm/__init__.pyi +++ b/mypy/typeshed/stdlib/dbm/__init__.pyi @@ -1,9 +1,76 @@ +from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Optional, Tuple, Type, Union +from typing import Iterator, MutableMapping, Tuple, Type, Union from typing_extensions import Literal _KeyType = Union[str, bytes] _ValueType = Union[str, bytes] +_TFlags = Literal[ + "r", + "w", + "c", + "n", + "rf", + "wf", + "cf", + "nf", + "rs", + "ws", + "cs", + "ns", + "ru", + "wu", + "cu", + "nu", + "rfs", + "wfs", + "cfs", + "nfs", + "rfu", + "wfu", + "cfu", + "nfu", + "rsf", + "wsf", + "csf", + "nsf", + "rsu", + "wsu", + "csu", + "nsu", + "ruf", + "wuf", + "cuf", + "nuf", + "rus", + "wus", + "cus", + "nus", + "rfsu", + "wfsu", + "cfsu", + "nfsu", + "rfus", + "wfus", + "cfus", + "nfus", + "rsfu", + "wsfu", + "csfu", + "nsfu", + "rsuf", + "wsuf", + "csuf", + "nsuf", + "rufs", + "wufs", + "cufs", + "nufs", + "rusf", + "wusf", + "cusf", + "nusf", +] class _Database(MutableMapping[_KeyType, bytes]): def close(self) -> None: ... @@ -13,9 +80,9 @@ class _Database(MutableMapping[_KeyType, bytes]): def __iter__(self) -> Iterator[bytes]: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _Database: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _error(Exception): ... @@ -23,4 +90,4 @@ class _error(Exception): ... error = Tuple[Type[_error], Type[OSError]] def whichdb(filename: str) -> str: ... -def open(file: str, flag: Literal["r", "w", "c", "n"] = ..., mode: int = ...) -> _Database: ... +def open(file: str, flag: _TFlags = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/dbm/dumb.pyi b/mypy/typeshed/stdlib/dbm/dumb.pyi index 0b8ee50a79b7..0a941b070754 100644 --- a/mypy/typeshed/stdlib/dbm/dumb.pyi +++ b/mypy/typeshed/stdlib/dbm/dumb.pyi @@ -1,5 +1,6 @@ +from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Optional, Type, Union +from typing import Iterator, MutableMapping, Type, Union _KeyType = Union[str, bytes] _ValueType = Union[str, bytes] @@ -17,9 +18,9 @@ class _Database(MutableMapping[_KeyType, bytes]): def __iter__(self) -> Iterator[bytes]: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _Database: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def open(file: str, flag: str = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/dbm/gnu.pyi b/mypy/typeshed/stdlib/dbm/gnu.pyi index 8f13a2988488..7cec827e8992 100644 --- a/mypy/typeshed/stdlib/dbm/gnu.pyi +++ b/mypy/typeshed/stdlib/dbm/gnu.pyi @@ -1,5 +1,6 @@ +from _typeshed import Self from types import TracebackType -from typing import List, Optional, Type, TypeVar, Union, overload +from typing import Type, TypeVar, Union, overload _T = TypeVar("_T") _KeyType = Union[str, bytes] @@ -9,24 +10,25 @@ class error(OSError): ... # Actual typename gdbm, not exposed by the implementation class _gdbm: - def firstkey(self) -> Optional[bytes]: ... - def nextkey(self, key: _KeyType) -> Optional[bytes]: ... + def firstkey(self) -> bytes | None: ... + def nextkey(self, key: _KeyType) -> bytes | None: ... def reorganize(self) -> None: ... def sync(self) -> None: ... def close(self) -> None: ... def __getitem__(self, item: _KeyType) -> bytes: ... def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... def __delitem__(self, key: _KeyType) -> None: ... + def __contains__(self, key: _KeyType) -> bool: ... def __len__(self) -> int: ... - def __enter__(self) -> _gdbm: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... @overload - def get(self, k: _KeyType) -> Optional[bytes]: ... + def get(self, k: _KeyType) -> bytes | None: ... @overload - def get(self, k: _KeyType, default: Union[bytes, _T]) -> Union[bytes, _T]: ... - def keys(self) -> List[bytes]: ... + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime __new__: None # type: ignore diff --git a/mypy/typeshed/stdlib/dbm/ndbm.pyi b/mypy/typeshed/stdlib/dbm/ndbm.pyi index 020131543e13..a4b35a309dbd 100644 --- a/mypy/typeshed/stdlib/dbm/ndbm.pyi +++ b/mypy/typeshed/stdlib/dbm/ndbm.pyi @@ -1,5 +1,6 @@ +from _typeshed import Self from types import TracebackType -from typing import List, Optional, Type, TypeVar, Union, overload +from typing import Type, TypeVar, Union, overload _T = TypeVar("_T") _KeyType = Union[str, bytes] @@ -7,7 +8,7 @@ _ValueType = Union[str, bytes] class error(OSError): ... -library: str = ... +library: str # Actual typename dbm, not exposed by the implementation class _dbm: @@ -17,15 +18,15 @@ class _dbm: def __delitem__(self, key: _KeyType) -> None: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _dbm: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... @overload - def get(self, k: _KeyType) -> Optional[bytes]: ... + def get(self, k: _KeyType) -> bytes | None: ... @overload - def get(self, k: _KeyType, default: Union[bytes, _T]) -> Union[bytes, _T]: ... - def keys(self) -> List[bytes]: ... + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime __new__: None # type: ignore diff --git a/mypy/typeshed/stdlib/decimal.pyi b/mypy/typeshed/stdlib/decimal.pyi index c3a671d4ba5f..30c8e973348d 100644 --- a/mypy/typeshed/stdlib/decimal.pyi +++ b/mypy/typeshed/stdlib/decimal.pyi @@ -1,14 +1,10 @@ import numbers -import sys from types import TracebackType -from typing import Any, Container, Dict, List, NamedTuple, Optional, Sequence, Text, Tuple, Type, TypeVar, Union, overload +from typing import Any, Container, NamedTuple, Sequence, Tuple, Type, TypeVar, Union, overload _Decimal = Union[Decimal, int] -_DecimalNew = Union[Decimal, float, Text, Tuple[int, Sequence[int], int]] -if sys.version_info >= (3,): - _ComparableNum = Union[Decimal, float, numbers.Rational] -else: - _ComparableNum = Union[Decimal, float] +_DecimalNew = Union[Decimal, float, str, Tuple[int, Sequence[int], int]] +_ComparableNum = Union[Decimal, float, numbers.Rational] _DecimalT = TypeVar("_DecimalT", bound=Decimal) class DecimalTuple(NamedTuple): @@ -25,17 +21,13 @@ ROUND_UP: str ROUND_HALF_DOWN: str ROUND_05UP: str -if sys.version_info >= (3,): - HAVE_THREADS: bool - MAX_EMAX: int - MAX_PREC: int - MIN_EMIN: int - MIN_ETINY: int - -class DecimalException(ArithmeticError): - if sys.version_info < (3,): - def handle(self, context: Context, *args: Any) -> Optional[Decimal]: ... +HAVE_THREADS: bool +MAX_EMAX: int +MAX_PREC: int +MIN_EMIN: int +MIN_ETINY: int +class DecimalException(ArithmeticError): ... class Clamped(DecimalException): ... class InvalidOperation(DecimalException): ... class ConversionSyntax(InvalidOperation): ... @@ -48,82 +40,47 @@ class Rounded(DecimalException): ... class Subnormal(DecimalException): ... class Overflow(Inexact, Rounded): ... class Underflow(Inexact, Rounded, Subnormal): ... - -if sys.version_info >= (3,): - class FloatOperation(DecimalException, TypeError): ... +class FloatOperation(DecimalException, TypeError): ... def setcontext(__context: Context) -> None: ... def getcontext() -> Context: ... -def localcontext(ctx: Optional[Context] = ...) -> _ContextManager: ... +def localcontext(ctx: Context | None = ...) -> _ContextManager: ... class Decimal(object): - def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Optional[Context] = ...) -> _DecimalT: ... + def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Context | None = ...) -> _DecimalT: ... @classmethod def from_float(cls, __f: float) -> Decimal: ... - if sys.version_info >= (3,): - def __bool__(self) -> bool: ... - else: - def __nonzero__(self) -> bool: ... - def __div__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rdiv__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __ne__(self, other: object, context: Optional[Context] = ...) -> bool: ... - def compare(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... + def __bool__(self) -> bool: ... + def compare(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __hash__(self) -> int: ... def as_tuple(self) -> DecimalTuple: ... - if sys.version_info >= (3, 6): - def as_integer_ratio(self) -> Tuple[int, int]: ... - def to_eng_string(self, context: Optional[Context] = ...) -> str: ... - if sys.version_info >= (3,): - def __abs__(self) -> Decimal: ... - def __add__(self, other: _Decimal) -> Decimal: ... - def __divmod__(self, other: _Decimal) -> Tuple[Decimal, Decimal]: ... - def __eq__(self, other: object) -> bool: ... - def __floordiv__(self, other: _Decimal) -> Decimal: ... - def __ge__(self, other: _ComparableNum) -> bool: ... - def __gt__(self, other: _ComparableNum) -> bool: ... - def __le__(self, other: _ComparableNum) -> bool: ... - def __lt__(self, other: _ComparableNum) -> bool: ... - def __mod__(self, other: _Decimal) -> Decimal: ... - def __mul__(self, other: _Decimal) -> Decimal: ... - def __neg__(self) -> Decimal: ... - def __pos__(self) -> Decimal: ... - def __pow__(self, other: _Decimal, modulo: Optional[_Decimal] = ...) -> Decimal: ... - def __radd__(self, other: _Decimal) -> Decimal: ... - def __rdivmod__(self, other: _Decimal) -> Tuple[Decimal, Decimal]: ... - def __rfloordiv__(self, other: _Decimal) -> Decimal: ... - def __rmod__(self, other: _Decimal) -> Decimal: ... - def __rmul__(self, other: _Decimal) -> Decimal: ... - def __rsub__(self, other: _Decimal) -> Decimal: ... - def __rtruediv__(self, other: _Decimal) -> Decimal: ... - def __str__(self) -> str: ... - def __sub__(self, other: _Decimal) -> Decimal: ... - def __truediv__(self, other: _Decimal) -> Decimal: ... - else: - def __abs__(self, round: bool = ..., context: Optional[Context] = ...) -> Decimal: ... - def __add__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __divmod__(self, other: _Decimal, context: Optional[Context] = ...) -> Tuple[Decimal, Decimal]: ... - def __eq__(self, other: object, context: Optional[Context] = ...) -> bool: ... - def __floordiv__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __ge__(self, other: _ComparableNum, context: Optional[Context] = ...) -> bool: ... - def __gt__(self, other: _ComparableNum, context: Optional[Context] = ...) -> bool: ... - def __le__(self, other: _ComparableNum, context: Optional[Context] = ...) -> bool: ... - def __lt__(self, other: _ComparableNum, context: Optional[Context] = ...) -> bool: ... - def __mod__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __mul__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __neg__(self, context: Optional[Context] = ...) -> Decimal: ... - def __pos__(self, context: Optional[Context] = ...) -> Decimal: ... - def __pow__(self, other: _Decimal, modulo: Optional[_Decimal] = ..., context: Optional[Context] = ...) -> Decimal: ... - def __radd__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rdivmod__(self, other: _Decimal, context: Optional[Context] = ...) -> Tuple[Decimal, Decimal]: ... - def __rfloordiv__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rmod__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rmul__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rsub__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rtruediv__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __str__(self, eng: bool = ..., context: Optional[Context] = ...) -> str: ... - def __sub__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __truediv__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def remainder_near(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... + def as_integer_ratio(self) -> tuple[int, int]: ... + def to_eng_string(self, context: Context | None = ...) -> str: ... + def __abs__(self) -> Decimal: ... + def __add__(self, __other: _Decimal) -> Decimal: ... + def __divmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... + def __eq__(self, __other: object) -> bool: ... + def __floordiv__(self, __other: _Decimal) -> Decimal: ... + def __ge__(self, __other: _ComparableNum) -> bool: ... + def __gt__(self, __other: _ComparableNum) -> bool: ... + def __le__(self, __other: _ComparableNum) -> bool: ... + def __lt__(self, __other: _ComparableNum) -> bool: ... + def __mod__(self, __other: _Decimal) -> Decimal: ... + def __mul__(self, __other: _Decimal) -> Decimal: ... + def __neg__(self) -> Decimal: ... + def __pos__(self) -> Decimal: ... + def __pow__(self, __other: _Decimal, __modulo: _Decimal | None = ...) -> Decimal: ... + def __radd__(self, __other: _Decimal) -> Decimal: ... + def __rdivmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... + def __rfloordiv__(self, __other: _Decimal) -> Decimal: ... + def __rmod__(self, __other: _Decimal) -> Decimal: ... + def __rmul__(self, __other: _Decimal) -> Decimal: ... + def __rsub__(self, __other: _Decimal) -> Decimal: ... + def __rtruediv__(self, __other: _Decimal) -> Decimal: ... + def __str__(self) -> str: ... + def __sub__(self, __other: _Decimal) -> Decimal: ... + def __truediv__(self, __other: _Decimal) -> Decimal: ... + def remainder_near(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __float__(self) -> float: ... def __int__(self) -> int: ... def __trunc__(self) -> int: ... @@ -133,89 +90,70 @@ class Decimal(object): def imag(self) -> Decimal: ... def conjugate(self) -> Decimal: ... def __complex__(self) -> complex: ... - if sys.version_info >= (3,): - @overload - def __round__(self) -> int: ... - @overload - def __round__(self, ndigits: int) -> Decimal: ... - def __floor__(self) -> int: ... - def __ceil__(self) -> int: ... - else: - def __long__(self) -> long: ... - def fma(self, other: _Decimal, third: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __rpow__(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def normalize(self, context: Optional[Context] = ...) -> Decimal: ... - if sys.version_info >= (3,): - def quantize(self, exp: _Decimal, rounding: Optional[str] = ..., context: Optional[Context] = ...) -> Decimal: ... - def same_quantum(self, other: _Decimal, context: Optional[Context] = ...) -> bool: ... - else: - def quantize( - self, exp: _Decimal, rounding: Optional[str] = ..., context: Optional[Context] = ..., watchexp: bool = ... - ) -> Decimal: ... - def same_quantum(self, other: _Decimal) -> bool: ... - def to_integral_exact(self, rounding: Optional[str] = ..., context: Optional[Context] = ...) -> Decimal: ... - def to_integral_value(self, rounding: Optional[str] = ..., context: Optional[Context] = ...) -> Decimal: ... - def to_integral(self, rounding: Optional[str] = ..., context: Optional[Context] = ...) -> Decimal: ... - def sqrt(self, context: Optional[Context] = ...) -> Decimal: ... - def max(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def min(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... + @overload + def __round__(self) -> int: ... + @overload + def __round__(self, __ndigits: int) -> Decimal: ... + def __floor__(self) -> int: ... + def __ceil__(self) -> int: ... + def fma(self, other: _Decimal, third: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rpow__(self, __other: _Decimal, __context: Context | None = ...) -> Decimal: ... + def normalize(self, context: Context | None = ...) -> Decimal: ... + def quantize(self, exp: _Decimal, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def same_quantum(self, other: _Decimal, context: Context | None = ...) -> bool: ... + def to_integral_exact(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral_value(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def sqrt(self, context: Context | None = ...) -> Decimal: ... + def max(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def adjusted(self) -> int: ... - if sys.version_info >= (3,): - def canonical(self) -> Decimal: ... - else: - def canonical(self, context: Optional[Context] = ...) -> Decimal: ... - def compare_signal(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - if sys.version_info >= (3,): - def compare_total(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def compare_total_mag(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - else: - def compare_total(self, other: _Decimal) -> Decimal: ... - def compare_total_mag(self, other: _Decimal) -> Decimal: ... + def canonical(self) -> Decimal: ... + def compare_signal(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def compare_total(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def compare_total_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def copy_abs(self) -> Decimal: ... def copy_negate(self) -> Decimal: ... - if sys.version_info >= (3,): - def copy_sign(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - else: - def copy_sign(self, other: _Decimal) -> Decimal: ... - def exp(self, context: Optional[Context] = ...) -> Decimal: ... + def copy_sign(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def exp(self, context: Context | None = ...) -> Decimal: ... def is_canonical(self) -> bool: ... def is_finite(self) -> bool: ... def is_infinite(self) -> bool: ... def is_nan(self) -> bool: ... - def is_normal(self, context: Optional[Context] = ...) -> bool: ... + def is_normal(self, context: Context | None = ...) -> bool: ... def is_qnan(self) -> bool: ... def is_signed(self) -> bool: ... def is_snan(self) -> bool: ... - def is_subnormal(self, context: Optional[Context] = ...) -> bool: ... + def is_subnormal(self, context: Context | None = ...) -> bool: ... def is_zero(self) -> bool: ... - def ln(self, context: Optional[Context] = ...) -> Decimal: ... - def log10(self, context: Optional[Context] = ...) -> Decimal: ... - def logb(self, context: Optional[Context] = ...) -> Decimal: ... - def logical_and(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def logical_invert(self, context: Optional[Context] = ...) -> Decimal: ... - def logical_or(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def logical_xor(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def max_mag(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def min_mag(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def next_minus(self, context: Optional[Context] = ...) -> Decimal: ... - def next_plus(self, context: Optional[Context] = ...) -> Decimal: ... - def next_toward(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def number_class(self, context: Optional[Context] = ...) -> str: ... + def ln(self, context: Context | None = ...) -> Decimal: ... + def log10(self, context: Context | None = ...) -> Decimal: ... + def logb(self, context: Context | None = ...) -> Decimal: ... + def logical_and(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_invert(self, context: Context | None = ...) -> Decimal: ... + def logical_or(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_xor(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def max_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def next_minus(self, context: Context | None = ...) -> Decimal: ... + def next_plus(self, context: Context | None = ...) -> Decimal: ... + def next_toward(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def number_class(self, context: Context | None = ...) -> str: ... def radix(self) -> Decimal: ... - def rotate(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def scaleb(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def shift(self, other: _Decimal, context: Optional[Context] = ...) -> Decimal: ... - def __reduce__(self) -> Tuple[Type[Decimal], Tuple[str]]: ... + def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __reduce__(self) -> tuple[Type[Decimal], tuple[str]]: ... def __copy__(self) -> Decimal: ... - def __deepcopy__(self, memo: Any) -> Decimal: ... - def __format__(self, specifier: str, context: Optional[Context] = ...) -> str: ... + def __deepcopy__(self, __memo: Any) -> Decimal: ... + def __format__(self, __specifier: str, __context: Context | None = ...) -> str: ... class _ContextManager(object): new_context: Context saved_context: Context def __init__(self, new_context: Context) -> None: ... def __enter__(self) -> Context: ... - def __exit__(self, t: Optional[Type[BaseException]], v: Optional[BaseException], tb: Optional[TracebackType]) -> None: ... + def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... _TrapType = Type[DecimalException] @@ -225,49 +163,30 @@ class Context(object): Emin: int Emax: int capitals: int - if sys.version_info >= (3,): - clamp: int - else: - _clamp: int - traps: Dict[_TrapType, bool] - flags: Dict[_TrapType, bool] - if sys.version_info >= (3,): - def __init__( - self, - prec: Optional[int] = ..., - rounding: Optional[str] = ..., - Emin: Optional[int] = ..., - Emax: Optional[int] = ..., - capitals: Optional[int] = ..., - clamp: Optional[int] = ..., - flags: Union[None, Dict[_TrapType, bool], Container[_TrapType]] = ..., - traps: Union[None, Dict[_TrapType, bool], Container[_TrapType]] = ..., - _ignored_flags: Optional[List[_TrapType]] = ..., - ) -> None: ... - else: - def __init__( - self, - prec: Optional[int] = ..., - rounding: Optional[str] = ..., - traps: Union[None, Dict[_TrapType, bool], Container[_TrapType]] = ..., - flags: Union[None, Dict[_TrapType, bool], Container[_TrapType]] = ..., - Emin: Optional[int] = ..., - Emax: Optional[int] = ..., - capitals: Optional[int] = ..., - _clamp: Optional[int] = ..., - _ignored_flags: Optional[List[_TrapType]] = ..., - ) -> None: ... - if sys.version_info >= (3,): - # __setattr__() only allows to set a specific set of attributes, - # already defined above. - def __delattr__(self, name: str) -> None: ... - def __reduce__(self) -> Tuple[Type[Context], Tuple[Any, ...]]: ... + clamp: int + traps: dict[_TrapType, bool] + flags: dict[_TrapType, bool] + def __init__( + self, + prec: int | None = ..., + rounding: str | None = ..., + Emin: int | None = ..., + Emax: int | None = ..., + capitals: int | None = ..., + clamp: int | None = ..., + flags: None | dict[_TrapType, bool] | Container[_TrapType] = ..., + traps: None | dict[_TrapType, bool] | Container[_TrapType] = ..., + _ignored_flags: list[_TrapType] | None = ..., + ) -> None: ... + # __setattr__() only allows to set a specific set of attributes, + # already defined above. + def __delattr__(self, __name: str) -> None: ... + def __reduce__(self) -> tuple[Type[Context], Tuple[Any, ...]]: ... def clear_flags(self) -> None: ... - if sys.version_info >= (3,): - def clear_traps(self) -> None: ... + def clear_traps(self) -> None: ... def copy(self) -> Context: ... def __copy__(self) -> Context: ... - __hash__: Any = ... + __hash__: Any def Etiny(self) -> int: ... def Etop(self) -> int: ... def create_decimal(self, __num: _DecimalNew = ...) -> Decimal: ... @@ -285,7 +204,7 @@ class Context(object): def copy_sign(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... def divide(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... def divide_int(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def divmod(self, __x: _Decimal, __y: _Decimal) -> Tuple[Decimal, Decimal]: ... + def divmod(self, __x: _Decimal, __y: _Decimal) -> tuple[Decimal, Decimal]: ... def exp(self, __x: _Decimal) -> Decimal: ... def fma(self, __x: _Decimal, __y: _Decimal, __z: _Decimal) -> Decimal: ... def is_canonical(self, __x: _Decimal) -> bool: ... @@ -317,7 +236,7 @@ class Context(object): def normalize(self, __x: _Decimal) -> Decimal: ... def number_class(self, __x: _Decimal) -> str: ... def plus(self, __x: _Decimal) -> Decimal: ... - def power(self, a: _Decimal, b: _Decimal, modulo: Optional[_Decimal] = ...) -> Decimal: ... + def power(self, a: _Decimal, b: _Decimal, modulo: _Decimal | None = ...) -> Decimal: ... def quantize(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... def radix(self) -> Decimal: ... def remainder(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... diff --git a/mypy/typeshed/stdlib/difflib.pyi b/mypy/typeshed/stdlib/difflib.pyi index 572972ccda9e..7c4ae8e2f246 100644 --- a/mypy/typeshed/stdlib/difflib.pyi +++ b/mypy/typeshed/stdlib/difflib.pyi @@ -1,34 +1,11 @@ import sys -from typing import ( - Any, - AnyStr, - Callable, - Generic, - Iterable, - Iterator, - List, - NamedTuple, - Optional, - Sequence, - Text, - Tuple, - TypeVar, - Union, - overload, -) +from typing import Any, AnyStr, Callable, Generic, Iterable, Iterator, NamedTuple, Sequence, TypeVar, Union, overload if sys.version_info >= (3, 9): from types import GenericAlias _T = TypeVar("_T") - -if sys.version_info >= (3,): - _StrType = Text -else: - # Aliases can't point to type vars, so we need to redeclare AnyStr - _StrType = TypeVar("_StrType", Text, bytes) - -_JunkCallback = Union[Callable[[Text], bool], Callable[[str], bool]] +_JunkCallback = Union[Callable[[str], bool], Callable[[str], bool]] class Match(NamedTuple): a: int @@ -37,20 +14,18 @@ class Match(NamedTuple): class SequenceMatcher(Generic[_T]): def __init__( - self, isjunk: Optional[Callable[[_T], bool]] = ..., a: Sequence[_T] = ..., b: Sequence[_T] = ..., autojunk: bool = ... + self, isjunk: Callable[[_T], bool] | None = ..., a: Sequence[_T] = ..., b: Sequence[_T] = ..., autojunk: bool = ... ) -> None: ... def set_seqs(self, a: Sequence[_T], b: Sequence[_T]) -> None: ... def set_seq1(self, a: Sequence[_T]) -> None: ... def set_seq2(self, b: Sequence[_T]) -> None: ... if sys.version_info >= (3, 9): - def find_longest_match( - self, alo: int = ..., ahi: Optional[int] = ..., blo: int = ..., bhi: Optional[int] = ... - ) -> Match: ... + def find_longest_match(self, alo: int = ..., ahi: int | None = ..., blo: int = ..., bhi: int | None = ...) -> Match: ... else: def find_longest_match(self, alo: int, ahi: int, blo: int, bhi: int) -> Match: ... - def get_matching_blocks(self) -> List[Match]: ... - def get_opcodes(self) -> List[Tuple[str, int, int, int, int]]: ... - def get_grouped_opcodes(self, n: int = ...) -> Iterable[List[Tuple[str, int, int, int, int]]]: ... + def get_matching_blocks(self) -> list[Match]: ... + def get_opcodes(self) -> list[tuple[str, int, int, int, int]]: ... + def get_grouped_opcodes(self, n: int = ...) -> Iterable[list[tuple[str, int, int, int, int]]]: ... def ratio(self) -> float: ... def quick_ratio(self) -> float: ... def real_quick_ratio(self) -> float: ... @@ -61,93 +36,80 @@ class SequenceMatcher(Generic[_T]): @overload def get_close_matches( # type: ignore word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ... -) -> List[AnyStr]: ... +) -> list[AnyStr]: ... @overload def get_close_matches( word: Sequence[_T], possibilities: Iterable[Sequence[_T]], n: int = ..., cutoff: float = ... -) -> List[Sequence[_T]]: ... +) -> list[Sequence[_T]]: ... class Differ: - def __init__(self, linejunk: Optional[_JunkCallback] = ..., charjunk: Optional[_JunkCallback] = ...) -> None: ... - def compare(self, a: Sequence[_StrType], b: Sequence[_StrType]) -> Iterator[_StrType]: ... + def __init__(self, linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ...) -> None: ... + def compare(self, a: Sequence[str], b: Sequence[str]) -> Iterator[str]: ... -def IS_LINE_JUNK(line: _StrType, pat: Any = ...) -> bool: ... # pat is undocumented -def IS_CHARACTER_JUNK(ch: _StrType, ws: _StrType = ...) -> bool: ... # ws is undocumented +def IS_LINE_JUNK(line: str, pat: Any = ...) -> bool: ... # pat is undocumented +def IS_CHARACTER_JUNK(ch: str, ws: str = ...) -> bool: ... # ws is undocumented def unified_diff( - a: Sequence[_StrType], - b: Sequence[_StrType], - fromfile: _StrType = ..., - tofile: _StrType = ..., - fromfiledate: _StrType = ..., - tofiledate: _StrType = ..., + a: Sequence[str], + b: Sequence[str], + fromfile: str = ..., + tofile: str = ..., + fromfiledate: str = ..., + tofiledate: str = ..., n: int = ..., - lineterm: _StrType = ..., -) -> Iterator[_StrType]: ... + lineterm: str = ..., +) -> Iterator[str]: ... def context_diff( - a: Sequence[_StrType], - b: Sequence[_StrType], - fromfile: _StrType = ..., - tofile: _StrType = ..., - fromfiledate: _StrType = ..., - tofiledate: _StrType = ..., + a: Sequence[str], + b: Sequence[str], + fromfile: str = ..., + tofile: str = ..., + fromfiledate: str = ..., + tofiledate: str = ..., n: int = ..., - lineterm: _StrType = ..., -) -> Iterator[_StrType]: ... + lineterm: str = ..., +) -> Iterator[str]: ... def ndiff( - a: Sequence[_StrType], b: Sequence[_StrType], linejunk: Optional[_JunkCallback] = ..., charjunk: Optional[_JunkCallback] = ... -) -> Iterator[_StrType]: ... + a: Sequence[str], b: Sequence[str], linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ... +) -> Iterator[str]: ... class HtmlDiff(object): def __init__( self, tabsize: int = ..., - wrapcolumn: Optional[int] = ..., - linejunk: Optional[_JunkCallback] = ..., - charjunk: Optional[_JunkCallback] = ..., + wrapcolumn: int | None = ..., + linejunk: _JunkCallback | None = ..., + charjunk: _JunkCallback | None = ..., ) -> None: ... - if sys.version_info >= (3, 5): - def make_file( - self, - fromlines: Sequence[_StrType], - tolines: Sequence[_StrType], - fromdesc: _StrType = ..., - todesc: _StrType = ..., - context: bool = ..., - numlines: int = ..., - *, - charset: str = ..., - ) -> _StrType: ... - else: - def make_file( - self, - fromlines: Sequence[_StrType], - tolines: Sequence[_StrType], - fromdesc: _StrType = ..., - todesc: _StrType = ..., - context: bool = ..., - numlines: int = ..., - ) -> _StrType: ... + def make_file( + self, + fromlines: Sequence[str], + tolines: Sequence[str], + fromdesc: str = ..., + todesc: str = ..., + context: bool = ..., + numlines: int = ..., + *, + charset: str = ..., + ) -> str: ... def make_table( self, - fromlines: Sequence[_StrType], - tolines: Sequence[_StrType], - fromdesc: _StrType = ..., - todesc: _StrType = ..., + fromlines: Sequence[str], + tolines: Sequence[str], + fromdesc: str = ..., + todesc: str = ..., context: bool = ..., numlines: int = ..., - ) -> _StrType: ... + ) -> str: ... -def restore(delta: Iterable[_StrType], which: int) -> Iterator[_StrType]: ... - -if sys.version_info >= (3, 5): - def diff_bytes( - dfunc: Callable[[Sequence[str], Sequence[str], str, str, str, str, int, str], Iterator[str]], - a: Sequence[bytes], - b: Sequence[bytes], - fromfile: bytes = ..., - tofile: bytes = ..., - fromfiledate: bytes = ..., - tofiledate: bytes = ..., - n: int = ..., - lineterm: bytes = ..., - ) -> Iterator[bytes]: ... +def restore(delta: Iterable[str], which: int) -> Iterator[str]: ... +def diff_bytes( + dfunc: Callable[[Sequence[str], Sequence[str], str, str, str, str, int, str], Iterator[str]], + a: Sequence[bytes], + b: Sequence[bytes], + fromfile: bytes = ..., + tofile: bytes = ..., + fromfiledate: bytes = ..., + tofiledate: bytes = ..., + n: int = ..., + lineterm: bytes = ..., +) -> Iterator[bytes]: ... diff --git a/mypy/typeshed/stdlib/dis.pyi b/mypy/typeshed/stdlib/dis.pyi index b52d0ed624f6..a6ea3e950b95 100644 --- a/mypy/typeshed/stdlib/dis.pyi +++ b/mypy/typeshed/stdlib/dis.pyi @@ -11,73 +11,54 @@ from opcode import ( hasjrel as hasjrel, haslocal as haslocal, hasname as hasname, + hasnargs as hasnargs, opmap as opmap, opname as opname, + stack_effect as stack_effect, ) -from typing import IO, Any, Callable, Dict, Iterator, List, NamedTuple, Optional, Tuple, Union - -if sys.version_info >= (3, 4): - from opcode import stack_effect as stack_effect - -if sys.version_info >= (3, 6): - from opcode import hasnargs as hasnargs +from typing import IO, Any, Callable, Iterator, NamedTuple, Union # Strictly this should not have to include Callable, but mypy doesn't use FunctionType # for functions (python/mypy#3171) _have_code = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] _have_code_or_string = Union[_have_code, str, bytes] -if sys.version_info >= (3, 4): - class Instruction(NamedTuple): - opname: str - opcode: int - arg: Optional[int] - argval: Any - argrepr: str - offset: int - starts_line: Optional[int] - is_jump_target: bool - class Bytecode: - codeobj: types.CodeType - first_line: int - def __init__( - self, x: _have_code_or_string, *, first_line: Optional[int] = ..., current_offset: Optional[int] = ... - ) -> None: ... - def __iter__(self) -> Iterator[Instruction]: ... - def __repr__(self) -> str: ... - def info(self) -> str: ... - def dis(self) -> str: ... - @classmethod - def from_traceback(cls, tb: types.TracebackType) -> Bytecode: ... +class Instruction(NamedTuple): + opname: str + opcode: int + arg: int | None + argval: Any + argrepr: str + offset: int + starts_line: int | None + is_jump_target: bool -COMPILER_FLAG_NAMES: Dict[int, str] +class Bytecode: + codeobj: types.CodeType + first_line: int + def __init__(self, x: _have_code_or_string, *, first_line: int | None = ..., current_offset: int | None = ...) -> None: ... + def __iter__(self) -> Iterator[Instruction]: ... + def __repr__(self) -> str: ... + def info(self) -> str: ... + def dis(self) -> str: ... + @classmethod + def from_traceback(cls, tb: types.TracebackType) -> Bytecode: ... -def findlabels(code: _have_code) -> List[int]: ... -def findlinestarts(code: _have_code) -> Iterator[Tuple[int, int]]: ... +COMPILER_FLAG_NAMES: dict[int, str] -if sys.version_info >= (3, 0): - def pretty_flags(flags: int) -> str: ... - def code_info(x: _have_code_or_string) -> str: ... +def findlabels(code: _have_code) -> list[int]: ... +def findlinestarts(code: _have_code) -> Iterator[tuple[int, int]]: ... +def pretty_flags(flags: int) -> str: ... +def code_info(x: _have_code_or_string) -> str: ... if sys.version_info >= (3, 7): - def dis(x: Optional[_have_code_or_string] = ..., *, file: Optional[IO[str]] = ..., depth: Optional[int] = ...) -> None: ... - -elif sys.version_info >= (3, 4): - def dis(x: Optional[_have_code_or_string] = ..., *, file: Optional[IO[str]] = ...) -> None: ... + def dis(x: _have_code_or_string | None = ..., *, file: IO[str] | None = ..., depth: int | None = ...) -> None: ... else: - def dis(x: _have_code_or_string = ...) -> None: ... + def dis(x: _have_code_or_string | None = ..., *, file: IO[str] | None = ...) -> None: ... -if sys.version_info >= (3, 4): - def distb(tb: Optional[types.TracebackType] = ..., *, file: Optional[IO[str]] = ...) -> None: ... - def disassemble(co: _have_code, lasti: int = ..., *, file: Optional[IO[str]] = ...) -> None: ... - def disco(co: _have_code, lasti: int = ..., *, file: Optional[IO[str]] = ...) -> None: ... - def show_code(co: _have_code, *, file: Optional[IO[str]] = ...) -> None: ... - def get_instructions(x: _have_code, *, first_line: Optional[int] = ...) -> Iterator[Instruction]: ... - -else: - def distb(tb: types.TracebackType = ...) -> None: ... - def disassemble(co: _have_code, lasti: int = ...) -> None: ... - def disco(co: _have_code, lasti: int = ...) -> None: ... - if sys.version_info >= (3, 0): - def show_code(co: _have_code) -> None: ... +def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ...) -> None: ... +def disassemble(co: _have_code, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... +def disco(co: _have_code, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... +def show_code(co: _have_code, *, file: IO[str] | None = ...) -> None: ... +def get_instructions(x: _have_code, *, first_line: int | None = ...) -> Iterator[Instruction]: ... diff --git a/mypy/typeshed/stdlib/distutils/archive_util.pyi b/mypy/typeshed/stdlib/distutils/archive_util.pyi index 76ae158de3e6..38458fc0e003 100644 --- a/mypy/typeshed/stdlib/distutils/archive_util.pyi +++ b/mypy/typeshed/stdlib/distutils/archive_util.pyi @@ -1,22 +1,20 @@ -from typing import Optional - def make_archive( base_name: str, format: str, - root_dir: Optional[str] = ..., - base_dir: Optional[str] = ..., + root_dir: str | None = ..., + base_dir: str | None = ..., verbose: int = ..., dry_run: int = ..., - owner: Optional[str] = ..., - group: Optional[str] = ..., + owner: str | None = ..., + group: str | None = ..., ) -> str: ... def make_tarball( base_name: str, base_dir: str, - compress: Optional[str] = ..., + compress: str | None = ..., verbose: int = ..., dry_run: int = ..., - owner: Optional[str] = ..., - group: Optional[str] = ..., + owner: str | None = ..., + group: str | None = ..., ) -> str: ... def make_zipfile(base_name: str, base_dir: str, verbose: int = ..., dry_run: int = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/distutils/ccompiler.pyi index 831311d2cb52..d21de4691503 100644 --- a/mypy/typeshed/stdlib/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/distutils/ccompiler.pyi @@ -1,14 +1,14 @@ -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import Any, Callable, Optional, Tuple, Union _Macro = Union[Tuple[str], Tuple[str, Optional[str]]] def gen_lib_options( - compiler: CCompiler, library_dirs: List[str], runtime_library_dirs: List[str], libraries: List[str] -) -> List[str]: ... -def gen_preprocess_options(macros: List[_Macro], include_dirs: List[str]) -> List[str]: ... -def get_default_compiler(osname: Optional[str] = ..., platform: Optional[str] = ...) -> str: ... + compiler: CCompiler, library_dirs: list[str], runtime_library_dirs: list[str], libraries: list[str] +) -> list[str]: ... +def gen_preprocess_options(macros: list[_Macro], include_dirs: list[str]) -> list[str]: ... +def get_default_compiler(osname: str | None = ..., platform: str | None = ...) -> str: ... def new_compiler( - plat: Optional[str] = ..., compiler: Optional[str] = ..., verbose: int = ..., dry_run: int = ..., force: int = ... + plat: str | None = ..., compiler: str | None = ..., verbose: int = ..., dry_run: int = ..., force: int = ... ) -> CCompiler: ... def show_compilers() -> None: ... @@ -16,35 +16,35 @@ class CCompiler: dry_run: bool force: bool verbose: bool - output_dir: Optional[str] - macros: List[_Macro] - include_dirs: List[str] - libraries: List[str] - library_dirs: List[str] - runtime_library_dirs: List[str] - objects: List[str] + output_dir: str | None + macros: list[_Macro] + include_dirs: list[str] + libraries: list[str] + library_dirs: list[str] + runtime_library_dirs: list[str] + objects: list[str] def __init__(self, verbose: int = ..., dry_run: int = ..., force: int = ...) -> None: ... def add_include_dir(self, dir: str) -> None: ... - def set_include_dirs(self, dirs: List[str]) -> None: ... + def set_include_dirs(self, dirs: list[str]) -> None: ... def add_library(self, libname: str) -> None: ... - def set_libraries(self, libnames: List[str]) -> None: ... + def set_libraries(self, libnames: list[str]) -> None: ... def add_library_dir(self, dir: str) -> None: ... - def set_library_dirs(self, dirs: List[str]) -> None: ... + def set_library_dirs(self, dirs: list[str]) -> None: ... def add_runtime_library_dir(self, dir: str) -> None: ... - def set_runtime_library_dirs(self, dirs: List[str]) -> None: ... - def define_macro(self, name: str, value: Optional[str] = ...) -> None: ... + def set_runtime_library_dirs(self, dirs: list[str]) -> None: ... + def define_macro(self, name: str, value: str | None = ...) -> None: ... def undefine_macro(self, name: str) -> None: ... def add_link_object(self, object: str) -> None: ... - def set_link_objects(self, objects: List[str]) -> None: ... - def detect_language(self, sources: Union[str, List[str]]) -> Optional[str]: ... - def find_library_file(self, dirs: List[str], lib: str, debug: bool = ...) -> Optional[str]: ... + def set_link_objects(self, objects: list[str]) -> None: ... + def detect_language(self, sources: str | list[str]) -> str | None: ... + def find_library_file(self, dirs: list[str], lib: str, debug: bool = ...) -> str | None: ... def has_function( self, funcname: str, - includes: Optional[List[str]] = ..., - include_dirs: Optional[List[str]] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., + includes: list[str] | None = ..., + include_dirs: list[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., ) -> bool: ... def library_dir_option(self, dir: str) -> str: ... def library_option(self, lib: str) -> str: ... @@ -52,97 +52,97 @@ class CCompiler: def set_executables(self, **args: str) -> None: ... def compile( self, - sources: List[str], - output_dir: Optional[str] = ..., - macros: Optional[_Macro] = ..., - include_dirs: Optional[List[str]] = ..., + sources: list[str], + output_dir: str | None = ..., + macros: _Macro | None = ..., + include_dirs: list[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - depends: Optional[List[str]] = ..., - ) -> List[str]: ... + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + depends: list[str] | None = ..., + ) -> list[str]: ... def create_static_lib( self, - objects: List[str], + objects: list[str], output_libname: str, - output_dir: Optional[str] = ..., + output_dir: str | None = ..., debug: bool = ..., - target_lang: Optional[str] = ..., + target_lang: str | None = ..., ) -> None: ... def link( self, target_desc: str, - objects: List[str], + objects: list[str], output_filename: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_executable( self, - objects: List[str], + objects: list[str], output_progname: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - target_lang: Optional[str] = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_shared_lib( self, - objects: List[str], + objects: list[str], output_libname: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def link_shared_object( self, - objects: List[str], + objects: list[str], output_filename: str, - output_dir: Optional[str] = ..., - libraries: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., + output_dir: str | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., - build_temp: Optional[str] = ..., - target_lang: Optional[str] = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + build_temp: str | None = ..., + target_lang: str | None = ..., ) -> None: ... def preprocess( self, source: str, - output_file: Optional[str] = ..., - macros: Optional[List[_Macro]] = ..., - include_dirs: Optional[List[str]] = ..., - extra_preargs: Optional[List[str]] = ..., - extra_postargs: Optional[List[str]] = ..., + output_file: str | None = ..., + macros: list[_Macro] | None = ..., + include_dirs: list[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., ) -> None: ... def executable_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... def library_filename(self, libname: str, lib_type: str = ..., strip_dir: int = ..., output_dir: str = ...) -> str: ... - def object_filenames(self, source_filenames: List[str], strip_dir: int = ..., output_dir: str = ...) -> List[str]: ... + def object_filenames(self, source_filenames: list[str], strip_dir: int = ..., output_dir: str = ...) -> list[str]: ... def shared_object_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... - def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: Optional[str] = ..., level: int = ...) -> None: ... - def spawn(self, cmd: List[str]) -> None: ... + def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... + def spawn(self, cmd: list[str]) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def move_file(self, src: str, dst: str) -> str: ... def announce(self, msg: str, level: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/cmd.pyi b/mypy/typeshed/stdlib/distutils/cmd.pyi index 93bfc7c9dbb5..875e851bed39 100644 --- a/mypy/typeshed/stdlib/distutils/cmd.pyi +++ b/mypy/typeshed/stdlib/distutils/cmd.pyi @@ -1,9 +1,9 @@ from abc import abstractmethod from distutils.dist import Distribution -from typing import Any, Callable, Iterable, List, Optional, Tuple, Union +from typing import Any, Callable, Iterable class Command: - sub_commands: List[Tuple[str, Optional[Callable[[Command], bool]]]] + sub_commands: list[tuple[str, Callable[[Command], bool] | None]] def __init__(self, dist: Distribution) -> None: ... @abstractmethod def initialize_options(self) -> None: ... @@ -13,18 +13,18 @@ class Command: def run(self) -> None: ... def announce(self, msg: str, level: int = ...) -> None: ... def debug_print(self, msg: str) -> None: ... - def ensure_string(self, option: str, default: Optional[str] = ...) -> None: ... - def ensure_string_list(self, option: Union[str, List[str]]) -> None: ... + def ensure_string(self, option: str, default: str | None = ...) -> None: ... + def ensure_string_list(self, option: str | list[str]) -> None: ... def ensure_filename(self, option: str) -> None: ... def ensure_dirname(self, option: str) -> None: ... def get_command_name(self) -> str: ... - def set_undefined_options(self, src_cmd: str, *option_pairs: Tuple[str, str]) -> None: ... + def set_undefined_options(self, src_cmd: str, *option_pairs: tuple[str, str]) -> None: ... def get_finalized_command(self, command: str, create: int = ...) -> Command: ... - def reinitialize_command(self, command: Union[Command, str], reinit_subcommands: int = ...) -> Command: ... + def reinitialize_command(self, command: Command | str, reinit_subcommands: int = ...) -> Command: ... def run_command(self, command: str) -> None: ... - def get_sub_commands(self) -> List[str]: ... + def get_sub_commands(self) -> list[str]: ... def warn(self, msg: str) -> None: ... - def execute(self, func: Callable[..., Any], args: Iterable[Any], msg: Optional[str] = ..., level: int = ...) -> None: ... + def execute(self, func: Callable[..., Any], args: Iterable[Any], msg: str | None = ..., level: int = ...) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def copy_file( self, @@ -32,9 +32,9 @@ class Command: outfile: str, preserve_mode: int = ..., preserve_times: int = ..., - link: Optional[str] = ..., + link: str | None = ..., level: Any = ..., - ) -> Tuple[str, bool]: ... # level is not used + ) -> tuple[str, bool]: ... # level is not used def copy_tree( self, infile: str, @@ -43,25 +43,25 @@ class Command: preserve_times: int = ..., preserve_symlinks: int = ..., level: Any = ..., - ) -> List[str]: ... # level is not used + ) -> list[str]: ... # level is not used def move_file(self, src: str, dst: str, level: Any = ...) -> str: ... # level is not used def spawn(self, cmd: Iterable[str], search_path: int = ..., level: Any = ...) -> None: ... # level is not used def make_archive( self, base_name: str, format: str, - root_dir: Optional[str] = ..., - base_dir: Optional[str] = ..., - owner: Optional[str] = ..., - group: Optional[str] = ..., + root_dir: str | None = ..., + base_dir: str | None = ..., + owner: str | None = ..., + group: str | None = ..., ) -> str: ... def make_file( self, - infiles: Union[str, List[str], Tuple[str]], + infiles: str | list[str] | tuple[str], outfile: str, func: Callable[..., Any], - args: List[Any], - exec_msg: Optional[str] = ..., - skip_msg: Optional[str] = ..., + args: list[Any], + exec_msg: str | None = ..., + skip_msg: str | None = ..., level: Any = ..., ) -> None: ... # level is not used diff --git a/mypy/typeshed/stdlib/distutils/command/bdist.pyi b/mypy/typeshed/stdlib/distutils/command/bdist.pyi index e69de29bb2d1..e1f141d3a40f 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist.pyi @@ -0,0 +1,25 @@ +from typing import Any + +from ..cmd import Command + +def show_formats() -> None: ... + +class bdist(Command): + description: str + user_options: Any + boolean_options: Any + help_options: Any + no_format_option: Any + default_format: Any + format_commands: Any + format_command: Any + bdist_base: Any + plat_name: Any + formats: Any + dist_dir: Any + skip_build: int + group: Any + owner: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/bdist_dumb.pyi b/mypy/typeshed/stdlib/distutils/command/bdist_dumb.pyi index e69de29bb2d1..74cca4d13cd0 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist_dumb.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist_dumb.pyi @@ -0,0 +1,21 @@ +from typing import Any + +from ..cmd import Command + +class bdist_dumb(Command): + description: str + user_options: Any + boolean_options: Any + default_format: Any + bdist_dir: Any + plat_name: Any + format: Any + keep_temp: int + dist_dir: Any + skip_build: Any + relative: int + owner: Any + group: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi b/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi index a761792018a9..e4f64ff6a59e 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi @@ -1,6 +1,43 @@ -from distutils.cmd import Command +import sys +from typing import Any -class bdist_msi(Command): - def initialize_options(self) -> None: ... - def finalize_options(self) -> None: ... - def run(self) -> None: ... +from ..cmd import Command + +if sys.platform == "win32": + from msilib import Dialog + class PyDialog(Dialog): + def __init__(self, *args, **kw) -> None: ... + def title(self, title) -> None: ... + def back(self, title, next, name: str = ..., active: int = ...): ... + def cancel(self, title, next, name: str = ..., active: int = ...): ... + def next(self, title, next, name: str = ..., active: int = ...): ... + def xbutton(self, name, title, next, xpos): ... + class bdist_msi(Command): + description: str + user_options: Any + boolean_options: Any + all_versions: Any + other_version: str + if sys.version_info >= (3, 9): + def __init__(self, *args, **kw) -> None: ... + bdist_dir: Any + plat_name: Any + keep_temp: int + no_target_compile: int + no_target_optimize: int + target_version: Any + dist_dir: Any + skip_build: Any + install_script: Any + pre_install_script: Any + versions: Any + def initialize_options(self) -> None: ... + install_script_key: Any + def finalize_options(self) -> None: ... + db: Any + def run(self) -> None: ... + def add_files(self) -> None: ... + def add_find_python(self) -> None: ... + def add_scripts(self) -> None: ... + def add_ui(self) -> None: ... + def get_installer_filename(self, fullname): ... diff --git a/mypy/typeshed/stdlib/distutils/command/bdist_rpm.pyi b/mypy/typeshed/stdlib/distutils/command/bdist_rpm.pyi index e69de29bb2d1..76691310b599 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist_rpm.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist_rpm.pyi @@ -0,0 +1,52 @@ +from typing import Any + +from ..cmd import Command + +class bdist_rpm(Command): + description: str + user_options: Any + boolean_options: Any + negative_opt: Any + bdist_base: Any + rpm_base: Any + dist_dir: Any + python: Any + fix_python: Any + spec_only: Any + binary_only: Any + source_only: Any + use_bzip2: Any + distribution_name: Any + group: Any + release: Any + serial: Any + vendor: Any + packager: Any + doc_files: Any + changelog: Any + icon: Any + prep_script: Any + build_script: Any + install_script: Any + clean_script: Any + verify_script: Any + pre_install: Any + post_install: Any + pre_uninstall: Any + post_uninstall: Any + prep: Any + provides: Any + requires: Any + conflicts: Any + build_requires: Any + obsoletes: Any + keep_temp: int + use_rpm_opt_flags: int + rpm3_mode: int + no_autoreq: int + force_arch: Any + quiet: int + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def finalize_package_data(self) -> None: ... + def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/build.pyi b/mypy/typeshed/stdlib/distutils/command/build.pyi index e69de29bb2d1..cf3c8a562ff3 100644 --- a/mypy/typeshed/stdlib/distutils/command/build.pyi +++ b/mypy/typeshed/stdlib/distutils/command/build.pyi @@ -0,0 +1,31 @@ +from typing import Any + +from ..cmd import Command + +def show_compilers() -> None: ... + +class build(Command): + description: str + user_options: Any + boolean_options: Any + help_options: Any + build_base: str + build_purelib: Any + build_platlib: Any + build_lib: Any + build_temp: Any + build_scripts: Any + compiler: Any + plat_name: Any + debug: Any + force: int + executable: Any + parallel: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def has_pure_modules(self): ... + def has_c_libraries(self): ... + def has_ext_modules(self): ... + def has_scripts(self): ... + sub_commands: Any diff --git a/mypy/typeshed/stdlib/distutils/command/build_clib.pyi b/mypy/typeshed/stdlib/distutils/command/build_clib.pyi index e69de29bb2d1..32ab182b30d0 100644 --- a/mypy/typeshed/stdlib/distutils/command/build_clib.pyi +++ b/mypy/typeshed/stdlib/distutils/command/build_clib.pyi @@ -0,0 +1,27 @@ +from typing import Any + +from ..cmd import Command + +def show_compilers() -> None: ... + +class build_clib(Command): + description: str + user_options: Any + boolean_options: Any + help_options: Any + build_clib: Any + build_temp: Any + libraries: Any + include_dirs: Any + define: Any + undef: Any + debug: Any + force: int + compiler: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def check_library_list(self, libraries) -> None: ... + def get_library_names(self): ... + def get_source_files(self): ... + def build_libraries(self, libraries) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/build_ext.pyi b/mypy/typeshed/stdlib/distutils/command/build_ext.pyi index e69de29bb2d1..80cd78936cb9 100644 --- a/mypy/typeshed/stdlib/distutils/command/build_ext.pyi +++ b/mypy/typeshed/stdlib/distutils/command/build_ext.pyi @@ -0,0 +1,50 @@ +from typing import Any + +from ..cmd import Command + +extension_name_re: Any + +def show_compilers() -> None: ... + +class build_ext(Command): + description: str + sep_by: Any + user_options: Any + boolean_options: Any + help_options: Any + extensions: Any + build_lib: Any + plat_name: Any + build_temp: Any + inplace: int + package: Any + include_dirs: Any + define: Any + undef: Any + libraries: Any + library_dirs: Any + rpath: Any + link_objects: Any + debug: Any + force: Any + compiler: Any + swig: Any + swig_cpp: Any + swig_opts: Any + user: Any + parallel: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def check_extensions_list(self, extensions) -> None: ... + def get_source_files(self): ... + def get_outputs(self): ... + def build_extensions(self) -> None: ... + def build_extension(self, ext) -> None: ... + def swig_sources(self, sources, extension): ... + def find_swig(self): ... + def get_ext_fullpath(self, ext_name): ... + def get_ext_fullname(self, ext_name): ... + def get_ext_filename(self, ext_name): ... + def get_export_symbols(self, ext): ... + def get_libraries(self, ext): ... diff --git a/mypy/typeshed/stdlib/distutils/command/build_py.pyi b/mypy/typeshed/stdlib/distutils/command/build_py.pyi index 4e8c9af4a546..3c6e022c2a10 100644 --- a/mypy/typeshed/stdlib/distutils/command/build_py.pyi +++ b/mypy/typeshed/stdlib/distutils/command/build_py.pyi @@ -1,8 +1,44 @@ -from distutils.cmd import Command +from typing import Any + +from ..cmd import Command +from ..util import Mixin2to3 as Mixin2to3 class build_py(Command): + description: str + user_options: Any + boolean_options: Any + negative_opt: Any + build_lib: Any + py_modules: Any + package: Any + package_data: Any + package_dir: Any + compile: int + optimize: int + force: Any def initialize_options(self) -> None: ... + packages: Any + data_files: Any def finalize_options(self) -> None: ... def run(self) -> None: ... + def get_data_files(self): ... + def find_data_files(self, package, src_dir): ... + def build_package_data(self) -> None: ... + def get_package_dir(self, package): ... + def check_package(self, package, package_dir): ... + def check_module(self, module, module_file): ... + def find_package_modules(self, package, package_dir): ... + def find_modules(self): ... + def find_all_modules(self): ... + def get_source_files(self): ... + def get_module_outfile(self, build_dir, package, module): ... + def get_outputs(self, include_bytecode: int = ...): ... + def build_module(self, module, module_file, package): ... + def build_modules(self) -> None: ... + def build_packages(self) -> None: ... + def byte_compile(self, files) -> None: ... -class build_py_2to3(build_py): ... +class build_py_2to3(build_py, Mixin2to3): + updated_files: Any + def run(self) -> None: ... + def build_module(self, module, module_file, package): ... diff --git a/mypy/typeshed/stdlib/distutils/command/build_scripts.pyi b/mypy/typeshed/stdlib/distutils/command/build_scripts.pyi index e69de29bb2d1..42135eceafef 100644 --- a/mypy/typeshed/stdlib/distutils/command/build_scripts.pyi +++ b/mypy/typeshed/stdlib/distutils/command/build_scripts.pyi @@ -0,0 +1,24 @@ +from typing import Any + +from ..cmd import Command +from ..util import Mixin2to3 as Mixin2to3 + +first_line_re: Any + +class build_scripts(Command): + description: str + user_options: Any + boolean_options: Any + build_dir: Any + scripts: Any + force: Any + executable: Any + outfiles: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def get_source_files(self): ... + def run(self) -> None: ... + def copy_scripts(self): ... + +class build_scripts_2to3(build_scripts, Mixin2to3): + def copy_scripts(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/check.pyi b/mypy/typeshed/stdlib/distutils/command/check.pyi index e69de29bb2d1..9149b540f715 100644 --- a/mypy/typeshed/stdlib/distutils/command/check.pyi +++ b/mypy/typeshed/stdlib/distutils/command/check.pyi @@ -0,0 +1,36 @@ +from typing import Any + +from ..cmd import Command + +_Reporter = Any # really docutils.utils.Reporter + +# Only defined if docutils is installed. +class SilentReporter(_Reporter): # type: ignore + messages: Any + def __init__( + self, + source, + report_level, + halt_level, + stream: Any | None = ..., + debug: int = ..., + encoding: str = ..., + error_handler: str = ..., + ) -> None: ... + def system_message(self, level, message, *children, **kwargs): ... + +HAS_DOCUTILS: bool + +class check(Command): + description: str + user_options: Any + boolean_options: Any + restructuredtext: int + metadata: int + strict: int + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def warn(self, msg): ... + def run(self) -> None: ... + def check_metadata(self) -> None: ... + def check_restructuredtext(self) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/clean.pyi b/mypy/typeshed/stdlib/distutils/command/clean.pyi index e69de29bb2d1..99560aa8a716 100644 --- a/mypy/typeshed/stdlib/distutils/command/clean.pyi +++ b/mypy/typeshed/stdlib/distutils/command/clean.pyi @@ -0,0 +1,17 @@ +from typing import Any + +from ..cmd import Command + +class clean(Command): + description: str + user_options: Any + boolean_options: Any + build_base: Any + build_lib: Any + build_temp: Any + build_scripts: Any + bdist_base: Any + all: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/config.pyi b/mypy/typeshed/stdlib/distutils/command/config.pyi index 6b57a64b48b1..7ad71e185df8 100644 --- a/mypy/typeshed/stdlib/distutils/command/config.pyi +++ b/mypy/typeshed/stdlib/distutils/command/config.pyi @@ -1,87 +1,82 @@ -from distutils import log as log -from distutils.ccompiler import CCompiler -from distutils.core import Command as Command -from distutils.errors import DistutilsExecError as DistutilsExecError -from distutils.sysconfig import customize_compiler as customize_compiler -from typing import Dict, List, Optional, Pattern, Sequence, Tuple, Union +from collections.abc import Sequence +from typing import Any, Pattern -LANG_EXT: Dict[str, str] +from ..ccompiler import CCompiler +from ..cmd import Command + +LANG_EXT: dict[str, str] class config(Command): - description: str = ... + description: str # Tuple is full name, short name, description - user_options: Sequence[Tuple[str, Optional[str], str]] = ... - compiler: Optional[Union[str, CCompiler]] = ... - cc: Optional[str] = ... - include_dirs: Optional[Sequence[str]] = ... - libraries: Optional[Sequence[str]] = ... - library_dirs: Optional[Sequence[str]] = ... - noisy: int = ... - dump_source: int = ... - temp_files: Sequence[str] = ... + user_options: Sequence[tuple[str, str | None, str]] + compiler: str | CCompiler + cc: str | None + include_dirs: Sequence[str] | None + libraries: Sequence[str] | None + library_dirs: Sequence[str] | None + noisy: int + dump_source: int + temp_files: Sequence[str] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... def run(self) -> None: ... def try_cpp( self, - body: Optional[str] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., + body: str | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def search_cpp( self, - pattern: Union[Pattern[str], str], - body: Optional[str] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., + pattern: Pattern[str] | str, + body: str | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def try_compile( - self, body: str, headers: Optional[Sequence[str]] = ..., include_dirs: Optional[Sequence[str]] = ..., lang: str = ... + self, body: str, headers: Sequence[str] | None = ..., include_dirs: Sequence[str] | None = ..., lang: str = ... ) -> bool: ... def try_link( self, body: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def try_run( self, body: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., lang: str = ..., ) -> bool: ... def check_func( self, func: str, - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - libraries: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + libraries: Sequence[str] | None = ..., + library_dirs: Sequence[str] | None = ..., decl: int = ..., call: int = ..., ) -> bool: ... def check_lib( self, library: str, - library_dirs: Optional[Sequence[str]] = ..., - headers: Optional[Sequence[str]] = ..., - include_dirs: Optional[Sequence[str]] = ..., - other_libraries: List[str] = ..., + library_dirs: Sequence[str] | None = ..., + headers: Sequence[str] | None = ..., + include_dirs: Sequence[str] | None = ..., + other_libraries: list[str] = ..., ) -> bool: ... def check_header( - self, - header: str, - include_dirs: Optional[Sequence[str]] = ..., - library_dirs: Optional[Sequence[str]] = ..., - lang: str = ..., + self, header: str, include_dirs: Sequence[str] | None = ..., library_dirs: Sequence[str] | None = ..., lang: str = ... ) -> bool: ... -def dump_file(filename: str, head: Optional[str] = ...) -> None: ... +def dump_file(filename: str, head: Any | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/install.pyi b/mypy/typeshed/stdlib/distutils/command/install.pyi index 12e83d976a2d..47fa8b08d1b2 100644 --- a/mypy/typeshed/stdlib/distutils/command/install.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install.pyi @@ -1,14 +1,63 @@ -from distutils.cmd import Command -from typing import Optional, Tuple +from typing import Any, Tuple +from ..cmd import Command + +HAS_USER_SITE: bool SCHEME_KEYS: Tuple[str, ...] +INSTALL_SCHEMES: dict[str, dict[Any, Any]] class install(Command): + description: str + user_options: Any + boolean_options: Any + negative_opt: Any + prefix: str | None + exec_prefix: Any + home: str | None user: bool - prefix: Optional[str] - home: Optional[str] - root: Optional[str] - install_lib: Optional[str] + install_base: Any + install_platbase: Any + root: str | None + install_purelib: Any + install_platlib: Any + install_headers: Any + install_lib: str | None + install_scripts: Any + install_data: Any + install_userbase: Any + install_usersite: Any + compile: Any + optimize: Any + extra_path: Any + install_path_file: int + force: int + skip_build: int + warn_dir: int + build_base: Any + build_lib: Any + record: Any def initialize_options(self) -> None: ... + config_vars: Any + install_libbase: Any def finalize_options(self) -> None: ... + def dump_dirs(self, msg) -> None: ... + def finalize_unix(self) -> None: ... + def finalize_other(self) -> None: ... + def select_scheme(self, name) -> None: ... + def expand_basedirs(self) -> None: ... + def expand_dirs(self) -> None: ... + def convert_paths(self, *names) -> None: ... + path_file: Any + extra_dirs: Any + def handle_extra_path(self) -> None: ... + def change_roots(self, *names) -> None: ... + def create_home_path(self) -> None: ... def run(self) -> None: ... + def create_path_file(self) -> None: ... + def get_outputs(self): ... + def get_inputs(self): ... + def has_lib(self): ... + def has_headers(self): ... + def has_scripts(self): ... + def has_data(self): ... + sub_commands: Any diff --git a/mypy/typeshed/stdlib/distutils/command/install_data.pyi b/mypy/typeshed/stdlib/distutils/command/install_data.pyi index e69de29bb2d1..6cc9b528ac9d 100644 --- a/mypy/typeshed/stdlib/distutils/command/install_data.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install_data.pyi @@ -0,0 +1,19 @@ +from typing import Any + +from ..cmd import Command + +class install_data(Command): + description: str + user_options: Any + boolean_options: Any + install_dir: Any + outfiles: Any + root: Any + force: int + data_files: Any + warn_dir: int + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def get_inputs(self): ... + def get_outputs(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/install_egg_info.pyi b/mypy/typeshed/stdlib/distutils/command/install_egg_info.pyi index 80ffb19bda74..776eafc1de09 100644 --- a/mypy/typeshed/stdlib/distutils/command/install_egg_info.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install_egg_info.pyi @@ -1,10 +1,18 @@ -from distutils.cmd import Command -from typing import ClassVar, List, Optional, Tuple +from typing import Any, ClassVar + +from ..cmd import Command class install_egg_info(Command): description: ClassVar[str] - user_options: ClassVar[List[Tuple[str, Optional[str], str]]] + user_options: ClassVar[list[tuple[str, str | None, str]]] + install_dir: Any def initialize_options(self) -> None: ... + target: Any + outputs: Any def finalize_options(self) -> None: ... def run(self) -> None: ... - def get_outputs(self) -> List[str]: ... + def get_outputs(self) -> list[str]: ... + +def safe_name(name): ... +def safe_version(version): ... +def to_filename(name): ... diff --git a/mypy/typeshed/stdlib/distutils/command/install_headers.pyi b/mypy/typeshed/stdlib/distutils/command/install_headers.pyi index e69de29bb2d1..795bd1cf8356 100644 --- a/mypy/typeshed/stdlib/distutils/command/install_headers.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install_headers.pyi @@ -0,0 +1,16 @@ +from typing import Any + +from ..cmd import Command + +class install_headers(Command): + description: str + user_options: Any + boolean_options: Any + install_dir: Any + force: int + outfiles: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def get_inputs(self): ... + def get_outputs(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/install_lib.pyi b/mypy/typeshed/stdlib/distutils/command/install_lib.pyi index e69de29bb2d1..a6a5e4e73f4c 100644 --- a/mypy/typeshed/stdlib/distutils/command/install_lib.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install_lib.pyi @@ -0,0 +1,25 @@ +from typing import Any + +from ..cmd import Command + +PYTHON_SOURCE_EXTENSION: str + +class install_lib(Command): + description: str + user_options: Any + boolean_options: Any + negative_opt: Any + install_dir: Any + build_dir: Any + force: int + compile: Any + optimize: Any + skip_build: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def build(self) -> None: ... + def install(self): ... + def byte_compile(self, files) -> None: ... + def get_outputs(self): ... + def get_inputs(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/install_scripts.pyi b/mypy/typeshed/stdlib/distutils/command/install_scripts.pyi index e69de29bb2d1..92728a16a747 100644 --- a/mypy/typeshed/stdlib/distutils/command/install_scripts.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install_scripts.pyi @@ -0,0 +1,18 @@ +from typing import Any + +from ..cmd import Command + +class install_scripts(Command): + description: str + user_options: Any + boolean_options: Any + install_dir: Any + force: int + build_dir: Any + skip_build: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + outfiles: Any + def run(self) -> None: ... + def get_inputs(self): ... + def get_outputs(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/register.pyi b/mypy/typeshed/stdlib/distutils/command/register.pyi index e69de29bb2d1..a1a7a45fb3d7 100644 --- a/mypy/typeshed/stdlib/distutils/command/register.pyi +++ b/mypy/typeshed/stdlib/distutils/command/register.pyi @@ -0,0 +1,18 @@ +from typing import Any + +from ..config import PyPIRCCommand + +class register(PyPIRCCommand): + description: str + sub_commands: Any + list_classifiers: int + strict: int + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def check_metadata(self) -> None: ... + def classifiers(self) -> None: ... + def verify_metadata(self) -> None: ... + def send_metadata(self) -> None: ... + def build_post_data(self, action): ... + def post_to_server(self, data, auth: Any | None = ...): ... diff --git a/mypy/typeshed/stdlib/distutils/command/sdist.pyi b/mypy/typeshed/stdlib/distutils/command/sdist.pyi index e69de29bb2d1..636c4a351d19 100644 --- a/mypy/typeshed/stdlib/distutils/command/sdist.pyi +++ b/mypy/typeshed/stdlib/distutils/command/sdist.pyi @@ -0,0 +1,42 @@ +from typing import Any + +from ..cmd import Command + +def show_formats() -> None: ... + +class sdist(Command): + description: str + def checking_metadata(self): ... + user_options: Any + boolean_options: Any + help_options: Any + negative_opt: Any + sub_commands: Any + READMES: Any + template: Any + manifest: Any + use_defaults: int + prune: int + manifest_only: int + force_manifest: int + formats: Any + keep_temp: int + dist_dir: Any + archive_files: Any + metadata_check: int + owner: Any + group: Any + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + filelist: Any + def run(self) -> None: ... + def check_metadata(self) -> None: ... + def get_file_list(self) -> None: ... + def add_defaults(self) -> None: ... + def read_template(self) -> None: ... + def prune_file_list(self) -> None: ... + def write_manifest(self) -> None: ... + def read_manifest(self) -> None: ... + def make_release_tree(self, base_dir, files) -> None: ... + def make_distribution(self) -> None: ... + def get_archive_files(self): ... diff --git a/mypy/typeshed/stdlib/distutils/command/upload.pyi b/mypy/typeshed/stdlib/distutils/command/upload.pyi index ef4bbc332230..e6b77825c5f5 100644 --- a/mypy/typeshed/stdlib/distutils/command/upload.pyi +++ b/mypy/typeshed/stdlib/distutils/command/upload.pyi @@ -1,8 +1,17 @@ -from distutils.config import PyPIRCCommand -from typing import ClassVar, List +from typing import Any, ClassVar + +from ..config import PyPIRCCommand class upload(PyPIRCCommand): description: ClassVar[str] - boolean_options: ClassVar[List[str]] + username: str + password: str + show_response: int + sign: bool + identity: Any + def initialize_options(self) -> None: ... + repository: Any + realm: Any + def finalize_options(self) -> None: ... def run(self) -> None: ... def upload_file(self, command: str, pyversion: str, filename: str) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/config.pyi b/mypy/typeshed/stdlib/distutils/config.pyi index e60507e0b65a..5814a82841cc 100644 --- a/mypy/typeshed/stdlib/distutils/config.pyi +++ b/mypy/typeshed/stdlib/distutils/config.pyi @@ -1,6 +1,6 @@ from abc import abstractmethod from distutils.cmd import Command -from typing import ClassVar, List, Optional, Tuple +from typing import ClassVar DEFAULT_PYPIRC: str @@ -9,8 +9,8 @@ class PyPIRCCommand(Command): DEFAULT_REALM: ClassVar[str] repository: None realm: None - user_options: ClassVar[List[Tuple[str, Optional[str], str]]] - boolean_options: ClassVar[List[str]] + user_options: ClassVar[list[tuple[str, str | None, str]]] + boolean_options: ClassVar[list[str]] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/distutils/core.pyi b/mypy/typeshed/stdlib/distutils/core.pyi index 9a3fa70fd381..fc4cd81c4752 100644 --- a/mypy/typeshed/stdlib/distutils/core.pyi +++ b/mypy/typeshed/stdlib/distutils/core.pyi @@ -1,7 +1,7 @@ from distutils.cmd import Command as Command from distutils.dist import Distribution as Distribution from distutils.extension import Extension as Extension -from typing import Any, List, Mapping, Optional, Tuple, Type, Union +from typing import Any, Mapping, Type def setup( *, @@ -15,34 +15,34 @@ def setup( maintainer_email: str = ..., url: str = ..., download_url: str = ..., - packages: List[str] = ..., - py_modules: List[str] = ..., - scripts: List[str] = ..., - ext_modules: List[Extension] = ..., - classifiers: List[str] = ..., + packages: list[str] = ..., + py_modules: list[str] = ..., + scripts: list[str] = ..., + ext_modules: list[Extension] = ..., + classifiers: list[str] = ..., distclass: Type[Distribution] = ..., script_name: str = ..., - script_args: List[str] = ..., + script_args: list[str] = ..., options: Mapping[str, Any] = ..., license: str = ..., - keywords: Union[List[str], str] = ..., - platforms: Union[List[str], str] = ..., + keywords: list[str] | str = ..., + platforms: list[str] | str = ..., cmdclass: Mapping[str, Type[Command]] = ..., - data_files: List[Tuple[str, List[str]]] = ..., + data_files: list[tuple[str, list[str]]] = ..., package_dir: Mapping[str, str] = ..., - obsoletes: List[str] = ..., - provides: List[str] = ..., - requires: List[str] = ..., - command_packages: List[str] = ..., - command_options: Mapping[str, Mapping[str, Tuple[Any, Any]]] = ..., - package_data: Mapping[str, List[str]] = ..., + obsoletes: list[str] = ..., + provides: list[str] = ..., + requires: list[str] = ..., + command_packages: list[str] = ..., + command_options: Mapping[str, Mapping[str, tuple[Any, Any]]] = ..., + package_data: Mapping[str, list[str]] = ..., include_package_data: bool = ..., - libraries: List[str] = ..., - headers: List[str] = ..., + libraries: list[str] = ..., + headers: list[str] = ..., ext_package: str = ..., - include_dirs: List[str] = ..., + include_dirs: list[str] = ..., password: str = ..., fullname: str = ..., **attrs: Any, ) -> None: ... -def run_setup(script_name: str, script_args: Optional[List[str]] = ..., stop_after: str = ...) -> Distribution: ... +def run_setup(script_name: str, script_args: list[str] | None = ..., stop_after: str = ...) -> Distribution: ... diff --git a/mypy/typeshed/stdlib/distutils/debug.pyi b/mypy/typeshed/stdlib/distutils/debug.pyi index 89a7f3854ab4..11f28a8bc8ae 100644 --- a/mypy/typeshed/stdlib/distutils/debug.pyi +++ b/mypy/typeshed/stdlib/distutils/debug.pyi @@ -1,3 +1 @@ -from typing import Optional - -DEBUG: Optional[bool] +DEBUG: bool | None diff --git a/mypy/typeshed/stdlib/distutils/dep_util.pyi b/mypy/typeshed/stdlib/distutils/dep_util.pyi index 6f779d540e5e..929d6ffd0c81 100644 --- a/mypy/typeshed/stdlib/distutils/dep_util.pyi +++ b/mypy/typeshed/stdlib/distutils/dep_util.pyi @@ -1,5 +1,3 @@ -from typing import List, Tuple - def newer(source: str, target: str) -> bool: ... -def newer_pairwise(sources: List[str], targets: List[str]) -> List[Tuple[str, str]]: ... -def newer_group(sources: List[str], target: str, missing: str = ...) -> bool: ... +def newer_pairwise(sources: list[str], targets: list[str]) -> list[tuple[str, str]]: ... +def newer_group(sources: list[str], target: str, missing: str = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/distutils/dir_util.pyi b/mypy/typeshed/stdlib/distutils/dir_util.pyi index 4c4a22102558..ffe5ff1cfbd4 100644 --- a/mypy/typeshed/stdlib/distutils/dir_util.pyi +++ b/mypy/typeshed/stdlib/distutils/dir_util.pyi @@ -1,7 +1,5 @@ -from typing import List - -def mkpath(name: str, mode: int = ..., verbose: int = ..., dry_run: int = ...) -> List[str]: ... -def create_tree(base_dir: str, files: List[str], mode: int = ..., verbose: int = ..., dry_run: int = ...) -> None: ... +def mkpath(name: str, mode: int = ..., verbose: int = ..., dry_run: int = ...) -> list[str]: ... +def create_tree(base_dir: str, files: list[str], mode: int = ..., verbose: int = ..., dry_run: int = ...) -> None: ... def copy_tree( src: str, dst: str, @@ -11,5 +9,5 @@ def copy_tree( update: int = ..., verbose: int = ..., dry_run: int = ..., -) -> List[str]: ... +) -> list[str]: ... def remove_tree(directory: str, verbose: int = ..., dry_run: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/dist.pyi b/mypy/typeshed/stdlib/distutils/dist.pyi index d3acdafbd5b1..5bb04b049995 100644 --- a/mypy/typeshed/stdlib/distutils/dist.pyi +++ b/mypy/typeshed/stdlib/distutils/dist.pyi @@ -1,26 +1,26 @@ -from _typeshed import AnyPath, SupportsWrite +from _typeshed import StrOrBytesPath, SupportsWrite from distutils.cmd import Command -from typing import IO, Any, Dict, Iterable, List, Mapping, Optional, Tuple, Type, Union +from typing import IO, Any, Iterable, Mapping, Type class DistributionMetadata: - def __init__(self, path: Optional[Union[int, AnyPath]] = ...) -> None: ... - name: Optional[str] - version: Optional[str] - author: Optional[str] - author_email: Optional[str] - maintainer: Optional[str] - maintainer_email: Optional[str] - url: Optional[str] - license: Optional[str] - description: Optional[str] - long_description: Optional[str] - keywords: Optional[Union[str, List[str]]] - platforms: Optional[Union[str, List[str]]] - classifiers: Optional[Union[str, List[str]]] - download_url: Optional[str] - provides: Optional[List[str]] - requires: Optional[List[str]] - obsoletes: Optional[List[str]] + def __init__(self, path: int | StrOrBytesPath | None = ...) -> None: ... + name: str | None + version: str | None + author: str | None + author_email: str | None + maintainer: str | None + maintainer_email: str | None + url: str | None + license: str | None + description: str | None + long_description: str | None + keywords: str | list[str] | None + platforms: str | list[str] | None + classifiers: str | list[str] | None + download_url: str | None + provides: list[str] | None + requires: list[str] | None + obsoletes: list[str] | None def read_pkg_file(self, file: IO[str]) -> None: ... def write_pkg_info(self, base_dir: str) -> None: ... def write_pkg_file(self, file: SupportsWrite[str]) -> None: ... @@ -38,21 +38,21 @@ class DistributionMetadata: def get_licence(self) -> str: ... def get_description(self) -> str: ... def get_long_description(self) -> str: ... - def get_keywords(self) -> Union[str, List[str]]: ... - def get_platforms(self) -> Union[str, List[str]]: ... - def get_classifiers(self) -> Union[str, List[str]]: ... + def get_keywords(self) -> str | list[str]: ... + def get_platforms(self) -> str | list[str]: ... + def get_classifiers(self) -> str | list[str]: ... def get_download_url(self) -> str: ... - def get_requires(self) -> List[str]: ... + def get_requires(self) -> list[str]: ... def set_requires(self, value: Iterable[str]) -> None: ... - def get_provides(self) -> List[str]: ... + def get_provides(self) -> list[str]: ... def set_provides(self, value: Iterable[str]) -> None: ... - def get_obsoletes(self) -> List[str]: ... + def get_obsoletes(self) -> list[str]: ... def set_obsoletes(self, value: Iterable[str]) -> None: ... class Distribution: - cmdclass: Dict[str, Type[Command]] + cmdclass: dict[str, Type[Command]] metadata: DistributionMetadata - def __init__(self, attrs: Optional[Mapping[str, Any]] = ...) -> None: ... - def get_option_dict(self, command: str) -> Dict[str, Tuple[str, str]]: ... - def parse_config_files(self, filenames: Optional[Iterable[str]] = ...) -> None: ... - def get_command_obj(self, command: str, create: bool = ...) -> Optional[Command]: ... + def __init__(self, attrs: Mapping[str, Any] | None = ...) -> None: ... + def get_option_dict(self, command: str) -> dict[str, tuple[str, str]]: ... + def parse_config_files(self, filenames: Iterable[str] | None = ...) -> None: ... + def get_command_obj(self, command: str, create: bool = ...) -> Command | None: ... diff --git a/mypy/typeshed/stdlib/distutils/extension.pyi b/mypy/typeshed/stdlib/distutils/extension.pyi index 47aa8ad4f040..655ea1e9e347 100644 --- a/mypy/typeshed/stdlib/distutils/extension.pyi +++ b/mypy/typeshed/stdlib/distutils/extension.pyi @@ -1,22 +1,20 @@ -from typing import List, Optional, Tuple - class Extension: def __init__( self, name: str, - sources: List[str], - include_dirs: Optional[List[str]] = ..., - define_macros: Optional[List[Tuple[str, Optional[str]]]] = ..., - undef_macros: Optional[List[str]] = ..., - library_dirs: Optional[List[str]] = ..., - libraries: Optional[List[str]] = ..., - runtime_library_dirs: Optional[List[str]] = ..., - extra_objects: Optional[List[str]] = ..., - extra_compile_args: Optional[List[str]] = ..., - extra_link_args: Optional[List[str]] = ..., - export_symbols: Optional[List[str]] = ..., - swig_opts: Optional[str] = ..., # undocumented - depends: Optional[List[str]] = ..., - language: Optional[str] = ..., - optional: Optional[bool] = ..., + sources: list[str], + include_dirs: list[str] | None = ..., + define_macros: list[tuple[str, str | None]] | None = ..., + undef_macros: list[str] | None = ..., + library_dirs: list[str] | None = ..., + libraries: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + extra_objects: list[str] | None = ..., + extra_compile_args: list[str] | None = ..., + extra_link_args: list[str] | None = ..., + export_symbols: list[str] | None = ..., + swig_opts: str | None = ..., # undocumented + depends: list[str] | None = ..., + language: str | None = ..., + optional: bool | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi index 00f2cd648aeb..06a0847e4687 100644 --- a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi @@ -1,22 +1,22 @@ -from typing import Any, Iterable, List, Mapping, Optional, Tuple, Union, overload +from typing import Any, Iterable, List, Mapping, Optional, Tuple, overload _Option = Tuple[str, Optional[str], str] _GR = Tuple[List[str], OptionDummy] def fancy_getopt( - options: List[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: Optional[List[str]] -) -> Union[List[str], _GR]: ... -def wrap_text(text: str, width: int) -> List[str]: ... + options: list[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: list[str] | None +) -> list[str] | _GR: ... +def wrap_text(text: str, width: int) -> list[str]: ... class FancyGetopt: - def __init__(self, option_table: Optional[List[_Option]] = ...) -> None: ... + def __init__(self, option_table: list[_Option] | None = ...) -> None: ... # TODO kinda wrong, `getopt(object=object())` is invalid @overload - def getopt(self, args: Optional[List[str]] = ...) -> _GR: ... + def getopt(self, args: list[str] | None = ...) -> _GR: ... @overload - def getopt(self, args: Optional[List[str]], object: Any) -> List[str]: ... - def get_option_order(self) -> List[Tuple[str, str]]: ... - def generate_help(self, header: Optional[str] = ...) -> List[str]: ... + def getopt(self, args: list[str] | None, object: Any) -> list[str]: ... + def get_option_order(self) -> list[tuple[str, str]]: ... + def generate_help(self, header: str | None = ...) -> list[str]: ... class OptionDummy: def __init__(self, options: Iterable[str] = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/file_util.pyi b/mypy/typeshed/stdlib/distutils/file_util.pyi index 018339733df0..a7f24105a678 100644 --- a/mypy/typeshed/stdlib/distutils/file_util.pyi +++ b/mypy/typeshed/stdlib/distutils/file_util.pyi @@ -1,4 +1,4 @@ -from typing import Optional, Sequence, Tuple +from typing import Sequence def copy_file( src: str, @@ -6,9 +6,9 @@ def copy_file( preserve_mode: bool = ..., preserve_times: bool = ..., update: bool = ..., - link: Optional[str] = ..., + link: str | None = ..., verbose: bool = ..., dry_run: bool = ..., -) -> Tuple[str, str]: ... +) -> tuple[str, str]: ... def move_file(src: str, dst: str, verbose: bool = ..., dry_run: bool = ...) -> str: ... def write_file(filename: str, contents: Sequence[str]) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/filelist.pyi b/mypy/typeshed/stdlib/distutils/filelist.pyi index 99e26218f171..2b436938f13e 100644 --- a/mypy/typeshed/stdlib/distutils/filelist.pyi +++ b/mypy/typeshed/stdlib/distutils/filelist.pyi @@ -1,10 +1,10 @@ -from typing import Iterable, List, Optional, Pattern, Union, overload +from typing import Iterable, Pattern, overload from typing_extensions import Literal # class is entirely undocumented class FileList: - allfiles: Optional[Iterable[str]] = ... - files: List[str] = ... + allfiles: Iterable[str] | None + files: list[str] def __init__(self, warn: None = ..., debug_print: None = ...) -> None: ... def set_allfiles(self, allfiles: Iterable[str]) -> None: ... def findall(self, dir: str = ...) -> None: ... @@ -16,45 +16,34 @@ class FileList: def process_template_line(self, line: str) -> None: ... @overload def include_pattern( - self, pattern: str, anchor: Union[int, bool] = ..., prefix: Optional[str] = ..., is_regex: Literal[0, False] = ... + self, pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... ) -> bool: ... @overload - def include_pattern(self, pattern: Union[str, Pattern[str]], *, is_regex: Literal[True, 1] = ...) -> bool: ... + def include_pattern(self, pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> bool: ... @overload def include_pattern( - self, - pattern: Union[str, Pattern[str]], - anchor: Union[int, bool] = ..., - prefix: Optional[str] = ..., - is_regex: Union[int, bool] = ..., + self, pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... ) -> bool: ... @overload def exclude_pattern( - self, pattern: str, anchor: Union[int, bool] = ..., prefix: Optional[str] = ..., is_regex: Literal[0, False] = ... + self, pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... ) -> bool: ... @overload - def exclude_pattern(self, pattern: Union[str, Pattern[str]], *, is_regex: Literal[True, 1] = ...) -> bool: ... + def exclude_pattern(self, pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> bool: ... @overload def exclude_pattern( - self, - pattern: Union[str, Pattern[str]], - anchor: Union[int, bool] = ..., - prefix: Optional[str] = ..., - is_regex: Union[int, bool] = ..., + self, pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... ) -> bool: ... -def findall(dir: str = ...) -> List[str]: ... +def findall(dir: str = ...) -> list[str]: ... def glob_to_re(pattern: str) -> str: ... @overload def translate_pattern( - pattern: str, anchor: Union[int, bool] = ..., prefix: Optional[str] = ..., is_regex: Literal[False, 0] = ... + pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[False, 0] = ... ) -> Pattern[str]: ... @overload -def translate_pattern(pattern: Union[str, Pattern[str]], *, is_regex: Literal[True, 1] = ...) -> Pattern[str]: ... +def translate_pattern(pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> Pattern[str]: ... @overload def translate_pattern( - pattern: Union[str, Pattern[str]], - anchor: Union[int, bool] = ..., - prefix: Optional[str] = ..., - is_regex: Union[int, bool] = ..., + pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... ) -> Pattern[str]: ... diff --git a/mypy/typeshed/stdlib/distutils/spawn.pyi b/mypy/typeshed/stdlib/distutils/spawn.pyi index e12eae99bf29..dda05ad7e85a 100644 --- a/mypy/typeshed/stdlib/distutils/spawn.pyi +++ b/mypy/typeshed/stdlib/distutils/spawn.pyi @@ -1,4 +1,2 @@ -from typing import List, Optional - -def spawn(cmd: List[str], search_path: bool = ..., verbose: bool = ..., dry_run: bool = ...) -> None: ... -def find_executable(executable: str, path: Optional[str] = ...) -> Optional[str]: ... +def spawn(cmd: list[str], search_path: bool = ..., verbose: bool = ..., dry_run: bool = ...) -> None: ... +def find_executable(executable: str, path: str | None = ...) -> str | None: ... diff --git a/mypy/typeshed/stdlib/distutils/sysconfig.pyi b/mypy/typeshed/stdlib/distutils/sysconfig.pyi index 4b4baf416ffa..3f579be40882 100644 --- a/mypy/typeshed/stdlib/distutils/sysconfig.pyi +++ b/mypy/typeshed/stdlib/distutils/sysconfig.pyi @@ -1,13 +1,13 @@ from distutils.ccompiler import CCompiler -from typing import Mapping, Optional, Union +from typing import Mapping PREFIX: str EXEC_PREFIX: str -def get_config_var(name: str) -> Union[int, str, None]: ... -def get_config_vars(*args: str) -> Mapping[str, Union[int, str]]: ... +def get_config_var(name: str) -> int | str | None: ... +def get_config_vars(*args: str) -> Mapping[str, int | str]: ... def get_config_h_filename() -> str: ... def get_makefile_filename() -> str: ... -def get_python_inc(plat_specific: bool = ..., prefix: Optional[str] = ...) -> str: ... -def get_python_lib(plat_specific: bool = ..., standard_lib: bool = ..., prefix: Optional[str] = ...) -> str: ... +def get_python_inc(plat_specific: bool = ..., prefix: str | None = ...) -> str: ... +def get_python_lib(plat_specific: bool = ..., standard_lib: bool = ..., prefix: str | None = ...) -> str: ... def customize_compiler(compiler: CCompiler) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/text_file.pyi b/mypy/typeshed/stdlib/distutils/text_file.pyi index a65f37305d94..ace642e027cf 100644 --- a/mypy/typeshed/stdlib/distutils/text_file.pyi +++ b/mypy/typeshed/stdlib/distutils/text_file.pyi @@ -1,10 +1,10 @@ -from typing import IO, List, Optional, Tuple, Union +from typing import IO class TextFile: def __init__( self, - filename: Optional[str] = ..., - file: Optional[IO[str]] = ..., + filename: str | None = ..., + file: IO[str] | None = ..., *, strip_comments: bool = ..., lstrip_ws: bool = ..., @@ -15,7 +15,7 @@ class TextFile: ) -> None: ... def open(self, filename: str) -> None: ... def close(self) -> None: ... - def warn(self, msg: str, line: Optional[Union[List[int], Tuple[int, int], int]] = ...) -> None: ... - def readline(self) -> Optional[str]: ... - def readlines(self) -> List[str]: ... + def warn(self, msg: str, line: list[int] | tuple[int, int] | int | None = ...) -> None: ... + def readline(self) -> str | None: ... + def readlines(self) -> list[str]: ... def unreadline(self, line: str) -> str: ... diff --git a/mypy/typeshed/stdlib/distutils/util.pyi b/mypy/typeshed/stdlib/distutils/util.pyi index 0086d726af65..9b0915570ece 100644 --- a/mypy/typeshed/stdlib/distutils/util.pyi +++ b/mypy/typeshed/stdlib/distutils/util.pyi @@ -1,23 +1,45 @@ -from typing import Any, Callable, List, Mapping, Optional, Tuple +from _typeshed import StrPath +from collections.abc import Callable, Container, Iterable, Mapping +from typing import Any, Tuple def get_platform() -> str: ... def convert_path(pathname: str) -> str: ... def change_root(new_root: str, pathname: str) -> str: ... def check_environ() -> None: ... def subst_vars(s: str, local_vars: Mapping[str, str]) -> None: ... -def split_quoted(s: str) -> List[str]: ... +def split_quoted(s: str) -> list[str]: ... def execute( - func: Callable[..., None], args: Tuple[Any, ...], msg: Optional[str] = ..., verbose: bool = ..., dry_run: bool = ... + func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... ) -> None: ... def strtobool(val: str) -> bool: ... def byte_compile( - py_files: List[str], + py_files: list[str], optimize: int = ..., force: bool = ..., - prefix: Optional[str] = ..., - base_dir: Optional[str] = ..., + prefix: str | None = ..., + base_dir: str | None = ..., verbose: bool = ..., dry_run: bool = ..., - direct: Optional[bool] = ..., + direct: bool | None = ..., ) -> None: ... def rfc822_escape(header: str) -> str: ... +def run_2to3( + files: Iterable[str], + fixer_names: Iterable[str] | None = ..., + options: Mapping[str, Any] | None = ..., + explicit: Container[str] | None = ..., # unused +) -> None: ... +def copydir_run_2to3( + src: StrPath, + dest: StrPath, + template: str | None = ..., + fixer_names: Iterable[str] | None = ..., + options: Mapping[str, Any] | None = ..., + explicit: Container[str] | None = ..., +) -> list[str]: ... + +class Mixin2to3: + fixer_names: Iterable[str] | None + options: Mapping[str, Any] | None + explicit: Container[str] | None + def run_2to3(self, files: Iterable[str]) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/version.pyi b/mypy/typeshed/stdlib/distutils/version.pyi index 311b0bead960..9921dde39af6 100644 --- a/mypy/typeshed/stdlib/distutils/version.pyi +++ b/mypy/typeshed/stdlib/distutils/version.pyi @@ -1,38 +1,38 @@ from abc import abstractmethod -from typing import Optional, Pattern, Tuple, TypeVar, Union +from typing import Pattern, Tuple, TypeVar _T = TypeVar("_T", bound=Version) class Version: def __repr__(self) -> str: ... def __eq__(self, other: object) -> bool: ... - def __lt__(self: _T, other: Union[_T, str]) -> bool: ... - def __le__(self: _T, other: Union[_T, str]) -> bool: ... - def __gt__(self: _T, other: Union[_T, str]) -> bool: ... - def __ge__(self: _T, other: Union[_T, str]) -> bool: ... + def __lt__(self: _T, other: _T | str) -> bool: ... + def __le__(self: _T, other: _T | str) -> bool: ... + def __gt__(self: _T, other: _T | str) -> bool: ... + def __ge__(self: _T, other: _T | str) -> bool: ... @abstractmethod - def __init__(self, vstring: Optional[str] = ...) -> None: ... + def __init__(self, vstring: str | None = ...) -> None: ... @abstractmethod def parse(self: _T, vstring: str) -> _T: ... @abstractmethod def __str__(self) -> str: ... @abstractmethod - def _cmp(self: _T, other: Union[_T, str]) -> bool: ... + def _cmp(self: _T, other: _T | str) -> bool: ... class StrictVersion(Version): version_re: Pattern[str] - version: Tuple[int, int, int] - prerelease: Optional[Tuple[str, int]] - def __init__(self, vstring: Optional[str] = ...) -> None: ... + version: tuple[int, int, int] + prerelease: tuple[str, int] | None + def __init__(self, vstring: str | None = ...) -> None: ... def parse(self: _T, vstring: str) -> _T: ... def __str__(self) -> str: ... - def _cmp(self: _T, other: Union[_T, str]) -> bool: ... + def _cmp(self: _T, other: _T | str) -> bool: ... class LooseVersion(Version): component_re: Pattern[str] vstring: str - version: Tuple[Union[str, int], ...] - def __init__(self, vstring: Optional[str] = ...) -> None: ... + version: Tuple[str | int, ...] + def __init__(self, vstring: str | None = ...) -> None: ... def parse(self: _T, vstring: str) -> _T: ... def __str__(self) -> str: ... - def _cmp(self: _T, other: Union[_T, str]) -> bool: ... + def _cmp(self: _T, other: _T | str) -> bool: ... diff --git a/mypy/typeshed/stdlib/doctest.pyi b/mypy/typeshed/stdlib/doctest.pyi index ae84c2c25efc..9a9f83b0d8fe 100644 --- a/mypy/typeshed/stdlib/doctest.pyi +++ b/mypy/typeshed/stdlib/doctest.pyi @@ -1,13 +1,12 @@ -import sys import types import unittest -from typing import Any, Callable, Dict, List, NamedTuple, Optional, Tuple, Type, Union +from typing import Any, Callable, NamedTuple, Tuple, Type class TestResults(NamedTuple): failed: int attempted: int -OPTIONFLAGS_BY_NAME: Dict[str, int] +OPTIONFLAGS_BY_NAME: dict[str, int] def register_optionflag(name: str) -> int: ... @@ -24,8 +23,7 @@ REPORT_UDIFF: int REPORT_CDIFF: int REPORT_NDIFF: int REPORT_ONLY_FIRST_FAILURE: int -if sys.version_info >= (3, 4): - FAIL_FAST: int +FAIL_FAST: int REPORTING_FLAGS: int @@ -35,46 +33,44 @@ ELLIPSIS_MARKER: str class Example: source: str want: str - exc_msg: Optional[str] + exc_msg: str | None lineno: int indent: int - options: Dict[int, bool] + options: dict[int, bool] def __init__( self, source: str, want: str, - exc_msg: Optional[str] = ..., + exc_msg: str | None = ..., lineno: int = ..., indent: int = ..., - options: Optional[Dict[int, bool]] = ..., + options: dict[int, bool] | None = ..., ) -> None: ... def __hash__(self) -> int: ... class DocTest: - examples: List[Example] - globs: Dict[str, Any] + examples: list[Example] + globs: dict[str, Any] name: str - filename: Optional[str] - lineno: Optional[int] - docstring: Optional[str] + filename: str | None + lineno: int | None + docstring: str | None def __init__( self, - examples: List[Example], - globs: Dict[str, Any], + examples: list[Example], + globs: dict[str, Any], name: str, - filename: Optional[str], - lineno: Optional[int], - docstring: Optional[str], + filename: str | None, + lineno: int | None, + docstring: str | None, ) -> None: ... def __hash__(self) -> int: ... def __lt__(self, other: DocTest) -> bool: ... class DocTestParser: - def parse(self, string: str, name: str = ...) -> List[Union[str, Example]]: ... - def get_doctest( - self, string: str, globs: Dict[str, Any], name: str, filename: Optional[str], lineno: Optional[int] - ) -> DocTest: ... - def get_examples(self, string: str, name: str = ...) -> List[Example]: ... + def parse(self, string: str, name: str = ...) -> list[str | Example]: ... + def get_doctest(self, string: str, globs: dict[str, Any], name: str, filename: str | None, lineno: int | None) -> DocTest: ... + def get_examples(self, string: str, name: str = ...) -> list[Example]: ... class DocTestFinder: def __init__( @@ -83,11 +79,11 @@ class DocTestFinder: def find( self, obj: object, - name: Optional[str] = ..., - module: Union[None, bool, types.ModuleType] = ..., - globs: Optional[Dict[str, Any]] = ..., - extraglobs: Optional[Dict[str, Any]] = ..., - ) -> List[DocTest]: ... + name: str | None = ..., + module: None | bool | types.ModuleType = ..., + globs: dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., + ) -> list[DocTest]: ... _Out = Callable[[str], Any] _ExcInfo = Tuple[Type[BaseException], BaseException, types.TracebackType] @@ -99,15 +95,15 @@ class DocTestRunner: tries: int failures: int test: DocTest - def __init__(self, checker: Optional[OutputChecker] = ..., verbose: Optional[bool] = ..., optionflags: int = ...) -> None: ... + def __init__(self, checker: OutputChecker | None = ..., verbose: bool | None = ..., optionflags: int = ...) -> None: ... def report_start(self, out: _Out, test: DocTest, example: Example) -> None: ... def report_success(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... def report_failure(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... def report_unexpected_exception(self, out: _Out, test: DocTest, example: Example, exc_info: _ExcInfo) -> None: ... def run( - self, test: DocTest, compileflags: Optional[int] = ..., out: Optional[_Out] = ..., clear_globs: bool = ... + self, test: DocTest, compileflags: int | None = ..., out: _Out | None = ..., clear_globs: bool = ... ) -> TestResults: ... - def summarize(self, verbose: Optional[bool] = ...) -> TestResults: ... + def summarize(self, verbose: bool | None = ...) -> TestResults: ... def merge(self, other: DocTestRunner) -> None: ... class OutputChecker: @@ -128,40 +124,35 @@ class UnexpectedException(Exception): class DebugRunner(DocTestRunner): ... -master: Optional[DocTestRunner] +master: DocTestRunner | None def testmod( - m: Optional[types.ModuleType] = ..., - name: Optional[str] = ..., - globs: Optional[Dict[str, Any]] = ..., - verbose: Optional[bool] = ..., + m: types.ModuleType | None = ..., + name: str | None = ..., + globs: dict[str, Any] | None = ..., + verbose: bool | None = ..., report: bool = ..., optionflags: int = ..., - extraglobs: Optional[Dict[str, Any]] = ..., + extraglobs: dict[str, Any] | None = ..., raise_on_error: bool = ..., exclude_empty: bool = ..., ) -> TestResults: ... def testfile( filename: str, module_relative: bool = ..., - name: Optional[str] = ..., - package: Union[None, str, types.ModuleType] = ..., - globs: Optional[Dict[str, Any]] = ..., - verbose: Optional[bool] = ..., + name: str | None = ..., + package: None | str | types.ModuleType = ..., + globs: dict[str, Any] | None = ..., + verbose: bool | None = ..., report: bool = ..., optionflags: int = ..., - extraglobs: Optional[Dict[str, Any]] = ..., + extraglobs: dict[str, Any] | None = ..., raise_on_error: bool = ..., parser: DocTestParser = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., ) -> TestResults: ... def run_docstring_examples( - f: object, - globs: Dict[str, Any], - verbose: bool = ..., - name: str = ..., - compileflags: Optional[int] = ..., - optionflags: int = ..., + f: object, globs: dict[str, Any], verbose: bool = ..., name: str = ..., compileflags: int | None = ..., optionflags: int = ... ) -> None: ... def set_unittest_reportflags(flags: int) -> int: ... @@ -170,9 +161,9 @@ class DocTestCase(unittest.TestCase): self, test: DocTest, optionflags: int = ..., - setUp: Optional[Callable[[DocTest], Any]] = ..., - tearDown: Optional[Callable[[DocTest], Any]] = ..., - checker: Optional[OutputChecker] = ..., + setUp: Callable[[DocTest], Any] | None = ..., + tearDown: Callable[[DocTest], Any] | None = ..., + checker: OutputChecker | None = ..., ) -> None: ... def setUp(self) -> None: ... def tearDown(self) -> None: ... @@ -189,17 +180,13 @@ class SkipDocTestCase(DocTestCase): def test_skip(self) -> None: ... def shortDescription(self) -> str: ... -if sys.version_info >= (3, 4): - class _DocTestSuite(unittest.TestSuite): ... - -else: - _DocTestSuite = unittest.TestSuite +class _DocTestSuite(unittest.TestSuite): ... def DocTestSuite( - module: Union[None, str, types.ModuleType] = ..., - globs: Optional[Dict[str, Any]] = ..., - extraglobs: Optional[Dict[str, Any]] = ..., - test_finder: Optional[DocTestFinder] = ..., + module: None | str | types.ModuleType = ..., + globs: dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., + test_finder: DocTestFinder | None = ..., **options: Any, ) -> _DocTestSuite: ... @@ -210,15 +197,15 @@ class DocFileCase(DocTestCase): def DocFileTest( path: str, module_relative: bool = ..., - package: Union[None, str, types.ModuleType] = ..., - globs: Optional[Dict[str, Any]] = ..., + package: None | str | types.ModuleType = ..., + globs: dict[str, Any] | None = ..., parser: DocTestParser = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., **options: Any, ) -> DocFileCase: ... def DocFileSuite(*paths: str, **kw: Any) -> _DocTestSuite: ... def script_from_examples(s: str) -> str: ... -def testsource(module: Union[None, str, types.ModuleType], name: str) -> str: ... -def debug_src(src: str, pm: bool = ..., globs: Optional[Dict[str, Any]] = ...) -> None: ... -def debug_script(src: str, pm: bool = ..., globs: Optional[Dict[str, Any]] = ...) -> None: ... -def debug(module: Union[None, str, types.ModuleType], name: str, pm: bool = ...) -> None: ... +def testsource(module: None | str | types.ModuleType, name: str) -> str: ... +def debug_src(src: str, pm: bool = ..., globs: dict[str, Any] | None = ...) -> None: ... +def debug_script(src: str, pm: bool = ..., globs: dict[str, Any] | None = ...) -> None: ... +def debug(module: None | str | types.ModuleType, name: str, pm: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/_header_value_parser.pyi b/mypy/typeshed/stdlib/email/_header_value_parser.pyi index 22a2a643ed1b..f1b08b5d5805 100644 --- a/mypy/typeshed/stdlib/email/_header_value_parser.pyi +++ b/mypy/typeshed/stdlib/email/_header_value_parser.pyi @@ -1,22 +1,22 @@ import sys from email.errors import HeaderParseError, MessageDefect from email.policy import Policy -from typing import Any, Iterable, Iterator, List, Optional, Pattern, Set, Tuple, Type, TypeVar, Union +from typing import Any, Iterable, Iterator, List, Pattern, Type, TypeVar, Union from typing_extensions import Final _T = TypeVar("_T") -WSP: Final[Set[str]] = ... -CFWS_LEADER: Final[Set[str]] = ... -SPECIALS: Final[Set[str]] = ... -ATOM_ENDS: Final[Set[str]] = ... -DOT_ATOM_ENDS: Final[Set[str]] = ... -PHRASE_ENDS: Final[Set[str]] = ... -TSPECIALS: Final[Set[str]] = ... -TOKEN_ENDS: Final[Set[str]] = ... -ASPECIALS: Final[Set[str]] = ... -ATTRIBUTE_ENDS: Final[Set[str]] = ... -EXTENDED_ATTRIBUTE_ENDS: Final[Set[str]] = ... +WSP: Final[set[str]] +CFWS_LEADER: Final[set[str]] +SPECIALS: Final[set[str]] +ATOM_ENDS: Final[set[str]] +DOT_ATOM_ENDS: Final[set[str]] +PHRASE_ENDS: Final[set[str]] +TSPECIALS: Final[set[str]] +TOKEN_ENDS: Final[set[str]] +ASPECIALS: Final[set[str]] +ATTRIBUTE_ENDS: Final[set[str]] +EXTENDED_ATTRIBUTE_ENDS: Final[set[str]] def quote_string(value: Any) -> str: ... @@ -24,20 +24,20 @@ if sys.version_info >= (3, 7): rfc2047_matcher: Pattern[str] class TokenList(List[Union[TokenList, Terminal]]): - token_type: Optional[str] = ... - syntactic_break: bool = ... - ew_combine_allowed: bool = ... - defects: List[MessageDefect] = ... + token_type: str | None + syntactic_break: bool + ew_combine_allowed: bool + defects: list[MessageDefect] def __init__(self, *args: Any, **kw: Any) -> None: ... @property def value(self) -> str: ... @property - def all_defects(self) -> List[MessageDefect]: ... + def all_defects(self) -> list[MessageDefect]: ... def startswith_fws(self) -> bool: ... @property def as_ew_allowed(self) -> bool: ... @property - def comments(self) -> List[str]: ... + def comments(self) -> list[str]: ... def fold(self, *, policy: Policy) -> str: ... def pprint(self, indent: str = ...) -> None: ... def ppstr(self, indent: str = ...) -> str: ... @@ -46,35 +46,35 @@ class WhiteSpaceTokenList(TokenList): @property def value(self) -> str: ... @property - def comments(self) -> List[str]: ... + def comments(self) -> list[str]: ... class UnstructuredTokenList(TokenList): - token_type: str = ... + token_type: str class Phrase(TokenList): - token_type: str = ... + token_type: str class Word(TokenList): - token_type: str = ... + token_type: str class CFWSList(WhiteSpaceTokenList): - token_type: str = ... + token_type: str class Atom(TokenList): - token_type: str = ... + token_type: str class Token(TokenList): - token_type: str = ... - encode_as_ew: bool = ... + token_type: str + encode_as_ew: bool class EncodedWord(TokenList): - token_type: str = ... - cte: Optional[str] = ... - charset: Optional[str] = ... - lang: Optional[str] = ... + token_type: str + cte: str | None + charset: str | None + lang: str | None class QuotedString(TokenList): - token_type: str = ... + token_type: str @property def content(self) -> str: ... @property @@ -83,61 +83,61 @@ class QuotedString(TokenList): def stripped_value(self) -> str: ... class BareQuotedString(QuotedString): - token_type: str = ... + token_type: str @property def value(self) -> str: ... class Comment(WhiteSpaceTokenList): - token_type: str = ... + token_type: str def quote(self, value: Any) -> str: ... @property def content(self) -> str: ... @property - def comments(self) -> List[str]: ... + def comments(self) -> list[str]: ... class AddressList(TokenList): - token_type: str = ... + token_type: str @property - def addresses(self) -> List[Address]: ... + def addresses(self) -> list[Address]: ... @property - def mailboxes(self) -> List[Mailbox]: ... + def mailboxes(self) -> list[Mailbox]: ... @property - def all_mailboxes(self) -> List[Mailbox]: ... + def all_mailboxes(self) -> list[Mailbox]: ... class Address(TokenList): - token_type: str = ... + token_type: str @property def display_name(self) -> str: ... @property - def mailboxes(self) -> List[Mailbox]: ... + def mailboxes(self) -> list[Mailbox]: ... @property - def all_mailboxes(self) -> List[Mailbox]: ... + def all_mailboxes(self) -> list[Mailbox]: ... class MailboxList(TokenList): - token_type: str = ... + token_type: str @property - def mailboxes(self) -> List[Mailbox]: ... + def mailboxes(self) -> list[Mailbox]: ... @property - def all_mailboxes(self) -> List[Mailbox]: ... + def all_mailboxes(self) -> list[Mailbox]: ... class GroupList(TokenList): - token_type: str = ... + token_type: str @property - def mailboxes(self) -> List[Mailbox]: ... + def mailboxes(self) -> list[Mailbox]: ... @property - def all_mailboxes(self) -> List[Mailbox]: ... + def all_mailboxes(self) -> list[Mailbox]: ... class Group(TokenList): - token_type: str = ... + token_type: str @property - def mailboxes(self) -> List[Mailbox]: ... + def mailboxes(self) -> list[Mailbox]: ... @property - def all_mailboxes(self) -> List[Mailbox]: ... + def all_mailboxes(self) -> list[Mailbox]: ... @property def display_name(self) -> str: ... class NameAddr(TokenList): - token_type: str = ... + token_type: str @property def display_name(self) -> str: ... @property @@ -145,28 +145,28 @@ class NameAddr(TokenList): @property def domain(self) -> str: ... @property - def route(self) -> Optional[List[Domain]]: ... + def route(self) -> list[Domain] | None: ... @property def addr_spec(self) -> str: ... class AngleAddr(TokenList): - token_type: str = ... + token_type: str @property def local_part(self) -> str: ... @property def domain(self) -> str: ... @property - def route(self) -> Optional[List[Domain]]: ... + def route(self) -> list[Domain] | None: ... @property def addr_spec(self) -> str: ... class ObsRoute(TokenList): - token_type: str = ... + token_type: str @property - def domains(self) -> List[Domain]: ... + def domains(self) -> list[Domain]: ... class Mailbox(TokenList): - token_type: str = ... + token_type: str @property def display_name(self) -> str: ... @property @@ -174,40 +174,40 @@ class Mailbox(TokenList): @property def domain(self) -> str: ... @property - def route(self) -> List[str]: ... + def route(self) -> list[str]: ... @property def addr_spec(self) -> str: ... class InvalidMailbox(TokenList): - token_type: str = ... + token_type: str @property def display_name(self) -> None: ... - local_part: None = ... - domain: None = ... - route: None = ... - addr_spec: None = ... + local_part: None + domain: None + route: None + addr_spec: None class Domain(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool @property def domain(self) -> str: ... class DotAtom(TokenList): - token_type: str = ... + token_type: str class DotAtomText(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool if sys.version_info >= (3, 8): class NoFoldLiteral(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool class AddrSpec(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool @property def local_part(self) -> str: ... @property @@ -218,123 +218,123 @@ class AddrSpec(TokenList): def addr_spec(self) -> str: ... class ObsLocalPart(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool class DisplayName(Phrase): - token_type: str = ... - ew_combine_allowed: bool = ... + token_type: str + ew_combine_allowed: bool @property def display_name(self) -> str: ... @property def value(self) -> str: ... class LocalPart(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool @property def value(self) -> str: ... @property def local_part(self) -> str: ... class DomainLiteral(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool @property def domain(self) -> str: ... @property def ip(self) -> str: ... class MIMEVersion(TokenList): - token_type: str = ... - major: Optional[int] = ... - minor: Optional[int] = ... + token_type: str + major: int | None + minor: int | None class Parameter(TokenList): - token_type: str = ... - sectioned: bool = ... - extended: bool = ... - charset: str = ... + token_type: str + sectioned: bool + extended: bool + charset: str @property def section_number(self) -> int: ... @property def param_value(self) -> str: ... class InvalidParameter(Parameter): - token_type: str = ... + token_type: str class Attribute(TokenList): - token_type: str = ... + token_type: str @property def stripped_value(self) -> str: ... class Section(TokenList): - token_type: str = ... - number: Optional[int] = ... + token_type: str + number: int | None class Value(TokenList): - token_type: str = ... + token_type: str @property def stripped_value(self) -> str: ... class MimeParameters(TokenList): - token_type: str = ... - syntactic_break: bool = ... + token_type: str + syntactic_break: bool @property - def params(self) -> Iterator[Tuple[str, str]]: ... + def params(self) -> Iterator[tuple[str, str]]: ... class ParameterizedHeaderValue(TokenList): - syntactic_break: bool = ... + syntactic_break: bool @property - def params(self) -> Iterable[Tuple[str, str]]: ... + def params(self) -> Iterable[tuple[str, str]]: ... class ContentType(ParameterizedHeaderValue): - token_type: str = ... - as_ew_allowed: bool = ... - maintype: str = ... - subtype: str = ... + token_type: str + as_ew_allowed: bool + maintype: str + subtype: str class ContentDisposition(ParameterizedHeaderValue): - token_type: str = ... - as_ew_allowed: bool = ... - content_disposition: Any = ... + token_type: str + as_ew_allowed: bool + content_disposition: Any class ContentTransferEncoding(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... - cte: str = ... + token_type: str + as_ew_allowed: bool + cte: str class HeaderLabel(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool if sys.version_info >= (3, 8): class MsgID(TokenList): - token_type: str = ... - as_ew_allowed: bool = ... + token_type: str + as_ew_allowed: bool def fold(self, policy: Policy) -> str: ... class MessageID(MsgID): - token_type: str = ... + token_type: str class InvalidMessageID(MessageID): - token_type: str = ... + token_type: str class Header(TokenList): - token_type: str = ... + token_type: str class Terminal(str): - as_ew_allowed: bool = ... - ew_combine_allowed: bool = ... - syntactic_break: bool = ... - token_type: str = ... - defects: List[MessageDefect] = ... + as_ew_allowed: bool + ew_combine_allowed: bool + syntactic_break: bool + token_type: str + defects: list[MessageDefect] def __new__(cls: Type[_T], value: str, token_type: str) -> _T: ... def pprint(self) -> None: ... @property - def all_defects(self) -> List[MessageDefect]: ... + def all_defects(self) -> list[MessageDefect]: ... def pop_trailing_ws(self) -> None: ... @property - def comments(self) -> List[str]: ... - def __getnewargs__(self) -> Tuple[str, str]: ... # type: ignore + def comments(self) -> list[str]: ... + def __getnewargs__(self) -> tuple[str, str]: ... # type: ignore class WhiteSpaceTerminal(Terminal): @property @@ -356,55 +356,55 @@ DOT: Final[ValueTerminal] ListSeparator: Final[ValueTerminal] RouteComponentMarker: Final[ValueTerminal] -def get_fws(value: str) -> Tuple[WhiteSpaceTerminal, str]: ... -def get_encoded_word(value: str) -> Tuple[EncodedWord, str]: ... +def get_fws(value: str) -> tuple[WhiteSpaceTerminal, str]: ... +def get_encoded_word(value: str) -> tuple[EncodedWord, str]: ... def get_unstructured(value: str) -> UnstructuredTokenList: ... -def get_qp_ctext(value: str) -> Tuple[WhiteSpaceTerminal, str]: ... -def get_qcontent(value: str) -> Tuple[ValueTerminal, str]: ... -def get_atext(value: str) -> Tuple[ValueTerminal, str]: ... -def get_bare_quoted_string(value: str) -> Tuple[BareQuotedString, str]: ... -def get_comment(value: str) -> Tuple[Comment, str]: ... -def get_cfws(value: str) -> Tuple[CFWSList, str]: ... -def get_quoted_string(value: str) -> Tuple[QuotedString, str]: ... -def get_atom(value: str) -> Tuple[Atom, str]: ... -def get_dot_atom_text(value: str) -> Tuple[DotAtomText, str]: ... -def get_dot_atom(value: str) -> Tuple[DotAtom, str]: ... -def get_word(value: str) -> Tuple[Any, str]: ... -def get_phrase(value: str) -> Tuple[Phrase, str]: ... -def get_local_part(value: str) -> Tuple[LocalPart, str]: ... -def get_obs_local_part(value: str) -> Tuple[ObsLocalPart, str]: ... -def get_dtext(value: str) -> Tuple[ValueTerminal, str]: ... -def get_domain_literal(value: str) -> Tuple[DomainLiteral, str]: ... -def get_domain(value: str) -> Tuple[Domain, str]: ... -def get_addr_spec(value: str) -> Tuple[AddrSpec, str]: ... -def get_obs_route(value: str) -> Tuple[ObsRoute, str]: ... -def get_angle_addr(value: str) -> Tuple[AngleAddr, str]: ... -def get_display_name(value: str) -> Tuple[DisplayName, str]: ... -def get_name_addr(value: str) -> Tuple[NameAddr, str]: ... -def get_mailbox(value: str) -> Tuple[Mailbox, str]: ... -def get_invalid_mailbox(value: str, endchars: str) -> Tuple[InvalidMailbox, str]: ... -def get_mailbox_list(value: str) -> Tuple[MailboxList, str]: ... -def get_group_list(value: str) -> Tuple[GroupList, str]: ... -def get_group(value: str) -> Tuple[Group, str]: ... -def get_address(value: str) -> Tuple[Address, str]: ... -def get_address_list(value: str) -> Tuple[AddressList, str]: ... +def get_qp_ctext(value: str) -> tuple[WhiteSpaceTerminal, str]: ... +def get_qcontent(value: str) -> tuple[ValueTerminal, str]: ... +def get_atext(value: str) -> tuple[ValueTerminal, str]: ... +def get_bare_quoted_string(value: str) -> tuple[BareQuotedString, str]: ... +def get_comment(value: str) -> tuple[Comment, str]: ... +def get_cfws(value: str) -> tuple[CFWSList, str]: ... +def get_quoted_string(value: str) -> tuple[QuotedString, str]: ... +def get_atom(value: str) -> tuple[Atom, str]: ... +def get_dot_atom_text(value: str) -> tuple[DotAtomText, str]: ... +def get_dot_atom(value: str) -> tuple[DotAtom, str]: ... +def get_word(value: str) -> tuple[Any, str]: ... +def get_phrase(value: str) -> tuple[Phrase, str]: ... +def get_local_part(value: str) -> tuple[LocalPart, str]: ... +def get_obs_local_part(value: str) -> tuple[ObsLocalPart, str]: ... +def get_dtext(value: str) -> tuple[ValueTerminal, str]: ... +def get_domain_literal(value: str) -> tuple[DomainLiteral, str]: ... +def get_domain(value: str) -> tuple[Domain, str]: ... +def get_addr_spec(value: str) -> tuple[AddrSpec, str]: ... +def get_obs_route(value: str) -> tuple[ObsRoute, str]: ... +def get_angle_addr(value: str) -> tuple[AngleAddr, str]: ... +def get_display_name(value: str) -> tuple[DisplayName, str]: ... +def get_name_addr(value: str) -> tuple[NameAddr, str]: ... +def get_mailbox(value: str) -> tuple[Mailbox, str]: ... +def get_invalid_mailbox(value: str, endchars: str) -> tuple[InvalidMailbox, str]: ... +def get_mailbox_list(value: str) -> tuple[MailboxList, str]: ... +def get_group_list(value: str) -> tuple[GroupList, str]: ... +def get_group(value: str) -> tuple[Group, str]: ... +def get_address(value: str) -> tuple[Address, str]: ... +def get_address_list(value: str) -> tuple[AddressList, str]: ... if sys.version_info >= (3, 8): - def get_no_fold_literal(value: str) -> Tuple[NoFoldLiteral, str]: ... - def get_msg_id(value: str) -> Tuple[MsgID, str]: ... + def get_no_fold_literal(value: str) -> tuple[NoFoldLiteral, str]: ... + def get_msg_id(value: str) -> tuple[MsgID, str]: ... def parse_message_id(value: str) -> MessageID: ... def parse_mime_version(value: str) -> MIMEVersion: ... -def get_invalid_parameter(value: str) -> Tuple[InvalidParameter, str]: ... -def get_ttext(value: str) -> Tuple[ValueTerminal, str]: ... -def get_token(value: str) -> Tuple[Token, str]: ... -def get_attrtext(value: str) -> Tuple[ValueTerminal, str]: ... -def get_attribute(value: str) -> Tuple[Attribute, str]: ... -def get_extended_attrtext(value: str) -> Tuple[ValueTerminal, str]: ... -def get_extended_attribute(value: str) -> Tuple[Attribute, str]: ... -def get_section(value: str) -> Tuple[Section, str]: ... -def get_value(value: str) -> Tuple[Value, str]: ... -def get_parameter(value: str) -> Tuple[Parameter, str]: ... +def get_invalid_parameter(value: str) -> tuple[InvalidParameter, str]: ... +def get_ttext(value: str) -> tuple[ValueTerminal, str]: ... +def get_token(value: str) -> tuple[Token, str]: ... +def get_attrtext(value: str) -> tuple[ValueTerminal, str]: ... +def get_attribute(value: str) -> tuple[Attribute, str]: ... +def get_extended_attrtext(value: str) -> tuple[ValueTerminal, str]: ... +def get_extended_attribute(value: str) -> tuple[Attribute, str]: ... +def get_section(value: str) -> tuple[Section, str]: ... +def get_value(value: str) -> tuple[Value, str]: ... +def get_parameter(value: str) -> tuple[Parameter, str]: ... def parse_mime_parameters(value: str) -> MimeParameters: ... def parse_content_type_header(value: str) -> ContentType: ... def parse_content_disposition_header(value: str) -> ContentDisposition: ... diff --git a/mypy/typeshed/stdlib/email/charset.pyi b/mypy/typeshed/stdlib/email/charset.pyi index 7c8e8ae711b9..4bf5d11690eb 100644 --- a/mypy/typeshed/stdlib/email/charset.pyi +++ b/mypy/typeshed/stdlib/email/charset.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterator, List, Optional +from typing import Any, Iterator QP: int # undocumented BASE64: int # undocumented @@ -8,21 +8,21 @@ class Charset: input_charset: str header_encoding: int body_encoding: int - output_charset: Optional[str] - input_codec: Optional[str] - output_codec: Optional[str] + output_charset: str | None + input_codec: str | None + output_codec: str | None def __init__(self, input_charset: str = ...) -> None: ... def get_body_encoding(self) -> str: ... - def get_output_charset(self) -> Optional[str]: ... + def get_output_charset(self) -> str | None: ... def header_encode(self, string: str) -> str: ... - def header_encode_lines(self, string: str, maxlengths: Iterator[int]) -> List[str]: ... + def header_encode_lines(self, string: str, maxlengths: Iterator[int]) -> list[str]: ... def body_encode(self, string: str) -> str: ... def __str__(self) -> str: ... def __eq__(self, other: Any) -> bool: ... def __ne__(self, other: Any) -> bool: ... def add_charset( - charset: str, header_enc: Optional[int] = ..., body_enc: Optional[int] = ..., output_charset: Optional[str] = ... + charset: str, header_enc: int | None = ..., body_enc: int | None = ..., output_charset: str | None = ... ) -> None: ... def add_alias(alias: str, canonical: str) -> None: ... def add_codec(charset: str, codecname: str) -> None: ... diff --git a/mypy/typeshed/stdlib/email/errors.pyi b/mypy/typeshed/stdlib/email/errors.pyi index 64ad41407857..656cbd374ac4 100644 --- a/mypy/typeshed/stdlib/email/errors.pyi +++ b/mypy/typeshed/stdlib/email/errors.pyi @@ -1,5 +1,4 @@ import sys -from typing import Optional class MessageError(Exception): ... class MessageParseError(MessageError): ... @@ -9,7 +8,7 @@ class MultipartConversionError(MessageError, TypeError): ... class CharsetError(MessageError): ... class MessageDefect(ValueError): - def __init__(self, line: Optional[str] = ...) -> None: ... + def __init__(self, line: str | None = ...) -> None: ... class NoBoundaryInMultipartDefect(MessageDefect): ... class StartBoundaryNotFoundDefect(MessageDefect): ... @@ -31,7 +30,7 @@ class InvalidHeaderDefect(HeaderDefect): ... class HeaderMissingRequiredValue(HeaderDefect): ... class NonPrintableDefect(HeaderDefect): - def __init__(self, non_printables: Optional[str]) -> None: ... + def __init__(self, non_printables: str | None) -> None: ... class ObsoleteHeaderDefect(HeaderDefect): ... class NonASCIILocalPartDefect(HeaderDefect): ... diff --git a/mypy/typeshed/stdlib/email/generator.pyi b/mypy/typeshed/stdlib/email/generator.pyi index 522f74f31a43..1a810558a0da 100644 --- a/mypy/typeshed/stdlib/email/generator.pyi +++ b/mypy/typeshed/stdlib/email/generator.pyi @@ -1,40 +1,30 @@ from email.message import Message from email.policy import Policy -from typing import BinaryIO, Optional, TextIO +from typing import BinaryIO, TextIO class Generator: def clone(self, fp: TextIO) -> Generator: ... def write(self, s: str) -> None: ... def __init__( - self, - outfp: TextIO, - mangle_from_: Optional[bool] = ..., - maxheaderlen: Optional[int] = ..., - *, - policy: Optional[Policy] = ..., + self, outfp: TextIO, mangle_from_: bool | None = ..., maxheaderlen: int | None = ..., *, policy: Policy | None = ... ) -> None: ... - def flatten(self, msg: Message, unixfrom: bool = ..., linesep: Optional[str] = ...) -> None: ... + def flatten(self, msg: Message, unixfrom: bool = ..., linesep: str | None = ...) -> None: ... class BytesGenerator: def clone(self, fp: BinaryIO) -> BytesGenerator: ... def write(self, s: str) -> None: ... def __init__( - self, - outfp: BinaryIO, - mangle_from_: Optional[bool] = ..., - maxheaderlen: Optional[int] = ..., - *, - policy: Optional[Policy] = ..., + self, outfp: BinaryIO, mangle_from_: bool | None = ..., maxheaderlen: int | None = ..., *, policy: Policy | None = ... ) -> None: ... - def flatten(self, msg: Message, unixfrom: bool = ..., linesep: Optional[str] = ...) -> None: ... + def flatten(self, msg: Message, unixfrom: bool = ..., linesep: str | None = ...) -> None: ... class DecodedGenerator(Generator): def __init__( self, outfp: TextIO, - mangle_from_: Optional[bool] = ..., - maxheaderlen: Optional[int] = ..., - fmt: Optional[str] = ..., + mangle_from_: bool | None = ..., + maxheaderlen: int | None = ..., + fmt: str | None = ..., *, - policy: Optional[Policy] = ..., + policy: Policy | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/email/header.pyi b/mypy/typeshed/stdlib/email/header.pyi index 1a5e1a2e4853..4bebd50c45e4 100644 --- a/mypy/typeshed/stdlib/email/header.pyi +++ b/mypy/typeshed/stdlib/email/header.pyi @@ -1,26 +1,26 @@ from email.charset import Charset -from typing import Any, List, Optional, Tuple, Union +from typing import Any class Header: def __init__( self, - s: Union[bytes, str, None] = ..., - charset: Union[Charset, str, None] = ..., - maxlinelen: Optional[int] = ..., - header_name: Optional[str] = ..., + s: bytes | str | None = ..., + charset: Charset | str | None = ..., + maxlinelen: int | None = ..., + header_name: str | None = ..., continuation_ws: str = ..., errors: str = ..., ) -> None: ... - def append(self, s: Union[bytes, str], charset: Union[Charset, str, None] = ..., errors: str = ...) -> None: ... - def encode(self, splitchars: str = ..., maxlinelen: Optional[int] = ..., linesep: str = ...) -> str: ... + def append(self, s: bytes | str, charset: Charset | str | None = ..., errors: str = ...) -> None: ... + def encode(self, splitchars: str = ..., maxlinelen: int | None = ..., linesep: str = ...) -> str: ... def __str__(self) -> str: ... def __eq__(self, other: Any) -> bool: ... def __ne__(self, other: Any) -> bool: ... -def decode_header(header: Union[Header, str]) -> List[Tuple[bytes, Optional[str]]]: ... +def decode_header(header: Header | str) -> list[tuple[bytes, str | None]]: ... def make_header( - decoded_seq: List[Tuple[bytes, Optional[str]]], - maxlinelen: Optional[int] = ..., - header_name: Optional[str] = ..., + decoded_seq: list[tuple[bytes, str | None]], + maxlinelen: int | None = ..., + header_name: str | None = ..., continuation_ws: str = ..., ) -> Header: ... diff --git a/mypy/typeshed/stdlib/email/headerregistry.pyi b/mypy/typeshed/stdlib/email/headerregistry.pyi index b661496b9b62..69e7bf315d9f 100644 --- a/mypy/typeshed/stdlib/email/headerregistry.pyi +++ b/mypy/typeshed/stdlib/email/headerregistry.pyi @@ -1,4 +1,5 @@ import sys +import types from datetime import datetime as _datetime from email._header_value_parser import ( AddressList, @@ -11,7 +12,7 @@ from email._header_value_parser import ( ) from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Dict, Iterable, Mapping, Optional, Tuple, Type, Union +from typing import Any, Iterable, Tuple, Type class BaseHeader(str): @property @@ -19,7 +20,7 @@ class BaseHeader(str): @property def defects(self) -> Tuple[MessageDefect, ...]: ... @property - def max_count(self) -> Optional[int]: ... + def max_count(self) -> int | None: ... def __new__(cls, name: str, value: Any) -> BaseHeader: ... def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... def fold(self, *, policy: Policy) -> str: ... @@ -28,7 +29,7 @@ class UnstructuredHeader: @staticmethod def value_parser(value: str) -> UnstructuredTokenList: ... @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class UniqueUnstructuredHeader(UnstructuredHeader): ... @@ -38,7 +39,7 @@ class DateHeader: @staticmethod def value_parser(value: str) -> UnstructuredTokenList: ... @classmethod - def parse(cls, value: Union[str, _datetime], kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str | _datetime, kwds: dict[str, Any]) -> None: ... class UniqueDateHeader(DateHeader): ... @@ -50,7 +51,7 @@ class AddressHeader: @staticmethod def value_parser(value: str) -> AddressList: ... @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class UniqueAddressHeader(AddressHeader): ... @@ -62,21 +63,21 @@ class UniqueSingleAddressHeader(SingleAddressHeader): ... class MIMEVersionHeader: @property - def version(self) -> Optional[str]: ... + def version(self) -> str | None: ... @property - def major(self) -> Optional[int]: ... + def major(self) -> int | None: ... @property - def minor(self) -> Optional[int]: ... + def minor(self) -> int | None: ... @staticmethod def value_parser(value: str) -> MIMEVersion: ... @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class ParameterizedMIMEHeader: @property - def params(self) -> Mapping[str, Any]: ... + def params(self) -> types.MappingProxyType[str, Any]: ... @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class ContentTypeHeader(ParameterizedMIMEHeader): @property @@ -98,7 +99,7 @@ class ContentTransferEncodingHeader: @property def cte(self) -> str: ... @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... @staticmethod def value_parser(value: str) -> ContentTransferEncoding: ... @@ -106,7 +107,7 @@ if sys.version_info >= (3, 8): from email._header_value_parser import MessageID class MessageIDHeader: @classmethod - def parse(cls, value: str, kwds: Dict[str, Any]) -> None: ... + def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... @staticmethod def value_parser(value: str) -> MessageID: ... @@ -128,14 +129,14 @@ class Address: @property def addr_spec(self) -> str: ... def __init__( - self, display_name: str = ..., username: Optional[str] = ..., domain: Optional[str] = ..., addr_spec: Optional[str] = ... + self, display_name: str = ..., username: str | None = ..., domain: str | None = ..., addr_spec: str | None = ... ) -> None: ... def __str__(self) -> str: ... class Group: @property - def display_name(self) -> Optional[str]: ... + def display_name(self) -> str | None: ... @property def addresses(self) -> Tuple[Address, ...]: ... - def __init__(self, display_name: Optional[str] = ..., addresses: Optional[Iterable[Address]] = ...) -> None: ... + def __init__(self, display_name: str | None = ..., addresses: Iterable[Address] | None = ...) -> None: ... def __str__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/email/iterators.pyi b/mypy/typeshed/stdlib/email/iterators.pyi index 2b3d14c2ebeb..9081a3e3ba73 100644 --- a/mypy/typeshed/stdlib/email/iterators.pyi +++ b/mypy/typeshed/stdlib/email/iterators.pyi @@ -1,5 +1,5 @@ from email.message import Message -from typing import Iterator, Optional +from typing import Iterator def body_line_iterator(msg: Message, decode: bool = ...) -> Iterator[str]: ... -def typed_subpart_iterator(msg: Message, maintype: str = ..., subtype: Optional[str] = ...) -> Iterator[str]: ... +def typed_subpart_iterator(msg: Message, maintype: str = ..., subtype: str | None = ...) -> Iterator[str]: ... diff --git a/mypy/typeshed/stdlib/email/message.pyi b/mypy/typeshed/stdlib/email/message.pyi index 37c9caffa916..a1749a4cfc2e 100644 --- a/mypy/typeshed/stdlib/email/message.pyi +++ b/mypy/typeshed/stdlib/email/message.pyi @@ -14,28 +14,29 @@ _HeaderType = Any class Message: policy: Policy # undocumented - preamble: Optional[str] - epilogue: Optional[str] - defects: List[MessageDefect] + preamble: str | None + epilogue: str | None + defects: list[MessageDefect] def __str__(self) -> str: ... def is_multipart(self) -> bool: ... def set_unixfrom(self, unixfrom: str) -> None: ... - def get_unixfrom(self) -> Optional[str]: ... + def get_unixfrom(self) -> str | None: ... def attach(self, payload: Message) -> None: ... - def get_payload(self, i: Optional[int] = ..., decode: bool = ...) -> Any: ... # returns Optional[_PayloadType] + def get_payload(self, i: int | None = ..., decode: bool = ...) -> Any: ... # returns _PayloadType | None def set_payload(self, payload: _PayloadType, charset: _CharsetType = ...) -> None: ... def set_charset(self, charset: _CharsetType) -> None: ... def get_charset(self) -> _CharsetType: ... def __len__(self) -> int: ... def __contains__(self, name: str) -> bool: ... + def __iter__(self) -> Iterator[str]: ... def __getitem__(self, name: str) -> _HeaderType: ... def __setitem__(self, name: str, val: _HeaderType) -> None: ... def __delitem__(self, name: str) -> None: ... - def keys(self) -> List[str]: ... - def values(self) -> List[_HeaderType]: ... - def items(self) -> List[Tuple[str, _HeaderType]]: ... - def get(self, name: str, failobj: _T = ...) -> Union[_HeaderType, _T]: ... - def get_all(self, name: str, failobj: _T = ...) -> Union[List[_HeaderType], _T]: ... + def keys(self) -> list[str]: ... + def values(self) -> list[_HeaderType]: ... + def items(self) -> list[tuple[str, _HeaderType]]: ... + def get(self, name: str, failobj: _T = ...) -> _HeaderType | _T: ... + def get_all(self, name: str, failobj: _T = ...) -> list[_HeaderType] | _T: ... def add_header(self, _name: str, _value: str, **_params: _ParamsType) -> None: ... def replace_header(self, _name: str, _value: _HeaderType) -> None: ... def get_content_type(self) -> str: ... @@ -43,19 +44,19 @@ class Message: def get_content_subtype(self) -> str: ... def get_default_type(self) -> str: ... def set_default_type(self, ctype: str) -> None: ... - def get_params(self, failobj: _T = ..., header: str = ..., unquote: bool = ...) -> Union[List[Tuple[str, str]], _T]: ... - def get_param(self, param: str, failobj: _T = ..., header: str = ..., unquote: bool = ...) -> Union[_T, _ParamType]: ... + def get_params(self, failobj: _T = ..., header: str = ..., unquote: bool = ...) -> list[tuple[str, str]] | _T: ... + def get_param(self, param: str, failobj: _T = ..., header: str = ..., unquote: bool = ...) -> _T | _ParamType: ... def del_param(self, param: str, header: str = ..., requote: bool = ...) -> None: ... def set_type(self, type: str, header: str = ..., requote: bool = ...) -> None: ... - def get_filename(self, failobj: _T = ...) -> Union[_T, str]: ... - def get_boundary(self, failobj: _T = ...) -> Union[_T, str]: ... + def get_filename(self, failobj: _T = ...) -> _T | str: ... + def get_boundary(self, failobj: _T = ...) -> _T | str: ... def set_boundary(self, boundary: str) -> None: ... - def get_content_charset(self, failobj: _T = ...) -> Union[_T, str]: ... - def get_charsets(self, failobj: _T = ...) -> Union[_T, List[str]]: ... + def get_content_charset(self, failobj: _T = ...) -> _T | str: ... + def get_charsets(self, failobj: _T = ...) -> _T | list[str]: ... def walk(self) -> Generator[Message, None, None]: ... - def get_content_disposition(self) -> Optional[str]: ... - def as_string(self, unixfrom: bool = ..., maxheaderlen: int = ..., policy: Optional[Policy] = ...) -> str: ... - def as_bytes(self, unixfrom: bool = ..., policy: Optional[Policy] = ...) -> bytes: ... + def get_content_disposition(self) -> str | None: ... + def as_string(self, unixfrom: bool = ..., maxheaderlen: int = ..., policy: Policy | None = ...) -> str: ... + def as_bytes(self, unixfrom: bool = ..., policy: Policy | None = ...) -> bytes: ... def __bytes__(self) -> bytes: ... def set_param( self, @@ -63,28 +64,28 @@ class Message: value: str, header: str = ..., requote: bool = ..., - charset: Optional[str] = ..., + charset: str | None = ..., language: str = ..., replace: bool = ..., ) -> None: ... def __init__(self, policy: Policy = ...) -> None: ... class MIMEPart(Message): - def __init__(self, policy: Optional[Policy] = ...) -> None: ... - def get_body(self, preferencelist: Sequence[str] = ...) -> Optional[Message]: ... + def __init__(self, policy: Policy | None = ...) -> None: ... + def get_body(self, preferencelist: Sequence[str] = ...) -> Message | None: ... def iter_attachments(self) -> Iterator[Message]: ... def iter_parts(self) -> Iterator[Message]: ... - def get_content(self, *args: Any, content_manager: Optional[ContentManager] = ..., **kw: Any) -> Any: ... - def set_content(self, *args: Any, content_manager: Optional[ContentManager] = ..., **kw: Any) -> None: ... - def make_related(self, boundary: Optional[str] = ...) -> None: ... - def make_alternative(self, boundary: Optional[str] = ...) -> None: ... - def make_mixed(self, boundary: Optional[str] = ...) -> None: ... - def add_related(self, *args: Any, content_manager: Optional[ContentManager] = ..., **kw: Any) -> None: ... - def add_alternative(self, *args: Any, content_manager: Optional[ContentManager] = ..., **kw: Any) -> None: ... - def add_attachment(self, *args: Any, content_manager: Optional[ContentManager] = ..., **kw: Any) -> None: ... + def get_content(self, *args: Any, content_manager: ContentManager | None = ..., **kw: Any) -> Any: ... + def set_content(self, *args: Any, content_manager: ContentManager | None = ..., **kw: Any) -> None: ... + def make_related(self, boundary: str | None = ...) -> None: ... + def make_alternative(self, boundary: str | None = ...) -> None: ... + def make_mixed(self, boundary: str | None = ...) -> None: ... + def add_related(self, *args: Any, content_manager: ContentManager | None = ..., **kw: Any) -> None: ... + def add_alternative(self, *args: Any, content_manager: ContentManager | None = ..., **kw: Any) -> None: ... + def add_attachment(self, *args: Any, content_manager: ContentManager | None = ..., **kw: Any) -> None: ... def clear(self) -> None: ... def clear_content(self) -> None: ... - def as_string(self, unixfrom: bool = ..., maxheaderlen: Optional[int] = ..., policy: Optional[Policy] = ...) -> str: ... + def as_string(self, unixfrom: bool = ..., maxheaderlen: int | None = ..., policy: Policy | None = ...) -> str: ... def is_attachment(self) -> bool: ... class EmailMessage(MIMEPart): ... diff --git a/mypy/typeshed/stdlib/email/mime/application.pyi b/mypy/typeshed/stdlib/email/mime/application.pyi index d1b2f1dad6b4..11fc470e9dd1 100644 --- a/mypy/typeshed/stdlib/email/mime/application.pyi +++ b/mypy/typeshed/stdlib/email/mime/application.pyi @@ -7,10 +7,10 @@ _ParamsType = Union[str, None, Tuple[str, Optional[str], str]] class MIMEApplication(MIMENonMultipart): def __init__( self, - _data: Union[str, bytes], + _data: str | bytes, _subtype: str = ..., _encoder: Callable[[MIMEApplication], None] = ..., *, - policy: Optional[Policy] = ..., + policy: Policy | None = ..., **_params: _ParamsType, ) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/audio.pyi b/mypy/typeshed/stdlib/email/mime/audio.pyi index 9bd5b5ca57b0..ee6de410bf53 100644 --- a/mypy/typeshed/stdlib/email/mime/audio.pyi +++ b/mypy/typeshed/stdlib/email/mime/audio.pyi @@ -7,10 +7,10 @@ _ParamsType = Union[str, None, Tuple[str, Optional[str], str]] class MIMEAudio(MIMENonMultipart): def __init__( self, - _audiodata: Union[str, bytes], - _subtype: Optional[str] = ..., + _audiodata: str | bytes, + _subtype: str | None = ..., _encoder: Callable[[MIMEAudio], None] = ..., *, - policy: Optional[Policy] = ..., + policy: Policy | None = ..., **_params: _ParamsType, ) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/base.pyi b/mypy/typeshed/stdlib/email/mime/base.pyi index 1e3223315e88..b88dfd492554 100644 --- a/mypy/typeshed/stdlib/email/mime/base.pyi +++ b/mypy/typeshed/stdlib/email/mime/base.pyi @@ -5,4 +5,4 @@ from typing import Optional, Tuple, Union _ParamsType = Union[str, None, Tuple[str, Optional[str], str]] class MIMEBase(email.message.Message): - def __init__(self, _maintype: str, _subtype: str, *, policy: Optional[Policy] = ..., **_params: _ParamsType) -> None: ... + def __init__(self, _maintype: str, _subtype: str, *, policy: Policy | None = ..., **_params: _ParamsType) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/image.pyi b/mypy/typeshed/stdlib/email/mime/image.pyi index f192494ec74c..886aa74d5fe5 100644 --- a/mypy/typeshed/stdlib/email/mime/image.pyi +++ b/mypy/typeshed/stdlib/email/mime/image.pyi @@ -7,10 +7,10 @@ _ParamsType = Union[str, None, Tuple[str, Optional[str], str]] class MIMEImage(MIMENonMultipart): def __init__( self, - _imagedata: Union[str, bytes], - _subtype: Optional[str] = ..., + _imagedata: str | bytes, + _subtype: str | None = ..., _encoder: Callable[[MIMEImage], None] = ..., *, - policy: Optional[Policy] = ..., + policy: Policy | None = ..., **_params: _ParamsType, ) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/message.pyi b/mypy/typeshed/stdlib/email/mime/message.pyi index d2ce81818a24..8878741e8db3 100644 --- a/mypy/typeshed/stdlib/email/mime/message.pyi +++ b/mypy/typeshed/stdlib/email/mime/message.pyi @@ -1,7 +1,6 @@ from email.message import Message from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Optional class MIMEMessage(MIMENonMultipart): - def __init__(self, _msg: Message, _subtype: str = ..., *, policy: Optional[Policy] = ...) -> None: ... + def __init__(self, _msg: Message, _subtype: str = ..., *, policy: Policy | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/multipart.pyi b/mypy/typeshed/stdlib/email/mime/multipart.pyi index eb5f662de058..6259ddf5ab8f 100644 --- a/mypy/typeshed/stdlib/email/mime/multipart.pyi +++ b/mypy/typeshed/stdlib/email/mime/multipart.pyi @@ -9,9 +9,9 @@ class MIMEMultipart(MIMEBase): def __init__( self, _subtype: str = ..., - boundary: Optional[str] = ..., - _subparts: Optional[Sequence[Message]] = ..., + boundary: str | None = ..., + _subparts: Sequence[Message] | None = ..., *, - policy: Optional[Policy] = ..., + policy: Policy | None = ..., **_params: _ParamsType, ) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/text.pyi b/mypy/typeshed/stdlib/email/mime/text.pyi index aa5590ebb60f..afcafa66ee60 100644 --- a/mypy/typeshed/stdlib/email/mime/text.pyi +++ b/mypy/typeshed/stdlib/email/mime/text.pyi @@ -1,8 +1,5 @@ from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Optional class MIMEText(MIMENonMultipart): - def __init__( - self, _text: str, _subtype: str = ..., _charset: Optional[str] = ..., *, policy: Optional[Policy] = ... - ) -> None: ... + def __init__(self, _text: str, _subtype: str = ..., _charset: str | None = ..., *, policy: Policy | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/parser.pyi b/mypy/typeshed/stdlib/email/parser.pyi index d081540a9d81..574c927eeaf5 100644 --- a/mypy/typeshed/stdlib/email/parser.pyi +++ b/mypy/typeshed/stdlib/email/parser.pyi @@ -1,18 +1,18 @@ import email.feedparser from email.message import Message from email.policy import Policy -from typing import BinaryIO, Callable, Optional, TextIO +from typing import BinaryIO, Callable, TextIO FeedParser = email.feedparser.FeedParser BytesFeedParser = email.feedparser.BytesFeedParser class Parser: - def __init__(self, _class: Optional[Callable[[], Message]] = ..., *, policy: Policy = ...) -> None: ... + def __init__(self, _class: Callable[[], Message] | None = ..., *, policy: Policy = ...) -> None: ... def parse(self, fp: TextIO, headersonly: bool = ...) -> Message: ... def parsestr(self, text: str, headersonly: bool = ...) -> Message: ... class HeaderParser(Parser): - def __init__(self, _class: Optional[Callable[[], Message]] = ..., *, policy: Policy = ...) -> None: ... + def __init__(self, _class: Callable[[], Message] | None = ..., *, policy: Policy = ...) -> None: ... def parse(self, fp: TextIO, headersonly: bool = ...) -> Message: ... def parsestr(self, text: str, headersonly: bool = ...) -> Message: ... diff --git a/mypy/typeshed/stdlib/email/policy.pyi b/mypy/typeshed/stdlib/email/policy.pyi index d0906ebf1cf5..72a54bcfbf08 100644 --- a/mypy/typeshed/stdlib/email/policy.pyi +++ b/mypy/typeshed/stdlib/email/policy.pyi @@ -3,10 +3,10 @@ from email.contentmanager import ContentManager from email.errors import MessageDefect from email.header import Header from email.message import Message -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import Any, Callable class Policy: - max_line_length: Optional[int] + max_line_length: int | None linesep: str cte_type: str raise_on_defect: bool @@ -15,11 +15,11 @@ class Policy: def clone(self, **kw: Any) -> Policy: ... def handle_defect(self, obj: Message, defect: MessageDefect) -> None: ... def register_defect(self, obj: Message, defect: MessageDefect) -> None: ... - def header_max_count(self, name: str) -> Optional[int]: ... + def header_max_count(self, name: str) -> int | None: ... @abstractmethod - def header_source_parse(self, sourcelines: List[str]) -> Tuple[str, str]: ... + def header_source_parse(self, sourcelines: list[str]) -> tuple[str, str]: ... @abstractmethod - def header_store_parse(self, name: str, value: str) -> Tuple[str, str]: ... + def header_store_parse(self, name: str, value: str) -> tuple[str, str]: ... @abstractmethod def header_fetch_parse(self, name: str, value: str) -> str: ... @abstractmethod @@ -28,9 +28,9 @@ class Policy: def fold_binary(self, name: str, value: str) -> bytes: ... class Compat32(Policy): - def header_source_parse(self, sourcelines: List[str]) -> Tuple[str, str]: ... - def header_store_parse(self, name: str, value: str) -> Tuple[str, str]: ... - def header_fetch_parse(self, name: str, value: str) -> Union[str, Header]: ... # type: ignore + def header_source_parse(self, sourcelines: list[str]) -> tuple[str, str]: ... + def header_store_parse(self, name: str, value: str) -> tuple[str, str]: ... + def header_fetch_parse(self, name: str, value: str) -> str | Header: ... # type: ignore def fold(self, name: str, value: str) -> str: ... def fold_binary(self, name: str, value: str) -> bytes: ... @@ -41,8 +41,8 @@ class EmailPolicy(Policy): refold_source: str header_factory: Callable[[str, str], str] content_manager: ContentManager - def header_source_parse(self, sourcelines: List[str]) -> Tuple[str, str]: ... - def header_store_parse(self, name: str, value: str) -> Tuple[str, str]: ... + def header_source_parse(self, sourcelines: list[str]) -> tuple[str, str]: ... + def header_store_parse(self, name: str, value: str) -> tuple[str, str]: ... def header_fetch_parse(self, name: str, value: str) -> str: ... def fold(self, name: str, value: str) -> str: ... def fold_binary(self, name: str, value: str) -> bytes: ... diff --git a/mypy/typeshed/stdlib/email/utils.pyi b/mypy/typeshed/stdlib/email/utils.pyi index 3a39d4fcfd02..3c07e98079fc 100644 --- a/mypy/typeshed/stdlib/email/utils.pyi +++ b/mypy/typeshed/stdlib/email/utils.pyi @@ -1,24 +1,24 @@ import datetime import sys from email.charset import Charset -from typing import List, Optional, Tuple, Union, overload +from typing import Optional, Tuple, Union, overload _ParamType = Union[str, Tuple[Optional[str], Optional[str], str]] _PDTZ = Tuple[int, int, int, int, int, int, int, int, int, Optional[int]] def quote(str: str) -> str: ... def unquote(str: str) -> str: ... -def parseaddr(addr: Optional[str]) -> Tuple[str, str]: ... -def formataddr(pair: Tuple[Optional[str], str], charset: Union[str, Charset] = ...) -> str: ... -def getaddresses(fieldvalues: List[str]) -> List[Tuple[str, str]]: ... +def parseaddr(addr: str | None) -> tuple[str, str]: ... +def formataddr(pair: tuple[str | None, str], charset: str | Charset = ...) -> str: ... +def getaddresses(fieldvalues: list[str]) -> list[tuple[str, str]]: ... @overload def parsedate(data: None) -> None: ... @overload -def parsedate(data: str) -> Optional[Tuple[int, int, int, int, int, int, int, int, int]]: ... +def parsedate(data: str) -> tuple[int, int, int, int, int, int, int, int, int] | None: ... @overload def parsedate_tz(data: None) -> None: ... @overload -def parsedate_tz(data: str) -> Optional[_PDTZ]: ... +def parsedate_tz(data: str) -> _PDTZ | None: ... if sys.version_info >= (3, 10): @overload @@ -30,11 +30,11 @@ else: def parsedate_to_datetime(data: str) -> datetime.datetime: ... def mktime_tz(data: _PDTZ) -> int: ... -def formatdate(timeval: Optional[float] = ..., localtime: bool = ..., usegmt: bool = ...) -> str: ... +def formatdate(timeval: float | None = ..., localtime: bool = ..., usegmt: bool = ...) -> str: ... def format_datetime(dt: datetime.datetime, usegmt: bool = ...) -> str: ... -def localtime(dt: Optional[datetime.datetime] = ..., isdst: int = ...) -> datetime.datetime: ... -def make_msgid(idstring: Optional[str] = ..., domain: Optional[str] = ...) -> str: ... -def decode_rfc2231(s: str) -> Tuple[Optional[str], Optional[str], str]: ... -def encode_rfc2231(s: str, charset: Optional[str] = ..., language: Optional[str] = ...) -> str: ... +def localtime(dt: datetime.datetime | None = ..., isdst: int = ...) -> datetime.datetime: ... +def make_msgid(idstring: str | None = ..., domain: str | None = ...) -> str: ... +def decode_rfc2231(s: str) -> tuple[str | None, str | None, str]: ... +def encode_rfc2231(s: str, charset: str | None = ..., language: str | None = ...) -> str: ... def collapse_rfc2231_value(value: _ParamType, errors: str = ..., fallback_charset: str = ...) -> str: ... -def decode_params(params: List[Tuple[str, str]]) -> List[Tuple[str, _ParamType]]: ... +def decode_params(params: list[tuple[str, str]]) -> list[tuple[str, _ParamType]]: ... diff --git a/mypy/typeshed/stdlib/encodings/__init__.pyi b/mypy/typeshed/stdlib/encodings/__init__.pyi index 951a53f1c786..d86466762268 100644 --- a/mypy/typeshed/stdlib/encodings/__init__.pyi +++ b/mypy/typeshed/stdlib/encodings/__init__.pyi @@ -1,10 +1,10 @@ from codecs import CodecInfo -from typing import Any, Optional, Union +from typing import Any class CodecRegistryError(LookupError, SystemError): ... -def normalize_encoding(encoding: Union[str, bytes]) -> str: ... -def search_function(encoding: str) -> Optional[CodecInfo]: ... +def normalize_encoding(encoding: str | bytes) -> str: ... +def search_function(encoding: str) -> CodecInfo | None: ... # Needed for submodules def __getattr__(name: str) -> Any: ... # incomplete diff --git a/mypy/typeshed/stdlib/encodings/utf_8.pyi b/mypy/typeshed/stdlib/encodings/utf_8.pyi index 96a156c792b6..568fa6013373 100644 --- a/mypy/typeshed/stdlib/encodings/utf_8.pyi +++ b/mypy/typeshed/stdlib/encodings/utf_8.pyi @@ -1,21 +1,20 @@ import codecs -from typing import Optional, Tuple class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input: str, final: bool = ...) -> bytes: ... class IncrementalDecoder(codecs.BufferedIncrementalDecoder): @staticmethod - def _buffer_decode(__data: bytes, __errors: Optional[str] = ..., __final: bool = ...) -> Tuple[str, int]: ... + def _buffer_decode(__data: bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... class StreamWriter(codecs.StreamWriter): @staticmethod - def encode(__str: str, __errors: Optional[str] = ...) -> Tuple[bytes, int]: ... + def encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... class StreamReader(codecs.StreamReader): @staticmethod - def decode(__data: bytes, __errors: Optional[str] = ..., __final: bool = ...) -> Tuple[str, int]: ... + def decode(__data: bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... def getregentry() -> codecs.CodecInfo: ... -def encode(__str: str, __errors: Optional[str] = ...) -> Tuple[bytes, int]: ... -def decode(input: bytes, errors: Optional[str] = ...) -> Tuple[str, int]: ... +def encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... +def decode(input: bytes, errors: str | None = ...) -> tuple[str, int]: ... diff --git a/mypy/typeshed/stdlib/ensurepip/__init__.pyi b/mypy/typeshed/stdlib/ensurepip/__init__.pyi index a411dbb456d2..749fedc04424 100644 --- a/mypy/typeshed/stdlib/ensurepip/__init__.pyi +++ b/mypy/typeshed/stdlib/ensurepip/__init__.pyi @@ -1,25 +1,10 @@ -import sys -from typing import Optional - def version() -> str: ... - -if sys.version_info >= (3, 0): - def bootstrap( - *, - root: Optional[str] = ..., - upgrade: bool = ..., - user: bool = ..., - altinstall: bool = ..., - default_pip: bool = ..., - verbosity: int = ..., - ) -> None: ... - -else: - def bootstrap( - root: Optional[str] = ..., - upgrade: bool = ..., - user: bool = ..., - altinstall: bool = ..., - default_pip: bool = ..., - verbosity: int = ..., - ) -> None: ... +def bootstrap( + *, + root: str | None = ..., + upgrade: bool = ..., + user: bool = ..., + altinstall: bool = ..., + default_pip: bool = ..., + verbosity: int = ..., +) -> None: ... diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index b5549253afc7..07fea104cec7 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -1,7 +1,8 @@ import sys +import types from abc import ABCMeta from builtins import property as _builtins_property -from typing import Any, Dict, Iterator, List, Mapping, Type, TypeVar, Union +from typing import Any, Iterator, Type, TypeVar _T = TypeVar("_T") _S = TypeVar("_S", bound=Type[Enum]) @@ -17,36 +18,36 @@ class EnumMeta(ABCMeta): def __contains__(self: Type[Any], member: object) -> bool: ... def __getitem__(self: Type[_T], name: str) -> _T: ... @_builtins_property - def __members__(self: Type[_T]) -> Mapping[str, _T]: ... + def __members__(self: Type[_T]) -> types.MappingProxyType[str, _T]: ... def __len__(self) -> int: ... + _member_names_: list[str] # undocumented + _member_map_: dict[str, Enum] # undocumented + _value2member_map_: dict[Any, Enum] # undocumented class Enum(metaclass=EnumMeta): name: str value: Any _name_: str _value_: Any - _member_names_: List[str] # undocumented - _member_map_: Dict[str, Enum] # undocumented - _value2member_map_: Dict[int, Enum] # undocumented if sys.version_info >= (3, 7): - _ignore_: Union[str, List[str]] + _ignore_: str | list[str] _order_: str __order__: str @classmethod def _missing_(cls, value: object) -> Any: ... @staticmethod - def _generate_next_value_(name: str, start: int, count: int, last_values: List[Any]) -> Any: ... + def _generate_next_value_(name: str, start: int, count: int, last_values: list[Any]) -> Any: ... def __new__(cls: Type[_T], value: object) -> _T: ... def __repr__(self) -> str: ... def __str__(self) -> str: ... - def __dir__(self) -> List[str]: ... + def __dir__(self) -> list[str]: ... def __format__(self, format_spec: str) -> str: ... def __hash__(self) -> Any: ... def __reduce_ex__(self, proto: object) -> Any: ... class IntEnum(int, Enum): value: int - def __new__(cls: Type[_T], value: Union[int, _T]) -> _T: ... + def __new__(cls: Type[_T], value: int | _T) -> _T: ... def unique(enumeration: _S) -> _S: ... @@ -58,6 +59,8 @@ class auto(IntFlag): def __new__(cls: Type[_T]) -> _T: ... class Flag(Enum): + name: str | None # type: ignore + value: int def __contains__(self: _T, other: _T) -> bool: ... def __repr__(self) -> str: ... def __str__(self) -> str: ... @@ -68,17 +71,17 @@ class Flag(Enum): def __invert__(self: _T) -> _T: ... class IntFlag(int, Flag): - def __new__(cls: Type[_T], value: Union[int, _T]) -> _T: ... - def __or__(self: _T, other: Union[int, _T]) -> _T: ... - def __and__(self: _T, other: Union[int, _T]) -> _T: ... - def __xor__(self: _T, other: Union[int, _T]) -> _T: ... - __ror__ = __or__ - __rand__ = __and__ - __rxor__ = __xor__ + def __new__(cls: Type[_T], value: int | _T) -> _T: ... + def __or__(self: _T, other: int | _T) -> _T: ... + def __and__(self: _T, other: int | _T) -> _T: ... + def __xor__(self: _T, other: int | _T) -> _T: ... + def __ror__(self: _T, n: int | _T) -> _T: ... + def __rand__(self: _T, n: int | _T) -> _T: ... + def __rxor__(self: _T, n: int | _T) -> _T: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 11): class StrEnum(str, Enum): - def __new__(cls: Type[_T], value: Union[int, _T]) -> _T: ... + def __new__(cls: Type[_T], value: int | _T) -> _T: ... class FlagBoundary(StrEnum): STRICT: str CONFORM: str diff --git a/mypy/typeshed/stdlib/fcntl.pyi b/mypy/typeshed/stdlib/fcntl.pyi index ebaa31749528..141f9ee9360a 100644 --- a/mypy/typeshed/stdlib/fcntl.pyi +++ b/mypy/typeshed/stdlib/fcntl.pyi @@ -1,7 +1,6 @@ import sys -from _typeshed import FileDescriptorLike -from array import array -from typing import Any, Union, overload +from _typeshed import FileDescriptorLike, ReadOnlyBuffer, WriteableBuffer +from typing import Any, overload from typing_extensions import Literal FASYNC: int @@ -85,17 +84,13 @@ LOCK_WRITE: int def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: int = ...) -> int: ... @overload def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: bytes) -> bytes: ... - -_ReadOnlyBuffer = bytes -_WritableBuffer = Union[bytearray, memoryview, array[Any]] - @overload def ioctl(__fd: FileDescriptorLike, __request: int, __arg: int = ..., __mutate_flag: bool = ...) -> int: ... @overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: _WritableBuffer, __mutate_flag: Literal[True] = ...) -> int: ... +def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[True] = ...) -> int: ... @overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: _WritableBuffer, __mutate_flag: Literal[False]) -> bytes: ... +def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[False]) -> bytes: ... @overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: _ReadOnlyBuffer, __mutate_flag: bool = ...) -> bytes: ... +def ioctl(__fd: FileDescriptorLike, __request: int, __arg: ReadOnlyBuffer, __mutate_flag: bool = ...) -> bytes: ... def flock(__fd: FileDescriptorLike, __operation: int) -> None: ... def lockf(__fd: FileDescriptorLike, __cmd: int, __len: int = ..., __start: int = ..., __whence: int = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/filecmp.pyi b/mypy/typeshed/stdlib/filecmp.pyi index b05eebac07c9..1c3d0a142a33 100644 --- a/mypy/typeshed/stdlib/filecmp.pyi +++ b/mypy/typeshed/stdlib/filecmp.pyi @@ -1,65 +1,47 @@ import sys -from typing import Any, AnyStr, Callable, Dict, Generic, Iterable, List, Optional, Sequence, Text, Tuple, Union - -if sys.version_info >= (3, 6): - from os import PathLike +from _typeshed import StrOrBytesPath +from os import PathLike +from typing import Any, AnyStr, Callable, Generic, Iterable, Sequence if sys.version_info >= (3, 9): from types import GenericAlias -DEFAULT_IGNORES: List[str] - -if sys.version_info >= (3, 6): - def cmp( - f1: Union[bytes, Text, PathLike[AnyStr]], f2: Union[bytes, Text, PathLike[AnyStr]], shallow: Union[int, bool] = ... - ) -> bool: ... - def cmpfiles( - a: Union[AnyStr, PathLike[AnyStr]], - b: Union[AnyStr, PathLike[AnyStr]], - common: Iterable[AnyStr], - shallow: Union[int, bool] = ..., - ) -> Tuple[List[AnyStr], List[AnyStr], List[AnyStr]]: ... +DEFAULT_IGNORES: list[str] -else: - def cmp(f1: Union[bytes, Text], f2: Union[bytes, Text], shallow: Union[int, bool] = ...) -> bool: ... - def cmpfiles( - a: AnyStr, b: AnyStr, common: Iterable[AnyStr], shallow: Union[int, bool] = ... - ) -> Tuple[List[AnyStr], List[AnyStr], List[AnyStr]]: ... +def cmp(f1: StrOrBytesPath, f2: StrOrBytesPath, shallow: int | bool = ...) -> bool: ... +def cmpfiles( + a: AnyStr | PathLike[AnyStr], b: AnyStr | PathLike[AnyStr], common: Iterable[AnyStr], shallow: int | bool = ... +) -> tuple[list[AnyStr], list[AnyStr], list[AnyStr]]: ... class dircmp(Generic[AnyStr]): - if sys.version_info >= (3, 6): - def __init__( - self, - a: Union[AnyStr, PathLike[AnyStr]], - b: Union[AnyStr, PathLike[AnyStr]], - ignore: Optional[Sequence[AnyStr]] = ..., - hide: Optional[Sequence[AnyStr]] = ..., - ) -> None: ... - else: - def __init__( - self, a: AnyStr, b: AnyStr, ignore: Optional[Sequence[AnyStr]] = ..., hide: Optional[Sequence[AnyStr]] = ... - ) -> None: ... + def __init__( + self, + a: AnyStr | PathLike[AnyStr], + b: AnyStr | PathLike[AnyStr], + ignore: Sequence[AnyStr] | None = ..., + hide: Sequence[AnyStr] | None = ..., + ) -> None: ... left: AnyStr right: AnyStr hide: Sequence[AnyStr] ignore: Sequence[AnyStr] # These properties are created at runtime by __getattr__ - subdirs: Dict[AnyStr, dircmp[AnyStr]] - same_files: List[AnyStr] - diff_files: List[AnyStr] - funny_files: List[AnyStr] - common_dirs: List[AnyStr] - common_files: List[AnyStr] - common_funny: List[AnyStr] - common: List[AnyStr] - left_only: List[AnyStr] - right_only: List[AnyStr] - left_list: List[AnyStr] - right_list: List[AnyStr] + subdirs: dict[AnyStr, dircmp[AnyStr]] + same_files: list[AnyStr] + diff_files: list[AnyStr] + funny_files: list[AnyStr] + common_dirs: list[AnyStr] + common_files: list[AnyStr] + common_funny: list[AnyStr] + common: list[AnyStr] + left_only: list[AnyStr] + right_only: list[AnyStr] + left_list: list[AnyStr] + right_list: list[AnyStr] def report(self) -> None: ... def report_partial_closure(self) -> None: ... def report_full_closure(self) -> None: ... - methodmap: Dict[str, Callable[[], None]] + methodmap: dict[str, Callable[[], None]] def phase0(self) -> None: ... def phase1(self) -> None: ... def phase2(self) -> None: ... @@ -69,5 +51,4 @@ class dircmp(Generic[AnyStr]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -if sys.version_info >= (3,): - def clear_cache() -> None: ... +def clear_cache() -> None: ... diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi index fbb602b3bf45..3c14b736ca50 100644 --- a/mypy/typeshed/stdlib/fileinput.pyi +++ b/mypy/typeshed/stdlib/fileinput.pyi @@ -1,25 +1,40 @@ import sys -from _typeshed import AnyPath -from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator, Optional, Union +from _typeshed import Self, StrOrBytesPath +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 9): + from types import GenericAlias + +if sys.version_info >= (3, 10): def input( - files: Union[AnyPath, Iterable[AnyPath], None] = ..., + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., *, mode: str = ..., - openhook: Callable[[AnyPath, str], IO[AnyStr]] = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + encoding: str | None = ..., + errors: str | None = ..., + ) -> FileInput[AnyStr]: ... + +elif sys.version_info >= (3, 8): + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: str = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., ) -> FileInput[AnyStr]: ... else: def input( - files: Union[AnyPath, Iterable[AnyPath], None] = ..., + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., bufsize: int = ..., mode: str = ..., - openhook: Callable[[AnyPath, str], IO[AnyStr]] = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., ) -> FileInput[AnyStr]: ... def close() -> None: ... @@ -32,31 +47,42 @@ def isfirstline() -> bool: ... def isstdin() -> bool: ... class FileInput(Iterable[AnyStr], Generic[AnyStr]): - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 10): def __init__( self, - files: Union[None, AnyPath, Iterable[AnyPath]] = ..., + files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., inplace: bool = ..., backup: str = ..., *, mode: str = ..., - openhook: Callable[[AnyPath, str], IO[AnyStr]] = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + encoding: str | None = ..., + errors: str | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 8): + def __init__( + self, + files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: str = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., ) -> None: ... else: def __init__( self, - files: Union[None, AnyPath, Iterable[AnyPath]] = ..., + files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., inplace: bool = ..., backup: str = ..., bufsize: int = ..., mode: str = ..., - openhook: Callable[[AnyPath, str], IO[AnyStr]] = ..., + openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., ) -> None: ... def __del__(self) -> None: ... def close(self) -> None: ... - if sys.version_info >= (3, 2): - def __enter__(self) -> FileInput[AnyStr]: ... - def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... def __next__(self) -> AnyStr: ... def __getitem__(self, i: int) -> AnyStr: ... @@ -68,11 +94,15 @@ class FileInput(Iterable[AnyStr], Generic[AnyStr]): def fileno(self) -> int: ... def isfirstline(self) -> bool: ... def isstdin(self) -> bool: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... -def hook_compressed(filename: AnyPath, mode: str) -> IO[Any]: ... - -if sys.version_info >= (3, 6): - def hook_encoded(encoding: str, errors: Optional[str] = ...) -> Callable[[AnyPath, str], IO[Any]]: ... +if sys.version_info >= (3, 10): + def hook_compressed( + filename: StrOrBytesPath, mode: str, *, encoding: str | None = ..., errors: str | None = ... + ) -> IO[Any]: ... else: - def hook_encoded(encoding: str) -> Callable[[AnyPath, str], IO[Any]]: ... + def hook_compressed(filename: StrOrBytesPath, mode: str) -> IO[Any]: ... + +def hook_encoded(encoding: str, errors: str | None = ...) -> Callable[[StrOrBytesPath, str], IO[Any]]: ... diff --git a/mypy/typeshed/stdlib/fnmatch.pyi b/mypy/typeshed/stdlib/fnmatch.pyi index 5311f13e8874..1cbcf00729ed 100644 --- a/mypy/typeshed/stdlib/fnmatch.pyi +++ b/mypy/typeshed/stdlib/fnmatch.pyi @@ -1,6 +1,6 @@ -from typing import AnyStr, Iterable, List +from typing import AnyStr, Iterable def fnmatch(name: AnyStr, pat: AnyStr) -> bool: ... def fnmatchcase(name: AnyStr, pat: AnyStr) -> bool: ... -def filter(names: Iterable[AnyStr], pat: AnyStr) -> List[AnyStr]: ... +def filter(names: Iterable[AnyStr], pat: AnyStr) -> list[AnyStr]: ... def translate(pat: str) -> str: ... diff --git a/mypy/typeshed/stdlib/formatter.pyi b/mypy/typeshed/stdlib/formatter.pyi index 31c45592a215..7c3b97688dbd 100644 --- a/mypy/typeshed/stdlib/formatter.pyi +++ b/mypy/typeshed/stdlib/formatter.pyi @@ -1,37 +1,37 @@ -from typing import IO, Any, Iterable, List, Optional, Tuple +from typing import IO, Any, Iterable, Tuple AS_IS: None _FontType = Tuple[str, bool, bool, bool] _StylesType = Tuple[Any, ...] class NullFormatter: - writer: Optional[NullWriter] - def __init__(self, writer: Optional[NullWriter] = ...) -> None: ... + writer: NullWriter | None + def __init__(self, writer: NullWriter | None = ...) -> None: ... def end_paragraph(self, blankline: int) -> None: ... def add_line_break(self) -> None: ... def add_hor_rule(self, *args: Any, **kw: Any) -> None: ... - def add_label_data(self, format: str, counter: int, blankline: Optional[int] = ...) -> None: ... + def add_label_data(self, format: str, counter: int, blankline: int | None = ...) -> None: ... def add_flowing_data(self, data: str) -> None: ... def add_literal_data(self, data: str) -> None: ... def flush_softspace(self) -> None: ... - def push_alignment(self, align: Optional[str]) -> None: ... + def push_alignment(self, align: str | None) -> None: ... def pop_alignment(self) -> None: ... def push_font(self, x: _FontType) -> None: ... def pop_font(self) -> None: ... def push_margin(self, margin: int) -> None: ... def pop_margin(self) -> None: ... - def set_spacing(self, spacing: Optional[str]) -> None: ... + def set_spacing(self, spacing: str | None) -> None: ... def push_style(self, *styles: _StylesType) -> None: ... def pop_style(self, n: int = ...) -> None: ... def assert_line_data(self, flag: int = ...) -> None: ... class AbstractFormatter: writer: NullWriter - align: Optional[str] - align_stack: List[Optional[str]] - font_stack: List[_FontType] - margin_stack: List[int] - spacing: Optional[str] + align: str | None + align_stack: list[str | None] + font_stack: list[_FontType] + margin_stack: list[int] + spacing: str | None style_stack: Any nospace: int softspace: int @@ -43,20 +43,20 @@ class AbstractFormatter: def end_paragraph(self, blankline: int) -> None: ... def add_line_break(self) -> None: ... def add_hor_rule(self, *args: Any, **kw: Any) -> None: ... - def add_label_data(self, format: str, counter: int, blankline: Optional[int] = ...) -> None: ... + def add_label_data(self, format: str, counter: int, blankline: int | None = ...) -> None: ... def format_counter(self, format: Iterable[str], counter: int) -> str: ... def format_letter(self, case: str, counter: int) -> str: ... def format_roman(self, case: str, counter: int) -> str: ... def add_flowing_data(self, data: str) -> None: ... def add_literal_data(self, data: str) -> None: ... def flush_softspace(self) -> None: ... - def push_alignment(self, align: Optional[str]) -> None: ... + def push_alignment(self, align: str | None) -> None: ... def pop_alignment(self) -> None: ... def push_font(self, font: _FontType) -> None: ... def pop_font(self) -> None: ... def push_margin(self, margin: int) -> None: ... def pop_margin(self) -> None: ... - def set_spacing(self, spacing: Optional[str]) -> None: ... + def set_spacing(self, spacing: str | None) -> None: ... def push_style(self, *styles: _StylesType) -> None: ... def pop_style(self, n: int = ...) -> None: ... def assert_line_data(self, flag: int = ...) -> None: ... @@ -64,10 +64,10 @@ class AbstractFormatter: class NullWriter: def __init__(self) -> None: ... def flush(self) -> None: ... - def new_alignment(self, align: Optional[str]) -> None: ... + def new_alignment(self, align: str | None) -> None: ... def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... - def new_spacing(self, spacing: Optional[str]) -> None: ... + def new_spacing(self, spacing: str | None) -> None: ... def new_styles(self, styles: Tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... @@ -77,10 +77,10 @@ class NullWriter: def send_literal_data(self, data: str) -> None: ... class AbstractWriter(NullWriter): - def new_alignment(self, align: Optional[str]) -> None: ... + def new_alignment(self, align: str | None) -> None: ... def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... - def new_spacing(self, spacing: Optional[str]) -> None: ... + def new_spacing(self, spacing: str | None) -> None: ... def new_styles(self, styles: Tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... @@ -92,7 +92,7 @@ class AbstractWriter(NullWriter): class DumbWriter(NullWriter): file: IO[str] maxcol: int - def __init__(self, file: Optional[IO[str]] = ..., maxcol: int = ...) -> None: ... + def __init__(self, file: IO[str] | None = ..., maxcol: int = ...) -> None: ... def reset(self) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... @@ -100,4 +100,4 @@ class DumbWriter(NullWriter): def send_literal_data(self, data: str) -> None: ... def send_flowing_data(self, data: str) -> None: ... -def test(file: Optional[str] = ...) -> None: ... +def test(file: str | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/fractions.pyi b/mypy/typeshed/stdlib/fractions.pyi index 75cfa48a1cf6..3c6808651275 100644 --- a/mypy/typeshed/stdlib/fractions.pyi +++ b/mypy/typeshed/stdlib/fractions.pyi @@ -1,7 +1,7 @@ import sys from decimal import Decimal from numbers import Integral, Rational, Real -from typing import Optional, Tuple, Type, TypeVar, Union, overload +from typing import Type, TypeVar, Union, overload from typing_extensions import Literal _ComparableNum = Union[int, float, Decimal, Real] @@ -20,141 +20,120 @@ if sys.version_info < (3, 9): class Fraction(Rational): @overload def __new__( - cls: Type[_T], - numerator: Union[int, Rational] = ..., - denominator: Optional[Union[int, Rational]] = ..., - *, - _normalize: bool = ..., + cls: Type[_T], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... ) -> _T: ... @overload - def __new__(cls: Type[_T], __value: Union[float, Decimal, str], *, _normalize: bool = ...) -> _T: ... + def __new__(cls: Type[_T], __value: float | Decimal | str, *, _normalize: bool = ...) -> _T: ... @classmethod def from_float(cls, f: float) -> Fraction: ... @classmethod def from_decimal(cls, dec: Decimal) -> Fraction: ... def limit_denominator(self, max_denominator: int = ...) -> Fraction: ... if sys.version_info >= (3, 8): - def as_integer_ratio(self) -> Tuple[int, int]: ... + def as_integer_ratio(self) -> tuple[int, int]: ... @property def numerator(self) -> int: ... @property def denominator(self) -> int: ... @overload - def __add__(self, other: Union[int, Fraction]) -> Fraction: ... + def __add__(self, other: int | Fraction) -> Fraction: ... @overload def __add__(self, other: float) -> float: ... @overload def __add__(self, other: complex) -> complex: ... @overload - def __radd__(self, other: Union[int, Fraction]) -> Fraction: ... + def __radd__(self, other: int | Fraction) -> Fraction: ... @overload def __radd__(self, other: float) -> float: ... @overload def __radd__(self, other: complex) -> complex: ... @overload - def __sub__(self, other: Union[int, Fraction]) -> Fraction: ... + def __sub__(self, other: int | Fraction) -> Fraction: ... @overload def __sub__(self, other: float) -> float: ... @overload def __sub__(self, other: complex) -> complex: ... @overload - def __rsub__(self, other: Union[int, Fraction]) -> Fraction: ... + def __rsub__(self, other: int | Fraction) -> Fraction: ... @overload def __rsub__(self, other: float) -> float: ... @overload def __rsub__(self, other: complex) -> complex: ... @overload - def __mul__(self, other: Union[int, Fraction]) -> Fraction: ... + def __mul__(self, other: int | Fraction) -> Fraction: ... @overload def __mul__(self, other: float) -> float: ... @overload def __mul__(self, other: complex) -> complex: ... @overload - def __rmul__(self, other: Union[int, Fraction]) -> Fraction: ... + def __rmul__(self, other: int | Fraction) -> Fraction: ... @overload def __rmul__(self, other: float) -> float: ... @overload def __rmul__(self, other: complex) -> complex: ... @overload - def __truediv__(self, other: Union[int, Fraction]) -> Fraction: ... + def __truediv__(self, other: int | Fraction) -> Fraction: ... @overload def __truediv__(self, other: float) -> float: ... @overload def __truediv__(self, other: complex) -> complex: ... @overload - def __rtruediv__(self, other: Union[int, Fraction]) -> Fraction: ... + def __rtruediv__(self, other: int | Fraction) -> Fraction: ... @overload def __rtruediv__(self, other: float) -> float: ... @overload def __rtruediv__(self, other: complex) -> complex: ... - if sys.version_info < (3, 0): - @overload - def __div__(self, other: Union[int, Fraction]) -> Fraction: ... - @overload - def __div__(self, other: float) -> float: ... - @overload - def __div__(self, other: complex) -> complex: ... - @overload - def __rdiv__(self, other: Union[int, Fraction]) -> Fraction: ... - @overload - def __rdiv__(self, other: float) -> float: ... - @overload - def __rdiv__(self, other: complex) -> complex: ... - @overload - def __floordiv__(self, other: Union[int, Fraction]) -> int: ... + @overload + def __floordiv__(self, other: int | Fraction) -> int: ... @overload def __floordiv__(self, other: float) -> float: ... @overload - def __rfloordiv__(self, other: Union[int, Fraction]) -> int: ... + def __rfloordiv__(self, other: int | Fraction) -> int: ... @overload def __rfloordiv__(self, other: float) -> float: ... @overload - def __mod__(self, other: Union[int, Fraction]) -> Fraction: ... + def __mod__(self, other: int | Fraction) -> Fraction: ... @overload def __mod__(self, other: float) -> float: ... @overload - def __rmod__(self, other: Union[int, Fraction]) -> Fraction: ... + def __rmod__(self, other: int | Fraction) -> Fraction: ... @overload def __rmod__(self, other: float) -> float: ... @overload - def __divmod__(self, other: Union[int, Fraction]) -> Tuple[int, Fraction]: ... + def __divmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __divmod__(self, other: float) -> Tuple[float, Fraction]: ... + def __divmod__(self, other: float) -> tuple[float, Fraction]: ... @overload - def __rdivmod__(self, other: Union[int, Fraction]) -> Tuple[int, Fraction]: ... + def __rdivmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __rdivmod__(self, other: float) -> Tuple[float, Fraction]: ... + def __rdivmod__(self, other: float) -> tuple[float, Fraction]: ... @overload def __pow__(self, other: int) -> Fraction: ... @overload - def __pow__(self, other: Union[float, Fraction]) -> float: ... + def __pow__(self, other: float | Fraction) -> float: ... @overload def __pow__(self, other: complex) -> complex: ... @overload - def __rpow__(self, other: Union[int, float, Fraction]) -> float: ... + def __rpow__(self, other: int | float | Fraction) -> float: ... @overload def __rpow__(self, other: complex) -> complex: ... def __pos__(self) -> Fraction: ... def __neg__(self) -> Fraction: ... def __abs__(self) -> Fraction: ... def __trunc__(self) -> int: ... - if sys.version_info >= (3, 0): - def __floor__(self) -> int: ... - def __ceil__(self) -> int: ... - @overload - def __round__(self, ndigits: None = ...) -> int: ... - @overload - def __round__(self, ndigits: int) -> Fraction: ... + def __floor__(self) -> int: ... + def __ceil__(self) -> int: ... + @overload + def __round__(self, ndigits: None = ...) -> int: ... + @overload + def __round__(self, ndigits: int) -> Fraction: ... def __hash__(self) -> int: ... def __eq__(self, other: object) -> bool: ... def __lt__(self, other: _ComparableNum) -> bool: ... def __gt__(self, other: _ComparableNum) -> bool: ... def __le__(self, other: _ComparableNum) -> bool: ... def __ge__(self, other: _ComparableNum) -> bool: ... - if sys.version_info >= (3, 0): - def __bool__(self) -> bool: ... - else: - def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... # Not actually defined within fractions.py, but provides more useful # overrides @property diff --git a/mypy/typeshed/stdlib/ftplib.pyi b/mypy/typeshed/stdlib/ftplib.pyi index bdb1716549c0..3f4f892bb516 100644 --- a/mypy/typeshed/stdlib/ftplib.pyi +++ b/mypy/typeshed/stdlib/ftplib.pyi @@ -1,20 +1,16 @@ import sys -from _typeshed import SupportsRead, SupportsReadline +from _typeshed import Self, SupportsRead, SupportsReadline from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, BinaryIO, Callable, Dict, Iterable, Iterator, List, Optional, Text, TextIO, Tuple, Type, TypeVar, Union +from typing import Any, Callable, Iterable, Iterator, TextIO, Tuple, Type from typing_extensions import Literal -_T = TypeVar("_T") -_IntOrStr = Union[int, Text] - MSG_OOB: int FTP_PORT: int MAXLINE: int CRLF: str -if sys.version_info >= (3,): - B_CRLF: bytes +B_CRLF: bytes class Error(Exception): ... class error_reply(Error): ... @@ -26,135 +22,143 @@ all_errors: Tuple[Type[Exception], ...] class FTP: debugging: int - - # Note: This is technically the type that's passed in as the host argument. But to make it easier in Python 2 we - # accept Text but return str. host: str - port: int maxline: int - sock: Optional[socket] - welcome: Optional[str] + sock: socket | None + welcome: str | None passiveserver: int timeout: int af: int lastresp: str + file: TextIO | None + encoding: str - if sys.version_info >= (3,): - file: Optional[TextIO] - encoding: str - def __enter__(self: _T) -> _T: ... - def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> None: ... - else: - file: Optional[BinaryIO] - - if sys.version_info >= (3, 3): - source_address: Optional[Tuple[str, int]] + # The following variable is intentionally left undocumented. + # See https://bugs.python.org/issue43285 for relevant discussion + # trust_server_pasv_ipv4_address: bool + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + source_address: tuple[str, int] | None + if sys.version_info >= (3, 9): def __init__( self, - host: Text = ..., - user: Text = ..., - passwd: Text = ..., - acct: Text = ..., + host: str = ..., + user: str = ..., + passwd: str = ..., + acct: str = ..., timeout: float = ..., - source_address: Optional[Tuple[str, int]] = ..., + source_address: tuple[str, int] | None = ..., + *, + encoding: str = ..., ) -> None: ... - def connect( - self, host: Text = ..., port: int = ..., timeout: float = ..., source_address: Optional[Tuple[str, int]] = ... - ) -> str: ... else: def __init__( - self, host: Text = ..., user: Text = ..., passwd: Text = ..., acct: Text = ..., timeout: float = ... + self, + host: str = ..., + user: str = ..., + passwd: str = ..., + acct: str = ..., + timeout: float = ..., + source_address: tuple[str, int] | None = ..., ) -> None: ... - def connect(self, host: Text = ..., port: int = ..., timeout: float = ...) -> str: ... + def connect( + self, host: str = ..., port: int = ..., timeout: float = ..., source_address: tuple[str, int] | None = ... + ) -> str: ... def getwelcome(self) -> str: ... def set_debuglevel(self, level: int) -> None: ... def debug(self, level: int) -> None: ... - def set_pasv(self, val: Union[bool, int]) -> None: ... - def sanitize(self, s: Text) -> str: ... - def putline(self, line: Text) -> None: ... - def putcmd(self, line: Text) -> None: ... + def set_pasv(self, val: bool | int) -> None: ... + def sanitize(self, s: str) -> str: ... + def putline(self, line: str) -> None: ... + def putcmd(self, line: str) -> None: ... def getline(self) -> str: ... def getmultiline(self) -> str: ... def getresp(self) -> str: ... def voidresp(self) -> str: ... def abort(self) -> str: ... - def sendcmd(self, cmd: Text) -> str: ... - def voidcmd(self, cmd: Text) -> str: ... - def sendport(self, host: Text, port: int) -> str: ... - def sendeprt(self, host: Text, port: int) -> str: ... + def sendcmd(self, cmd: str) -> str: ... + def voidcmd(self, cmd: str) -> str: ... + def sendport(self, host: str, port: int) -> str: ... + def sendeprt(self, host: str, port: int) -> str: ... def makeport(self) -> socket: ... - def makepasv(self) -> Tuple[str, int]: ... - def login(self, user: Text = ..., passwd: Text = ..., acct: Text = ...) -> str: ... + def makepasv(self) -> tuple[str, int]: ... + def login(self, user: str = ..., passwd: str = ..., acct: str = ...) -> str: ... # In practice, `rest` rest can actually be anything whose str() is an integer sequence, so to make it simple we allow integers. - def ntransfercmd(self, cmd: Text, rest: Optional[_IntOrStr] = ...) -> Tuple[socket, int]: ... - def transfercmd(self, cmd: Text, rest: Optional[_IntOrStr] = ...) -> socket: ... + def ntransfercmd(self, cmd: str, rest: int | str | None = ...) -> tuple[socket, int]: ... + def transfercmd(self, cmd: str, rest: int | str | None = ...) -> socket: ... def retrbinary( - self, cmd: Text, callback: Callable[[bytes], Any], blocksize: int = ..., rest: Optional[_IntOrStr] = ... + self, cmd: str, callback: Callable[[bytes], Any], blocksize: int = ..., rest: int | str | None = ... ) -> str: ... def storbinary( self, - cmd: Text, + cmd: str, fp: SupportsRead[bytes], blocksize: int = ..., - callback: Optional[Callable[[bytes], Any]] = ..., - rest: Optional[_IntOrStr] = ..., + callback: Callable[[bytes], Any] | None = ..., + rest: int | str | None = ..., ) -> str: ... - def retrlines(self, cmd: Text, callback: Optional[Callable[[str], Any]] = ...) -> str: ... - def storlines(self, cmd: Text, fp: SupportsReadline[bytes], callback: Optional[Callable[[bytes], Any]] = ...) -> str: ... - def acct(self, password: Text) -> str: ... - def nlst(self, *args: Text) -> List[str]: ... + def retrlines(self, cmd: str, callback: Callable[[str], Any] | None = ...) -> str: ... + def storlines(self, cmd: str, fp: SupportsReadline[bytes], callback: Callable[[bytes], Any] | None = ...) -> str: ... + def acct(self, password: str) -> str: ... + def nlst(self, *args: str) -> list[str]: ... # Technically only the last arg can be a Callable but ... - def dir(self, *args: Union[str, Callable[[str], None]]) -> None: ... - if sys.version_info >= (3, 3): - def mlsd(self, path: Text = ..., facts: Iterable[str] = ...) -> Iterator[Tuple[str, Dict[str, str]]]: ... - def rename(self, fromname: Text, toname: Text) -> str: ... - def delete(self, filename: Text) -> str: ... - def cwd(self, dirname: Text) -> str: ... - def size(self, filename: Text) -> Optional[int]: ... - def mkd(self, dirname: Text) -> str: ... - def rmd(self, dirname: Text) -> str: ... + def dir(self, *args: str | Callable[[str], None]) -> None: ... + def mlsd(self, path: str = ..., facts: Iterable[str] = ...) -> Iterator[tuple[str, dict[str, str]]]: ... + def rename(self, fromname: str, toname: str) -> str: ... + def delete(self, filename: str) -> str: ... + def cwd(self, dirname: str) -> str: ... + def size(self, filename: str) -> int | None: ... + def mkd(self, dirname: str) -> str: ... + def rmd(self, dirname: str) -> str: ... def pwd(self) -> str: ... def quit(self) -> str: ... def close(self) -> None: ... class FTP_TLS(FTP): - def __init__( - self, - host: Text = ..., - user: Text = ..., - passwd: Text = ..., - acct: Text = ..., - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., - context: Optional[SSLContext] = ..., - timeout: float = ..., - source_address: Optional[Tuple[str, int]] = ..., - ) -> None: ... + if sys.version_info >= (3, 9): + def __init__( + self, + host: str = ..., + user: str = ..., + passwd: str = ..., + acct: str = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + context: SSLContext | None = ..., + timeout: float = ..., + source_address: tuple[str, int] | None = ..., + *, + encoding: str = ..., + ) -> None: ... + else: + def __init__( + self, + host: str = ..., + user: str = ..., + passwd: str = ..., + acct: str = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + context: SSLContext | None = ..., + timeout: float = ..., + source_address: tuple[str, int] | None = ..., + ) -> None: ... ssl_version: int - keyfile: Optional[str] - certfile: Optional[str] + keyfile: str | None + certfile: str | None context: SSLContext - def login(self, user: Text = ..., passwd: Text = ..., acct: Text = ..., secure: bool = ...) -> str: ... + def login(self, user: str = ..., passwd: str = ..., acct: str = ..., secure: bool = ...) -> str: ... def auth(self) -> str: ... def prot_p(self) -> str: ... def prot_c(self) -> str: ... - if sys.version_info >= (3, 3): - def ccc(self) -> str: ... - -if sys.version_info < (3,): - class Netrc: - def __init__(self, filename: Optional[Text] = ...) -> None: ... - def get_hosts(self) -> List[str]: ... - def get_account(self, host: Text) -> Tuple[Optional[str], Optional[str], Optional[str]]: ... - def get_macros(self) -> List[str]: ... - def get_macro(self, macro: Text) -> Tuple[str, ...]: ... + def ccc(self) -> str: ... -def parse150(resp: str) -> Optional[int]: ... # undocumented -def parse227(resp: str) -> Tuple[str, int]: ... # undocumented -def parse229(resp: str, peer: Any) -> Tuple[str, int]: ... # undocumented +def parse150(resp: str) -> int | None: ... # undocumented +def parse227(resp: str) -> tuple[str, int]: ... # undocumented +def parse229(resp: str, peer: Any) -> tuple[str, int]: ... # undocumented def parse257(resp: str) -> str: ... # undocumented def ftpcp( source: FTP, sourcename: str, target: FTP, targetname: str = ..., type: Literal["A", "I"] = ... diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index d4a492c0102e..b5e52bf59920 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,24 +1,8 @@ import sys +import types from _typeshed import SupportsItems, SupportsLessThan -from typing import ( - Any, - Callable, - Dict, - Generic, - Hashable, - Iterable, - Mapping, - NamedTuple, - Optional, - Sequence, - Set, - Sized, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, Tuple, Type, TypeVar, overload +from typing_extensions import final if sys.version_info >= (3, 9): from types import GenericAlias @@ -39,6 +23,7 @@ class _CacheInfo(NamedTuple): maxsize: int currsize: int +@final class _lru_cache_wrapper(Generic[_T]): __wrapped__: Callable[..., _T] def __call__(self, *args: Hashable, **kwargs: Hashable) -> _T: ... @@ -47,12 +32,12 @@ class _lru_cache_wrapper(Generic[_T]): if sys.version_info >= (3, 8): @overload - def lru_cache(maxsize: Optional[int] = ..., typed: bool = ...) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ... + def lru_cache(maxsize: int | None = ..., typed: bool = ...) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ... @overload def lru_cache(maxsize: Callable[..., _T], typed: bool = ...) -> _lru_cache_wrapper[_T]: ... else: - def lru_cache(maxsize: Optional[int] = ..., typed: bool = ...) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ... + def lru_cache(maxsize: int | None = ..., typed: bool = ...) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ... WRAPPER_ASSIGNMENTS: Sequence[str] WRAPPER_UPDATES: Sequence[str] @@ -65,7 +50,7 @@ def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsLessTha class partial(Generic[_T]): func: Callable[..., _T] args: Tuple[Any, ...] - keywords: Dict[str, Any] + keywords: dict[str, Any] def __init__(self, func: Callable[..., _T], *args: Any, **kwargs: Any) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> _T: ... if sys.version_info >= (3, 9): @@ -75,9 +60,9 @@ class partial(Generic[_T]): _Descriptor = Any class partialmethod(Generic[_T]): - func: Union[Callable[..., _T], _Descriptor] + func: Callable[..., _T] | _Descriptor args: Tuple[Any, ...] - keywords: Dict[str, Any] + keywords: dict[str, Any] @overload def __init__(self, __func: Callable[..., _T], *args: Any, **keywords: Any) -> None: ... @overload @@ -89,7 +74,7 @@ class partialmethod(Generic[_T]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... class _SingleDispatchCallable(Generic[_T]): - registry: Mapping[Any, Callable[..., _T]] + registry: types.MappingProxyType[Any, Callable[..., _T]] def dispatch(self, cls: Any) -> Callable[..., _T]: ... # @fun.register(complex) # def _(arg, verbose=False): ... @@ -121,12 +106,12 @@ if sys.version_info >= (3, 8): def __call__(self, *args: Any, **kwargs: Any) -> _T: ... class cached_property(Generic[_T]): func: Callable[[Any], _T] - attrname: Optional[str] + attrname: str | None def __init__(self, func: Callable[[Any], _T]) -> None: ... @overload - def __get__(self, instance: None, owner: Optional[Type[Any]] = ...) -> cached_property[_T]: ... + def __get__(self, instance: None, owner: Type[Any] | None = ...) -> cached_property[_T]: ... @overload - def __get__(self, instance: object, owner: Optional[Type[Any]] = ...) -> _T: ... + def __get__(self, instance: object, owner: Type[Any] | None = ...) -> _T: ... def __set_name__(self, owner: Type[Any], name: str) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -139,7 +124,7 @@ def _make_key( kwds: SupportsItems[Any, Any], typed: bool, kwd_mark: Tuple[object, ...] = ..., - fasttypes: Set[type] = ..., + fasttypes: set[type] = ..., tuple: type = ..., type: Any = ..., len: Callable[[Sized], int] = ..., diff --git a/mypy/typeshed/stdlib/gc.pyi b/mypy/typeshed/stdlib/gc.pyi index 841ffd8b34d2..39d2776783ef 100644 --- a/mypy/typeshed/stdlib/gc.pyi +++ b/mypy/typeshed/stdlib/gc.pyi @@ -1,35 +1,35 @@ import sys -from typing import Any, Dict, List, Optional, Tuple +from typing import Any DEBUG_COLLECTABLE: int DEBUG_LEAK: int DEBUG_SAVEALL: int DEBUG_STATS: int DEBUG_UNCOLLECTABLE: int -callbacks: List[Any] -garbage: List[Any] +callbacks: list[Any] +garbage: list[Any] def collect(generation: int = ...) -> int: ... def disable() -> None: ... def enable() -> None: ... -def get_count() -> Tuple[int, int, int]: ... +def get_count() -> tuple[int, int, int]: ... def get_debug() -> int: ... if sys.version_info >= (3, 8): - def get_objects(generation: Optional[int] = ...) -> List[Any]: ... + def get_objects(generation: int | None = ...) -> list[Any]: ... else: - def get_objects() -> List[Any]: ... + def get_objects() -> list[Any]: ... if sys.version_info >= (3, 7): def freeze() -> None: ... def unfreeze() -> None: ... def get_freeze_count() -> int: ... -def get_referents(*objs: Any) -> List[Any]: ... -def get_referrers(*objs: Any) -> List[Any]: ... -def get_stats() -> List[Dict[str, Any]]: ... -def get_threshold() -> Tuple[int, int, int]: ... +def get_referents(*objs: Any) -> list[Any]: ... +def get_referrers(*objs: Any) -> list[Any]: ... +def get_stats() -> list[dict[str, Any]]: ... +def get_threshold() -> tuple[int, int, int]: ... def is_tracked(__obj: Any) -> bool: ... if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/genericpath.pyi b/mypy/typeshed/stdlib/genericpath.pyi index 28c94ae1676a..56683e323178 100644 --- a/mypy/typeshed/stdlib/genericpath.pyi +++ b/mypy/typeshed/stdlib/genericpath.pyi @@ -1,32 +1,29 @@ import os -import sys -from _typeshed import AnyPath, BytesPath, StrPath, SupportsLessThanT -from typing import List, Sequence, Tuple, Union, overload +from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsLessThanT +from typing import Sequence, Tuple, overload from typing_extensions import Literal # All overloads can return empty string. Ideally, Literal[""] would be a valid -# Iterable[T], so that Union[List[T], Literal[""]] could be used as a return +# Iterable[T], so that list[T] | Literal[""] could be used as a return # type. But because this only works when T is str, we need Sequence[T] instead. @overload def commonprefix(m: Sequence[StrPath]) -> str: ... @overload -def commonprefix(m: Sequence[BytesPath]) -> Union[bytes, Literal[""]]: ... +def commonprefix(m: Sequence[BytesPath]) -> bytes | Literal[""]: ... @overload -def commonprefix(m: Sequence[List[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... +def commonprefix(m: Sequence[list[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... @overload def commonprefix(m: Sequence[Tuple[SupportsLessThanT, ...]]) -> Sequence[SupportsLessThanT]: ... -def exists(path: AnyPath) -> bool: ... -def getsize(filename: AnyPath) -> int: ... -def isfile(path: AnyPath) -> bool: ... -def isdir(s: AnyPath) -> bool: ... +def exists(path: StrOrBytesPath | int) -> bool: ... +def getsize(filename: StrOrBytesPath | int) -> int: ... +def isfile(path: StrOrBytesPath | int) -> bool: ... +def isdir(s: StrOrBytesPath | int) -> bool: ... # These return float if os.stat_float_times() == True, # but int is a subclass of float. -def getatime(filename: AnyPath) -> float: ... -def getmtime(filename: AnyPath) -> float: ... -def getctime(filename: AnyPath) -> float: ... - -if sys.version_info >= (3, 4): - def samefile(f1: AnyPath, f2: AnyPath) -> bool: ... - def sameopenfile(fp1: int, fp2: int) -> bool: ... - def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... +def getatime(filename: StrOrBytesPath | int) -> float: ... +def getmtime(filename: StrOrBytesPath | int) -> float: ... +def getctime(filename: StrOrBytesPath | int) -> float: ... +def samefile(f1: StrOrBytesPath | int, f2: StrOrBytesPath | int) -> bool: ... +def sameopenfile(fp1: int, fp2: int) -> bool: ... +def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... diff --git a/mypy/typeshed/stdlib/getpass.pyi b/mypy/typeshed/stdlib/getpass.pyi index aac162a5166b..27f4c6a9b635 100644 --- a/mypy/typeshed/stdlib/getpass.pyi +++ b/mypy/typeshed/stdlib/getpass.pyi @@ -1,6 +1,6 @@ -from typing import Optional, TextIO +from typing import TextIO -def getpass(prompt: str = ..., stream: Optional[TextIO] = ...) -> str: ... +def getpass(prompt: str = ..., stream: TextIO | None = ...) -> str: ... def getuser() -> str: ... class GetPassWarning(UserWarning): ... diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index dcbd214e04f8..b408d3f7485c 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -1,10 +1,10 @@ import sys from _typeshed import StrPath -from typing import IO, Any, Container, Iterable, Optional, Sequence, Type, TypeVar, overload +from typing import IO, Any, Container, Iterable, Sequence, Type, TypeVar, overload from typing_extensions import Literal class NullTranslations: - def __init__(self, fp: Optional[IO[str]] = ...) -> None: ... + def __init__(self, fp: IO[str] | None = ...) -> None: ... def _parse(self, fp: IO[str]) -> None: ... def add_fallback(self, fallback: NullTranslations) -> None: ... def gettext(self, message: str) -> str: ... @@ -18,7 +18,7 @@ class NullTranslations: def charset(self) -> Any: ... def output_charset(self) -> Any: ... def set_output_charset(self, charset: str) -> None: ... - def install(self, names: Optional[Container[str]] = ...) -> None: ... + def install(self, names: Container[str] | None = ...) -> None: ... class GNUTranslations(NullTranslations): LE_MAGIC: int @@ -26,43 +26,43 @@ class GNUTranslations(NullTranslations): CONTEXT: str VERSIONS: Sequence[int] -def find(domain: str, localedir: Optional[StrPath] = ..., languages: Optional[Iterable[str]] = ..., all: bool = ...) -> Any: ... +def find(domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., all: bool = ...) -> Any: ... _T = TypeVar("_T") @overload def translation( domain: str, - localedir: Optional[StrPath] = ..., - languages: Optional[Iterable[str]] = ..., + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., class_: None = ..., fallback: bool = ..., - codeset: Optional[str] = ..., + codeset: str | None = ..., ) -> NullTranslations: ... @overload def translation( domain: str, - localedir: Optional[StrPath] = ..., - languages: Optional[Iterable[str]] = ..., + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., class_: Type[_T] = ..., fallback: Literal[False] = ..., - codeset: Optional[str] = ..., + codeset: str | None = ..., ) -> _T: ... @overload def translation( domain: str, - localedir: Optional[StrPath] = ..., - languages: Optional[Iterable[str]] = ..., + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., class_: Type[Any] = ..., fallback: Literal[True] = ..., - codeset: Optional[str] = ..., + codeset: str | None = ..., ) -> Any: ... def install( - domain: str, localedir: Optional[StrPath] = ..., codeset: Optional[str] = ..., names: Optional[Container[str]] = ... + domain: str, localedir: StrPath | None = ..., codeset: str | None = ..., names: Container[str] | None = ... ) -> None: ... -def textdomain(domain: Optional[str] = ...) -> str: ... -def bindtextdomain(domain: str, localedir: Optional[StrPath] = ...) -> str: ... -def bind_textdomain_codeset(domain: str, codeset: Optional[str] = ...) -> str: ... +def textdomain(domain: str | None = ...) -> str: ... +def bindtextdomain(domain: str, localedir: StrPath | None = ...) -> str: ... +def bind_textdomain_codeset(domain: str, codeset: str | None = ...) -> str: ... def dgettext(domain: str, message: str) -> str: ... def ldgettext(domain: str, message: str) -> str: ... def dngettext(domain: str, msgid1: str, msgid2: str, n: int) -> str: ... diff --git a/mypy/typeshed/stdlib/glob.pyi b/mypy/typeshed/stdlib/glob.pyi index 42269e95d896..c1cd176f500c 100644 --- a/mypy/typeshed/stdlib/glob.pyi +++ b/mypy/typeshed/stdlib/glob.pyi @@ -1,21 +1,21 @@ import sys -from _typeshed import AnyPath -from typing import AnyStr, Iterator, List, Optional, Union +from _typeshed import StrOrBytesPath +from typing import AnyStr, Iterator -def glob0(dirname: AnyStr, pattern: AnyStr) -> List[AnyStr]: ... -def glob1(dirname: AnyStr, pattern: AnyStr) -> List[AnyStr]: ... +def glob0(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... +def glob1(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... if sys.version_info >= (3, 10): def glob( - pathname: AnyStr, *, root_dir: Optional[AnyPath] = ..., dir_fd: Optional[int] = ..., recursive: bool = ... - ) -> List[AnyStr]: ... + pathname: AnyStr, *, root_dir: StrOrBytesPath | None = ..., dir_fd: int | None = ..., recursive: bool = ... + ) -> list[AnyStr]: ... def iglob( - pathname: AnyStr, *, root_dir: Optional[AnyPath] = ..., dir_fd: Optional[int] = ..., recursive: bool = ... + pathname: AnyStr, *, root_dir: StrOrBytesPath | None = ..., dir_fd: int | None = ..., recursive: bool = ... ) -> Iterator[AnyStr]: ... else: - def glob(pathname: AnyStr, *, recursive: bool = ...) -> List[AnyStr]: ... + def glob(pathname: AnyStr, *, recursive: bool = ...) -> list[AnyStr]: ... def iglob(pathname: AnyStr, *, recursive: bool = ...) -> Iterator[AnyStr]: ... def escape(pathname: AnyStr) -> AnyStr: ... -def has_magic(s: Union[str, bytes]) -> bool: ... # undocumented +def has_magic(s: str | bytes) -> bool: ... # undocumented diff --git a/mypy/typeshed/stdlib/graphlib.pyi b/mypy/typeshed/stdlib/graphlib.pyi index ca21b42329d2..0872af4a54a4 100644 --- a/mypy/typeshed/stdlib/graphlib.pyi +++ b/mypy/typeshed/stdlib/graphlib.pyi @@ -1,10 +1,10 @@ from _typeshed import SupportsItems -from typing import Generic, Iterable, Optional, Tuple, TypeVar +from typing import Generic, Iterable, Tuple, TypeVar _T = TypeVar("_T") class TopologicalSorter(Generic[_T]): - def __init__(self, graph: Optional[SupportsItems[_T, Iterable[_T]]] = ...) -> None: ... + def __init__(self, graph: SupportsItems[_T, Iterable[_T]] | None = ...) -> None: ... def add(self, node: _T, *predecessors: _T) -> None: ... def prepare(self) -> None: ... def is_active(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/grp.pyi b/mypy/typeshed/stdlib/grp.pyi index 8447f21736bb..08cbe6b86476 100644 --- a/mypy/typeshed/stdlib/grp.pyi +++ b/mypy/typeshed/stdlib/grp.pyi @@ -1,11 +1,11 @@ -from typing import List, NamedTuple, Optional +from typing import NamedTuple class struct_group(NamedTuple): gr_name: str - gr_passwd: Optional[str] + gr_passwd: str | None gr_gid: int - gr_mem: List[str] + gr_mem: list[str] -def getgrall() -> List[struct_group]: ... +def getgrall() -> list[struct_group]: ... def getgrgid(id: int) -> struct_group: ... def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/gzip.pyi b/mypy/typeshed/stdlib/gzip.pyi index 8d061e051b93..070ceac48282 100644 --- a/mypy/typeshed/stdlib/gzip.pyi +++ b/mypy/typeshed/stdlib/gzip.pyi @@ -1,9 +1,9 @@ import _compression import sys import zlib -from _typeshed import AnyPath, ReadableBuffer +from _typeshed import ReadableBuffer, StrOrBytesPath from io import FileIO -from typing import Any, Optional, Protocol, TextIO, Union, overload +from typing import Any, Protocol, TextIO, overload from typing_extensions import Literal _ReadBinaryMode = Literal["r", "rb"] @@ -31,7 +31,7 @@ class _WritableFileobj(Protocol): @overload def open( - filename: Union[AnyPath, _ReadableFileobj], + filename: StrOrBytesPath | _ReadableFileobj, mode: _ReadBinaryMode = ..., compresslevel: int = ..., encoding: None = ..., @@ -40,7 +40,7 @@ def open( ) -> GzipFile: ... @overload def open( - filename: Union[AnyPath, _WritableFileobj], + filename: StrOrBytesPath | _WritableFileobj, mode: _WriteBinaryMode, compresslevel: int = ..., encoding: None = ..., @@ -49,22 +49,22 @@ def open( ) -> GzipFile: ... @overload def open( - filename: AnyPath, + filename: StrOrBytesPath, mode: _OpenTextMode, compresslevel: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., ) -> TextIO: ... @overload def open( - filename: Union[AnyPath, _ReadableFileobj, _WritableFileobj], + filename: StrOrBytesPath | _ReadableFileobj | _WritableFileobj, mode: str, compresslevel: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., -) -> Union[GzipFile, TextIO]: ... + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> GzipFile | TextIO: ... class _PaddedFile: file: _ReadableFileobj @@ -78,19 +78,19 @@ if sys.version_info >= (3, 8): class BadGzipFile(OSError): ... class GzipFile(_compression.BaseStream): - myfileobj: Optional[FileIO] + myfileobj: FileIO | None mode: Literal[1, 2] name: str compress: zlib._Compress - fileobj: Union[_ReadableFileobj, _WritableFileobj] + fileobj: _ReadableFileobj | _WritableFileobj @overload def __init__( self, - filename: Optional[AnyPath], + filename: StrOrBytesPath | None, mode: _ReadBinaryMode, compresslevel: int = ..., - fileobj: Optional[_ReadableFileobj] = ..., - mtime: Optional[float] = ..., + fileobj: _ReadableFileobj | None = ..., + mtime: float | None = ..., ) -> None: ... @overload def __init__( @@ -98,17 +98,17 @@ class GzipFile(_compression.BaseStream): *, mode: _ReadBinaryMode, compresslevel: int = ..., - fileobj: Optional[_ReadableFileobj] = ..., - mtime: Optional[float] = ..., + fileobj: _ReadableFileobj | None = ..., + mtime: float | None = ..., ) -> None: ... @overload def __init__( self, - filename: Optional[AnyPath], + filename: StrOrBytesPath | None, mode: _WriteBinaryMode, compresslevel: int = ..., - fileobj: Optional[_WritableFileobj] = ..., - mtime: Optional[float] = ..., + fileobj: _WritableFileobj | None = ..., + mtime: float | None = ..., ) -> None: ... @overload def __init__( @@ -116,25 +116,25 @@ class GzipFile(_compression.BaseStream): *, mode: _WriteBinaryMode, compresslevel: int = ..., - fileobj: Optional[_WritableFileobj] = ..., - mtime: Optional[float] = ..., + fileobj: _WritableFileobj | None = ..., + mtime: float | None = ..., ) -> None: ... @overload def __init__( self, - filename: Optional[AnyPath] = ..., - mode: Optional[str] = ..., + filename: StrOrBytesPath | None = ..., + mode: str | None = ..., compresslevel: int = ..., - fileobj: Union[_ReadableFileobj, _WritableFileobj, None] = ..., - mtime: Optional[float] = ..., + fileobj: _ReadableFileobj | _WritableFileobj | None = ..., + mtime: float | None = ..., ) -> None: ... @property def filename(self) -> str: ... @property - def mtime(self) -> Optional[int]: ... + def mtime(self) -> int | None: ... crc: int def write(self, data: ReadableBuffer) -> int: ... - def read(self, size: Optional[int] = ...) -> bytes: ... + def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... def peek(self, n: int) -> bytes: ... @property @@ -147,14 +147,14 @@ class GzipFile(_compression.BaseStream): def writable(self) -> bool: ... def seekable(self) -> bool: ... def seek(self, offset: int, whence: int = ...) -> int: ... - def readline(self, size: Optional[int] = ...) -> bytes: ... + def readline(self, size: int | None = ...) -> bytes: ... class _GzipReader(_compression.DecompressReader): def __init__(self, fp: _ReadableFileobj) -> None: ... def read(self, size: int = ...) -> bytes: ... if sys.version_info >= (3, 8): - def compress(data: bytes, compresslevel: int = ..., *, mtime: Optional[float] = ...) -> bytes: ... + def compress(data: bytes, compresslevel: int = ..., *, mtime: float | None = ...) -> bytes: ... else: def compress(data: bytes, compresslevel: int = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/hashlib.pyi b/mypy/typeshed/stdlib/hashlib.pyi index e4aee21450cc..e39f2f25326e 100644 --- a/mypy/typeshed/stdlib/hashlib.pyi +++ b/mypy/typeshed/stdlib/hashlib.pyi @@ -1,17 +1,16 @@ import sys -from _typeshed import ReadableBuffer -from typing import AbstractSet, Optional +from _typeshed import ReadableBuffer, Self +from typing import AbstractSet class _Hash(object): - digest_size: int - block_size: int - - # [Python documentation note] Changed in version 3.4: The name attribute has - # been present in CPython since its inception, but until Python 3.4 was not - # formally specified, so may not exist on some platforms - name: str + @property + def digest_size(self) -> int: ... + @property + def block_size(self) -> int: ... + @property + def name(self) -> str: ... def __init__(self, data: ReadableBuffer = ...) -> None: ... - def copy(self) -> _Hash: ... + def copy(self: Self) -> Self: ... def digest(self) -> bytes: ... def hexdigest(self) -> str: ... def update(self, __data: ReadableBuffer) -> None: ... @@ -47,7 +46,7 @@ algorithms_guaranteed: AbstractSet[str] algorithms_available: AbstractSet[str] def pbkdf2_hmac( - hash_name: str, password: ReadableBuffer, salt: ReadableBuffer, iterations: int, dklen: Optional[int] = ... + hash_name: str, password: ReadableBuffer, salt: ReadableBuffer, iterations: int, dklen: int | None = ... ) -> bytes: ... class _VarLenHash(object): @@ -70,10 +69,10 @@ shake_256 = _VarLenHash def scrypt( password: ReadableBuffer, *, - salt: Optional[ReadableBuffer] = ..., - n: Optional[int] = ..., - r: Optional[int] = ..., - p: Optional[int] = ..., + salt: ReadableBuffer | None = ..., + n: int | None = ..., + r: int | None = ..., + p: int | None = ..., maxmem: int = ..., dklen: int = ..., ) -> bytes: ... diff --git a/mypy/typeshed/stdlib/heapq.pyi b/mypy/typeshed/stdlib/heapq.pyi index 3d27a30bb412..81ee02582a6a 100644 --- a/mypy/typeshed/stdlib/heapq.pyi +++ b/mypy/typeshed/stdlib/heapq.pyi @@ -1,14 +1,14 @@ from _typeshed import SupportsLessThan -from typing import Any, Callable, Iterable, List, Optional, TypeVar +from typing import Any, Callable, Iterable, TypeVar _T = TypeVar("_T") -def heappush(__heap: List[_T], __item: _T) -> None: ... -def heappop(__heap: List[_T]) -> _T: ... -def heappushpop(__heap: List[_T], __item: _T) -> _T: ... -def heapify(__heap: List[Any]) -> None: ... -def heapreplace(__heap: List[_T], __item: _T) -> _T: ... -def merge(*iterables: Iterable[_T], key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ...) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsLessThan]] = ...) -> List[_T]: ... -def _heapify_max(__x: List[Any]) -> None: ... # undocumented +def heappush(__heap: list[_T], __item: _T) -> None: ... +def heappop(__heap: list[_T]) -> _T: ... +def heappushpop(__heap: list[_T], __item: _T) -> _T: ... +def heapify(__heap: list[Any]) -> None: ... +def heapreplace(__heap: list[_T], __item: _T) -> _T: ... +def merge(*iterables: Iterable[_T], key: Callable[[_T], Any] | None = ..., reverse: bool = ...) -> Iterable[_T]: ... +def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... +def _heapify_max(__x: list[Any]) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/hmac.pyi b/mypy/typeshed/stdlib/hmac.pyi index ca4013da7879..440bddd7919c 100644 --- a/mypy/typeshed/stdlib/hmac.pyi +++ b/mypy/typeshed/stdlib/hmac.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import ReadableBuffer from types import ModuleType -from typing import Any, AnyStr, Callable, Optional, Union, overload +from typing import Any, AnyStr, Callable, Union, overload # TODO more precise type for object of hashlib _Hash = Any @@ -13,23 +13,18 @@ if sys.version_info >= (3, 8): # In reality digestmod has a default value, but the function always throws an error # if the argument is not given, so we pretend it is a required argument. @overload - def new(key: bytes, msg: Optional[ReadableBuffer], digestmod: _DigestMod) -> HMAC: ... + def new(key: bytes, msg: ReadableBuffer | None, digestmod: _DigestMod) -> HMAC: ... @overload def new(key: bytes, *, digestmod: _DigestMod) -> HMAC: ... -elif sys.version_info >= (3, 4): - def new(key: bytes, msg: Optional[ReadableBuffer] = ..., digestmod: Optional[_DigestMod] = ...) -> HMAC: ... - else: - def new(key: bytes, msg: Optional[ReadableBuffer] = ..., digestmod: Optional[_DigestMod] = ...) -> HMAC: ... + def new(key: bytes, msg: ReadableBuffer | None = ..., digestmod: _DigestMod | None = ...) -> HMAC: ... class HMAC: - if sys.version_info >= (3,): - digest_size: int - if sys.version_info >= (3, 4): - block_size: int - name: str - def __init__(self, key: bytes, msg: Optional[ReadableBuffer] = ..., digestmod: _DigestMod = ...) -> None: ... + digest_size: int + block_size: int + name: str + def __init__(self, key: bytes, msg: ReadableBuffer | None = ..., digestmod: _DigestMod = ...) -> None: ... def update(self, msg: ReadableBuffer) -> None: ... def digest(self) -> bytes: ... def hexdigest(self) -> str: ... diff --git a/mypy/typeshed/stdlib/html/entities.pyi b/mypy/typeshed/stdlib/html/entities.pyi index 97d9b2d320bc..1743fccf32b9 100644 --- a/mypy/typeshed/stdlib/html/entities.pyi +++ b/mypy/typeshed/stdlib/html/entities.pyi @@ -1,6 +1,4 @@ -from typing import Dict - -name2codepoint: Dict[str, int] -html5: Dict[str, str] -codepoint2name: Dict[int, str] -entitydefs: Dict[str, str] +name2codepoint: dict[str, int] +html5: dict[str, str] +codepoint2name: dict[int, str] +entitydefs: dict[str, str] diff --git a/mypy/typeshed/stdlib/html/parser.pyi b/mypy/typeshed/stdlib/html/parser.pyi index 82431b7e1d3e..fec3f3509522 100644 --- a/mypy/typeshed/stdlib/html/parser.pyi +++ b/mypy/typeshed/stdlib/html/parser.pyi @@ -1,16 +1,16 @@ from _markupbase import ParserBase -from typing import List, Optional, Tuple +from typing import Tuple class HTMLParser(ParserBase): def __init__(self, *, convert_charrefs: bool = ...) -> None: ... def feed(self, data: str) -> None: ... def close(self) -> None: ... def reset(self) -> None: ... - def getpos(self) -> Tuple[int, int]: ... - def get_starttag_text(self) -> Optional[str]: ... - def handle_starttag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None: ... + def getpos(self) -> tuple[int, int]: ... + def get_starttag_text(self) -> str | None: ... + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: ... def handle_endtag(self, tag: str) -> None: ... - def handle_startendtag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None: ... + def handle_startendtag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: ... def handle_data(self, data: str) -> None: ... def handle_entityref(self, name: str) -> None: ... def handle_charref(self, name: str) -> None: ... diff --git a/mypy/typeshed/stdlib/http/client.pyi b/mypy/typeshed/stdlib/http/client.pyi index c35228928d77..c450db587135 100644 --- a/mypy/typeshed/stdlib/http/client.pyi +++ b/mypy/typeshed/stdlib/http/client.pyi @@ -3,26 +3,9 @@ import io import ssl import sys import types -from _typeshed import WriteableBuffer +from _typeshed import Self, WriteableBuffer from socket import socket -from typing import ( - IO, - Any, - BinaryIO, - Callable, - Dict, - Iterable, - Iterator, - List, - Mapping, - Optional, - Protocol, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, Mapping, Protocol, Type, TypeVar, Union, overload _DataType = Union[bytes, IO[Any], Iterable[bytes], str] _T = TypeVar("_T") @@ -88,9 +71,10 @@ INSUFFICIENT_STORAGE: int NOT_EXTENDED: int NETWORK_AUTHENTICATION_REQUIRED: int -responses: Dict[int, str] +responses: dict[int, str] -class HTTPMessage(email.message.Message): ... +class HTTPMessage(email.message.Message): + def getallmatchingheaders(self, name: str) -> list[str]: ... # undocumented def parse_headers(fp: io.BufferedIOBase, _class: Callable[[], email.message.Message] = ...) -> HTTPMessage: ... @@ -99,26 +83,32 @@ class HTTPResponse(io.BufferedIOBase, BinaryIO): headers: HTTPMessage version: int debuglevel: int + fp: io.BufferedReader closed: bool status: int reason: str - def __init__(self, sock: socket, debuglevel: int = ..., method: Optional[str] = ..., url: Optional[str] = ...) -> None: ... - def read(self, amt: Optional[int] = ...) -> bytes: ... + chunked: bool + chunk_left: int | None + length: int | None + will_close: bool + def __init__(self, sock: socket, debuglevel: int = ..., method: str | None = ..., url: str | None = ...) -> None: ... + def peek(self, n: int = ...) -> bytes: ... + def read(self, amt: int | None = ...) -> bytes: ... def read1(self, n: int = ...) -> bytes: ... def readinto(self, b: WriteableBuffer) -> int: ... def readline(self, limit: int = ...) -> bytes: ... # type: ignore @overload - def getheader(self, name: str) -> Optional[str]: ... + def getheader(self, name: str) -> str | None: ... @overload - def getheader(self, name: str, default: _T) -> Union[str, _T]: ... - def getheaders(self) -> List[Tuple[str, str]]: ... + def getheader(self, name: str, default: _T) -> str | _T: ... + def getheaders(self) -> list[tuple[str, str]]: ... def fileno(self) -> int: ... def isclosed(self) -> bool: ... def __iter__(self) -> Iterator[bytes]: ... - def __enter__(self) -> HTTPResponse: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[types.TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> bool | None: ... def info(self) -> email.message.Message: ... def geturl(self) -> str: ... def getcode(self) -> int: ... @@ -131,18 +121,22 @@ class _HTTPConnectionProtocol(Protocol): def __call__( self, host: str, - port: Optional[int] = ..., + port: int | None = ..., timeout: float = ..., - source_address: Optional[Tuple[str, int]] = ..., + source_address: tuple[str, int] | None = ..., blocksize: int = ..., ) -> HTTPConnection: ... else: def __call__( - self, host: str, port: Optional[int] = ..., timeout: float = ..., source_address: Optional[Tuple[str, int]] = ... + self, host: str, port: int | None = ..., timeout: float = ..., source_address: tuple[str, int] | None = ... ) -> HTTPConnection: ... class HTTPConnection: - timeout: Optional[float] + auto_open: int # undocumented + debuglevel: int + default_port: int # undocumented + response_class: Type[HTTPResponse] # undocumented + timeout: float | None host: str port: int sock: Any @@ -150,36 +144,26 @@ class HTTPConnection: def __init__( self, host: str, - port: Optional[int] = ..., - timeout: Optional[float] = ..., - source_address: Optional[Tuple[str, int]] = ..., + port: int | None = ..., + timeout: float | None = ..., + source_address: tuple[str, int] | None = ..., blocksize: int = ..., ) -> None: ... else: def __init__( - self, - host: str, - port: Optional[int] = ..., - timeout: Optional[float] = ..., - source_address: Optional[Tuple[str, int]] = ..., + self, host: str, port: int | None = ..., timeout: float | None = ..., source_address: tuple[str, int] | None = ... ) -> None: ... def request( - self, - method: str, - url: str, - body: Optional[_DataType] = ..., - headers: Mapping[str, str] = ..., - *, - encode_chunked: bool = ..., + self, method: str, url: str, body: _DataType | None = ..., headers: Mapping[str, str] = ..., *, encode_chunked: bool = ... ) -> None: ... def getresponse(self) -> HTTPResponse: ... def set_debuglevel(self, level: int) -> None: ... - def set_tunnel(self, host: str, port: Optional[int] = ..., headers: Optional[Mapping[str, str]] = ...) -> None: ... + def set_tunnel(self, host: str, port: int | None = ..., headers: Mapping[str, str] | None = ...) -> None: ... def connect(self) -> None: ... def close(self) -> None: ... def putrequest(self, method: str, url: str, skip_host: bool = ..., skip_accept_encoding: bool = ...) -> None: ... def putheader(self, header: str, *argument: str) -> None: ... - def endheaders(self, message_body: Optional[_DataType] = ..., *, encode_chunked: bool = ...) -> None: ... + def endheaders(self, message_body: _DataType | None = ..., *, encode_chunked: bool = ...) -> None: ... def send(self, data: _DataType) -> None: ... class HTTPSConnection(HTTPConnection): @@ -187,28 +171,28 @@ class HTTPSConnection(HTTPConnection): def __init__( self, host: str, - port: Optional[int] = ..., - key_file: Optional[str] = ..., - cert_file: Optional[str] = ..., - timeout: Optional[float] = ..., - source_address: Optional[Tuple[str, int]] = ..., + port: int | None = ..., + key_file: str | None = ..., + cert_file: str | None = ..., + timeout: float | None = ..., + source_address: tuple[str, int] | None = ..., *, - context: Optional[ssl.SSLContext] = ..., - check_hostname: Optional[bool] = ..., + context: ssl.SSLContext | None = ..., + check_hostname: bool | None = ..., blocksize: int = ..., ) -> None: ... else: def __init__( self, host: str, - port: Optional[int] = ..., - key_file: Optional[str] = ..., - cert_file: Optional[str] = ..., - timeout: Optional[float] = ..., - source_address: Optional[Tuple[str, int]] = ..., + port: int | None = ..., + key_file: str | None = ..., + cert_file: str | None = ..., + timeout: float | None = ..., + source_address: tuple[str, int] | None = ..., *, - context: Optional[ssl.SSLContext] = ..., - check_hostname: Optional[bool] = ..., + context: ssl.SSLContext | None = ..., + check_hostname: bool | None = ..., ) -> None: ... class HTTPException(Exception): ... @@ -225,7 +209,9 @@ class UnknownTransferEncoding(HTTPException): ... class UnimplementedFileMode(HTTPException): ... class IncompleteRead(HTTPException): - def __init__(self, partial: bytes, expected: Optional[int] = ...) -> None: ... + def __init__(self, partial: bytes, expected: int | None = ...) -> None: ... + partial: bytes + expected: int | None class ImproperConnectionState(HTTPException): ... class CannotSendRequest(ImproperConnectionState): ... diff --git a/mypy/typeshed/stdlib/http/cookiejar.pyi b/mypy/typeshed/stdlib/http/cookiejar.pyi index 9398bae00951..f37fb19cebe9 100644 --- a/mypy/typeshed/stdlib/http/cookiejar.pyi +++ b/mypy/typeshed/stdlib/http/cookiejar.pyi @@ -1,7 +1,7 @@ import sys +from _typeshed import StrPath from http.client import HTTPResponse -from os import PathLike -from typing import Dict, Iterable, Iterator, Optional, Sequence, Tuple, TypeVar, Union, overload +from typing import ClassVar, Iterable, Iterator, Pattern, Sequence, Tuple, TypeVar, overload from urllib.request import Request _T = TypeVar("_T") @@ -9,34 +9,40 @@ _T = TypeVar("_T") class LoadError(OSError): ... class CookieJar(Iterable[Cookie]): - def __init__(self, policy: Optional[CookiePolicy] = ...) -> None: ... + non_word_re: ClassVar[Pattern[str]] # undocumented + quote_re: ClassVar[Pattern[str]] # undocumented + strict_domain_re: ClassVar[Pattern[str]] # undocumented + domain_re: ClassVar[Pattern[str]] # undocumented + dots_re: ClassVar[Pattern[str]] # undocumented + magic_re: ClassVar[Pattern[str]] # undocumented + def __init__(self, policy: CookiePolicy | None = ...) -> None: ... def add_cookie_header(self, request: Request) -> None: ... def extract_cookies(self, response: HTTPResponse, request: Request) -> None: ... def set_policy(self, policy: CookiePolicy) -> None: ... def make_cookies(self, response: HTTPResponse, request: Request) -> Sequence[Cookie]: ... def set_cookie(self, cookie: Cookie) -> None: ... def set_cookie_if_ok(self, cookie: Cookie, request: Request) -> None: ... - def clear(self, domain: Optional[str] = ..., path: Optional[str] = ..., name: Optional[str] = ...) -> None: ... + def clear(self, domain: str | None = ..., path: str | None = ..., name: str | None = ...) -> None: ... def clear_session_cookies(self) -> None: ... + def clear_expired_cookies(self) -> None: ... # undocumented def __iter__(self) -> Iterator[Cookie]: ... def __len__(self) -> int: ... + def __repr__(self) -> str: ... + def __str__(self) -> str: ... class FileCookieJar(CookieJar): filename: str delayload: bool if sys.version_info >= (3, 8): - def __init__( - self, filename: Optional[Union[str, PathLike[str]]] = ..., delayload: bool = ..., policy: Optional[CookiePolicy] = ... - ) -> None: ... + def __init__(self, filename: StrPath | None = ..., delayload: bool = ..., policy: CookiePolicy | None = ...) -> None: ... else: - def __init__( - self, filename: Optional[str] = ..., delayload: bool = ..., policy: Optional[CookiePolicy] = ... - ) -> None: ... - def save(self, filename: Optional[str] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... - def load(self, filename: Optional[str] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... - def revert(self, filename: Optional[str] = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... + def __init__(self, filename: str | None = ..., delayload: bool = ..., policy: CookiePolicy | None = ...) -> None: ... + def save(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... + def load(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... + def revert(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... -class MozillaCookieJar(FileCookieJar): ... +class MozillaCookieJar(FileCookieJar): + header: ClassVar[str] # undocumented class LWPCookieJar(FileCookieJar): def as_lwp_str(self, ignore_discard: bool = ..., ignore_expires: bool = ...) -> str: ... # undocumented @@ -58,19 +64,19 @@ class DefaultCookiePolicy(CookiePolicy): strict_ns_domain: int strict_ns_set_initial_dollar: bool strict_ns_set_path: bool - DomainStrictNoDots: int - DomainStrictNonDomain: int - DomainRFC2965Match: int - DomainLiberal: int - DomainStrict: int + DomainStrictNoDots: ClassVar[int] + DomainStrictNonDomain: ClassVar[int] + DomainRFC2965Match: ClassVar[int] + DomainLiberal: ClassVar[int] + DomainStrict: ClassVar[int] if sys.version_info >= (3, 8): def __init__( self, - blocked_domains: Optional[Sequence[str]] = ..., - allowed_domains: Optional[Sequence[str]] = ..., + blocked_domains: Sequence[str] | None = ..., + allowed_domains: Sequence[str] | None = ..., netscape: bool = ..., rfc2965: bool = ..., - rfc2109_as_netscape: Optional[bool] = ..., + rfc2109_as_netscape: bool | None = ..., hide_cookie2: bool = ..., strict_domain: bool = ..., strict_rfc2965_unverifiable: bool = ..., @@ -83,11 +89,11 @@ class DefaultCookiePolicy(CookiePolicy): else: def __init__( self, - blocked_domains: Optional[Sequence[str]] = ..., - allowed_domains: Optional[Sequence[str]] = ..., + blocked_domains: Sequence[str] | None = ..., + allowed_domains: Sequence[str] | None = ..., netscape: bool = ..., rfc2965: bool = ..., - rfc2109_as_netscape: Optional[bool] = ..., + rfc2109_as_netscape: bool | None = ..., hide_cookie2: bool = ..., strict_domain: bool = ..., strict_rfc2965_unverifiable: bool = ..., @@ -99,22 +105,34 @@ class DefaultCookiePolicy(CookiePolicy): def blocked_domains(self) -> Tuple[str, ...]: ... def set_blocked_domains(self, blocked_domains: Sequence[str]) -> None: ... def is_blocked(self, domain: str) -> bool: ... - def allowed_domains(self) -> Optional[Tuple[str, ...]]: ... - def set_allowed_domains(self, allowed_domains: Optional[Sequence[str]]) -> None: ... + def allowed_domains(self) -> Tuple[str, ...] | None: ... + def set_allowed_domains(self, allowed_domains: Sequence[str] | None) -> None: ... def is_not_allowed(self, domain: str) -> bool: ... + def set_ok_version(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def set_ok_verifiability(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def set_ok_name(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def set_ok_path(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def set_ok_domain(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def set_ok_port(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_version(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_verifiability(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_secure(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_expires(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_port(self, cookie: Cookie, request: Request) -> bool: ... # undocumented + def return_ok_domain(self, cookie: Cookie, request: Request) -> bool: ... # undocumented class Cookie: - version: Optional[int] + version: int | None name: str - value: Optional[str] - port: Optional[str] + value: str | None + port: str | None path: str path_specified: bool secure: bool - expires: Optional[int] + expires: int | None discard: bool - comment: Optional[str] - comment_url: Optional[str] + comment: str | None + comment_url: str | None rfc2109: bool port_specified: bool domain: str # undocumented @@ -122,10 +140,10 @@ class Cookie: domain_initial_dot: bool def __init__( self, - version: Optional[int], + version: int | None, name: str, - value: Optional[str], # undocumented - port: Optional[str], + value: str | None, # undocumented + port: str | None, port_specified: bool, domain: str, domain_specified: bool, @@ -133,17 +151,17 @@ class Cookie: path: str, path_specified: bool, secure: bool, - expires: Optional[int], + expires: int | None, discard: bool, - comment: Optional[str], - comment_url: Optional[str], - rest: Dict[str, str], + comment: str | None, + comment_url: str | None, + rest: dict[str, str], rfc2109: bool = ..., ) -> None: ... def has_nonstandard_attr(self, name: str) -> bool: ... @overload - def get_nonstandard_attr(self, name: str) -> Optional[str]: ... + def get_nonstandard_attr(self, name: str) -> str | None: ... @overload - def get_nonstandard_attr(self, name: str, default: _T) -> Union[str, _T]: ... + def get_nonstandard_attr(self, name: str, default: _T) -> str | _T: ... def set_nonstandard_attr(self, name: str, value: str) -> None: ... - def is_expired(self, now: Optional[int] = ...) -> bool: ... + def is_expired(self, now: int | None = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/http/cookies.pyi b/mypy/typeshed/stdlib/http/cookies.pyi index 1fc2179ecfd6..7e9513adb1a1 100644 --- a/mypy/typeshed/stdlib/http/cookies.pyi +++ b/mypy/typeshed/stdlib/http/cookies.pyi @@ -1,5 +1,8 @@ import sys -from typing import Any, Dict, Generic, Iterable, List, Mapping, Optional, Tuple, TypeVar, Union, overload +from typing import Any, Dict, Generic, Iterable, Mapping, TypeVar, Union, overload + +if sys.version_info >= (3, 9): + from types import GenericAlias _DataType = Union[str, Mapping[str, Union[str, Morsel[Any]]]] _T = TypeVar("_T") @@ -24,24 +27,26 @@ class Morsel(Dict[str, Any], Generic[_T]): def set(self, key: str, val: str, coded_val: _T) -> None: ... else: def set(self, key: str, val: str, coded_val: _T, LegalChars: str = ...) -> None: ... - def setdefault(self, key: str, val: Optional[str] = ...) -> str: ... + def setdefault(self, key: str, val: str | None = ...) -> str: ... # The dict update can also get a keywords argument so this is incompatible @overload # type: ignore def update(self, values: Mapping[str, str]) -> None: ... @overload - def update(self, values: Iterable[Tuple[str, str]]) -> None: ... + def update(self, values: Iterable[tuple[str, str]]) -> None: ... def isReservedKey(self, K: str) -> bool: ... - def output(self, attrs: Optional[List[str]] = ..., header: str = ...) -> str: ... - def js_output(self, attrs: Optional[List[str]] = ...) -> str: ... - def OutputString(self, attrs: Optional[List[str]] = ...) -> str: ... + def output(self, attrs: list[str] | None = ..., header: str = ...) -> str: ... + def js_output(self, attrs: list[str] | None = ...) -> str: ... + def OutputString(self, attrs: list[str] | None = ...) -> str: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class BaseCookie(Dict[str, Morsel[_T]], Generic[_T]): - def __init__(self, input: Optional[_DataType] = ...) -> None: ... + def __init__(self, input: _DataType | None = ...) -> None: ... def value_decode(self, val: str) -> _T: ... def value_encode(self, val: _T) -> str: ... - def output(self, attrs: Optional[List[str]] = ..., header: str = ..., sep: str = ...) -> str: ... - def js_output(self, attrs: Optional[List[str]] = ...) -> str: ... + def output(self, attrs: list[str] | None = ..., header: str = ..., sep: str = ...) -> str: ... + def js_output(self, attrs: list[str] | None = ...) -> str: ... def load(self, rawdata: _DataType) -> None: ... - def __setitem__(self, key: str, value: Union[str, Morsel[_T]]) -> None: ... + def __setitem__(self, key: str, value: str | Morsel[_T]) -> None: ... class SimpleCookie(BaseCookie[_T], Generic[_T]): ... diff --git a/mypy/typeshed/stdlib/http/server.pyi b/mypy/typeshed/stdlib/http/server.pyi index f9a13d013167..e3d0a8c318f4 100644 --- a/mypy/typeshed/stdlib/http/server.pyi +++ b/mypy/typeshed/stdlib/http/server.pyi @@ -1,8 +1,9 @@ import email.message +import io import socketserver import sys -from os import PathLike -from typing import Any, ClassVar, Dict, List, Mapping, Optional, Sequence, Tuple, Union +from _typeshed import StrPath, SupportsRead, SupportsWrite +from typing import Any, AnyStr, BinaryIO, ClassVar, Mapping, Sequence class HTTPServer(socketserver.TCPServer): server_name: str @@ -13,7 +14,7 @@ if sys.version_info >= (3, 7): daemon_threads: bool # undocumented class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): - client_address: Tuple[str, int] + client_address: tuple[str, int] server: socketserver.BaseServer close_connection: bool requestline: str @@ -27,43 +28,53 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): error_content_type: str protocol_version: str MessageClass: type - responses: Mapping[int, Tuple[str, str]] - weekdayname: ClassVar[Sequence[str]] = ... # Undocumented - monthname: ClassVar[Sequence[Optional[str]]] = ... # Undocumented - def __init__(self, request: bytes, client_address: Tuple[str, int], server: socketserver.BaseServer) -> None: ... + responses: Mapping[int, tuple[str, str]] + default_request_version: str # undocumented + weekdayname: ClassVar[Sequence[str]] # undocumented + monthname: ClassVar[Sequence[str | None]] # undocumented + def __init__(self, request: bytes, client_address: tuple[str, int], server: socketserver.BaseServer) -> None: ... def handle(self) -> None: ... def handle_one_request(self) -> None: ... def handle_expect_100(self) -> bool: ... - def send_error(self, code: int, message: Optional[str] = ..., explain: Optional[str] = ...) -> None: ... - def send_response(self, code: int, message: Optional[str] = ...) -> None: ... + def send_error(self, code: int, message: str | None = ..., explain: str | None = ...) -> None: ... + def send_response(self, code: int, message: str | None = ...) -> None: ... def send_header(self, keyword: str, value: str) -> None: ... - def send_response_only(self, code: int, message: Optional[str] = ...) -> None: ... + def send_response_only(self, code: int, message: str | None = ...) -> None: ... def end_headers(self) -> None: ... def flush_headers(self) -> None: ... - def log_request(self, code: Union[int, str] = ..., size: Union[int, str] = ...) -> None: ... + def log_request(self, code: int | str = ..., size: int | str = ...) -> None: ... def log_error(self, format: str, *args: Any) -> None: ... def log_message(self, format: str, *args: Any) -> None: ... def version_string(self) -> str: ... - def date_time_string(self, timestamp: Optional[int] = ...) -> str: ... + def date_time_string(self, timestamp: int | None = ...) -> str: ... def log_date_time_string(self) -> str: ... def address_string(self) -> str: ... - def parse_request(self) -> bool: ... # Undocumented + def parse_request(self) -> bool: ... # undocumented class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): - extensions_map: Dict[str, str] + server_version: str + extensions_map: dict[str, str] if sys.version_info >= (3, 7): def __init__( - self, - request: bytes, - client_address: Tuple[str, int], - server: socketserver.BaseServer, - directory: Optional[Union[str, PathLike[str]]] = ..., + self, request: bytes, client_address: tuple[str, int], server: socketserver.BaseServer, directory: str | None = ... ) -> None: ... else: - def __init__(self, request: bytes, client_address: Tuple[str, int], server: socketserver.BaseServer) -> None: ... + def __init__(self, request: bytes, client_address: tuple[str, int], server: socketserver.BaseServer) -> None: ... def do_GET(self) -> None: ... def do_HEAD(self) -> None: ... + def send_head(self) -> io.BytesIO | BinaryIO | None: ... # undocumented + def list_directory(self, path: StrPath) -> io.BytesIO | None: ... # undocumented + def translate_path(self, path: str) -> str: ... # undocumented + def copyfile(self, source: SupportsRead[AnyStr], outputfile: SupportsWrite[AnyStr]) -> None: ... # undocumented + def guess_type(self, path: StrPath) -> str: ... # undocumented + +def executable(path: StrPath) -> bool: ... # undocumented class CGIHTTPRequestHandler(SimpleHTTPRequestHandler): - cgi_directories: List[str] + cgi_directories: list[str] + have_fork: bool # undocumented def do_POST(self) -> None: ... + def is_cgi(self) -> bool: ... # undocumented + def is_executable(self, path: StrPath) -> bool: ... # undocumented + def is_python(self, path: StrPath) -> bool: ... # undocumented + def run_cgi(self) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/imaplib.pyi b/mypy/typeshed/stdlib/imaplib.pyi index bb9e9c6db132..a9f19048c9ae 100644 --- a/mypy/typeshed/stdlib/imaplib.pyi +++ b/mypy/typeshed/stdlib/imaplib.pyi @@ -1,10 +1,11 @@ import subprocess import sys import time +from _typeshed import Self from socket import socket as _socket from ssl import SSLContext, SSLSocket from types import TracebackType -from typing import IO, Any, Callable, Dict, List, Optional, Pattern, Text, Tuple, Type, Union +from typing import IO, Any, Callable, List, Pattern, Tuple, Type, Union from typing_extensions import Literal # TODO: Commands should use their actual return types, not this type alias. @@ -13,35 +14,37 @@ _CommandResults = Tuple[str, List[Any]] _AnyResponseData = Union[List[None], List[Union[bytes, Tuple[bytes, bytes]]]] +_list = list # conflicts with a method named "list" + class IMAP4: - error: Type[Exception] = ... - abort: Type[Exception] = ... - readonly: Type[Exception] = ... - mustquote: Pattern[Text] = ... - debug: int = ... - state: str = ... - literal: Optional[Text] = ... - tagged_commands: Dict[bytes, Optional[List[bytes]]] - untagged_responses: Dict[str, List[Union[bytes, Tuple[bytes, bytes]]]] - continuation_response: str = ... - is_readonly: bool = ... - tagnum: int = ... - tagpre: str = ... - tagre: Pattern[Text] = ... - welcome: bytes = ... - capabilities: Tuple[str] = ... - PROTOCOL_VERSION: str = ... + error: Type[Exception] + abort: Type[Exception] + readonly: Type[Exception] + mustquote: Pattern[str] + debug: int + state: str + literal: str | None + tagged_commands: dict[bytes, _list[bytes] | None] + untagged_responses: dict[str, _list[bytes | tuple[bytes, bytes]]] + continuation_response: str + is_readonly: bool + tagnum: int + tagpre: str + tagre: Pattern[str] + welcome: bytes + capabilities: tuple[str] + PROTOCOL_VERSION: str if sys.version_info >= (3, 9): - def __init__(self, host: str = ..., port: int = ..., timeout: Optional[float] = ...) -> None: ... - def open(self, host: str = ..., port: int = ..., timeout: Optional[float] = ...) -> None: ... + def __init__(self, host: str = ..., port: int = ..., timeout: float | None = ...) -> None: ... + def open(self, host: str = ..., port: int = ..., timeout: float | None = ...) -> None: ... else: def __init__(self, host: str = ..., port: int = ...) -> None: ... def open(self, host: str = ..., port: int = ...) -> None: ... def __getattr__(self, attr: str) -> Any: ... - host: str = ... - port: int = ... - sock: _socket = ... - file: Union[IO[Text], IO[bytes]] = ... + host: str + port: int + sock: _socket + file: IO[str] | IO[bytes] def read(self, size: int) -> bytes: ... def readline(self) -> bytes: ... def send(self, data: bytes) -> None: ... @@ -50,7 +53,7 @@ class IMAP4: def recent(self) -> _CommandResults: ... def response(self, code: str) -> _CommandResults: ... def append(self, mailbox: str, flags: str, date_time: str, message: str) -> str: ... - def authenticate(self, mechanism: str, authobject: Callable[[bytes], Optional[bytes]]) -> Tuple[str, str]: ... + def authenticate(self, mechanism: str, authobject: Callable[[bytes], bytes | None]) -> tuple[str, str]: ... def capability(self) -> _CommandResults: ... def check(self) -> _CommandResults: ... def close(self) -> _CommandResults: ... @@ -58,35 +61,33 @@ class IMAP4: def create(self, mailbox: str) -> _CommandResults: ... def delete(self, mailbox: str) -> _CommandResults: ... def deleteacl(self, mailbox: str, who: str) -> _CommandResults: ... - if sys.version_info >= (3, 5): - def enable(self, capability: str) -> _CommandResults: ... - def __enter__(self) -> IMAP4: ... - def __exit__(self, t: Optional[Type[BaseException]], v: Optional[BaseException], tb: Optional[TracebackType]) -> None: ... + def enable(self, capability: str) -> _CommandResults: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... def expunge(self) -> _CommandResults: ... - def fetch(self, message_set: str, message_parts: str) -> Tuple[str, _AnyResponseData]: ... + def fetch(self, message_set: str, message_parts: str) -> tuple[str, _AnyResponseData]: ... def getacl(self, mailbox: str) -> _CommandResults: ... def getannotation(self, mailbox: str, entry: str, attribute: str) -> _CommandResults: ... def getquota(self, root: str) -> _CommandResults: ... def getquotaroot(self, mailbox: str) -> _CommandResults: ... - def list(self, directory: str = ..., pattern: str = ...) -> Tuple[str, _AnyResponseData]: ... - def login(self, user: str, password: str) -> Tuple[Literal["OK"], List[bytes]]: ... + def list(self, directory: str = ..., pattern: str = ...) -> tuple[str, _AnyResponseData]: ... + def login(self, user: str, password: str) -> tuple[Literal["OK"], _list[bytes]]: ... def login_cram_md5(self, user: str, password: str) -> _CommandResults: ... - def logout(self) -> Tuple[str, _AnyResponseData]: ... + def logout(self) -> tuple[str, _AnyResponseData]: ... def lsub(self, directory: str = ..., pattern: str = ...) -> _CommandResults: ... def myrights(self, mailbox: str) -> _CommandResults: ... def namespace(self) -> _CommandResults: ... - def noop(self) -> Tuple[str, List[bytes]]: ... + def noop(self) -> tuple[str, _list[bytes]]: ... def partial(self, message_num: str, message_part: str, start: str, length: str) -> _CommandResults: ... def proxyauth(self, user: str) -> _CommandResults: ... def rename(self, oldmailbox: str, newmailbox: str) -> _CommandResults: ... - def search(self, charset: Optional[str], *criteria: str) -> _CommandResults: ... - def select(self, mailbox: str = ..., readonly: bool = ...) -> Tuple[str, List[Optional[bytes]]]: ... + def search(self, charset: str | None, *criteria: str) -> _CommandResults: ... + def select(self, mailbox: str = ..., readonly: bool = ...) -> tuple[str, _list[bytes | None]]: ... def setacl(self, mailbox: str, who: str, what: str) -> _CommandResults: ... def setannotation(self, *args: str) -> _CommandResults: ... def setquota(self, root: str, limits: str) -> _CommandResults: ... def sort(self, sort_criteria: str, charset: str, *search_criteria: str) -> _CommandResults: ... - if sys.version_info >= (3,): - def starttls(self, ssl_context: Optional[Any] = ...) -> Tuple[Literal["OK"], List[None]]: ... + def starttls(self, ssl_context: Any | None = ...) -> tuple[Literal["OK"], _list[None]]: ... def status(self, mailbox: str, names: str) -> _CommandResults: ... def store(self, message_set: str, command: str, flags: str) -> _CommandResults: ... def subscribe(self, mailbox: str) -> _CommandResults: ... @@ -99,40 +100,36 @@ class IMAP4: def print_log(self) -> None: ... class IMAP4_SSL(IMAP4): - keyfile: str = ... - certfile: str = ... + keyfile: str + certfile: str if sys.version_info >= (3, 9): def __init__( self, host: str = ..., port: int = ..., - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., - ssl_context: Optional[SSLContext] = ..., - timeout: Optional[float] = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + ssl_context: SSLContext | None = ..., + timeout: float | None = ..., ) -> None: ... - elif sys.version_info >= (3, 3): + else: def __init__( self, host: str = ..., port: int = ..., - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., - ssl_context: Optional[SSLContext] = ..., - ) -> None: ... - else: - def __init__( - self, host: str = ..., port: int = ..., keyfile: Optional[str] = ..., certfile: Optional[str] = ... + keyfile: str | None = ..., + certfile: str | None = ..., + ssl_context: SSLContext | None = ..., ) -> None: ... - host: str = ... - port: int = ... - sock: _socket = ... - sslobj: SSLSocket = ... - file: IO[Any] = ... + host: str + port: int + sock: _socket + sslobj: SSLSocket + file: IO[Any] if sys.version_info >= (3, 9): - def open(self, host: str = ..., port: Optional[int] = ..., timeout: Optional[float] = ...) -> None: ... + def open(self, host: str = ..., port: int | None = ..., timeout: float | None = ...) -> None: ... else: - def open(self, host: str = ..., port: Optional[int] = ...) -> None: ... + def open(self, host: str = ..., port: int | None = ...) -> None: ... def read(self, size: int) -> bytes: ... def readline(self) -> bytes: ... def send(self, data: bytes) -> None: ... @@ -141,26 +138,26 @@ class IMAP4_SSL(IMAP4): def ssl(self) -> SSLSocket: ... class IMAP4_stream(IMAP4): - command: str = ... + command: str def __init__(self, command: str) -> None: ... - host: str = ... - port: int = ... - sock: _socket = ... - file: IO[Any] = ... - process: subprocess.Popen[bytes] = ... - writefile: IO[Any] = ... - readfile: IO[Any] = ... + host: str + port: int + sock: _socket + file: IO[Any] + process: subprocess.Popen[bytes] + writefile: IO[Any] + readfile: IO[Any] if sys.version_info >= (3, 9): - def open(self, host: Optional[str] = ..., port: Optional[int] = ..., timeout: Optional[float] = ...) -> None: ... + def open(self, host: str | None = ..., port: int | None = ..., timeout: float | None = ...) -> None: ... else: - def open(self, host: Optional[str] = ..., port: Optional[int] = ...) -> None: ... + def open(self, host: str | None = ..., port: int | None = ...) -> None: ... def read(self, size: int) -> bytes: ... def readline(self) -> bytes: ... def send(self, data: bytes) -> None: ... def shutdown(self) -> None: ... class _Authenticator: - mech: Callable[[bytes], bytes] = ... + mech: Callable[[bytes], bytes] def __init__(self, mechinst: Callable[[bytes], bytes]) -> None: ... def process(self, data: str) -> str: ... def encode(self, inp: bytes) -> str: ... @@ -168,5 +165,5 @@ class _Authenticator: def Internaldate2tuple(resp: str) -> time.struct_time: ... def Int2AP(num: int) -> str: ... -def ParseFlags(resp: str) -> Tuple[str]: ... -def Time2Internaldate(date_time: Union[float, time.struct_time, str]) -> str: ... +def ParseFlags(resp: str) -> tuple[str]: ... +def Time2Internaldate(date_time: float | time.struct_time | str) -> str: ... diff --git a/mypy/typeshed/stdlib/imghdr.pyi b/mypy/typeshed/stdlib/imghdr.pyi index ffdbbf20e97b..4515cf2269b0 100644 --- a/mypy/typeshed/stdlib/imghdr.pyi +++ b/mypy/typeshed/stdlib/imghdr.pyi @@ -1,20 +1,14 @@ -import os -import sys -from typing import Any, BinaryIO, Callable, List, Optional, Protocol, Text, Union, overload +from _typeshed import StrPath +from typing import Any, BinaryIO, Callable, Protocol, overload class _ReadableBinary(Protocol): def tell(self) -> int: ... def read(self, size: int) -> bytes: ... def seek(self, offset: int) -> Any: ... -if sys.version_info >= (3, 6): - _File = Union[Text, os.PathLike[Text], _ReadableBinary] -else: - _File = Union[Text, _ReadableBinary] - @overload -def what(file: _File, h: None = ...) -> Optional[str]: ... +def what(file: StrPath | _ReadableBinary, h: None = ...) -> str | None: ... @overload -def what(file: Any, h: bytes) -> Optional[str]: ... +def what(file: Any, h: bytes) -> str | None: ... -tests: List[Callable[[bytes, Optional[BinaryIO]], Optional[str]]] +tests: list[Callable[[bytes, BinaryIO | None], str | None]] diff --git a/mypy/typeshed/stdlib/imp.pyi b/mypy/typeshed/stdlib/imp.pyi index adcf6e097b84..88f2e789329b 100644 --- a/mypy/typeshed/stdlib/imp.pyi +++ b/mypy/typeshed/stdlib/imp.pyi @@ -1,7 +1,7 @@ -import os import types from _typeshed import StrPath -from typing import IO, Any, List, Optional, Protocol, Tuple, TypeVar, Union +from os import PathLike +from typing import IO, Any, Protocol, TypeVar from _imp import ( acquire_lock as acquire_lock, @@ -31,9 +31,9 @@ IMP_HOOK: int def new_module(name: str) -> types.ModuleType: ... def get_magic() -> bytes: ... def get_tag() -> str: ... -def cache_from_source(path: StrPath, debug_override: Optional[bool] = ...) -> str: ... +def cache_from_source(path: StrPath, debug_override: bool | None = ...) -> str: ... def source_from_cache(path: StrPath) -> str: ... -def get_suffixes() -> List[Tuple[str, str, int]]: ... +def get_suffixes() -> list[tuple[str, str, int]]: ... class NullImporter: def __init__(self, path: StrPath) -> None: ... @@ -44,21 +44,21 @@ class NullImporter: class _FileLike(Protocol): closed: bool mode: str - def read(self) -> Union[str, bytes]: ... + def read(self) -> str | bytes: ... def close(self) -> Any: ... def __enter__(self) -> Any: ... def __exit__(self, *args: Any) -> Any: ... # PathLike doesn't work for the pathname argument here -def load_source(name: str, pathname: str, file: Optional[_FileLike] = ...) -> types.ModuleType: ... -def load_compiled(name: str, pathname: str, file: Optional[_FileLike] = ...) -> types.ModuleType: ... +def load_source(name: str, pathname: str, file: _FileLike | None = ...) -> types.ModuleType: ... +def load_compiled(name: str, pathname: str, file: _FileLike | None = ...) -> types.ModuleType: ... def load_package(name: str, path: StrPath) -> types.ModuleType: ... -def load_module(name: str, file: Optional[_FileLike], filename: str, details: Tuple[str, str, int]) -> types.ModuleType: ... +def load_module(name: str, file: _FileLike | None, filename: str, details: tuple[str, str, int]) -> types.ModuleType: ... # IO[Any] is a TextIOWrapper if name is a .py file, and a FileIO otherwise. def find_module( - name: str, path: Union[None, List[str], List[os.PathLike[str]], List[StrPath]] = ... -) -> Tuple[IO[Any], str, Tuple[str, str, int]]: ... + name: str, path: None | list[str] | list[PathLike[str]] | list[StrPath] = ... +) -> tuple[IO[Any], str, tuple[str, str, int]]: ... def reload(module: types.ModuleType) -> types.ModuleType: ... -def init_builtin(name: str) -> Optional[types.ModuleType]: ... +def init_builtin(name: str) -> types.ModuleType | None: ... def load_dynamic(name: str, path: str, file: Any = ...) -> types.ModuleType: ... # file argument is ignored diff --git a/mypy/typeshed/stdlib/importlib/__init__.pyi b/mypy/typeshed/stdlib/importlib/__init__.pyi index d55393df315e..1b91cc55f2df 100644 --- a/mypy/typeshed/stdlib/importlib/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/__init__.pyi @@ -1,15 +1,18 @@ -import types from importlib.abc import Loader -from typing import Any, Mapping, Optional, Sequence +from types import ModuleType +from typing import Mapping, Sequence +# Signature of `builtins.__import__` should be kept identical to `importlib.__import__` def __import__( name: str, - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, object] | None = ..., + locals: Mapping[str, object] | None = ..., fromlist: Sequence[str] = ..., level: int = ..., -) -> types.ModuleType: ... -def import_module(name: str, package: Optional[str] = ...) -> types.ModuleType: ... -def find_loader(name: str, path: Optional[str] = ...) -> Optional[Loader]: ... +) -> ModuleType: ... + +# `importlib.import_module` return type should be kept the same as `builtins.__import__` +def import_module(name: str, package: str | None = ...) -> ModuleType: ... +def find_loader(name: str, path: str | None = ...) -> Loader | None: ... def invalidate_caches() -> None: ... -def reload(module: types.ModuleType) -> types.ModuleType: ... +def reload(module: ModuleType) -> ModuleType: ... diff --git a/mypy/typeshed/stdlib/importlib/abc.pyi b/mypy/typeshed/stdlib/importlib/abc.pyi index 62b391e216fc..2e18f3f899a2 100644 --- a/mypy/typeshed/stdlib/importlib/abc.pyi +++ b/mypy/typeshed/stdlib/importlib/abc.pyi @@ -1,9 +1,18 @@ import sys import types -from _typeshed import AnyPath +from _typeshed import ( + OpenBinaryMode, + OpenBinaryModeReading, + OpenBinaryModeUpdating, + OpenBinaryModeWriting, + OpenTextMode, + StrOrBytesPath, + StrPath, +) from abc import ABCMeta, abstractmethod from importlib.machinery import ModuleSpec -from typing import IO, Any, Iterator, Mapping, Optional, Protocol, Sequence, Tuple, Union +from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper +from typing import IO, Any, BinaryIO, Iterator, Mapping, Protocol, Sequence, Union, overload from typing_extensions import Literal, runtime_checkable _Path = Union[bytes, str] @@ -16,45 +25,45 @@ class ResourceLoader(Loader): class InspectLoader(Loader): def is_package(self, fullname: str) -> bool: ... - def get_code(self, fullname: str) -> Optional[types.CodeType]: ... + def get_code(self, fullname: str) -> types.CodeType | None: ... def load_module(self, fullname: str) -> types.ModuleType: ... @abstractmethod - def get_source(self, fullname: str) -> Optional[str]: ... + def get_source(self, fullname: str) -> str | None: ... def exec_module(self, module: types.ModuleType) -> None: ... @staticmethod - def source_to_code(data: Union[bytes, str], path: str = ...) -> types.CodeType: ... + def source_to_code(data: bytes | str, path: str = ...) -> types.CodeType: ... class ExecutionLoader(InspectLoader): @abstractmethod def get_filename(self, fullname: str) -> _Path: ... - def get_code(self, fullname: str) -> Optional[types.CodeType]: ... + def get_code(self, fullname: str) -> types.CodeType | None: ... class SourceLoader(ResourceLoader, ExecutionLoader, metaclass=ABCMeta): def path_mtime(self, path: _Path) -> float: ... def set_data(self, path: _Path, data: bytes) -> None: ... - def get_source(self, fullname: str) -> Optional[str]: ... + def get_source(self, fullname: str) -> str | None: ... def path_stats(self, path: _Path) -> Mapping[str, Any]: ... # Please keep in sync with sys._MetaPathFinder class MetaPathFinder(Finder): - def find_module(self, fullname: str, path: Optional[Sequence[_Path]]) -> Optional[Loader]: ... + def find_module(self, fullname: str, path: Sequence[_Path] | None) -> Loader | None: ... def invalidate_caches(self) -> None: ... # Not defined on the actual class, but expected to exist. def find_spec( - self, fullname: str, path: Optional[Sequence[_Path]], target: Optional[types.ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + self, fullname: str, path: Sequence[_Path] | None, target: types.ModuleType | None = ... + ) -> ModuleSpec | None: ... class PathEntryFinder(Finder): - def find_module(self, fullname: str) -> Optional[Loader]: ... - def find_loader(self, fullname: str) -> Tuple[Optional[Loader], Sequence[_Path]]: ... + def find_module(self, fullname: str) -> Loader | None: ... + def find_loader(self, fullname: str) -> tuple[Loader | None, Sequence[_Path]]: ... def invalidate_caches(self) -> None: ... # Not defined on the actual class, but expected to exist. - def find_spec(self, fullname: str, target: Optional[types.ModuleType] = ...) -> Optional[ModuleSpec]: ... + def find_spec(self, fullname: str, target: types.ModuleType | None = ...) -> ModuleSpec | None: ... class Loader(metaclass=ABCMeta): def load_module(self, fullname: str) -> types.ModuleType: ... def module_repr(self, module: types.ModuleType) -> str: ... - def create_module(self, spec: ModuleSpec) -> Optional[types.ModuleType]: ... + def create_module(self, spec: ModuleSpec) -> types.ModuleType | None: ... # Not defined on the actual class for backwards-compatibility reasons, # but expected in new code. def exec_module(self, module: types.ModuleType) -> None: ... @@ -67,15 +76,15 @@ class FileLoader(ResourceLoader, ExecutionLoader, metaclass=ABCMeta): path: _Path def __init__(self, fullname: str, path: _Path) -> None: ... def get_data(self, path: _Path) -> bytes: ... - def get_filename(self, name: Optional[str] = ...) -> _Path: ... - def load_module(self, name: Optional[str] = ...) -> types.ModuleType: ... + def get_filename(self, name: str | None = ...) -> _Path: ... + def load_module(self, name: str | None = ...) -> types.ModuleType: ... if sys.version_info >= (3, 7): class ResourceReader(metaclass=ABCMeta): @abstractmethod - def open_resource(self, resource: AnyPath) -> IO[bytes]: ... + def open_resource(self, resource: StrOrBytesPath) -> IO[bytes]: ... @abstractmethod - def resource_path(self, resource: AnyPath) -> str: ... + def resource_path(self, resource: StrOrBytesPath) -> str: ... @abstractmethod def is_resource(self, name: str) -> bool: ... @abstractmethod @@ -84,22 +93,79 @@ if sys.version_info >= (3, 7): if sys.version_info >= (3, 9): @runtime_checkable class Traversable(Protocol): + @abstractmethod + def is_dir(self) -> bool: ... + @abstractmethod + def is_file(self) -> bool: ... @abstractmethod def iterdir(self) -> Iterator[Traversable]: ... @abstractmethod - def read_bytes(self) -> bytes: ... + def joinpath(self, child: StrPath) -> Traversable: ... + # The .open method comes from pathlib.pyi and should be kept in sync. + @overload @abstractmethod - def read_text(self, encoding: Optional[str] = ...) -> str: ... + def open( + self, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> TextIOWrapper: ... + # Unbuffered binary mode: returns a FileIO + @overload @abstractmethod - def is_dir(self) -> bool: ... + def open( + self, mode: OpenBinaryMode, buffering: Literal[0], encoding: None = ..., errors: None = ..., newline: None = ... + ) -> FileIO: ... + # Buffering is on: return BufferedRandom, BufferedReader, or BufferedWriter + @overload @abstractmethod - def is_file(self) -> bool: ... + def open( + self, + mode: OpenBinaryModeUpdating, + buffering: Literal[-1, 1] = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., + ) -> BufferedRandom: ... + @overload @abstractmethod - def joinpath(self, child: _Path) -> Traversable: ... + def open( + self, + mode: OpenBinaryModeWriting, + buffering: Literal[-1, 1] = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., + ) -> BufferedWriter: ... + @overload @abstractmethod - def __truediv__(self, child: _Path) -> Traversable: ... + def open( + self, + mode: OpenBinaryModeReading, + buffering: Literal[-1, 1] = ..., + encoding: None = ..., + errors: None = ..., + newline: None = ..., + ) -> BufferedReader: ... + # Buffering cannot be determined: fall back to BinaryIO + @overload @abstractmethod - def open(self, mode: Literal["r", "rb"] = ..., *args: Any, **kwargs: Any) -> IO[Any]: ... - @property + def open( + self, mode: OpenBinaryMode, buffering: int, encoding: None = ..., errors: None = ..., newline: None = ... + ) -> BinaryIO: ... + # Fallback if mode is not specified + @overload @abstractmethod + def open( + self, mode: str, buffering: int = ..., encoding: str | None = ..., errors: str | None = ..., newline: str | None = ... + ) -> IO[Any]: ... + @property def name(self) -> str: ... + @abstractmethod + def __truediv__(self, key: StrPath) -> Traversable: ... + @abstractmethod + def read_bytes(self) -> bytes: ... + @abstractmethod + def read_text(self, encoding: str | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/importlib/machinery.pyi b/mypy/typeshed/stdlib/importlib/machinery.pyi index beae43bd3937..432bec901161 100644 --- a/mypy/typeshed/stdlib/importlib/machinery.pyi +++ b/mypy/typeshed/stdlib/importlib/machinery.pyi @@ -1,37 +1,34 @@ import importlib.abc import types -from typing import Any, Callable, List, Optional, Sequence, Tuple, Union +from typing import Any, Callable, Sequence -# TODO: the loaders seem a bit backwards, attribute is protocol but __init__ arg isn't? class ModuleSpec: def __init__( self, name: str, - loader: Optional[importlib.abc.Loader], + loader: importlib.abc.Loader | None, *, - origin: Optional[str] = ..., + origin: str | None = ..., loader_state: Any = ..., - is_package: Optional[bool] = ..., + is_package: bool | None = ..., ) -> None: ... name: str - loader: Optional[importlib.abc._LoaderProtocol] - origin: Optional[str] - submodule_search_locations: Optional[List[str]] + loader: importlib.abc.Loader | None + origin: str | None + submodule_search_locations: list[str] | None loader_state: Any - cached: Optional[str] - parent: Optional[str] + cached: str | None + parent: str | None has_location: bool class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): # MetaPathFinder @classmethod - def find_module( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ... - ) -> Optional[importlib.abc.Loader]: ... + def find_module(cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ...) -> importlib.abc.Loader | None: ... @classmethod def find_spec( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ..., target: Optional[types.ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ..., target: types.ModuleType | None = ... + ) -> ModuleSpec | None: ... # InspectLoader @classmethod def is_package(cls, fullname: str) -> bool: ... @@ -45,20 +42,18 @@ class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader) @staticmethod def module_repr(module: types.ModuleType) -> str: ... @classmethod - def create_module(cls, spec: ModuleSpec) -> Optional[types.ModuleType]: ... + def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... @classmethod def exec_module(cls, module: types.ModuleType) -> None: ... class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): # MetaPathFinder @classmethod - def find_module( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ... - ) -> Optional[importlib.abc.Loader]: ... + def find_module(cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ...) -> importlib.abc.Loader | None: ... @classmethod def find_spec( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ..., target: Optional[types.ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ..., target: types.ModuleType | None = ... + ) -> ModuleSpec | None: ... # InspectLoader @classmethod def is_package(cls, fullname: str) -> bool: ... @@ -72,44 +67,42 @@ class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): @staticmethod def module_repr(m: types.ModuleType) -> str: ... @classmethod - def create_module(cls, spec: ModuleSpec) -> Optional[types.ModuleType]: ... + def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... @staticmethod def exec_module(module: types.ModuleType) -> None: ... class WindowsRegistryFinder(importlib.abc.MetaPathFinder): @classmethod - def find_module( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ... - ) -> Optional[importlib.abc.Loader]: ... + def find_module(cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ...) -> importlib.abc.Loader | None: ... @classmethod def find_spec( - cls, fullname: str, path: Optional[Sequence[importlib.abc._Path]] = ..., target: Optional[types.ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + cls, fullname: str, path: Sequence[importlib.abc._Path] | None = ..., target: types.ModuleType | None = ... + ) -> ModuleSpec | None: ... class PathFinder: @classmethod def invalidate_caches(cls) -> None: ... @classmethod def find_spec( - cls, fullname: str, path: Optional[Sequence[Union[bytes, str]]] = ..., target: Optional[types.ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + cls, fullname: str, path: Sequence[bytes | str] | None = ..., target: types.ModuleType | None = ... + ) -> ModuleSpec | None: ... @classmethod - def find_module(cls, fullname: str, path: Optional[Sequence[Union[bytes, str]]] = ...) -> Optional[importlib.abc.Loader]: ... + def find_module(cls, fullname: str, path: Sequence[bytes | str] | None = ...) -> importlib.abc.Loader | None: ... -SOURCE_SUFFIXES: List[str] -DEBUG_BYTECODE_SUFFIXES: List[str] -OPTIMIZED_BYTECODE_SUFFIXES: List[str] -BYTECODE_SUFFIXES: List[str] -EXTENSION_SUFFIXES: List[str] +SOURCE_SUFFIXES: list[str] +DEBUG_BYTECODE_SUFFIXES: list[str] +OPTIMIZED_BYTECODE_SUFFIXES: list[str] +BYTECODE_SUFFIXES: list[str] +EXTENSION_SUFFIXES: list[str] -def all_suffixes() -> List[str]: ... +def all_suffixes() -> list[str]: ... class FileFinder(importlib.abc.PathEntryFinder): path: str - def __init__(self, path: str, *loader_details: Tuple[importlib.abc.Loader, List[str]]) -> None: ... + def __init__(self, path: str, *loader_details: tuple[importlib.abc.Loader, list[str]]) -> None: ... @classmethod def path_hook( - cls, *loader_details: Tuple[importlib.abc.Loader, List[str]] + cls, *loader_details: tuple[importlib.abc.Loader, list[str]] ) -> Callable[[str], importlib.abc.PathEntryFinder]: ... class SourceFileLoader(importlib.abc.FileLoader, importlib.abc.SourceLoader): @@ -119,5 +112,9 @@ class SourcelessFileLoader(importlib.abc.FileLoader, importlib.abc.SourceLoader) class ExtensionFileLoader(importlib.abc.ExecutionLoader): def __init__(self, name: str, path: importlib.abc._Path) -> None: ... - def get_filename(self, name: Optional[str] = ...) -> importlib.abc._Path: ... + def get_filename(self, name: str | None = ...) -> importlib.abc._Path: ... def get_source(self, fullname: str) -> None: ... + def create_module(self, spec: ModuleSpec) -> types.ModuleType: ... + def exec_module(self, module: types.ModuleType) -> None: ... + def is_package(self, fullname: str) -> bool: ... + def get_code(self, fullname: str) -> None: ... diff --git a/mypy/typeshed/stdlib/importlib/metadata.pyi b/mypy/typeshed/stdlib/importlib/metadata.pyi index ae39c89b542a..2c1041b76503 100644 --- a/mypy/typeshed/stdlib/importlib/metadata.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata.pyi @@ -1,11 +1,16 @@ import abc -import os import pathlib import sys +from _typeshed import StrPath +from collections.abc import Mapping from email.message import Message from importlib.abc import MetaPathFinder +from os import PathLike from pathlib import Path -from typing import Any, Dict, Iterable, List, NamedTuple, Optional, Tuple, Union, overload +from typing import Any, Iterable, NamedTuple, Tuple, overload + +if sys.version_info >= (3, 10): + def packages_distributions() -> Mapping[str, list[str]]: ... if sys.version_info >= (3, 8): class PackageNotFoundError(ModuleNotFoundError): ... @@ -16,14 +21,14 @@ if sys.version_info >= (3, 8): class EntryPoint(_EntryPointBase): def load(self) -> Any: ... # Callable[[], Any] or an importable module @property - def extras(self) -> List[str]: ... + def extras(self) -> list[str]: ... class PackagePath(pathlib.PurePosixPath): def read_text(self, encoding: str = ...) -> str: ... def read_binary(self) -> bytes: ... - def locate(self) -> os.PathLike[str]: ... + def locate(self) -> PathLike[str]: ... # The following attributes are not defined on PackagePath, but are dynamically added by Distribution.files: - hash: Optional[FileHash] - size: Optional[int] + hash: FileHash | None + size: int | None dist: Distribution class FileHash: mode: str @@ -31,9 +36,9 @@ if sys.version_info >= (3, 8): def __init__(self, spec: str) -> None: ... class Distribution: @abc.abstractmethod - def read_text(self, filename: str) -> Optional[str]: ... + def read_text(self, filename: str) -> str | None: ... @abc.abstractmethod - def locate_file(self, path: Union[os.PathLike[str], str]) -> os.PathLike[str]: ... + def locate_file(self, path: StrPath) -> PathLike[str]: ... @classmethod def from_name(cls, name: str) -> Distribution: ... @overload @@ -42,26 +47,26 @@ if sys.version_info >= (3, 8): @overload @classmethod def discover( - cls, *, context: None = ..., name: Optional[str] = ..., path: List[str] = ..., **kwargs: Any + cls, *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any ) -> Iterable[Distribution]: ... @staticmethod - def at(path: Union[str, os.PathLike[str]]) -> PathDistribution: ... + def at(path: StrPath) -> PathDistribution: ... @property def metadata(self) -> Message: ... @property def version(self) -> str: ... @property - def entry_points(self) -> List[EntryPoint]: ... + def entry_points(self) -> list[EntryPoint]: ... @property - def files(self) -> Optional[List[PackagePath]]: ... + def files(self) -> list[PackagePath] | None: ... @property - def requires(self) -> Optional[List[str]]: ... + def requires(self) -> list[str] | None: ... class DistributionFinder(MetaPathFinder): class Context: - name: Optional[str] - def __init__(self, *, name: Optional[str] = ..., path: List[str] = ..., **kwargs: Any) -> None: ... + name: str | None + def __init__(self, *, name: str | None = ..., path: list[str] = ..., **kwargs: Any) -> None: ... @property - def path(self) -> List[str]: ... + def path(self) -> list[str]: ... @abc.abstractmethod def find_distributions(self, context: DistributionFinder.Context = ...) -> Iterable[Distribution]: ... class MetadataPathFinder(DistributionFinder): @@ -69,17 +74,17 @@ if sys.version_info >= (3, 8): def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... class PathDistribution(Distribution): def __init__(self, path: Path) -> None: ... - def read_text(self, filename: Union[str, os.PathLike[str]]) -> str: ... - def locate_file(self, path: Union[str, os.PathLike[str]]) -> os.PathLike[str]: ... + def read_text(self, filename: StrPath) -> str: ... + def locate_file(self, path: StrPath) -> PathLike[str]: ... def distribution(distribution_name: str) -> Distribution: ... @overload def distributions(*, context: DistributionFinder.Context) -> Iterable[Distribution]: ... @overload def distributions( - *, context: None = ..., name: Optional[str] = ..., path: List[str] = ..., **kwargs: Any + *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any ) -> Iterable[Distribution]: ... def metadata(distribution_name: str) -> Message: ... def version(distribution_name: str) -> str: ... - def entry_points() -> Dict[str, Tuple[EntryPoint, ...]]: ... - def files(distribution_name: str) -> Optional[List[PackagePath]]: ... - def requires(distribution_name: str) -> Optional[List[str]]: ... + def entry_points() -> dict[str, Tuple[EntryPoint, ...]]: ... + def files(distribution_name: str) -> list[PackagePath] | None: ... + def requires(distribution_name: str) -> list[str] | None: ... diff --git a/mypy/typeshed/stdlib/importlib/resources.pyi b/mypy/typeshed/stdlib/importlib/resources.pyi index 075761abf9da..194c0bac2b6a 100644 --- a/mypy/typeshed/stdlib/importlib/resources.pyi +++ b/mypy/typeshed/stdlib/importlib/resources.pyi @@ -4,9 +4,10 @@ from typing import Any # This is a >=3.7 module, so we conditionally include its source. if sys.version_info >= (3, 7): import os + from contextlib import AbstractContextManager from pathlib import Path from types import ModuleType - from typing import BinaryIO, ContextManager, Iterator, TextIO, Union + from typing import BinaryIO, Iterator, TextIO, Union Package = Union[str, ModuleType] Resource = Union[str, os.PathLike[Any]] @@ -14,12 +15,11 @@ if sys.version_info >= (3, 7): def open_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> TextIO: ... def read_binary(package: Package, resource: Resource) -> bytes: ... def read_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> str: ... - def path(package: Package, resource: Resource) -> ContextManager[Path]: ... + def path(package: Package, resource: Resource) -> AbstractContextManager[Path]: ... def is_resource(package: Package, name: str) -> bool: ... def contents(package: Package) -> Iterator[str]: ... if sys.version_info >= (3, 9): - from contextlib import AbstractContextManager from importlib.abc import Traversable def files(package: Package) -> Traversable: ... def as_file(path: Traversable) -> AbstractContextManager[Path]: ... diff --git a/mypy/typeshed/stdlib/importlib/util.pyi b/mypy/typeshed/stdlib/importlib/util.pyi index e5d4ec399a22..30b8765fad04 100644 --- a/mypy/typeshed/stdlib/importlib/util.pyi +++ b/mypy/typeshed/stdlib/importlib/util.pyi @@ -1,35 +1,38 @@ import importlib.abc import importlib.machinery -import os import types -from typing import Any, Callable, List, Optional, Union +from _typeshed import StrOrBytesPath +from typing import Any, Callable +from typing_extensions import ParamSpec -def module_for_loader(fxn: Callable[..., types.ModuleType]) -> Callable[..., types.ModuleType]: ... -def set_loader(fxn: Callable[..., types.ModuleType]) -> Callable[..., types.ModuleType]: ... -def set_package(fxn: Callable[..., types.ModuleType]) -> Callable[..., types.ModuleType]: ... -def resolve_name(name: str, package: str) -> str: ... +_P = ParamSpec("_P") + +def module_for_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore +def set_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore +def set_package(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore +def resolve_name(name: str, package: str | None) -> str: ... MAGIC_NUMBER: bytes -def cache_from_source(path: str, debug_override: Optional[bool] = ..., *, optimization: Optional[Any] = ...) -> str: ... +def cache_from_source(path: str, debug_override: bool | None = ..., *, optimization: Any | None = ...) -> str: ... def source_from_cache(path: str) -> str: ... def decode_source(source_bytes: bytes) -> str: ... -def find_spec(name: str, package: Optional[str] = ...) -> Optional[importlib.machinery.ModuleSpec]: ... +def find_spec(name: str, package: str | None = ...) -> importlib.machinery.ModuleSpec | None: ... def spec_from_loader( - name: str, loader: Optional[importlib.abc.Loader], *, origin: Optional[str] = ..., is_package: Optional[bool] = ... -) -> Optional[importlib.machinery.ModuleSpec]: ... + name: str, loader: importlib.abc.Loader | None, *, origin: str | None = ..., is_package: bool | None = ... +) -> importlib.machinery.ModuleSpec | None: ... def spec_from_file_location( name: str, - location: Optional[Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]] = ..., + location: StrOrBytesPath | None = ..., *, - loader: Optional[importlib.abc.Loader] = ..., - submodule_search_locations: Optional[List[str]] = ..., -) -> Optional[importlib.machinery.ModuleSpec]: ... + loader: importlib.abc.Loader | None = ..., + submodule_search_locations: list[str] | None = ..., +) -> importlib.machinery.ModuleSpec | None: ... def module_from_spec(spec: importlib.machinery.ModuleSpec) -> types.ModuleType: ... class LazyLoader(importlib.abc.Loader): def __init__(self, loader: importlib.abc.Loader) -> None: ... @classmethod def factory(cls, loader: importlib.abc.Loader) -> Callable[..., LazyLoader]: ... - def create_module(self, spec: importlib.machinery.ModuleSpec) -> Optional[types.ModuleType]: ... + def create_module(self, spec: importlib.machinery.ModuleSpec) -> types.ModuleType | None: ... def exec_module(self, module: types.ModuleType) -> None: ... diff --git a/mypy/typeshed/stdlib/inspect.pyi b/mypy/typeshed/stdlib/inspect.pyi index fa49e4493b28..88002cf205b1 100644 --- a/mypy/typeshed/stdlib/inspect.pyi +++ b/mypy/typeshed/stdlib/inspect.pyi @@ -1,24 +1,30 @@ import enum import sys +import types +from _typeshed import Self from collections import OrderedDict -from types import CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType -from typing import ( - AbstractSet, - Any, - Callable, - ClassVar, - Dict, - Generator, - List, - Mapping, - NamedTuple, - Optional, - Sequence, - Tuple, - Type, - Union, +from collections.abc import Awaitable, Callable, Generator, Mapping, Sequence, Set as AbstractSet +from types import ( + AsyncGeneratorType, + BuiltinFunctionType, + BuiltinMethodType, + CodeType, + CoroutineType, + FrameType, + FunctionType, + GeneratorType, + GetSetDescriptorType, + LambdaType, + MethodType, + ModuleType, + TracebackType, ) -from typing_extensions import Literal + +if sys.version_info >= (3, 7): + from types import ClassMethodDescriptorType, WrapperDescriptorType, MemberDescriptorType, MethodDescriptorType + +from typing import Any, ClassVar, NamedTuple, Protocol, Tuple, Type, TypeVar, Union +from typing_extensions import Literal, TypeGuard # # Types and members @@ -33,7 +39,7 @@ class BlockFinder: indecorator: bool decoratorhasargs: bool last: int - def tokeneater(self, type: int, token: str, srowcol: Tuple[int, int], erowcol: Tuple[int, int], line: str) -> None: ... + def tokeneater(self, type: int, token: str, srowcol: tuple[int, int], erowcol: tuple[int, int], line: str) -> None: ... CO_OPTIMIZED: int CO_NEWLOCALS: int @@ -47,12 +53,12 @@ CO_ITERABLE_COROUTINE: int CO_ASYNC_GENERATOR: int TPFLAGS_IS_ABSTRACT: int -def getmembers(object: object, predicate: Optional[Callable[[Any], bool]] = ...) -> List[Tuple[str, Any]]: ... -def getmodulename(path: str) -> Optional[str]: ... -def ismodule(object: object) -> bool: ... -def isclass(object: object) -> bool: ... -def ismethod(object: object) -> bool: ... -def isfunction(object: object) -> bool: ... +def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> list[tuple[str, Any]]: ... +def getmodulename(path: str) -> str | None: ... +def ismodule(object: object) -> TypeGuard[ModuleType]: ... +def isclass(object: object) -> TypeGuard[Type[Any]]: ... +def ismethod(object: object) -> TypeGuard[MethodType]: ... +def isfunction(object: object) -> TypeGuard[FunctionType]: ... if sys.version_info >= (3, 8): def isgeneratorfunction(obj: object) -> bool: ... @@ -62,9 +68,9 @@ else: def isgeneratorfunction(object: object) -> bool: ... def iscoroutinefunction(object: object) -> bool: ... -def isgenerator(object: object) -> bool: ... -def iscoroutine(object: object) -> bool: ... -def isawaitable(object: object) -> bool: ... +def isgenerator(object: object) -> TypeGuard[GeneratorType[Any, Any, Any]]: ... +def iscoroutine(object: object) -> TypeGuard[CoroutineType[Any, Any, Any]]: ... +def isawaitable(object: object) -> TypeGuard[Awaitable[Any]]: ... if sys.version_info >= (3, 8): def isasyncgenfunction(obj: object) -> bool: ... @@ -72,32 +78,62 @@ if sys.version_info >= (3, 8): else: def isasyncgenfunction(object: object) -> bool: ... -def isasyncgen(object: object) -> bool: ... -def istraceback(object: object) -> bool: ... -def isframe(object: object) -> bool: ... -def iscode(object: object) -> bool: ... -def isbuiltin(object: object) -> bool: ... -def isroutine(object: object) -> bool: ... +_T_cont = TypeVar("_T_cont", contravariant=True) +_V_cont = TypeVar("_V_cont", contravariant=True) + +class _SupportsSet(Protocol[_T_cont, _V_cont]): + def __set__(self, __instance: _T_cont, __value: _V_cont) -> None: ... + +class _SupportsDelete(Protocol[_T_cont]): + def __delete__(self, __instance: _T_cont) -> None: ... + +def isasyncgen(object: object) -> TypeGuard[AsyncGeneratorType[Any, Any]]: ... +def istraceback(object: object) -> TypeGuard[TracebackType]: ... +def isframe(object: object) -> TypeGuard[FrameType]: ... +def iscode(object: object) -> TypeGuard[CodeType]: ... +def isbuiltin(object: object) -> TypeGuard[BuiltinFunctionType]: ... + +if sys.version_info < (3, 7): + def isroutine( + object: object, + ) -> TypeGuard[FunctionType | LambdaType | MethodType | BuiltinFunctionType | BuiltinMethodType]: ... + def ismethoddescriptor(object: object) -> bool: ... + def ismemberdescriptor(object: object) -> bool: ... + +else: + def isroutine( + object: object, + ) -> TypeGuard[ + FunctionType + | LambdaType + | MethodType + | BuiltinFunctionType + | BuiltinMethodType + | WrapperDescriptorType + | MethodDescriptorType + | ClassMethodDescriptorType + ]: ... + def ismethoddescriptor(object: object) -> TypeGuard[MethodDescriptorType]: ... + def ismemberdescriptor(object: object) -> TypeGuard[MemberDescriptorType]: ... + def isabstract(object: object) -> bool: ... -def ismethoddescriptor(object: object) -> bool: ... -def isdatadescriptor(object: object) -> bool: ... -def isgetsetdescriptor(object: object) -> bool: ... -def ismemberdescriptor(object: object) -> bool: ... +def isgetsetdescriptor(object: object) -> TypeGuard[GetSetDescriptorType]: ... +def isdatadescriptor(object: object) -> TypeGuard[_SupportsSet[Any, Any] | _SupportsDelete[Any]]: ... # # Retrieving source code # _SourceObjectType = Union[ModuleType, Type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] -def findsource(object: _SourceObjectType) -> Tuple[List[str], int]: ... -def getabsfile(object: _SourceObjectType, _filename: Optional[str] = ...) -> str: ... +def findsource(object: _SourceObjectType) -> tuple[list[str], int]: ... +def getabsfile(object: _SourceObjectType, _filename: str | None = ...) -> str: ... def getblock(lines: Sequence[str]) -> Sequence[str]: ... -def getdoc(object: object) -> Optional[str]: ... -def getcomments(object: object) -> Optional[str]: ... +def getdoc(object: object) -> str | None: ... +def getcomments(object: object) -> str | None: ... def getfile(object: _SourceObjectType) -> str: ... -def getmodule(object: object, _filename: Optional[str] = ...) -> Optional[ModuleType]: ... -def getsourcefile(object: _SourceObjectType) -> Optional[str]: ... -def getsourcelines(object: _SourceObjectType) -> Tuple[List[str], int]: ... +def getmodule(object: object, _filename: str | None = ...) -> ModuleType | None: ... +def getsourcefile(object: _SourceObjectType) -> str | None: ... +def getsourcelines(object: _SourceObjectType) -> tuple[list[str], int]: ... def getsource(object: _SourceObjectType) -> str: ... def cleandoc(doc: str) -> str: ... def indentsize(line: str) -> int: ... @@ -110,26 +146,32 @@ if sys.version_info >= (3, 10): obj: Callable[..., Any], *, follow_wrapped: bool = ..., - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, Any] | None = ..., + locals: Mapping[str, Any] | None = ..., eval_str: bool = ..., ) -> Signature: ... else: def signature(obj: Callable[..., Any], *, follow_wrapped: bool = ...) -> Signature: ... -class Signature: - def __init__(self, parameters: Optional[Sequence[Parameter]] = ..., *, return_annotation: Any = ...) -> None: ... - # TODO: can we be more specific here? - empty: object = ... - - parameters: Mapping[str, Parameter] +class _void: ... +class _empty: ... +class Signature: + def __init__( + self, parameters: Sequence[Parameter] | None = ..., *, return_annotation: Any = ..., __validate_parameters__: bool = ... + ) -> None: ... + empty = _empty + @property + def parameters(self) -> types.MappingProxyType[str, Parameter]: ... # TODO: can we be more specific here? - return_annotation: Any + @property + def return_annotation(self) -> Any: ... def bind(self, *args: Any, **kwargs: Any) -> BoundArguments: ... def bind_partial(self, *args: Any, **kwargs: Any) -> BoundArguments: ... - def replace(self, *, parameters: Optional[Sequence[Parameter]] = ..., return_annotation: Any = ...) -> Signature: ... + def replace( + self: Self, *, parameters: Sequence[Parameter] | Type[_void] | None = ..., return_annotation: Any = ... + ) -> Self: ... if sys.version_info >= (3, 10): @classmethod def from_callable( @@ -137,8 +179,8 @@ class Signature: obj: Callable[..., Any], *, follow_wrapped: bool = ..., - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, Any] | None = ..., + locals: Mapping[str, Any] | None = ..., eval_str: bool = ..., ) -> Signature: ... else: @@ -147,12 +189,12 @@ class Signature: if sys.version_info >= (3, 10): def get_annotations( - obj: Union[Callable[..., Any], Type[Any], ModuleType], + obj: Callable[..., Any] | Type[Any] | ModuleType, *, - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + globals: Mapping[str, Any] | None = ..., + locals: Mapping[str, Any] | None = ..., eval_str: bool = ..., - ) -> Dict[str, Any]: ... + ) -> dict[str, Any]: ... # The name is the same as the enum's name in CPython class _ParameterKind(enum.IntEnum): @@ -167,7 +209,7 @@ class _ParameterKind(enum.IntEnum): class Parameter: def __init__(self, name: str, kind: _ParameterKind, *, default: Any = ..., annotation: Any = ...) -> None: ... - empty: Any = ... + empty = _empty name: str default: Any annotation: Any @@ -179,13 +221,18 @@ class Parameter: KEYWORD_ONLY: ClassVar[Literal[_ParameterKind.KEYWORD_ONLY]] VAR_KEYWORD: ClassVar[Literal[_ParameterKind.VAR_KEYWORD]] def replace( - self, *, name: Optional[str] = ..., kind: Optional[_ParameterKind] = ..., default: Any = ..., annotation: Any = ... - ) -> Parameter: ... + self: Self, + *, + name: str | Type[_void] = ..., + kind: _ParameterKind | Type[_void] = ..., + default: Any = ..., + annotation: Any = ..., + ) -> Self: ... class BoundArguments: arguments: OrderedDict[str, Any] args: Tuple[Any, ...] - kwargs: Dict[str, Any] + kwargs: dict[str, Any] signature: Signature def __init__(self, signature: Signature, arguments: OrderedDict[str, Any]) -> None: ... def apply_defaults(self) -> None: ... @@ -194,54 +241,54 @@ class BoundArguments: # Classes and functions # -# TODO: The actual return type should be List[_ClassTreeItem] but mypy doesn't +# TODO: The actual return type should be list[_ClassTreeItem] but mypy doesn't # seem to be supporting this at the moment: -# _ClassTreeItem = Union[List[_ClassTreeItem], Tuple[type, Tuple[type, ...]]] -def getclasstree(classes: List[type], unique: bool = ...) -> List[Any]: ... -def walktree(classes: List[type], children: Dict[Type[Any], List[type]], parent: Optional[Type[Any]]) -> List[Any]: ... +# _ClassTreeItem = list[_ClassTreeItem] | Tuple[type, Tuple[type, ...]] +def getclasstree(classes: list[type], unique: bool = ...) -> list[Any]: ... +def walktree(classes: list[type], children: dict[Type[Any], list[type]], parent: Type[Any] | None) -> list[Any]: ... class ArgSpec(NamedTuple): - args: List[str] - varargs: Optional[str] - keywords: Optional[str] + args: list[str] + varargs: str | None + keywords: str | None defaults: Tuple[Any, ...] class Arguments(NamedTuple): - args: List[str] - varargs: Optional[str] - varkw: Optional[str] + args: list[str] + varargs: str | None + varkw: str | None def getargs(co: CodeType) -> Arguments: ... def getargspec(func: object) -> ArgSpec: ... class FullArgSpec(NamedTuple): - args: List[str] - varargs: Optional[str] - varkw: Optional[str] - defaults: Optional[Tuple[Any, ...]] - kwonlyargs: List[str] - kwonlydefaults: Optional[Dict[str, Any]] - annotations: Dict[str, Any] + args: list[str] + varargs: str | None + varkw: str | None + defaults: Tuple[Any, ...] | None + kwonlyargs: list[str] + kwonlydefaults: dict[str, Any] | None + annotations: dict[str, Any] def getfullargspec(func: object) -> FullArgSpec: ... class ArgInfo(NamedTuple): - args: List[str] - varargs: Optional[str] - keywords: Optional[str] - locals: Dict[str, Any] + args: list[str] + varargs: str | None + keywords: str | None + locals: dict[str, Any] def getargvalues(frame: FrameType) -> ArgInfo: ... -def formatannotation(annotation: object, base_module: Optional[str] = ...) -> str: ... +def formatannotation(annotation: object, base_module: str | None = ...) -> str: ... def formatannotationrelativeto(object: object) -> Callable[[object], str]: ... def formatargspec( - args: List[str], - varargs: Optional[str] = ..., - varkw: Optional[str] = ..., - defaults: Optional[Tuple[Any, ...]] = ..., - kwonlyargs: Optional[Sequence[str]] = ..., - kwonlydefaults: Optional[Dict[str, Any]] = ..., - annotations: Dict[str, Any] = ..., + args: list[str], + varargs: str | None = ..., + varkw: str | None = ..., + defaults: Tuple[Any, ...] | None = ..., + kwonlyargs: Sequence[str] | None = ..., + kwonlydefaults: dict[str, Any] | None = ..., + annotations: dict[str, Any] = ..., formatarg: Callable[[str], str] = ..., formatvarargs: Callable[[str], str] = ..., formatvarkw: Callable[[str], str] = ..., @@ -250,17 +297,17 @@ def formatargspec( formatannotation: Callable[[Any], str] = ..., ) -> str: ... def formatargvalues( - args: List[str], - varargs: Optional[str], - varkw: Optional[str], - locals: Optional[Dict[str, Any]], - formatarg: Optional[Callable[[str], str]] = ..., - formatvarargs: Optional[Callable[[str], str]] = ..., - formatvarkw: Optional[Callable[[str], str]] = ..., - formatvalue: Optional[Callable[[Any], str]] = ..., + args: list[str], + varargs: str | None, + varkw: str | None, + locals: dict[str, Any] | None, + formatarg: Callable[[str], str] | None = ..., + formatvarargs: Callable[[str], str] | None = ..., + formatvarkw: Callable[[str], str] | None = ..., + formatvalue: Callable[[Any], str] | None = ..., ) -> str: ... def getmro(cls: type) -> Tuple[type, ...]: ... -def getcallargs(__func: Callable[..., Any], *args: Any, **kwds: Any) -> Dict[str, Any]: ... +def getcallargs(__func: Callable[..., Any], *args: Any, **kwds: Any) -> dict[str, Any]: ... class ClosureVars(NamedTuple): nonlocals: Mapping[str, Any] @@ -269,7 +316,7 @@ class ClosureVars(NamedTuple): unbound: AbstractSet[str] def getclosurevars(func: Callable[..., Any]) -> ClosureVars: ... -def unwrap(func: Callable[..., Any], *, stop: Optional[Callable[[Any], Any]] = ...) -> Any: ... +def unwrap(func: Callable[..., Any], *, stop: Callable[[Any], Any] | None = ...) -> Any: ... # # The interpreter stack @@ -279,30 +326,30 @@ class Traceback(NamedTuple): filename: str lineno: int function: str - code_context: Optional[List[str]] - index: Optional[int] # type: ignore + code_context: list[str] | None + index: int | None # type: ignore class FrameInfo(NamedTuple): frame: FrameType filename: str lineno: int function: str - code_context: Optional[List[str]] - index: Optional[int] # type: ignore + code_context: list[str] | None + index: int | None # type: ignore -def getframeinfo(frame: Union[FrameType, TracebackType], context: int = ...) -> Traceback: ... -def getouterframes(frame: Any, context: int = ...) -> List[FrameInfo]: ... -def getinnerframes(tb: TracebackType, context: int = ...) -> List[FrameInfo]: ... +def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... +def getouterframes(frame: Any, context: int = ...) -> list[FrameInfo]: ... +def getinnerframes(tb: TracebackType, context: int = ...) -> list[FrameInfo]: ... def getlineno(frame: FrameType) -> int: ... -def currentframe() -> Optional[FrameType]: ... -def stack(context: int = ...) -> List[FrameInfo]: ... -def trace(context: int = ...) -> List[FrameInfo]: ... +def currentframe() -> FrameType | None: ... +def stack(context: int = ...) -> list[FrameInfo]: ... +def trace(context: int = ...) -> list[FrameInfo]: ... # # Fetching attributes statically # -def getattr_static(obj: object, attr: str, default: Optional[Any] = ...) -> Any: ... +def getattr_static(obj: object, attr: str, default: Any | None = ...) -> Any: ... # # Current State of Generators and Coroutines @@ -324,10 +371,10 @@ CORO_SUSPENDED: str CORO_CLOSED: str # TODO can we be more specific than "object"? def getcoroutinestate(coroutine: object) -> str: ... -def getgeneratorlocals(generator: Generator[Any, Any, Any]) -> Dict[str, Any]: ... +def getgeneratorlocals(generator: Generator[Any, Any, Any]) -> dict[str, Any]: ... # TODO can we be more specific than "object"? -def getcoroutinelocals(coroutine: object) -> Dict[str, Any]: ... +def getcoroutinelocals(coroutine: object) -> dict[str, Any]: ... # Create private type alias to avoid conflict with symbol of same # name created in Attribute class. @@ -339,7 +386,7 @@ class Attribute(NamedTuple): defining_class: type object: _Object -def classify_class_attrs(cls: type) -> List[Attribute]: ... +def classify_class_attrs(cls: type) -> list[Attribute]: ... if sys.version_info >= (3, 9): class ClassFoundException(Exception): ... diff --git a/mypy/typeshed/stdlib/io.pyi b/mypy/typeshed/stdlib/io.pyi index f03a9a8740fe..6342907004d5 100644 --- a/mypy/typeshed/stdlib/io.pyi +++ b/mypy/typeshed/stdlib/io.pyi @@ -1,9 +1,10 @@ import builtins import codecs import sys -from _typeshed import ReadableBuffer, WriteableBuffer +from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer +from os import _Opener from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, List, Optional, TextIO, Tuple, Type, TypeVar, Union +from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO, Tuple, Type DEFAULT_BUFFER_SIZE: int @@ -11,8 +12,6 @@ SEEK_SET: int SEEK_CUR: int SEEK_END: int -_T = TypeVar("_T", bound=IOBase) - open = builtins.open if sys.version_info >= (3, 8): @@ -25,35 +24,35 @@ class UnsupportedOperation(OSError, ValueError): ... class IOBase: def __iter__(self) -> Iterator[bytes]: ... def __next__(self) -> bytes: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... def close(self) -> None: ... def fileno(self) -> int: ... def flush(self) -> None: ... def isatty(self) -> bool: ... def readable(self) -> bool: ... read: Callable[..., Any] - def readlines(self, __hint: int = ...) -> List[bytes]: ... + def readlines(self, __hint: int = ...) -> list[bytes]: ... def seek(self, __offset: int, __whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, __size: Optional[int] = ...) -> int: ... + def truncate(self, __size: int | None = ...) -> int: ... def writable(self) -> bool: ... write: Callable[..., Any] def writelines(self, __lines: Iterable[ReadableBuffer]) -> None: ... - def readline(self, __size: Optional[int] = ...) -> bytes: ... + def readline(self, __size: int | None = ...) -> bytes: ... def __del__(self) -> None: ... @property def closed(self) -> bool: ... - def _checkClosed(self, msg: Optional[str] = ...) -> None: ... # undocumented + def _checkClosed(self, msg: str | None = ...) -> None: ... # undocumented class RawIOBase(IOBase): def readall(self) -> bytes: ... - def readinto(self, __buffer: WriteableBuffer) -> Optional[int]: ... - def write(self, __b: ReadableBuffer) -> Optional[int]: ... - def read(self, __size: int = ...) -> Optional[bytes]: ... + def readinto(self, __buffer: WriteableBuffer) -> int | None: ... + def write(self, __b: ReadableBuffer) -> int | None: ... + def read(self, __size: int = ...) -> bytes | None: ... class BufferedIOBase(IOBase): raw: RawIOBase # This is not part of the BufferedIOBase API and may not exist on some implementations. @@ -61,25 +60,20 @@ class BufferedIOBase(IOBase): def readinto(self, __buffer: WriteableBuffer) -> int: ... def write(self, __buffer: ReadableBuffer) -> int: ... def readinto1(self, __buffer: WriteableBuffer) -> int: ... - def read(self, __size: Optional[int] = ...) -> bytes: ... + def read(self, __size: int | None = ...) -> bytes: ... def read1(self, __size: int = ...) -> bytes: ... class FileIO(RawIOBase, BinaryIO): mode: str - # Technically this is whatever is passed in as file, either a str, a bytes, or an int. - name: Union[int, str] # type: ignore + name: StrOrBytesPath | int # type: ignore def __init__( - self, - file: Union[str, bytes, int], - mode: str = ..., - closefd: bool = ..., - opener: Optional[Callable[[Union[int, str], str], int]] = ..., + self, file: StrOrBytesPath | int, mode: str = ..., closefd: bool = ..., opener: _Opener | None = ... ) -> None: ... @property def closefd(self) -> bool: ... def write(self, __b: ReadableBuffer) -> int: ... def read(self, __size: int = ...) -> bytes: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... class BytesIO(BufferedIOBase, BinaryIO): def __init__(self, initial_bytes: bytes = ...) -> None: ... @@ -87,16 +81,16 @@ class BytesIO(BufferedIOBase, BinaryIO): # to allow BytesIO sub-classes to add this field, as it is defined # as a read-only property on IO[]. name: Any - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def getvalue(self) -> bytes: ... def getbuffer(self) -> memoryview: ... if sys.version_info >= (3, 7): - def read1(self, __size: Optional[int] = ...) -> bytes: ... + def read1(self, __size: int | None = ...) -> bytes: ... else: - def read1(self, __size: Optional[int]) -> bytes: ... # type: ignore + def read1(self, __size: int | None) -> bytes: ... # type: ignore class BufferedReader(BufferedIOBase, BinaryIO): - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... def peek(self, __size: int = ...) -> bytes: ... if sys.version_info >= (3, 7): @@ -105,12 +99,12 @@ class BufferedReader(BufferedIOBase, BinaryIO): def read1(self, __size: int) -> bytes: ... # type: ignore class BufferedWriter(BufferedIOBase, BinaryIO): - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... def write(self, __buffer: ReadableBuffer) -> int: ... class BufferedRandom(BufferedReader, BufferedWriter): - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __init__(self, raw: RawIOBase, buffer_size: int = ...) -> None: ... def seek(self, __target: int, __whence: int = ...) -> int: ... if sys.version_info >= (3, 7): @@ -124,25 +118,25 @@ class BufferedRWPair(BufferedIOBase): class TextIOBase(IOBase): encoding: str - errors: Optional[str] - newlines: Union[str, Tuple[str, ...], None] + errors: str | None + newlines: str | Tuple[str, ...] | None def __iter__(self) -> Iterator[str]: ... # type: ignore def __next__(self) -> str: ... # type: ignore def detach(self) -> BinaryIO: ... def write(self, __s: str) -> int: ... def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore def readline(self, __size: int = ...) -> str: ... # type: ignore - def readlines(self, __hint: int = ...) -> List[str]: ... # type: ignore - def read(self, __size: Optional[int] = ...) -> str: ... + def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore + def read(self, __size: int | None = ...) -> str: ... def tell(self) -> int: ... class TextIOWrapper(TextIOBase, TextIO): def __init__( self, buffer: IO[bytes], - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., line_buffering: bool = ..., write_through: bool = ..., ) -> None: ... @@ -158,23 +152,23 @@ class TextIOWrapper(TextIOBase, TextIO): def reconfigure( self, *, - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., - line_buffering: Optional[bool] = ..., - write_through: Optional[bool] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + line_buffering: bool | None = ..., + write_through: bool | None = ..., ) -> None: ... # These are inherited from TextIOBase, but must exist in the stub to satisfy mypy. - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __iter__(self) -> Iterator[str]: ... # type: ignore def __next__(self) -> str: ... # type: ignore def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore def readline(self, __size: int = ...) -> str: ... # type: ignore - def readlines(self, __hint: int = ...) -> List[str]: ... # type: ignore + def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore def seek(self, __cookie: int, __whence: int = ...) -> int: ... class StringIO(TextIOWrapper): - def __init__(self, initial_value: Optional[str] = ..., newline: Optional[str] = ...) -> None: ... + def __init__(self, initial_value: str | None = ..., newline: str | None = ...) -> None: ... # StringIO does not contain a "name" field. This workaround is necessary # to allow StringIO sub-classes to add this field, as it is defined # as a read-only property on IO[]. @@ -182,7 +176,7 @@ class StringIO(TextIOWrapper): def getvalue(self) -> str: ... class IncrementalNewlineDecoder(codecs.IncrementalDecoder): - def __init__(self, decoder: Optional[codecs.IncrementalDecoder], translate: bool, errors: str = ...) -> None: ... - def decode(self, input: Union[bytes, str], final: bool = ...) -> str: ... + def __init__(self, decoder: codecs.IncrementalDecoder | None, translate: bool, errors: str = ...) -> None: ... + def decode(self, input: bytes | str, final: bool = ...) -> str: ... @property - def newlines(self) -> Optional[Union[str, Tuple[str, ...]]]: ... + def newlines(self) -> str | Tuple[str, ...] | None: ... diff --git a/mypy/typeshed/stdlib/ipaddress.pyi b/mypy/typeshed/stdlib/ipaddress.pyi index b4e2b2c4b3f9..0ded1ef19b47 100644 --- a/mypy/typeshed/stdlib/ipaddress.pyi +++ b/mypy/typeshed/stdlib/ipaddress.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Container, Generic, Iterable, Iterator, Optional, SupportsInt, Tuple, TypeVar, overload +from typing import Any, Container, Generic, Iterable, Iterator, SupportsInt, TypeVar, overload # Undocumented length constants IPV4LENGTH: int @@ -9,9 +9,9 @@ _A = TypeVar("_A", IPv4Address, IPv6Address) _N = TypeVar("_N", IPv4Network, IPv6Network) _T = TypeVar("_T") -def ip_address(address: object) -> Any: ... # morally Union[IPv4Address, IPv6Address] -def ip_network(address: object, strict: bool = ...) -> Any: ... # morally Union[IPv4Network, IPv6Network] -def ip_interface(address: object) -> Any: ... # morally Union[IPv4Interface, IPv6Interface] +def ip_address(address: object) -> Any: ... # morally IPv4Address | IPv6Address +def ip_network(address: object, strict: bool = ...) -> Any: ... # morally IPv4Network | IPv6Network +def ip_interface(address: object) -> Any: ... # morally IPv4Interface | IPv6Interface class _IPAddressBase: def __eq__(self, other: Any) -> bool: ... @@ -90,8 +90,8 @@ class _BaseNetwork(_IPAddressBase, Container[_A], Iterable[_A], Generic[_A]): if sys.version_info >= (3, 7): def subnet_of(self: _T, other: _T) -> bool: ... def supernet_of(self: _T, other: _T) -> bool: ... - def subnets(self: _T, prefixlen_diff: int = ..., new_prefix: Optional[int] = ...) -> Iterator[_T]: ... - def supernet(self: _T, prefixlen_diff: int = ..., new_prefix: Optional[int] = ...) -> _T: ... + def subnets(self: _T, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> Iterator[_T]: ... + def supernet(self: _T, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> _T: ... @property def with_hostmask(self) -> str: ... @property @@ -120,13 +120,13 @@ class IPv4Interface(IPv4Address, _BaseInterface[IPv4Address, IPv4Network]): ... class IPv6Address(_BaseAddress): @property - def ipv4_mapped(self) -> Optional[IPv4Address]: ... + def ipv4_mapped(self) -> IPv4Address | None: ... @property def is_site_local(self) -> bool: ... @property - def sixtofour(self) -> Optional[IPv4Address]: ... + def sixtofour(self) -> IPv4Address | None: ... @property - def teredo(self) -> Optional[Tuple[IPv4Address, IPv4Address]]: ... + def teredo(self) -> tuple[IPv4Address, IPv4Address] | None: ... class IPv6Network(_BaseNetwork[IPv6Address]): @property @@ -142,11 +142,11 @@ def summarize_address_range(first: IPv4Address, last: IPv4Address) -> Iterator[I def summarize_address_range(first: IPv6Address, last: IPv6Address) -> Iterator[IPv6Network]: ... def collapse_addresses(addresses: Iterable[_N]) -> Iterator[_N]: ... @overload -def get_mixed_type_key(obj: _A) -> Tuple[int, _A]: ... +def get_mixed_type_key(obj: _A) -> tuple[int, _A]: ... @overload -def get_mixed_type_key(obj: IPv4Network) -> Tuple[int, IPv4Address, IPv4Address]: ... +def get_mixed_type_key(obj: IPv4Network) -> tuple[int, IPv4Address, IPv4Address]: ... @overload -def get_mixed_type_key(obj: IPv6Network) -> Tuple[int, IPv6Address, IPv6Address]: ... +def get_mixed_type_key(obj: IPv6Network) -> tuple[int, IPv6Address, IPv6Address]: ... class AddressValueError(ValueError): ... class NetmaskValueError(ValueError): ... diff --git a/mypy/typeshed/stdlib/itertools.pyi b/mypy/typeshed/stdlib/itertools.pyi index 7fe08ca80531..9d666d681781 100644 --- a/mypy/typeshed/stdlib/itertools.pyi +++ b/mypy/typeshed/stdlib/itertools.pyi @@ -6,7 +6,6 @@ from typing import ( Generic, Iterable, Iterator, - Optional, SupportsComplex, SupportsFloat, SupportsInt, @@ -53,11 +52,11 @@ class repeat(Iterator[_T], Generic[_T]): class accumulate(Iterator[_T], Generic[_T]): if sys.version_info >= (3, 8): @overload - def __init__(self, iterable: Iterable[_T], func: None = ..., *, initial: Optional[_T] = ...) -> None: ... + def __init__(self, iterable: Iterable[_T], func: None = ..., *, initial: _T | None = ...) -> None: ... @overload - def __init__(self, iterable: Iterable[_S], func: Callable[[_T, _S], _T], *, initial: Optional[_T] = ...) -> None: ... + def __init__(self, iterable: Iterable[_S], func: Callable[[_T, _S], _T], *, initial: _T | None = ...) -> None: ... else: - def __init__(self, iterable: Iterable[_T], func: Optional[Callable[[_T, _T], _T]] = ...) -> None: ... + def __init__(self, iterable: Iterable[_T], func: Callable[[_T, _T], _T] | None = ...) -> None: ... def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... @@ -80,7 +79,7 @@ class dropwhile(Iterator[_T], Generic[_T]): def __next__(self) -> _T: ... class filterfalse(Iterator[_T], Generic[_T]): - def __init__(self, __predicate: Optional[Predicate[_T]], __iterable: Iterable[_T]) -> None: ... + def __init__(self, __predicate: Predicate[_T] | None, __iterable: Iterable[_T]) -> None: ... def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... @@ -92,16 +91,14 @@ class groupby(Iterator[Tuple[_T, Iterator[_S]]], Generic[_T, _S]): def __new__(cls, iterable: Iterable[_T1], key: None = ...) -> groupby[_T1, _T1]: ... @overload def __new__(cls, iterable: Iterable[_T1], key: Callable[[_T1], _T2]) -> groupby[_T2, _T1]: ... - def __iter__(self) -> Iterator[Tuple[_T, Iterator[_S]]]: ... - def __next__(self) -> Tuple[_T, Iterator[_S]]: ... + def __iter__(self) -> Iterator[tuple[_T, Iterator[_S]]]: ... + def __next__(self) -> tuple[_T, Iterator[_S]]: ... class islice(Iterator[_T], Generic[_T]): @overload - def __init__(self, __iterable: Iterable[_T], __stop: Optional[int]) -> None: ... + def __init__(self, __iterable: Iterable[_T], __stop: int | None) -> None: ... @overload - def __init__( - self, __iterable: Iterable[_T], __start: Optional[int], __stop: Optional[int], __step: Optional[int] = ... - ) -> None: ... + def __init__(self, __iterable: Iterable[_T], __start: int | None, __stop: int | None, __step: int | None = ...) -> None: ... def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... @@ -129,15 +126,15 @@ _T6 = TypeVar("_T6") class product(Iterator[_T_co], Generic[_T_co]): @overload - def __new__(cls, __iter1: Iterable[_T1]) -> product[Tuple[_T1]]: ... + def __new__(cls, __iter1: Iterable[_T1]) -> product[tuple[_T1]]: ... @overload - def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> product[Tuple[_T1, _T2]]: ... + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> product[tuple[_T1, _T2]]: ... @overload - def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> product[Tuple[_T1, _T2, _T3]]: ... + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> product[tuple[_T1, _T2, _T3]]: ... @overload def __new__( cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] - ) -> product[Tuple[_T1, _T2, _T3, _T4]]: ... + ) -> product[tuple[_T1, _T2, _T3, _T4]]: ... @overload def __new__( cls, @@ -146,7 +143,7 @@ class product(Iterator[_T_co], Generic[_T_co]): __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5], - ) -> product[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... + ) -> product[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def __new__( cls, @@ -156,7 +153,7 @@ class product(Iterator[_T_co], Generic[_T_co]): __iter4: Iterable[_T4], __iter5: Iterable[_T5], __iter6: Iterable[_T6], - ) -> product[Tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... + ) -> product[tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... @overload def __new__( cls, @@ -177,19 +174,19 @@ class product(Iterator[_T_co], Generic[_T_co]): def __next__(self) -> _T_co: ... class permutations(Iterator[Tuple[_T, ...]], Generic[_T]): - def __init__(self, iterable: Iterable[_T], r: Optional[int] = ...) -> None: ... + def __init__(self, iterable: Iterable[_T], r: int | None = ...) -> None: ... def __iter__(self) -> Iterator[Tuple[_T, ...]]: ... def __next__(self) -> Tuple[_T, ...]: ... class combinations(Iterator[_T_co], Generic[_T_co]): @overload - def __new__(cls, iterable: Iterable[_T], r: Literal[2]) -> combinations[Tuple[_T, _T]]: ... + def __new__(cls, iterable: Iterable[_T], r: Literal[2]) -> combinations[tuple[_T, _T]]: ... @overload - def __new__(cls, iterable: Iterable[_T], r: Literal[3]) -> combinations[Tuple[_T, _T, _T]]: ... + def __new__(cls, iterable: Iterable[_T], r: Literal[3]) -> combinations[tuple[_T, _T, _T]]: ... @overload - def __new__(cls, iterable: Iterable[_T], r: Literal[4]) -> combinations[Tuple[_T, _T, _T, _T]]: ... + def __new__(cls, iterable: Iterable[_T], r: Literal[4]) -> combinations[tuple[_T, _T, _T, _T]]: ... @overload - def __new__(cls, iterable: Iterable[_T], r: Literal[5]) -> combinations[Tuple[_T, _T, _T, _T, _T]]: ... + def __new__(cls, iterable: Iterable[_T], r: Literal[5]) -> combinations[tuple[_T, _T, _T, _T, _T]]: ... @overload def __new__(cls, iterable: Iterable[_T], r: int) -> combinations[Tuple[_T, ...]]: ... def __iter__(self) -> Iterator[_T_co]: ... @@ -202,6 +199,6 @@ class combinations_with_replacement(Iterator[Tuple[_T, ...]], Generic[_T]): if sys.version_info >= (3, 10): class pairwise(Iterator[_T_co], Generic[_T_co]): - def __new__(cls, __iterable: Iterable[_T]) -> pairwise[Tuple[_T, _T]]: ... + def __new__(cls, __iterable: Iterable[_T]) -> pairwise[tuple[_T, _T]]: ... def __iter__(self) -> Iterator[_T_co]: ... def __next__(self) -> _T_co: ... diff --git a/mypy/typeshed/stdlib/json/__init__.pyi b/mypy/typeshed/stdlib/json/__init__.pyi index 7b7a89ae20e2..3e26d1b14f82 100644 --- a/mypy/typeshed/stdlib/json/__init__.pyi +++ b/mypy/typeshed/stdlib/json/__init__.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Type, Union +from typing import IO, Any, Callable, Type from .decoder import JSONDecodeError as JSONDecodeError, JSONDecoder as JSONDecoder from .encoder import JSONEncoder as JSONEncoder @@ -11,10 +11,10 @@ def dumps( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Optional[Type[JSONEncoder]] = ..., - indent: Union[None, int, str] = ..., - separators: Optional[Tuple[str, str]] = ..., - default: Optional[Callable[[Any], Any]] = ..., + cls: Type[JSONEncoder] | None = ..., + indent: None | int | str = ..., + separators: tuple[str, str] | None = ..., + default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., **kwds: Any, ) -> str: ... @@ -26,33 +26,33 @@ def dump( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Optional[Type[JSONEncoder]] = ..., - indent: Union[None, int, str] = ..., - separators: Optional[Tuple[str, str]] = ..., - default: Optional[Callable[[Any], Any]] = ..., + cls: Type[JSONEncoder] | None = ..., + indent: None | int | str = ..., + separators: tuple[str, str] | None = ..., + default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., **kwds: Any, ) -> None: ... def loads( - s: Union[str, bytes], + s: str | bytes, *, - cls: Optional[Type[JSONDecoder]] = ..., - object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ..., - parse_float: Optional[Callable[[str], Any]] = ..., - parse_int: Optional[Callable[[str], Any]] = ..., - parse_constant: Optional[Callable[[str], Any]] = ..., - object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ..., + cls: Type[JSONDecoder] | None = ..., + object_hook: Callable[[dict[Any, Any]], Any] | None = ..., + parse_float: Callable[[str], Any] | None = ..., + parse_int: Callable[[str], Any] | None = ..., + parse_constant: Callable[[str], Any] | None = ..., + object_pairs_hook: Callable[[list[tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... def load( - fp: SupportsRead[Union[str, bytes]], + fp: SupportsRead[str | bytes], *, - cls: Optional[Type[JSONDecoder]] = ..., - object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ..., - parse_float: Optional[Callable[[str], Any]] = ..., - parse_int: Optional[Callable[[str], Any]] = ..., - parse_constant: Optional[Callable[[str], Any]] = ..., - object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ..., + cls: Type[JSONDecoder] | None = ..., + object_hook: Callable[[dict[Any, Any]], Any] | None = ..., + parse_float: Callable[[str], Any] | None = ..., + parse_int: Callable[[str], Any] | None = ..., + parse_constant: Callable[[str], Any] | None = ..., + object_pairs_hook: Callable[[list[tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... def detect_encoding(b: bytes) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/json/decoder.pyi b/mypy/typeshed/stdlib/json/decoder.pyi index 19d7b4eb2545..adf09bb4bb7d 100644 --- a/mypy/typeshed/stdlib/json/decoder.pyi +++ b/mypy/typeshed/stdlib/json/decoder.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, List, Optional, Tuple +from typing import Any, Callable class JSONDecodeError(ValueError): msg: str @@ -9,21 +9,21 @@ class JSONDecodeError(ValueError): def __init__(self, msg: str, doc: str, pos: int) -> None: ... class JSONDecoder: - object_hook: Callable[[Dict[str, Any]], Any] + object_hook: Callable[[dict[str, Any]], Any] parse_float: Callable[[str], Any] parse_int: Callable[[str], Any] - parse_constant: Callable[[str], Any] = ... + parse_constant: Callable[[str], Any] strict: bool - object_pairs_hook: Callable[[List[Tuple[str, Any]]], Any] + object_pairs_hook: Callable[[list[tuple[str, Any]]], Any] def __init__( self, *, - object_hook: Optional[Callable[[Dict[str, Any]], Any]] = ..., - parse_float: Optional[Callable[[str], Any]] = ..., - parse_int: Optional[Callable[[str], Any]] = ..., - parse_constant: Optional[Callable[[str], Any]] = ..., + object_hook: Callable[[dict[str, Any]], Any] | None = ..., + parse_float: Callable[[str], Any] | None = ..., + parse_int: Callable[[str], Any] | None = ..., + parse_constant: Callable[[str], Any] | None = ..., strict: bool = ..., - object_pairs_hook: Optional[Callable[[List[Tuple[str, Any]]], Any]] = ..., + object_pairs_hook: Callable[[list[tuple[str, Any]]], Any] | None = ..., ) -> None: ... def decode(self, s: str, _w: Callable[..., Any] = ...) -> Any: ... # _w is undocumented - def raw_decode(self, s: str, idx: int = ...) -> Tuple[Any, int]: ... + def raw_decode(self, s: str, idx: int = ...) -> tuple[Any, int]: ... diff --git a/mypy/typeshed/stdlib/json/encoder.pyi b/mypy/typeshed/stdlib/json/encoder.pyi index 7d520149ba4a..9557a96eee78 100644 --- a/mypy/typeshed/stdlib/json/encoder.pyi +++ b/mypy/typeshed/stdlib/json/encoder.pyi @@ -1,4 +1,7 @@ -from typing import Any, Callable, Iterator, Optional, Tuple +from typing import Any, Callable, Iterator + +def py_encode_basestring(s: str) -> str: ... # undocumented +def py_encode_basestring_ascii(s: str) -> str: ... # undocumented class JSONEncoder: item_separator: str @@ -18,9 +21,9 @@ class JSONEncoder: check_circular: bool = ..., allow_nan: bool = ..., sort_keys: bool = ..., - indent: Optional[int] = ..., - separators: Optional[Tuple[str, str]] = ..., - default: Optional[Callable[..., Any]] = ..., + indent: int | None = ..., + separators: tuple[str, str] | None = ..., + default: Callable[..., Any] | None = ..., ) -> None: ... def default(self, o: Any) -> Any: ... def encode(self, o: Any) -> str: ... diff --git a/mypy/typeshed/stdlib/keyword.pyi b/mypy/typeshed/stdlib/keyword.pyi index 3e095ed5f94c..ac052feeba58 100644 --- a/mypy/typeshed/stdlib/keyword.pyi +++ b/mypy/typeshed/stdlib/keyword.pyi @@ -1,7 +1,7 @@ import sys -from typing import Sequence, Text +from typing import Sequence -def iskeyword(s: Text) -> bool: ... +def iskeyword(s: str) -> bool: ... kwlist: Sequence[str] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi index 841b0e4b1cb3..a8159dccf037 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi @@ -2,19 +2,19 @@ from _typeshed import StrPath from lib2to3.pgen2.grammar import Grammar from lib2to3.pytree import _NL, _Convert from logging import Logger -from typing import IO, Any, Iterable, Optional, Text +from typing import IO, Any, Iterable class Driver: grammar: Grammar logger: Logger convert: _Convert - def __init__(self, grammar: Grammar, convert: Optional[_Convert] = ..., logger: Optional[Logger] = ...) -> None: ... + def __init__(self, grammar: Grammar, convert: _Convert | None = ..., logger: Logger | None = ...) -> None: ... def parse_tokens(self, tokens: Iterable[Any], debug: bool = ...) -> _NL: ... - def parse_stream_raw(self, stream: IO[Text], debug: bool = ...) -> _NL: ... - def parse_stream(self, stream: IO[Text], debug: bool = ...) -> _NL: ... - def parse_file(self, filename: StrPath, encoding: Optional[Text] = ..., debug: bool = ...) -> _NL: ... - def parse_string(self, text: Text, debug: bool = ...) -> _NL: ... + def parse_stream_raw(self, stream: IO[str], debug: bool = ...) -> _NL: ... + def parse_stream(self, stream: IO[str], debug: bool = ...) -> _NL: ... + def parse_file(self, filename: StrPath, encoding: str | None = ..., debug: bool = ...) -> _NL: ... + def parse_string(self, text: str, debug: bool = ...) -> _NL: ... def load_grammar( - gt: Text = ..., gp: Optional[Text] = ..., save: bool = ..., force: bool = ..., logger: Optional[Logger] = ... + gt: str = ..., gp: str | None = ..., save: bool = ..., force: bool = ..., logger: Logger | None = ... ) -> Grammar: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi index 6ec97ce849d2..48cb4eae916c 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi @@ -1,20 +1,20 @@ from _typeshed import StrPath -from typing import Dict, List, Optional, Text, Tuple, TypeVar +from typing import Dict, List, Optional, Tuple, TypeVar _P = TypeVar("_P") -_Label = Tuple[int, Optional[Text]] +_Label = Tuple[int, Optional[str]] _DFA = List[List[Tuple[int, int]]] _DFAS = Tuple[_DFA, Dict[int, int]] class Grammar: - symbol2number: Dict[Text, int] - number2symbol: Dict[int, Text] - states: List[_DFA] - dfas: Dict[int, _DFAS] - labels: List[_Label] - keywords: Dict[Text, int] - tokens: Dict[int, int] - symbol2label: Dict[Text, int] + symbol2number: dict[str, int] + number2symbol: dict[int, str] + states: list[_DFA] + dfas: dict[int, _DFAS] + labels: list[_Label] + keywords: dict[str, int] + tokens: dict[int, int] + symbol2label: dict[str, int] start: int def __init__(self) -> None: ... def dump(self, filename: StrPath) -> None: ... @@ -22,5 +22,5 @@ class Grammar: def copy(self: _P) -> _P: ... def report(self) -> None: ... -opmap_raw: Text -opmap: Dict[Text, Text] +opmap_raw: str +opmap: dict[str, str] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/literals.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/literals.pyi index 160d6fd76f76..551ece19abd3 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/literals.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/literals.pyi @@ -1,7 +1,7 @@ -from typing import Dict, Match, Text +from typing import Match -simple_escapes: Dict[Text, Text] +simple_escapes: dict[str, str] -def escape(m: Match[str]) -> Text: ... -def evalString(s: Text) -> Text: ... +def escape(m: Match[str]) -> str: ... +def evalString(s: str) -> str: ... def test() -> None: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi index b7018cba9c1d..e776ed1e5a61 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi @@ -1,26 +1,26 @@ from lib2to3.pgen2.grammar import _DFAS, Grammar from lib2to3.pytree import _NL, _Convert, _RawNode -from typing import Any, List, Optional, Sequence, Set, Text, Tuple +from typing import Any, Sequence _Context = Sequence[Any] class ParseError(Exception): - msg: Text + msg: str type: int - value: Optional[Text] + value: str | None context: _Context - def __init__(self, msg: Text, type: int, value: Optional[Text], context: _Context) -> None: ... + def __init__(self, msg: str, type: int, value: str | None, context: _Context) -> None: ... class Parser: grammar: Grammar convert: _Convert - stack: List[Tuple[_DFAS, int, _RawNode]] - rootnode: Optional[_NL] - used_names: Set[Text] - def __init__(self, grammar: Grammar, convert: Optional[_Convert] = ...) -> None: ... - def setup(self, start: Optional[int] = ...) -> None: ... - def addtoken(self, type: int, value: Optional[Text], context: _Context) -> bool: ... - def classify(self, type: int, value: Optional[Text], context: _Context) -> int: ... - def shift(self, type: int, value: Optional[Text], newstate: int, context: _Context) -> None: ... + stack: list[tuple[_DFAS, int, _RawNode]] + rootnode: _NL | None + used_names: set[str] + def __init__(self, grammar: Grammar, convert: _Convert | None = ...) -> None: ... + def setup(self, start: int | None = ...) -> None: ... + def addtoken(self, type: int, value: str | None, context: _Context) -> bool: ... + def classify(self, type: int, value: str | None, context: _Context) -> int: ... + def shift(self, type: int, value: str | None, newstate: int, context: _Context) -> None: ... def push(self, type: int, newdfa: _DFAS, newstate: int, context: _Context) -> None: ... def pop(self) -> None: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi index 7920262f4f04..11680157d199 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi @@ -1,45 +1,45 @@ from _typeshed import StrPath from lib2to3.pgen2 import grammar from lib2to3.pgen2.tokenize import _TokenInfo -from typing import IO, Any, Dict, Iterable, Iterator, List, NoReturn, Optional, Text, Tuple +from typing import IO, Any, Iterable, Iterator, NoReturn class PgenGrammar(grammar.Grammar): ... class ParserGenerator: filename: StrPath - stream: IO[Text] + stream: IO[str] generator: Iterator[_TokenInfo] - first: Dict[Text, Dict[Text, int]] - def __init__(self, filename: StrPath, stream: Optional[IO[Text]] = ...) -> None: ... + first: dict[str, dict[str, int]] + def __init__(self, filename: StrPath, stream: IO[str] | None = ...) -> None: ... def make_grammar(self) -> PgenGrammar: ... - def make_first(self, c: PgenGrammar, name: Text) -> Dict[int, int]: ... - def make_label(self, c: PgenGrammar, label: Text) -> int: ... + def make_first(self, c: PgenGrammar, name: str) -> dict[int, int]: ... + def make_label(self, c: PgenGrammar, label: str) -> int: ... def addfirstsets(self) -> None: ... - def calcfirst(self, name: Text) -> None: ... - def parse(self) -> Tuple[Dict[Text, List[DFAState]], Text]: ... - def make_dfa(self, start: NFAState, finish: NFAState) -> List[DFAState]: ... - def dump_nfa(self, name: Text, start: NFAState, finish: NFAState) -> List[DFAState]: ... - def dump_dfa(self, name: Text, dfa: Iterable[DFAState]) -> None: ... - def simplify_dfa(self, dfa: List[DFAState]) -> None: ... - def parse_rhs(self) -> Tuple[NFAState, NFAState]: ... - def parse_alt(self) -> Tuple[NFAState, NFAState]: ... - def parse_item(self) -> Tuple[NFAState, NFAState]: ... - def parse_atom(self) -> Tuple[NFAState, NFAState]: ... - def expect(self, type: int, value: Optional[Any] = ...) -> Text: ... + def calcfirst(self, name: str) -> None: ... + def parse(self) -> tuple[dict[str, list[DFAState]], str]: ... + def make_dfa(self, start: NFAState, finish: NFAState) -> list[DFAState]: ... + def dump_nfa(self, name: str, start: NFAState, finish: NFAState) -> list[DFAState]: ... + def dump_dfa(self, name: str, dfa: Iterable[DFAState]) -> None: ... + def simplify_dfa(self, dfa: list[DFAState]) -> None: ... + def parse_rhs(self) -> tuple[NFAState, NFAState]: ... + def parse_alt(self) -> tuple[NFAState, NFAState]: ... + def parse_item(self) -> tuple[NFAState, NFAState]: ... + def parse_atom(self) -> tuple[NFAState, NFAState]: ... + def expect(self, type: int, value: Any | None = ...) -> str: ... def gettoken(self) -> None: ... def raise_error(self, msg: str, *args: Any) -> NoReturn: ... class NFAState: - arcs: List[Tuple[Optional[Text], NFAState]] + arcs: list[tuple[str | None, NFAState]] def __init__(self) -> None: ... - def addarc(self, next: NFAState, label: Optional[Text] = ...) -> None: ... + def addarc(self, next: NFAState, label: str | None = ...) -> None: ... class DFAState: - nfaset: Dict[NFAState, Any] + nfaset: dict[NFAState, Any] isfinal: bool - arcs: Dict[Text, DFAState] - def __init__(self, nfaset: Dict[NFAState, Any], final: NFAState) -> None: ... - def addarc(self, next: DFAState, label: Text) -> None: ... + arcs: dict[str, DFAState] + def __init__(self, nfaset: dict[NFAState, Any], final: NFAState) -> None: ... + def addarc(self, next: DFAState, label: str) -> None: ... def unifystate(self, old: DFAState, new: DFAState) -> None: ... def __eq__(self, other: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi index 19660cb0ce26..c4ab376eca64 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi @@ -1,6 +1,3 @@ -import sys -from typing import Dict, Text - ENDMARKER: int NAME: int NUMBER: int @@ -54,17 +51,15 @@ DOUBLESLASHEQUAL: int OP: int COMMENT: int NL: int -if sys.version_info >= (3,): - RARROW: int -if sys.version_info >= (3, 5): - AT: int - ATEQUAL: int - AWAIT: int - ASYNC: int +RARROW: int +AT: int +ATEQUAL: int +AWAIT: int +ASYNC: int ERRORTOKEN: int N_TOKENS: int NT_OFFSET: int -tok_name: Dict[int, Text] +tok_name: dict[int, str] def ISTERMINAL(x: int) -> bool: ... def ISNONTERMINAL(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi index 477341c1a54e..e96a0d8c8eb3 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi @@ -1,23 +1,23 @@ from lib2to3.pgen2.token import * # noqa -from typing import Callable, Iterable, Iterator, List, Text, Tuple +from typing import Callable, Iterable, Iterator, Tuple _Coord = Tuple[int, int] -_TokenEater = Callable[[int, Text, _Coord, _Coord, Text], None] -_TokenInfo = Tuple[int, Text, _Coord, _Coord, Text] +_TokenEater = Callable[[int, str, _Coord, _Coord, str], None] +_TokenInfo = Tuple[int, str, _Coord, _Coord, str] class TokenError(Exception): ... class StopTokenizing(Exception): ... -def tokenize(readline: Callable[[], Text], tokeneater: _TokenEater = ...) -> None: ... +def tokenize(readline: Callable[[], str], tokeneater: _TokenEater = ...) -> None: ... class Untokenizer: - tokens: List[Text] + tokens: list[str] prev_row: int prev_col: int def __init__(self) -> None: ... def add_whitespace(self, start: _Coord) -> None: ... - def untokenize(self, iterable: Iterable[_TokenInfo]) -> Text: ... - def compat(self, token: Tuple[int, Text], iterable: Iterable[_TokenInfo]) -> None: ... + def untokenize(self, iterable: Iterable[_TokenInfo]) -> str: ... + def compat(self, token: tuple[int, str], iterable: Iterable[_TokenInfo]) -> None: ... -def untokenize(iterable: Iterable[_TokenInfo]) -> Text: ... -def generate_tokens(readline: Callable[[], Text]) -> Iterator[_TokenInfo]: ... +def untokenize(iterable: Iterable[_TokenInfo]) -> str: ... +def generate_tokens(readline: Callable[[], str]) -> Iterator[_TokenInfo]: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/lib2to3/pytree.pyi index 955763588cd1..eab82cbc200d 100644 --- a/mypy/typeshed/stdlib/lib2to3/pytree.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pytree.pyi @@ -1,23 +1,22 @@ -import sys from lib2to3.pgen2.grammar import Grammar -from typing import Any, Callable, Dict, Iterator, List, Optional, Text, Tuple, TypeVar, Union +from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, TypeVar, Union _P = TypeVar("_P") _NL = Union[Node, Leaf] -_Context = Tuple[Text, int, int] -_Results = Dict[Text, _NL] -_RawNode = Tuple[int, Text, _Context, Optional[List[_NL]]] +_Context = Tuple[str, int, int] +_Results = Dict[str, _NL] +_RawNode = Tuple[int, str, _Context, Optional[List[_NL]]] _Convert = Callable[[Grammar, _RawNode], Any] HUGE: int -def type_repr(type_num: int) -> Text: ... +def type_repr(type_num: int) -> str: ... class Base: type: int - parent: Optional[Node] - prefix: Text - children: List[_NL] + parent: Node | None + prefix: str + children: list[_NL] was_changed: bool was_checked: bool def __eq__(self, other: Any) -> bool: ... @@ -25,30 +24,27 @@ class Base: def clone(self: _P) -> _P: ... def post_order(self) -> Iterator[_NL]: ... def pre_order(self) -> Iterator[_NL]: ... - def replace(self, new: Union[_NL, List[_NL]]) -> None: ... + def replace(self, new: _NL | list[_NL]) -> None: ... def get_lineno(self) -> int: ... def changed(self) -> None: ... - def remove(self) -> Optional[int]: ... + def remove(self) -> int | None: ... @property - def next_sibling(self) -> Optional[_NL]: ... + def next_sibling(self) -> _NL | None: ... @property - def prev_sibling(self) -> Optional[_NL]: ... + def prev_sibling(self) -> _NL | None: ... def leaves(self) -> Iterator[Leaf]: ... def depth(self) -> int: ... - def get_suffix(self) -> Text: ... - if sys.version_info < (3,): - def get_prefix(self) -> Text: ... - def set_prefix(self, prefix: Text) -> None: ... + def get_suffix(self) -> str: ... class Node(Base): - fixers_applied: List[Any] + fixers_applied: list[Any] def __init__( self, type: int, - children: List[_NL], - context: Optional[Any] = ..., - prefix: Optional[Text] = ..., - fixers_applied: Optional[List[Any]] = ..., + children: list[_NL], + context: Any | None = ..., + prefix: str | None = ..., + fixers_applied: list[Any] | None = ..., ) -> None: ... def set_child(self, i: int, child: _NL) -> None: ... def insert_child(self, i: int, child: _NL) -> None: ... @@ -57,41 +53,36 @@ class Node(Base): class Leaf(Base): lineno: int column: int - value: Text - fixers_applied: List[Any] + value: str + fixers_applied: list[Any] def __init__( - self, - type: int, - value: Text, - context: Optional[_Context] = ..., - prefix: Optional[Text] = ..., - fixers_applied: List[Any] = ..., + self, type: int, value: str, context: _Context | None = ..., prefix: str | None = ..., fixers_applied: list[Any] = ... ) -> None: ... def convert(gr: Grammar, raw_node: _RawNode) -> _NL: ... class BasePattern: type: int - content: Optional[Text] - name: Optional[Text] + content: str | None + name: str | None def optimize(self) -> BasePattern: ... # sic, subclasses are free to optimize themselves into different patterns - def match(self, node: _NL, results: Optional[_Results] = ...) -> bool: ... - def match_seq(self, nodes: List[_NL], results: Optional[_Results] = ...) -> bool: ... - def generate_matches(self, nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... + def match(self, node: _NL, results: _Results | None = ...) -> bool: ... + def match_seq(self, nodes: list[_NL], results: _Results | None = ...) -> bool: ... + def generate_matches(self, nodes: list[_NL]) -> Iterator[tuple[int, _Results]]: ... class LeafPattern(BasePattern): - def __init__(self, type: Optional[int] = ..., content: Optional[Text] = ..., name: Optional[Text] = ...) -> None: ... + def __init__(self, type: int | None = ..., content: str | None = ..., name: str | None = ...) -> None: ... class NodePattern(BasePattern): wildcards: bool - def __init__(self, type: Optional[int] = ..., content: Optional[Text] = ..., name: Optional[Text] = ...) -> None: ... + def __init__(self, type: int | None = ..., content: str | None = ..., name: str | None = ...) -> None: ... class WildcardPattern(BasePattern): min: int max: int - def __init__(self, content: Optional[Text] = ..., min: int = ..., max: int = ..., name: Optional[Text] = ...) -> None: ... + def __init__(self, content: str | None = ..., min: int = ..., max: int = ..., name: str | None = ...) -> None: ... class NegatedPattern(BasePattern): - def __init__(self, content: Optional[Text] = ...) -> None: ... + def __init__(self, content: str | None = ...) -> None: ... -def generate_matches(patterns: List[BasePattern], nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... +def generate_matches(patterns: list[BasePattern], nodes: list[_NL]) -> Iterator[tuple[int, _Results]]: ... diff --git a/mypy/typeshed/stdlib/lib2to3/refactor.pyi b/mypy/typeshed/stdlib/lib2to3/refactor.pyi new file mode 100644 index 000000000000..6687092d862c --- /dev/null +++ b/mypy/typeshed/stdlib/lib2to3/refactor.pyi @@ -0,0 +1,70 @@ +from collections.abc import Container, Generator, Iterable, Mapping +from logging import Logger +from typing import Any, ClassVar, NoReturn + +from .pgen2.grammar import Grammar + +_Driver = Any # really lib2to3.driver.Driver +_BottomMatcher = Any # really lib2to3.btm_matcher.BottomMatcher + +def get_all_fix_names(fixer_pkg: str, remove_prefix: bool = ...) -> list[str]: ... +def get_fixers_from_package(pkg_name: str) -> list[str]: ... + +class FixerError(Exception): ... + +class RefactoringTool: + CLASS_PREFIX: ClassVar[str] + FILE_PREFIX: ClassVar[str] + fixers: Iterable[str] + explicit: Container[str] + options: dict[str, Any] + grammar: Grammar + write_unchanged_files: bool + errors: list[Any] + logger: Logger + fixer_log: list[Any] + wrote: bool + driver: _Driver + pre_order: Any + post_order: Any + files: list[Any] + BM: _BottomMatcher + bmi_pre_order: list[Any] + bmi_post_order: list[Any] + def __init__( + self, fixer_names: Iterable[str], options: Mapping[str, Any] | None = ..., explicit: Container[str] | None = ... + ) -> None: ... + def get_fixers(self) -> tuple[list[Any], list[Any]]: ... + def log_error(self, msg: str, *args: Any, **kwds: Any) -> NoReturn: ... + def log_message(self, msg: str, *args: Any) -> None: ... + def log_debug(self, msg: str, *args: Any) -> None: ... + def print_output(self, old_text: str, new_text: str, filename: str, equal): ... + def refactor(self, items: Iterable[str], write: bool = ..., doctests_only: bool = ...) -> None: ... + def refactor_dir(self, dir_name: str, write: bool = ..., doctests_only: bool = ...) -> None: ... + def _read_python_source(self, filename: str) -> tuple[str, str]: ... + def refactor_file(self, filename: str, write: bool = ..., doctests_only: bool = ...) -> None: ... + def refactor_string(self, data: str, name: str): ... + def refactor_stdin(self, doctests_only: bool = ...) -> None: ... + def refactor_tree(self, tree, name: str) -> bool: ... + def traverse_by(self, fixers, traversal) -> None: ... + def processed_file( + self, new_text: str, filename: str, old_text: str | None = ..., write: bool = ..., encoding: str | None = ... + ) -> None: ... + def write_file(self, new_text: str, filename: str, old_text: str, encoding: str | None = ...) -> None: ... + PS1: ClassVar[str] + PS2: ClassVar[str] + def refactor_docstring(self, input: str, filename: str) -> str: ... + def refactor_doctest(self, block: list[str], lineno: int, indent: int, filename: str) -> list[str]: ... + def summarize(self) -> None: ... + def parse_block(self, block: Iterable[str], lineno: int, indent: int): ... + def wrap_toks( + self, block: Iterable[str], lineno: int, indent: int + ) -> Generator[tuple[Any, Any, tuple[int, int], tuple[int, int], str], None, None]: ... + def gen_lines(self, block: Iterable[str], indent: int) -> Generator[str, None, None]: ... + +class MultiprocessingUnsupported(Exception): ... + +class MultiprocessRefactoringTool(RefactoringTool): + queue: Any | None + output_lock: Any | None + def refactor(self, items: Iterable[str], write: bool = ..., doctests_only: bool = ..., num_processes: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/linecache.pyi b/mypy/typeshed/stdlib/linecache.pyi index f52267bdba98..a66614bf6b37 100644 --- a/mypy/typeshed/stdlib/linecache.pyi +++ b/mypy/typeshed/stdlib/linecache.pyi @@ -1,13 +1,16 @@ -import sys -from typing import Any, Dict, List, Optional, Text +from typing import Any, Dict, List, Protocol, Tuple _ModuleGlobals = Dict[str, Any] +_ModuleMetadata = Tuple[int, float, List[str], str] -def getline(filename: Text, lineno: int, module_globals: Optional[_ModuleGlobals] = ...) -> str: ... -def clearcache() -> None: ... -def getlines(filename: Text, module_globals: Optional[_ModuleGlobals] = ...) -> List[str]: ... -def checkcache(filename: Optional[Text] = ...) -> None: ... -def updatecache(filename: Text, module_globals: Optional[_ModuleGlobals] = ...) -> List[str]: ... +class _SourceLoader(Protocol): + def __call__(self) -> str | None: ... + +cache: dict[str, _SourceLoader | _ModuleMetadata] # undocumented -if sys.version_info >= (3, 5): - def lazycache(filename: Text, module_globals: _ModuleGlobals) -> bool: ... +def getline(filename: str, lineno: int, module_globals: _ModuleGlobals | None = ...) -> str: ... +def clearcache() -> None: ... +def getlines(filename: str, module_globals: _ModuleGlobals | None = ...) -> list[str]: ... +def checkcache(filename: str | None = ...) -> None: ... +def updatecache(filename: str, module_globals: _ModuleGlobals | None = ...) -> list[str]: ... +def lazycache(filename: str, module_globals: _ModuleGlobals) -> bool: ... diff --git a/mypy/typeshed/stdlib/locale.pyi b/mypy/typeshed/stdlib/locale.pyi index 9be4aa2735e1..1f80c8a62483 100644 --- a/mypy/typeshed/stdlib/locale.pyi +++ b/mypy/typeshed/stdlib/locale.pyi @@ -1,18 +1,18 @@ import sys -from decimal import Decimal -from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Union -# workaround for mypy#2010 -if sys.version_info >= (3, 0): - from builtins import str as _str -else: - from __builtin__ import str as _str +# This module defines a function "str()", which is why "str" can't be used +# as a type annotation or type alias. +from builtins import str as _str +from decimal import Decimal +from typing import Any, Callable, Iterable, Mapping, Sequence, Tuple CODESET: int D_T_FMT: int D_FMT: int T_FMT: int T_FMT_AMPM: int +AM_STR: int +PM_STR: int DAY_1: int DAY_2: int @@ -79,17 +79,17 @@ CHAR_MAX: int class Error(Exception): ... -def setlocale(category: int, locale: Union[_str, Iterable[_str], None] = ...) -> _str: ... -def localeconv() -> Mapping[_str, Union[int, _str, List[int]]]: ... +def setlocale(category: int, locale: _str | Iterable[_str] | None = ...) -> _str: ... +def localeconv() -> Mapping[_str, int | _str | list[int]]: ... def nl_langinfo(__key: int) -> _str: ... -def getdefaultlocale(envvars: Tuple[_str, ...] = ...) -> Tuple[Optional[_str], Optional[_str]]: ... +def getdefaultlocale(envvars: Tuple[_str, ...] = ...) -> tuple[_str | None, _str | None]: ... def getlocale(category: int = ...) -> Sequence[_str]: ... def getpreferredencoding(do_setlocale: bool = ...) -> _str: ... def normalize(localename: _str) -> _str: ... def resetlocale(category: int = ...) -> None: ... def strcoll(string1: _str, string2: _str) -> int: ... def strxfrm(string: _str) -> _str: ... -def format(percent: _str, value: Union[float, Decimal], grouping: bool = ..., monetary: bool = ..., *additional: Any) -> _str: ... +def format(percent: _str, value: float | Decimal, grouping: bool = ..., monetary: bool = ..., *additional: Any) -> _str: ... if sys.version_info >= (3, 7): def format_string(f: _str, val: Any, grouping: bool = ..., monetary: bool = ...) -> _str: ... @@ -97,15 +97,12 @@ if sys.version_info >= (3, 7): else: def format_string(f: _str, val: Any, grouping: bool = ...) -> _str: ... -def currency(val: Union[int, float, Decimal], symbol: bool = ..., grouping: bool = ..., international: bool = ...) -> _str: ... - -if sys.version_info >= (3, 5): - def delocalize(string: _str) -> _str: ... - +def currency(val: int | float | Decimal, symbol: bool = ..., grouping: bool = ..., international: bool = ...) -> _str: ... +def delocalize(string: _str) -> _str: ... def atof(string: _str, func: Callable[[_str], float] = ...) -> float: ... def atoi(string: _str) -> int: ... def str(val: float) -> _str: ... -locale_alias: Dict[_str, _str] # undocumented -locale_encoding_alias: Dict[_str, _str] # undocumented -windows_locale: Dict[int, _str] # undocumented +locale_alias: dict[_str, _str] # undocumented +locale_encoding_alias: dict[_str, _str] # undocumented +windows_locale: dict[int, _str] # undocumented diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index 1cce244e5798..c972559c9b60 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -2,22 +2,25 @@ import sys import threading from _typeshed import StrPath, SupportsWrite from collections.abc import Callable, Iterable, Mapping, MutableMapping, Sequence +from io import TextIOWrapper from string import Template from time import struct_time from types import FrameType, TracebackType -from typing import IO, Any, ClassVar, Optional, Pattern, Tuple, Type, Union +from typing import Any, ClassVar, Generic, Optional, Pattern, TextIO, Tuple, Type, TypeVar, Union, overload +from typing_extensions import Literal _SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, Optional[TracebackType]], Tuple[None, None, None]] _ExcInfoType = Union[None, bool, _SysExcInfoType, BaseException] -_ArgsType = Union[Tuple[Any, ...], Mapping[str, Any]] +_ArgsType = Union[Tuple[object, ...], Mapping[str, object]] _FilterType = Union[Filter, Callable[[LogRecord], int]] _Level = Union[int, str] +_FormatStyle = Literal["%", "{", "$"] raiseExceptions: bool logThreads: bool logMultiprocessing: bool logProcesses: bool -_srcfile: Optional[str] +_srcfile: str | None def currentframe() -> FrameType: ... @@ -35,9 +38,9 @@ class Manager(object): # undocumented root: RootLogger disable: int emittedNoHandlerWarning: bool - loggerDict: dict[str, Union[Logger, PlaceHolder]] - loggerClass: Optional[Type[Logger]] - logRecordFactory: Optional[Callable[..., LogRecord]] + loggerDict: dict[str, Logger | PlaceHolder] + loggerClass: Type[Logger] | None + logRecordFactory: Callable[..., LogRecord] | None def __init__(self, rootnode: RootLogger) -> None: ... def getLogger(self, name: str) -> Logger: ... def setLoggerClass(self, klass: Type[Logger]) -> None: ... @@ -46,7 +49,7 @@ class Manager(object): # undocumented class Logger(Filterer): name: str # undocumented level: int # undocumented - parent: Optional[Logger] # undocumented + parent: Logger | None # undocumented propagate: bool handlers: list[Handler] # undocumented disabled: bool # undocumented @@ -60,176 +63,160 @@ class Logger(Filterer): if sys.version_info >= (3, 8): def debug( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def info( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warning( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warn( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def error( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def exception( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def critical( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def log( self, level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def _log( self, level: int, - msg: Any, + msg: object, args: _ArgsType, - exc_info: Optional[_ExcInfoType] = ..., - extra: Optional[dict[str, Any]] = ..., + exc_info: _ExcInfoType | None = ..., + extra: Mapping[str, object] | None = ..., stack_info: bool = ..., stacklevel: int = ..., ) -> None: ... # undocumented else: def debug( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def info( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warning( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warn( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def error( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def critical( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def log( self, level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def exception( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def _log( self, level: int, - msg: Any, + msg: object, args: _ArgsType, - exc_info: Optional[_ExcInfoType] = ..., - extra: Optional[dict[str, Any]] = ..., + exc_info: _ExcInfoType | None = ..., + extra: Mapping[str, object] | None = ..., stack_info: bool = ..., ) -> None: ... # undocumented fatal = critical @@ -237,9 +224,9 @@ class Logger(Filterer): def addHandler(self, hdlr: Handler) -> None: ... def removeHandler(self, hdlr: Handler) -> None: ... if sys.version_info >= (3, 8): - def findCaller(self, stack_info: bool = ..., stacklevel: int = ...) -> tuple[str, int, str, Optional[str]]: ... + def findCaller(self, stack_info: bool = ..., stacklevel: int = ...) -> tuple[str, int, str, str | None]: ... else: - def findCaller(self, stack_info: bool = ...) -> tuple[str, int, str, Optional[str]]: ... + def findCaller(self, stack_info: bool = ...) -> tuple[str, int, str, str | None]: ... def handle(self, record: LogRecord) -> None: ... def makeRecord( self, @@ -247,12 +234,12 @@ class Logger(Filterer): level: int, fn: str, lno: int, - msg: Any, + msg: object, args: _ArgsType, - exc_info: Optional[_SysExcInfoType], - func: Optional[str] = ..., - extra: Optional[Mapping[str, Any]] = ..., - sinfo: Optional[str] = ..., + exc_info: _SysExcInfoType | None, + func: str | None = ..., + extra: Mapping[str, object] | None = ..., + sinfo: str | None = ..., ) -> LogRecord: ... def hasHandlers(self) -> bool: ... def callHandlers(self, record: LogRecord) -> None: ... # undocumented @@ -268,9 +255,9 @@ NOTSET: int class Handler(Filterer): level: int # undocumented - formatter: Optional[Formatter] # undocumented - lock: Optional[threading.Lock] # undocumented - name: Optional[str] # undocumented + formatter: Formatter | None # undocumented + lock: threading.Lock | None # undocumented + name: str | None # undocumented def __init__(self, level: _Level = ...) -> None: ... def get_name(self) -> str: ... # undocumented def set_name(self, name: str) -> None: ... # undocumented @@ -278,7 +265,7 @@ class Handler(Filterer): def acquire(self) -> None: ... def release(self) -> None: ... def setLevel(self, level: _Level) -> None: ... - def setFormatter(self, fmt: Optional[Formatter]) -> None: ... + def setFormatter(self, fmt: Formatter | None) -> None: ... def filter(self, record: LogRecord) -> bool: ... def flush(self) -> None: ... def close(self) -> None: ... @@ -288,24 +275,24 @@ class Handler(Filterer): def emit(self, record: LogRecord) -> None: ... class Formatter: - converter: Callable[[Optional[float]], struct_time] - _fmt: Optional[str] # undocumented - datefmt: Optional[str] # undocumented + converter: Callable[[float | None], struct_time] + _fmt: str | None # undocumented + datefmt: str | None # undocumented _style: PercentStyle # undocumented default_time_format: str if sys.version_info >= (3, 9): - default_msec_format: Optional[str] + default_msec_format: str | None else: default_msec_format: str if sys.version_info >= (3, 8): def __init__( - self, fmt: Optional[str] = ..., datefmt: Optional[str] = ..., style: str = ..., validate: bool = ... + self, fmt: str | None = ..., datefmt: str | None = ..., style: _FormatStyle = ..., validate: bool = ... ) -> None: ... else: - def __init__(self, fmt: Optional[str] = ..., datefmt: Optional[str] = ..., style: str = ...) -> None: ... + def __init__(self, fmt: str | None = ..., datefmt: str | None = ..., style: _FormatStyle = ...) -> None: ... def format(self, record: LogRecord) -> str: ... - def formatTime(self, record: LogRecord, datefmt: Optional[str] = ...) -> str: ... + def formatTime(self, record: LogRecord, datefmt: str | None = ...) -> str: ... def formatException(self, ei: _SysExcInfoType) -> str: ... def formatMessage(self, record: LogRecord) -> str: ... # undocumented def formatStack(self, stack_info: str) -> str: ... @@ -313,7 +300,7 @@ class Formatter: class BufferingFormatter: linefmt: Formatter - def __init__(self, linefmt: Optional[Formatter] = ...) -> None: ... + def __init__(self, linefmt: Formatter | None = ...) -> None: ... def formatHeader(self, records: Sequence[LogRecord]) -> str: ... def formatFooter(self, records: Sequence[LogRecord]) -> str: ... def format(self, records: Sequence[LogRecord]) -> str: ... @@ -325,11 +312,13 @@ class Filter: def filter(self, record: LogRecord) -> bool: ... class LogRecord: - args: _ArgsType + # args can be set to None by logging.handlers.QueueHandler + # (see https://bugs.python.org/issue44473) + args: _ArgsType | None asctime: str created: float - exc_info: Optional[_SysExcInfoType] - exc_text: Optional[str] + exc_info: _SysExcInfoType | None + exc_text: str | None filename: str funcName: str levelname: str @@ -341,191 +330,193 @@ class LogRecord: msg: str name: str pathname: str - process: Optional[int] - processName: Optional[str] + process: int | None + processName: str | None relativeCreated: float - stack_info: Optional[str] - thread: Optional[int] - threadName: Optional[str] + stack_info: str | None + thread: int | None + threadName: str | None def __init__( self, name: str, level: int, pathname: str, lineno: int, - msg: Any, - args: _ArgsType, - exc_info: Optional[_SysExcInfoType], - func: Optional[str] = ..., - sinfo: Optional[str] = ..., + msg: object, + args: _ArgsType | None, + exc_info: _SysExcInfoType | None, + func: str | None = ..., + sinfo: str | None = ..., ) -> None: ... def getMessage(self) -> str: ... -class LoggerAdapter: - logger: Logger +_L = TypeVar("_L", Logger, LoggerAdapter[Logger], LoggerAdapter[Any]) + +class LoggerAdapter(Generic[_L]): + logger: _L manager: Manager # undocumented if sys.version_info >= (3, 10): - extra: Optional[Mapping[str, Any]] - def __init__(self, logger: Logger, extra: Optional[Mapping[str, Any]]) -> None: ... + extra: Mapping[str, object] | None + def __init__(self, logger: _L, extra: Mapping[str, object] | None) -> None: ... else: - extra: Mapping[str, Any] - def __init__(self, logger: Logger, extra: Mapping[str, Any]) -> None: ... + extra: Mapping[str, object] + def __init__(self, logger: _L, extra: Mapping[str, object]) -> None: ... def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> tuple[Any, MutableMapping[str, Any]]: ... if sys.version_info >= (3, 8): def debug( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def info( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def warning( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def warn( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def error( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def exception( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def critical( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def log( self, level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... else: def debug( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def info( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def warning( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def warn( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def error( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def exception( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def critical( self, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def log( self, level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., + **kwargs: object, ) -> None: ... def isEnabledFor(self, level: int) -> bool: ... def getEffectiveLevel(self) -> int: ... @@ -534,159 +525,115 @@ class LoggerAdapter: def _log( self, level: int, - msg: Any, + msg: object, args: _ArgsType, - exc_info: Optional[_ExcInfoType] = ..., - extra: Optional[dict[str, Any]] = ..., + exc_info: _ExcInfoType | None = ..., + extra: Mapping[str, object] | None = ..., stack_info: bool = ..., ) -> None: ... # undocumented @property def name(self) -> str: ... # undocumented -def getLogger(name: Optional[str] = ...) -> Logger: ... +def getLogger(name: str | None = ...) -> Logger: ... def getLoggerClass() -> Type[Logger]: ... def getLogRecordFactory() -> Callable[..., LogRecord]: ... if sys.version_info >= (3, 8): def debug( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def info( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warning( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def warn( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def error( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def critical( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def exception( - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... def log( level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., stacklevel: int = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... else: def debug( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def info( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def warning( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def warn( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def error( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def critical( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def exception( - msg: Any, - *args: Any, - exc_info: _ExcInfoType = ..., - stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + msg: object, *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., extra: Mapping[str, object] | None = ... ) -> None: ... def log( level: int, - msg: Any, - *args: Any, + msg: object, + *args: object, exc_info: _ExcInfoType = ..., stack_info: bool = ..., - extra: Optional[dict[str, Any]] = ..., - **kwargs: Any, + extra: Mapping[str, object] | None = ..., ) -> None: ... fatal = critical @@ -699,33 +646,49 @@ else: def addLevelName(level: int, levelName: str) -> None: ... def getLevelName(level: _Level) -> Any: ... -def makeLogRecord(dict: Mapping[str, Any]) -> LogRecord: ... +def makeLogRecord(dict: Mapping[str, object]) -> LogRecord: ... -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 9): + def basicConfig( + *, + filename: StrPath | None = ..., + filemode: str = ..., + format: str = ..., + datefmt: str | None = ..., + style: _FormatStyle = ..., + level: _Level | None = ..., + stream: SupportsWrite[str] | None = ..., + handlers: Iterable[Handler] | None = ..., + force: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + ) -> None: ... + +elif sys.version_info >= (3, 8): def basicConfig( *, - filename: Optional[StrPath] = ..., + filename: StrPath | None = ..., filemode: str = ..., format: str = ..., - datefmt: Optional[str] = ..., - style: str = ..., - level: Optional[_Level] = ..., - stream: Optional[SupportsWrite[str]] = ..., - handlers: Optional[Iterable[Handler]] = ..., + datefmt: str | None = ..., + style: _FormatStyle = ..., + level: _Level | None = ..., + stream: SupportsWrite[str] | None = ..., + handlers: Iterable[Handler] | None = ..., force: bool = ..., ) -> None: ... else: def basicConfig( *, - filename: Optional[StrPath] = ..., + filename: StrPath | None = ..., filemode: str = ..., format: str = ..., - datefmt: Optional[str] = ..., - style: str = ..., - level: Optional[_Level] = ..., - stream: Optional[SupportsWrite[str]] = ..., - handlers: Optional[Iterable[Handler]] = ..., + datefmt: str | None = ..., + style: _FormatStyle = ..., + level: _Level | None = ..., + stream: SupportsWrite[str] | None = ..., + handlers: Iterable[Handler] | None = ..., ) -> None: ... def shutdown(handlerList: Sequence[Any] = ...) -> None: ... # handlerList is undocumented @@ -733,33 +696,33 @@ def setLoggerClass(klass: Type[Logger]) -> None: ... def captureWarnings(capture: bool) -> None: ... def setLogRecordFactory(factory: Callable[..., LogRecord]) -> None: ... -lastResort: Optional[StreamHandler] +lastResort: StreamHandler[Any] | None + +_StreamT = TypeVar("_StreamT", bound=SupportsWrite[str]) -class StreamHandler(Handler): - stream: SupportsWrite[str] # undocumented +class StreamHandler(Handler, Generic[_StreamT]): + stream: _StreamT # undocumented terminator: str - def __init__(self, stream: Optional[SupportsWrite[str]] = ...) -> None: ... + @overload + def __init__(self: StreamHandler[TextIO], stream: None = ...) -> None: ... + @overload + def __init__(self: StreamHandler[_StreamT], stream: _StreamT) -> None: ... if sys.version_info >= (3, 7): - def setStream(self, stream: SupportsWrite[str]) -> Optional[SupportsWrite[str]]: ... + def setStream(self, stream: _StreamT) -> _StreamT | None: ... -class FileHandler(StreamHandler): +class FileHandler(StreamHandler[TextIOWrapper]): baseFilename: str # undocumented mode: str # undocumented - encoding: Optional[str] # undocumented + encoding: str | None # undocumented delay: bool # undocumented if sys.version_info >= (3, 9): - errors: Optional[str] # undocumented + errors: str | None # undocumented def __init__( - self, - filename: StrPath, - mode: str = ..., - encoding: Optional[str] = ..., - delay: bool = ..., - errors: Optional[str] = ..., + self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ..., errors: str | None = ... ) -> None: ... else: - def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ... - def _open(self) -> IO[Any]: ... + def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... + def _open(self) -> TextIOWrapper: ... # undocumented class NullHandler(Handler): ... diff --git a/mypy/typeshed/stdlib/logging/config.pyi b/mypy/typeshed/stdlib/logging/config.pyi index be2f2e68508d..8ee9e7b339b5 100644 --- a/mypy/typeshed/stdlib/logging/config.pyi +++ b/mypy/typeshed/stdlib/logging/config.pyi @@ -1,17 +1,19 @@ import sys -from _typeshed import AnyPath, StrPath +from _typeshed import StrOrBytesPath, StrPath from collections.abc import Callable from configparser import RawConfigParser from threading import Thread -from typing import IO, Any, Optional, Pattern, Union +from typing import IO, Any, Pattern, Sequence + +from . import _Level if sys.version_info >= (3, 8): - from typing import Literal + from typing import Literal, TypedDict else: - from typing_extensions import Literal + from typing_extensions import Literal, TypedDict if sys.version_info >= (3, 7): - _Path = AnyPath + _Path = StrOrBytesPath else: _Path = StrPath @@ -19,23 +21,48 @@ DEFAULT_LOGGING_CONFIG_PORT: int RESET_ERROR: int # undocumented IDENTIFIER: Pattern[str] # undocumented -def dictConfig(config: dict[str, Any]) -> None: ... +class _RootLoggerConfiguration(TypedDict, total=False): + level: _Level + filters: Sequence[str] + handlers: Sequence[str] + +class _LoggerConfiguration(_RootLoggerConfiguration, TypedDict, total=False): + propagate: bool + +class _OptionalDictConfigArgs(TypedDict, total=False): + # these two can have custom factories (key: `()`) which can have extra keys + formatters: dict[str, dict[str, Any]] + filters: dict[str, dict[str, Any]] + # type checkers would warn about extra keys if this was a TypedDict + handlers: dict[str, dict[str, Any]] + loggers: dict[str, _LoggerConfiguration] + root: _RootLoggerConfiguration | None + incremental: bool + disable_existing_loggers: bool + +class _DictConfigArgs(_OptionalDictConfigArgs, TypedDict): + version: Literal[1] + +# Accept dict[str, Any] to avoid false positives if called with a dict +# type, since dict types are not compatible with TypedDicts. +# +# Also accept a TypedDict type, to allow callers to use TypedDict +# types, and for somewhat stricter type checking of dict literals. +def dictConfig(config: _DictConfigArgs | dict[str, Any]) -> None: ... if sys.version_info >= (3, 10): def fileConfig( - fname: Union[_Path, IO[str], RawConfigParser], - defaults: Optional[dict[str, str]] = ..., + fname: _Path | IO[str] | RawConfigParser, + defaults: dict[str, str] | None = ..., disable_existing_loggers: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., ) -> None: ... else: def fileConfig( - fname: Union[_Path, IO[str], RawConfigParser], - defaults: Optional[dict[str, str]] = ..., - disable_existing_loggers: bool = ..., + fname: _Path | IO[str] | RawConfigParser, defaults: dict[str, str] | None = ..., disable_existing_loggers: bool = ... ) -> None: ... def valid_ident(s: str) -> Literal[True]: ... # undocumented -def listen(port: int = ..., verify: Optional[Callable[[bytes], Optional[bytes]]] = ...) -> Thread: ... +def listen(port: int = ..., verify: Callable[[bytes], bytes | None] | None = ...) -> Thread: ... def stopListening() -> None: ... diff --git a/mypy/typeshed/stdlib/logging/handlers.pyi b/mypy/typeshed/stdlib/logging/handlers.pyi index a60190ee5bce..5be624872a14 100644 --- a/mypy/typeshed/stdlib/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/logging/handlers.pyi @@ -5,8 +5,8 @@ import sys from _typeshed import StrPath from collections.abc import Callable from logging import FileHandler, Handler, LogRecord -from socket import SocketKind, SocketType -from typing import Any, ClassVar, Optional, Pattern, Union +from socket import SocketKind, socket +from typing import Any, ClassVar, Pattern if sys.version_info >= (3, 7): from queue import Queue, SimpleQueue @@ -25,33 +25,28 @@ class WatchedFileHandler(FileHandler): ino: int # undocumented if sys.version_info >= (3, 9): def __init__( - self, - filename: StrPath, - mode: str = ..., - encoding: Optional[str] = ..., - delay: bool = ..., - errors: Optional[str] = ..., + self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ..., errors: str | None = ... ) -> None: ... else: - def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ... + def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... def _statstream(self) -> None: ... # undocumented def reopenIfNeeded(self) -> None: ... class BaseRotatingHandler(FileHandler): - namer: Optional[Callable[[str], str]] - rotator: Optional[Callable[[str, str], None]] + namer: Callable[[str], str] | None + rotator: Callable[[str, str], None] | None if sys.version_info >= (3, 9): def __init__( - self, filename: StrPath, mode: str, encoding: Optional[str] = ..., delay: bool = ..., errors: Optional[str] = ... + self, filename: StrPath, mode: str, encoding: str | None = ..., delay: bool = ..., errors: str | None = ... ) -> None: ... else: - def __init__(self, filename: StrPath, mode: str, encoding: Optional[str] = ..., delay: bool = ...) -> None: ... + def __init__(self, filename: StrPath, mode: str, encoding: str | None = ..., delay: bool = ...) -> None: ... def rotation_filename(self, default_name: str) -> str: ... def rotate(self, source: str, dest: str) -> None: ... class RotatingFileHandler(BaseRotatingHandler): maxBytes: str # undocumented - backupCount: str # undocumented + backupCount: int # undocumented if sys.version_info >= (3, 9): def __init__( self, @@ -59,9 +54,9 @@ class RotatingFileHandler(BaseRotatingHandler): mode: str = ..., maxBytes: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., - errors: Optional[str] = ..., + errors: str | None = ..., ) -> None: ... else: def __init__( @@ -70,7 +65,7 @@ class RotatingFileHandler(BaseRotatingHandler): mode: str = ..., maxBytes: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., ) -> None: ... def doRollover(self) -> None: ... @@ -78,9 +73,9 @@ class RotatingFileHandler(BaseRotatingHandler): class TimedRotatingFileHandler(BaseRotatingHandler): when: str # undocumented - backupCount: str # undocumented + backupCount: int # undocumented utc: bool # undocumented - atTime: Optional[datetime.datetime] # undocumented + atTime: datetime.datetime | None # undocumented interval: int # undocumented suffix: str # undocumented dayOfWeek: int # undocumented @@ -93,11 +88,11 @@ class TimedRotatingFileHandler(BaseRotatingHandler): when: str = ..., interval: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., utc: bool = ..., - atTime: Optional[datetime.datetime] = ..., - errors: Optional[str] = ..., + atTime: datetime.datetime | None = ..., + errors: str | None = ..., ) -> None: ... else: def __init__( @@ -106,10 +101,10 @@ class TimedRotatingFileHandler(BaseRotatingHandler): when: str = ..., interval: int = ..., backupCount: int = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., delay: bool = ..., utc: bool = ..., - atTime: Optional[datetime.datetime] = ..., + atTime: datetime.datetime | None = ..., ) -> None: ... def doRollover(self) -> None: ... def shouldRollover(self, record: LogRecord) -> int: ... # undocumented @@ -118,22 +113,22 @@ class TimedRotatingFileHandler(BaseRotatingHandler): class SocketHandler(Handler): host: str # undocumented - port: Optional[int] # undocumented - address: Union[tuple[str, int], str] # undocumented - sock: Optional[SocketType] # undocumented + port: int | None # undocumented + address: tuple[str, int] | str # undocumented + sock: socket | None # undocumented closeOnError: bool # undocumented - retryTime: Optional[float] # undocumented + retryTime: float | None # undocumented retryStart: float # undocumented retryFactor: float # undocumented retryMax: float # undocumented - def __init__(self, host: str, port: Optional[int]) -> None: ... - def makeSocket(self, timeout: float = ...) -> SocketType: ... # timeout is undocumented + def __init__(self, host: str, port: int | None) -> None: ... + def makeSocket(self, timeout: float = ...) -> socket: ... # timeout is undocumented def makePickle(self, record: LogRecord) -> bytes: ... def send(self, s: bytes) -> None: ... def createSocket(self) -> None: ... class DatagramHandler(SocketHandler): - def makeSocket(self) -> SocketType: ... # type: ignore + def makeSocket(self) -> socket: ... # type: ignore class SysLogHandler(Handler): LOG_EMERG: int @@ -172,6 +167,7 @@ class SysLogHandler(Handler): LOG_LOCAL5: int LOG_LOCAL6: int LOG_LOCAL7: int + address: tuple[str, int] | str # undocumented unixsocket: bool # undocumented socktype: SocketKind # undocumented ident: str # undocumented @@ -180,14 +176,12 @@ class SysLogHandler(Handler): priority_names: ClassVar[dict[str, int]] # undocumented facility_names: ClassVar[dict[str, int]] # undocumented priority_map: ClassVar[dict[str, str]] # undocumented - def __init__( - self, address: Union[tuple[str, int], str] = ..., facility: int = ..., socktype: Optional[SocketKind] = ... - ) -> None: ... - def encodePriority(self, facility: Union[int, str], priority: Union[int, str]) -> int: ... + def __init__(self, address: tuple[str, int] | str = ..., facility: int = ..., socktype: SocketKind | None = ...) -> None: ... + def encodePriority(self, facility: int | str, priority: int | str) -> int: ... def mapPriority(self, levelName: str) -> str: ... class NTEventLogHandler(Handler): - def __init__(self, appname: str, dllname: Optional[str] = ..., logtype: str = ...) -> None: ... + def __init__(self, appname: str, dllname: str | None = ..., logtype: str = ...) -> None: ... def getEventCategory(self, record: LogRecord) -> int: ... # TODO correct return value? def getEventType(self, record: LogRecord) -> int: ... @@ -195,23 +189,23 @@ class NTEventLogHandler(Handler): class SMTPHandler(Handler): mailhost: str # undocumented - mailport: Optional[int] # undocumented - username: Optional[str] # undocumented + mailport: int | None # undocumented + username: str | None # undocumented # password only exists as an attribute if passed credentials is a tuple or list password: str # undocumented fromaddr: str # undocumented toaddrs: list[str] # undocumented subject: str # undocumented - secure: Union[tuple[()], tuple[str], tuple[str, str], None] # undocumented + secure: tuple[()] | tuple[str] | tuple[str, str] | None # undocumented timeout: float # undocumented def __init__( self, - mailhost: Union[str, tuple[str, int]], + mailhost: str | tuple[str, int], fromaddr: str, - toaddrs: Union[str, list[str]], + toaddrs: str | list[str], subject: str, - credentials: Optional[tuple[str, str]] = ..., - secure: Union[tuple[()], tuple[str], tuple[str, str], None] = ..., + credentials: tuple[str, str] | None = ..., + secure: tuple[()] | tuple[str] | tuple[str, str] | None = ..., timeout: float = ..., ) -> None: ... def getSubject(self, record: LogRecord) -> str: ... @@ -224,28 +218,26 @@ class BufferingHandler(Handler): class MemoryHandler(BufferingHandler): flushLevel: int # undocumented - target: Optional[Handler] # undocumented + target: Handler | None # undocumented flushOnClose: bool # undocumented - def __init__( - self, capacity: int, flushLevel: int = ..., target: Optional[Handler] = ..., flushOnClose: bool = ... - ) -> None: ... - def setTarget(self, target: Optional[Handler]) -> None: ... + def __init__(self, capacity: int, flushLevel: int = ..., target: Handler | None = ..., flushOnClose: bool = ...) -> None: ... + def setTarget(self, target: Handler | None) -> None: ... class HTTPHandler(Handler): host: str # undocumented url: str # undocumented method: str # undocumented secure: bool # undocumented - credentials: Optional[tuple[str, str]] # undocumented - context: Optional[ssl.SSLContext] # undocumented + credentials: tuple[str, str] | None # undocumented + context: ssl.SSLContext | None # undocumented def __init__( self, host: str, url: str, method: str = ..., secure: bool = ..., - credentials: Optional[tuple[str, str]] = ..., - context: Optional[ssl.SSLContext] = ..., + credentials: tuple[str, str] | None = ..., + context: ssl.SSLContext | None = ..., ) -> None: ... def mapLogRecord(self, record: LogRecord) -> dict[str, Any]: ... if sys.version_info >= (3, 9): @@ -253,8 +245,8 @@ class HTTPHandler(Handler): class QueueHandler(Handler): if sys.version_info >= (3, 7): - queue: Union[SimpleQueue[Any], Queue[Any]] # undocumented - def __init__(self, queue: Union[SimpleQueue[Any], Queue[Any]]) -> None: ... + queue: SimpleQueue[Any] | Queue[Any] # undocumented + def __init__(self, queue: SimpleQueue[Any] | Queue[Any]) -> None: ... else: queue: Queue[Any] # undocumented def __init__(self, queue: Queue[Any]) -> None: ... @@ -265,9 +257,9 @@ class QueueListener: handlers: tuple[Handler] # undocumented respect_handler_level: bool # undocumented if sys.version_info >= (3, 7): - queue: Union[SimpleQueue[Any], Queue[Any]] # undocumented + queue: SimpleQueue[Any] | Queue[Any] # undocumented def __init__( - self, queue: Union[SimpleQueue[Any], Queue[Any]], *handlers: Handler, respect_handler_level: bool = ... + self, queue: SimpleQueue[Any] | Queue[Any], *handlers: Handler, respect_handler_level: bool = ... ) -> None: ... else: queue: Queue[Any] # undocumented diff --git a/mypy/typeshed/stdlib/lzma.pyi b/mypy/typeshed/stdlib/lzma.pyi index 7290a25b3bcd..e1da3024c4ac 100644 --- a/mypy/typeshed/stdlib/lzma.pyi +++ b/mypy/typeshed/stdlib/lzma.pyi @@ -1,15 +1,14 @@ import io -from _typeshed import AnyPath, ReadableBuffer -from typing import IO, Any, Mapping, Optional, Sequence, TextIO, TypeVar, Union, overload -from typing_extensions import Literal +from _typeshed import ReadableBuffer, Self, StrOrBytesPath +from typing import IO, Any, Mapping, Sequence, TextIO, Union, overload +from typing_extensions import Literal, final _OpenBinaryWritingMode = Literal["w", "wb", "x", "xb", "a", "ab"] _OpenTextWritingMode = Literal["wt", "xt", "at"] -_PathOrFile = Union[AnyPath, IO[bytes]] +_PathOrFile = Union[StrOrBytesPath, IO[bytes]] _FilterChain = Sequence[Mapping[str, Any]] -_T = TypeVar("_T") FORMAT_AUTO: int FORMAT_XZ: int @@ -41,10 +40,9 @@ PRESET_DEFAULT: int PRESET_EXTREME: int # from _lzma.c +@final class LZMADecompressor(object): - def __init__( - self, format: Optional[int] = ..., memlimit: Optional[int] = ..., filters: Optional[_FilterChain] = ... - ) -> None: ... + def __init__(self, format: int | None = ..., memlimit: int | None = ..., filters: _FilterChain | None = ...) -> None: ... def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... @property def check(self) -> int: ... @@ -56,9 +54,10 @@ class LZMADecompressor(object): def needs_input(self) -> bool: ... # from _lzma.c +@final class LZMACompressor(object): def __init__( - self, format: Optional[int] = ..., check: int = ..., preset: Optional[int] = ..., filters: Optional[_FilterChain] = ... + self, format: int | None = ..., check: int = ..., preset: int | None = ..., filters: _FilterChain | None = ... ) -> None: ... def compress(self, __data: bytes) -> bytes: ... def flush(self) -> bytes: ... @@ -68,15 +67,15 @@ class LZMAError(Exception): ... class LZMAFile(io.BufferedIOBase, IO[bytes]): def __init__( self, - filename: Optional[_PathOrFile] = ..., + filename: _PathOrFile | None = ..., mode: str = ..., *, - format: Optional[int] = ..., + format: int | None = ..., check: int = ..., - preset: Optional[int] = ..., - filters: Optional[_FilterChain] = ..., + preset: int | None = ..., + filters: _FilterChain | None = ..., ) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def close(self) -> None: ... @property def closed(self) -> bool: ... @@ -85,9 +84,9 @@ class LZMAFile(io.BufferedIOBase, IO[bytes]): def readable(self) -> bool: ... def writable(self) -> bool: ... def peek(self, size: int = ...) -> bytes: ... - def read(self, size: Optional[int] = ...) -> bytes: ... + def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... - def readline(self, size: Optional[int] = ...) -> bytes: ... + def readline(self, size: int | None = ...) -> bytes: ... def write(self, data: ReadableBuffer) -> int: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... @@ -97,10 +96,10 @@ def open( filename: _PathOrFile, mode: Literal["r", "rb"] = ..., *, - format: Optional[int] = ..., + format: int | None = ..., check: Literal[-1] = ..., preset: None = ..., - filters: Optional[_FilterChain] = ..., + filters: _FilterChain | None = ..., encoding: None = ..., errors: None = ..., newline: None = ..., @@ -110,55 +109,55 @@ def open( filename: _PathOrFile, mode: _OpenBinaryWritingMode, *, - format: Optional[int] = ..., + format: int | None = ..., check: int = ..., - preset: Optional[int] = ..., - filters: Optional[_FilterChain] = ..., + preset: int | None = ..., + filters: _FilterChain | None = ..., encoding: None = ..., errors: None = ..., newline: None = ..., ) -> LZMAFile: ... @overload def open( - filename: AnyPath, + filename: StrOrBytesPath, mode: Literal["rt"], *, - format: Optional[int] = ..., + format: int | None = ..., check: Literal[-1] = ..., preset: None = ..., - filters: Optional[_FilterChain] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + filters: _FilterChain | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., ) -> TextIO: ... @overload def open( - filename: AnyPath, + filename: StrOrBytesPath, mode: _OpenTextWritingMode, *, - format: Optional[int] = ..., + format: int | None = ..., check: int = ..., - preset: Optional[int] = ..., - filters: Optional[_FilterChain] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + preset: int | None = ..., + filters: _FilterChain | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., ) -> TextIO: ... @overload def open( filename: _PathOrFile, mode: str, *, - format: Optional[int] = ..., + format: int | None = ..., check: int = ..., - preset: Optional[int] = ..., - filters: Optional[_FilterChain] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., -) -> Union[LZMAFile, TextIO]: ... + preset: int | None = ..., + filters: _FilterChain | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> LZMAFile | TextIO: ... def compress( - data: bytes, format: int = ..., check: int = ..., preset: Optional[int] = ..., filters: Optional[_FilterChain] = ... + data: bytes, format: int = ..., check: int = ..., preset: int | None = ..., filters: _FilterChain | None = ... ) -> bytes: ... -def decompress(data: bytes, format: int = ..., memlimit: Optional[int] = ..., filters: Optional[_FilterChain] = ...) -> bytes: ... +def decompress(data: bytes, format: int = ..., memlimit: int | None = ..., filters: _FilterChain | None = ...) -> bytes: ... def is_check_supported(__check_id: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/macpath.pyi b/mypy/typeshed/stdlib/macpath.pyi index 296f3a9ba151..2512e086b735 100644 --- a/mypy/typeshed/stdlib/macpath.pyi +++ b/mypy/typeshed/stdlib/macpath.pyi @@ -1,5 +1,4 @@ -import sys -from _typeshed import AnyPath, BytesPath, StrPath +from _typeshed import BytesPath, StrOrBytesPath, StrPath from genericpath import ( commonprefix as commonprefix, exists as exists, @@ -9,10 +8,11 @@ from genericpath import ( getsize as getsize, isdir as isdir, isfile as isfile, + samefile as samefile, + sameopenfile as sameopenfile, + samestat as samestat, ) - -if sys.version_info >= (3, 4): - from genericpath import samefile as samefile, sameopenfile as sameopenfile, samestat as samestat +from os import PathLike # Re-export common definitions from posixpath to reduce duplication from posixpath import ( @@ -32,73 +32,38 @@ from posixpath import ( splitext as splitext, supports_unicode_filenames as supports_unicode_filenames, ) -from typing import AnyStr, Optional, Text, Tuple, overload - -altsep: Optional[str] - -if sys.version_info >= (3, 6): - from os import PathLike - @overload - def basename(s: PathLike[AnyStr]) -> AnyStr: ... - @overload - def basename(s: AnyStr) -> AnyStr: ... - @overload - def dirname(s: PathLike[AnyStr]) -> AnyStr: ... - @overload - def dirname(s: AnyStr) -> AnyStr: ... - @overload - def normcase(path: PathLike[AnyStr]) -> AnyStr: ... - @overload - def normcase(path: AnyStr) -> AnyStr: ... - @overload - def normpath(s: PathLike[AnyStr]) -> AnyStr: ... - @overload - def normpath(s: AnyStr) -> AnyStr: ... - @overload - def realpath(path: PathLike[AnyStr]) -> AnyStr: ... - @overload - def realpath(path: AnyStr) -> AnyStr: ... - -else: - def basename(s: AnyStr) -> AnyStr: ... - def dirname(s: AnyStr) -> AnyStr: ... - def normcase(path: AnyStr) -> AnyStr: ... - def normpath(s: AnyStr) -> AnyStr: ... - def realpath(path: AnyStr) -> AnyStr: ... - -def islink(s: AnyPath) -> bool: ... - -if sys.version_info >= (3, 6): - # Mypy complains that the signatures overlap, but things seem to behave correctly anyway. - @overload - def join(s: StrPath, *paths: StrPath) -> Text: ... - @overload - def join(s: BytesPath, *paths: BytesPath) -> bytes: ... - -elif sys.version_info >= (3, 0): - def join(s: AnyStr, *paths: AnyStr) -> AnyStr: ... +from typing import AnyStr, overload -else: - # Make sure signatures are disjunct, and allow combinations of bytes and unicode. - # (Since Python 2 allows that, too) - # Note that e.g. os.path.join("a", "b", "c", "d", u"e") will still result in - # a type error. - @overload - def join(__p1: bytes, *p: bytes) -> bytes: ... - @overload - def join(__p1: bytes, __p2: bytes, __p3: bytes, __p4: Text, *p: AnyPath) -> Text: ... - @overload - def join(__p1: bytes, __p2: bytes, __p3: Text, *p: AnyPath) -> Text: ... - @overload - def join(__p1: bytes, __p2: Text, *p: AnyPath) -> Text: ... - @overload - def join(__p1: Text, *p: AnyPath) -> Text: ... +altsep: str | None -if sys.version_info >= (3, 6): - @overload - def split(s: PathLike[AnyStr]) -> Tuple[AnyStr, AnyStr]: ... - @overload - def split(s: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +@overload +def basename(s: PathLike[AnyStr]) -> AnyStr: ... +@overload +def basename(s: AnyStr) -> AnyStr: ... +@overload +def dirname(s: PathLike[AnyStr]) -> AnyStr: ... +@overload +def dirname(s: AnyStr) -> AnyStr: ... +@overload +def normcase(path: PathLike[AnyStr]) -> AnyStr: ... +@overload +def normcase(path: AnyStr) -> AnyStr: ... +@overload +def normpath(s: PathLike[AnyStr]) -> AnyStr: ... +@overload +def normpath(s: AnyStr) -> AnyStr: ... +@overload +def realpath(path: PathLike[AnyStr]) -> AnyStr: ... +@overload +def realpath(path: AnyStr) -> AnyStr: ... +def islink(s: StrOrBytesPath) -> bool: ... -else: - def split(s: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +# Mypy complains that the signatures overlap, but things seem to behave correctly anyway. +@overload +def join(s: StrPath, *paths: StrPath) -> str: ... +@overload +def join(s: BytesPath, *paths: BytesPath) -> bytes: ... +@overload +def split(s: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... +@overload +def split(s: AnyStr) -> tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/macurl2path.pyi b/mypy/typeshed/stdlib/macurl2path.pyi index 025820b44e89..6aac6dfeace5 100644 --- a/mypy/typeshed/stdlib/macurl2path.pyi +++ b/mypy/typeshed/stdlib/macurl2path.pyi @@ -1,5 +1,3 @@ -from typing import Union - def url2pathname(pathname: str) -> str: ... def pathname2url(pathname: str) -> str: ... -def _pncomp2url(component: Union[str, bytes]) -> str: ... +def _pncomp2url(component: str | bytes) -> str: ... diff --git a/mypy/typeshed/stdlib/mailbox.pyi b/mypy/typeshed/stdlib/mailbox.pyi index d968e7d77244..ffd9c3005cec 100644 --- a/mypy/typeshed/stdlib/mailbox.pyi +++ b/mypy/typeshed/stdlib/mailbox.pyi @@ -1,23 +1,18 @@ import email.message import sys -from _typeshed import AnyPath +from _typeshed import Self, StrOrBytesPath from types import TracebackType from typing import ( IO, Any, AnyStr, Callable, - Dict, Generic, Iterable, Iterator, - List, Mapping, - Optional, Protocol, Sequence, - Text, - Tuple, Type, TypeVar, Union, @@ -33,27 +28,29 @@ _MessageT = TypeVar("_MessageT", bound=Message) _MessageData = Union[email.message.Message, bytes, str, IO[str], IO[bytes]] class _HasIteritems(Protocol): - def iteritems(self) -> Iterator[Tuple[str, _MessageData]]: ... + def iteritems(self) -> Iterator[tuple[str, _MessageData]]: ... class _HasItems(Protocol): - def items(self) -> Iterator[Tuple[str, _MessageData]]: ... + def items(self) -> Iterator[tuple[str, _MessageData]]: ... linesep: bytes class Mailbox(Generic[_MessageT]): - _path: Union[bytes, str] # undocumented - _factory: Optional[Callable[[IO[Any]], _MessageT]] # undocumented - def __init__(self, path: AnyPath, factory: Optional[Callable[[IO[Any]], _MessageT]] = ..., create: bool = ...) -> None: ... + _path: bytes | str # undocumented + _factory: Callable[[IO[Any]], _MessageT] | None # undocumented + def __init__( + self, path: StrOrBytesPath, factory: Callable[[IO[Any]], _MessageT] | None = ..., create: bool = ... + ) -> None: ... def add(self, message: _MessageData) -> str: ... def remove(self, key: str) -> None: ... def __delitem__(self, key: str) -> None: ... def discard(self, key: str) -> None: ... def __setitem__(self, key: str, message: _MessageData) -> None: ... @overload - def get(self, key: str, default: None = ...) -> Optional[_MessageT]: ... + def get(self, key: str, default: None = ...) -> _MessageT | None: ... @overload - def get(self, key: str, default: _T) -> Union[_MessageT, _T]: ... + def get(self, key: str, default: _T) -> _MessageT | _T: ... def __getitem__(self, key: str) -> _MessageT: ... def get_message(self, key: str) -> _MessageT: ... def get_string(self, key: str) -> str: ... @@ -61,21 +58,21 @@ class Mailbox(Generic[_MessageT]): # As '_ProxyFile' doesn't implement the full IO spec, and BytesIO is incompatible with it, get_file return is Any here def get_file(self, key: str) -> Any: ... def iterkeys(self) -> Iterator[str]: ... - def keys(self) -> List[str]: ... + def keys(self) -> list[str]: ... def itervalues(self) -> Iterator[_MessageT]: ... def __iter__(self) -> Iterator[_MessageT]: ... - def values(self) -> List[_MessageT]: ... - def iteritems(self) -> Iterator[Tuple[str, _MessageT]]: ... - def items(self) -> List[Tuple[str, _MessageT]]: ... + def values(self) -> list[_MessageT]: ... + def iteritems(self) -> Iterator[tuple[str, _MessageT]]: ... + def items(self) -> list[tuple[str, _MessageT]]: ... def __contains__(self, key: str) -> bool: ... def __len__(self) -> int: ... def clear(self) -> None: ... @overload - def pop(self, key: str, default: None = ...) -> Optional[_MessageT]: ... + def pop(self, key: str, default: None = ...) -> _MessageT | None: ... @overload - def pop(self, key: str, default: _T = ...) -> Union[_MessageT, _T]: ... - def popitem(self) -> Tuple[str, _MessageT]: ... - def update(self, arg: Optional[Union[_HasIteritems, _HasItems, Iterable[Tuple[str, _MessageData]]]] = ...) -> None: ... + def pop(self, key: str, default: _T = ...) -> _MessageT | _T: ... + def popitem(self) -> tuple[str, _MessageT]: ... + def update(self, arg: _HasIteritems | _HasItems | Iterable[tuple[str, _MessageData]] | None = ...) -> None: ... def flush(self) -> None: ... def lock(self) -> None: ... def unlock(self) -> None: ... @@ -87,15 +84,15 @@ class Maildir(Mailbox[MaildirMessage]): colon: str def __init__( - self, dirname: AnyPath, factory: Optional[Callable[[IO[Any]], MaildirMessage]] = ..., create: bool = ... + self, dirname: StrOrBytesPath, factory: Callable[[IO[Any]], MaildirMessage] | None = ..., create: bool = ... ) -> None: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... - def list_folders(self) -> List[str]: ... - def get_folder(self, folder: Text) -> Maildir: ... - def add_folder(self, folder: Text) -> Maildir: ... - def remove_folder(self, folder: Text) -> None: ... + def list_folders(self) -> list[str]: ... + def get_folder(self, folder: str) -> Maildir: ... + def add_folder(self, folder: str) -> Maildir: ... + def remove_folder(self, folder: str) -> None: ... def clean(self) -> None: ... - def next(self) -> Optional[str]: ... + def next(self) -> str | None: ... class _singlefileMailbox(Mailbox[_MessageT]): ... @@ -105,29 +102,37 @@ class _mboxMMDF(_singlefileMailbox[_MessageT]): def get_string(self, key: str, from_: bool = ...) -> str: ... class mbox(_mboxMMDF[mboxMessage]): - def __init__(self, path: AnyPath, factory: Optional[Callable[[IO[Any]], mboxMessage]] = ..., create: bool = ...) -> None: ... + def __init__( + self, path: StrOrBytesPath, factory: Callable[[IO[Any]], mboxMessage] | None = ..., create: bool = ... + ) -> None: ... class MMDF(_mboxMMDF[MMDFMessage]): - def __init__(self, path: AnyPath, factory: Optional[Callable[[IO[Any]], MMDFMessage]] = ..., create: bool = ...) -> None: ... + def __init__( + self, path: StrOrBytesPath, factory: Callable[[IO[Any]], MMDFMessage] | None = ..., create: bool = ... + ) -> None: ... class MH(Mailbox[MHMessage]): - def __init__(self, path: AnyPath, factory: Optional[Callable[[IO[Any]], MHMessage]] = ..., create: bool = ...) -> None: ... + def __init__( + self, path: StrOrBytesPath, factory: Callable[[IO[Any]], MHMessage] | None = ..., create: bool = ... + ) -> None: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... - def list_folders(self) -> List[str]: ... - def get_folder(self, folder: AnyPath) -> MH: ... - def add_folder(self, folder: AnyPath) -> MH: ... - def remove_folder(self, folder: AnyPath) -> None: ... - def get_sequences(self) -> Dict[str, List[int]]: ... + def list_folders(self) -> list[str]: ... + def get_folder(self, folder: StrOrBytesPath) -> MH: ... + def add_folder(self, folder: StrOrBytesPath) -> MH: ... + def remove_folder(self, folder: StrOrBytesPath) -> None: ... + def get_sequences(self) -> dict[str, list[int]]: ... def set_sequences(self, sequences: Mapping[str, Sequence[int]]) -> None: ... def pack(self) -> None: ... class Babyl(_singlefileMailbox[BabylMessage]): - def __init__(self, path: AnyPath, factory: Optional[Callable[[IO[Any]], BabylMessage]] = ..., create: bool = ...) -> None: ... + def __init__( + self, path: StrOrBytesPath, factory: Callable[[IO[Any]], BabylMessage] | None = ..., create: bool = ... + ) -> None: ... def get_file(self, key: str) -> IO[bytes]: ... - def get_labels(self) -> List[str]: ... + def get_labels(self) -> list[str]: ... class Message(email.message.Message): - def __init__(self, message: Optional[_MessageData] = ...) -> None: ... + def __init__(self, message: _MessageData | None = ...) -> None: ... class MaildirMessage(Message): def get_subdir(self) -> str: ... @@ -143,9 +148,7 @@ class MaildirMessage(Message): class _mboxMMDFMessage(Message): def get_from(self) -> str: ... - def set_from( - self, from_: str, time_: Optional[Union[bool, Tuple[int, int, int, int, int, int, int, int, int]]] = ... - ) -> None: ... + def set_from(self, from_: str, time_: bool | tuple[int, int, int, int, int, int, int, int, int] | None = ...) -> None: ... def get_flags(self) -> str: ... def set_flags(self, flags: Iterable[str]) -> None: ... def add_flag(self, flag: str) -> None: ... @@ -154,13 +157,13 @@ class _mboxMMDFMessage(Message): class mboxMessage(_mboxMMDFMessage): ... class MHMessage(Message): - def get_sequences(self) -> List[str]: ... + def get_sequences(self) -> list[str]: ... def set_sequences(self, sequences: Iterable[str]) -> None: ... def add_sequence(self, sequence: str) -> None: ... def remove_sequence(self, sequence: str) -> None: ... class BabylMessage(Message): - def get_labels(self) -> List[str]: ... + def get_labels(self) -> list[str]: ... def set_labels(self, labels: Iterable[str]) -> None: ... def add_label(self, label: str) -> None: ... def remove_label(self, label: str) -> None: ... @@ -171,19 +174,17 @@ class BabylMessage(Message): class MMDFMessage(_mboxMMDFMessage): ... class _ProxyFile(Generic[AnyStr]): - def __init__(self, f: IO[AnyStr], pos: Optional[int] = ...) -> None: ... - def read(self, size: Optional[int] = ...) -> AnyStr: ... - def read1(self, size: Optional[int] = ...) -> AnyStr: ... - def readline(self, size: Optional[int] = ...) -> AnyStr: ... - def readlines(self, sizehint: Optional[int] = ...) -> List[AnyStr]: ... + def __init__(self, f: IO[AnyStr], pos: int | None = ...) -> None: ... + def read(self, size: int | None = ...) -> AnyStr: ... + def read1(self, size: int | None = ...) -> AnyStr: ... + def readline(self, size: int | None = ...) -> AnyStr: ... + def readlines(self, sizehint: int | None = ...) -> list[AnyStr]: ... def __iter__(self) -> Iterator[AnyStr]: ... def tell(self) -> int: ... def seek(self, offset: int, whence: int = ...) -> None: ... def close(self) -> None: ... - def __enter__(self) -> _ProxyFile[AnyStr]: ... - def __exit__( - self, exc_type: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[TracebackType] - ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... def readable(self) -> bool: ... def writable(self) -> bool: ... def seekable(self) -> bool: ... @@ -194,7 +195,7 @@ class _ProxyFile(Generic[AnyStr]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... class _PartialFile(_ProxyFile[AnyStr]): - def __init__(self, f: IO[AnyStr], start: Optional[int] = ..., stop: Optional[int] = ...) -> None: ... + def __init__(self, f: IO[AnyStr], start: int | None = ..., stop: int | None = ...) -> None: ... class Error(Exception): ... class NoSuchMailboxError(Error): ... diff --git a/mypy/typeshed/stdlib/mailcap.pyi b/mypy/typeshed/stdlib/mailcap.pyi index a65cc3a329d3..9eaa771ed3d3 100644 --- a/mypy/typeshed/stdlib/mailcap.pyi +++ b/mypy/typeshed/stdlib/mailcap.pyi @@ -1,8 +1,8 @@ -from typing import Dict, List, Mapping, Optional, Sequence, Tuple, Union +from typing import Dict, Mapping, Sequence, Union _Cap = Dict[str, Union[str, int]] def findmatch( - caps: Mapping[str, List[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... -) -> Tuple[Optional[str], Optional[_Cap]]: ... -def getcaps() -> Dict[str, List[_Cap]]: ... + caps: Mapping[str, list[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... +) -> tuple[str | None, _Cap | None]: ... +def getcaps() -> dict[str, list[_Cap]]: ... diff --git a/mypy/typeshed/stdlib/math.pyi b/mypy/typeshed/stdlib/math.pyi index 6f9a89996dc0..f92a3d94f978 100644 --- a/mypy/typeshed/stdlib/math.pyi +++ b/mypy/typeshed/stdlib/math.pyi @@ -1,121 +1,119 @@ import sys -from typing import Iterable, Optional, SupportsFloat, SupportsInt, Tuple, overload +from _typeshed import SupportsTrunc +from typing import Iterable, SupportsFloat, Union, overload +from typing_extensions import SupportsIndex + +if sys.version_info >= (3, 8): + _SupportsFloatOrIndex = Union[SupportsFloat, SupportsIndex] +else: + _SupportsFloatOrIndex = SupportsFloat e: float pi: float -if sys.version_info >= (3, 5): - inf: float - nan: float -if sys.version_info >= (3, 6): - tau: float - -def acos(__x: SupportsFloat) -> float: ... -def acosh(__x: SupportsFloat) -> float: ... -def asin(__x: SupportsFloat) -> float: ... -def asinh(__x: SupportsFloat) -> float: ... -def atan(__x: SupportsFloat) -> float: ... -def atan2(__y: SupportsFloat, __x: SupportsFloat) -> float: ... -def atanh(__x: SupportsFloat) -> float: ... - -if sys.version_info >= (3,): - def ceil(__x: SupportsFloat) -> int: ... - -else: - def ceil(__x: SupportsFloat) -> float: ... +inf: float +nan: float +tau: float + +def acos(__x: _SupportsFloatOrIndex) -> float: ... +def acosh(__x: _SupportsFloatOrIndex) -> float: ... +def asin(__x: _SupportsFloatOrIndex) -> float: ... +def asinh(__x: _SupportsFloatOrIndex) -> float: ... +def atan(__x: _SupportsFloatOrIndex) -> float: ... +def atan2(__y: _SupportsFloatOrIndex, __x: _SupportsFloatOrIndex) -> float: ... +def atanh(__x: _SupportsFloatOrIndex) -> float: ... +def ceil(__x: _SupportsFloatOrIndex) -> int: ... if sys.version_info >= (3, 8): - def comb(__n: int, __k: int) -> int: ... + def comb(__n: SupportsIndex, __k: SupportsIndex) -> int: ... -def copysign(__x: SupportsFloat, __y: SupportsFloat) -> float: ... -def cos(__x: SupportsFloat) -> float: ... -def cosh(__x: SupportsFloat) -> float: ... -def degrees(__x: SupportsFloat) -> float: ... +def copysign(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... +def cos(__x: _SupportsFloatOrIndex) -> float: ... +def cosh(__x: _SupportsFloatOrIndex) -> float: ... +def degrees(__x: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 8): - def dist(__p: Iterable[SupportsFloat], __q: Iterable[SupportsFloat]) -> float: ... + def dist(__p: Iterable[_SupportsFloatOrIndex], __q: Iterable[_SupportsFloatOrIndex]) -> float: ... -def erf(__x: SupportsFloat) -> float: ... -def erfc(__x: SupportsFloat) -> float: ... -def exp(__x: SupportsFloat) -> float: ... -def expm1(__x: SupportsFloat) -> float: ... -def fabs(__x: SupportsFloat) -> float: ... -def factorial(__x: SupportsInt) -> int: ... +def erf(__x: _SupportsFloatOrIndex) -> float: ... +def erfc(__x: _SupportsFloatOrIndex) -> float: ... +def exp(__x: _SupportsFloatOrIndex) -> float: ... +def expm1(__x: _SupportsFloatOrIndex) -> float: ... +def fabs(__x: _SupportsFloatOrIndex) -> float: ... -if sys.version_info >= (3,): - def floor(__x: SupportsFloat) -> int: ... +if sys.version_info >= (3, 8): + def factorial(__x: SupportsIndex) -> int: ... else: - def floor(__x: SupportsFloat) -> float: ... + def factorial(__x: int) -> int: ... -def fmod(__x: SupportsFloat, __y: SupportsFloat) -> float: ... -def frexp(__x: SupportsFloat) -> Tuple[float, int]: ... -def fsum(__seq: Iterable[float]) -> float: ... -def gamma(__x: SupportsFloat) -> float: ... +def floor(__x: _SupportsFloatOrIndex) -> int: ... +def fmod(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... +def frexp(__x: _SupportsFloatOrIndex) -> tuple[float, int]: ... +def fsum(__seq: Iterable[_SupportsFloatOrIndex]) -> float: ... +def gamma(__x: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 9): - def gcd(*integers: int) -> int: ... + def gcd(*integers: SupportsIndex) -> int: ... -elif sys.version_info >= (3, 5): - def gcd(__x: int, __y: int) -> int: ... +else: + def gcd(__x: SupportsIndex, __y: SupportsIndex) -> int: ... if sys.version_info >= (3, 8): - def hypot(*coordinates: SupportsFloat) -> float: ... + def hypot(*coordinates: _SupportsFloatOrIndex) -> float: ... else: - def hypot(__x: SupportsFloat, __y: SupportsFloat) -> float: ... - -if sys.version_info >= (3, 5): - def isclose(a: SupportsFloat, b: SupportsFloat, *, rel_tol: SupportsFloat = ..., abs_tol: SupportsFloat = ...) -> bool: ... - -def isinf(__x: SupportsFloat) -> bool: ... - -if sys.version_info >= (3,): - def isfinite(__x: SupportsFloat) -> bool: ... - -def isnan(__x: SupportsFloat) -> bool: ... + def hypot(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... + +def isclose( + a: _SupportsFloatOrIndex, + b: _SupportsFloatOrIndex, + *, + rel_tol: _SupportsFloatOrIndex = ..., + abs_tol: _SupportsFloatOrIndex = ..., +) -> bool: ... +def isinf(__x: _SupportsFloatOrIndex) -> bool: ... +def isfinite(__x: _SupportsFloatOrIndex) -> bool: ... +def isnan(__x: _SupportsFloatOrIndex) -> bool: ... if sys.version_info >= (3, 8): - def isqrt(__n: int) -> int: ... + def isqrt(__n: SupportsIndex) -> int: ... if sys.version_info >= (3, 9): - def lcm(*integers: int) -> int: ... - -def ldexp(__x: SupportsFloat, __i: int) -> float: ... -def lgamma(__x: SupportsFloat) -> float: ... -def log(x: SupportsFloat, base: SupportsFloat = ...) -> float: ... -def log10(__x: SupportsFloat) -> float: ... -def log1p(__x: SupportsFloat) -> float: ... - -if sys.version_info >= (3, 3): - def log2(__x: SupportsFloat) -> float: ... + def lcm(*integers: SupportsIndex) -> int: ... -def modf(__x: SupportsFloat) -> Tuple[float, float]: ... +def ldexp(__x: _SupportsFloatOrIndex, __i: int) -> float: ... +def lgamma(__x: _SupportsFloatOrIndex) -> float: ... +def log(x: _SupportsFloatOrIndex, base: _SupportsFloatOrIndex = ...) -> float: ... +def log10(__x: _SupportsFloatOrIndex) -> float: ... +def log1p(__x: _SupportsFloatOrIndex) -> float: ... +def log2(__x: _SupportsFloatOrIndex) -> float: ... +def modf(__x: _SupportsFloatOrIndex) -> tuple[float, float]: ... if sys.version_info >= (3, 9): - def nextafter(__x: SupportsFloat, __y: SupportsFloat) -> float: ... + def nextafter(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 8): - def perm(__n: int, __k: Optional[int] = ...) -> int: ... + def perm(__n: SupportsIndex, __k: SupportsIndex | None = ...) -> int: ... -def pow(__x: SupportsFloat, __y: SupportsFloat) -> float: ... +def pow(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 8): @overload - def prod(__iterable: Iterable[int], *, start: int = ...) -> int: ... # type: ignore + def prod(__iterable: Iterable[SupportsIndex], *, start: SupportsIndex = ...) -> int: ... # type: ignore @overload - def prod(__iterable: Iterable[SupportsFloat], *, start: SupportsFloat = ...) -> float: ... + def prod(__iterable: Iterable[_SupportsFloatOrIndex], *, start: _SupportsFloatOrIndex = ...) -> float: ... -def radians(__x: SupportsFloat) -> float: ... +def radians(__x: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 7): - def remainder(__x: SupportsFloat, __y: SupportsFloat) -> float: ... + def remainder(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... -def sin(__x: SupportsFloat) -> float: ... -def sinh(__x: SupportsFloat) -> float: ... -def sqrt(__x: SupportsFloat) -> float: ... -def tan(__x: SupportsFloat) -> float: ... -def tanh(__x: SupportsFloat) -> float: ... -def trunc(__x: SupportsFloat) -> int: ... +def sin(__x: _SupportsFloatOrIndex) -> float: ... +def sinh(__x: _SupportsFloatOrIndex) -> float: ... +def sqrt(__x: _SupportsFloatOrIndex) -> float: ... +def tan(__x: _SupportsFloatOrIndex) -> float: ... +def tanh(__x: _SupportsFloatOrIndex) -> float: ... +def trunc(__x: SupportsTrunc) -> int: ... if sys.version_info >= (3, 9): - def ulp(__x: SupportsFloat) -> float: ... + def ulp(__x: _SupportsFloatOrIndex) -> float: ... diff --git a/mypy/typeshed/stdlib/mimetypes.pyi b/mypy/typeshed/stdlib/mimetypes.pyi index f0cfac32cafd..90c87d2cf385 100644 --- a/mypy/typeshed/stdlib/mimetypes.pyi +++ b/mypy/typeshed/stdlib/mimetypes.pyi @@ -1,35 +1,35 @@ import sys -from typing import IO, Dict, List, Optional, Sequence, Text, Tuple, Union +from _typeshed import StrPath +from typing import IO, Sequence, Tuple if sys.version_info >= (3, 8): - from os import PathLike - def guess_type(url: Union[Text, PathLike[str]], strict: bool = ...) -> Tuple[Optional[str], Optional[str]]: ... + def guess_type(url: StrPath, strict: bool = ...) -> tuple[str | None, str | None]: ... else: - def guess_type(url: Text, strict: bool = ...) -> Tuple[Optional[str], Optional[str]]: ... + def guess_type(url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... -def guess_all_extensions(type: str, strict: bool = ...) -> List[str]: ... -def guess_extension(type: str, strict: bool = ...) -> Optional[str]: ... -def init(files: Optional[Sequence[str]] = ...) -> None: ... -def read_mime_types(file: str) -> Optional[Dict[str, str]]: ... +def guess_all_extensions(type: str, strict: bool = ...) -> list[str]: ... +def guess_extension(type: str, strict: bool = ...) -> str | None: ... +def init(files: Sequence[str] | None = ...) -> None: ... +def read_mime_types(file: str) -> dict[str, str] | None: ... def add_type(type: str, ext: str, strict: bool = ...) -> None: ... inited: bool -knownfiles: List[str] -suffix_map: Dict[str, str] -encodings_map: Dict[str, str] -types_map: Dict[str, str] -common_types: Dict[str, str] +knownfiles: list[str] +suffix_map: dict[str, str] +encodings_map: dict[str, str] +types_map: dict[str, str] +common_types: dict[str, str] class MimeTypes: - suffix_map: Dict[str, str] - encodings_map: Dict[str, str] - types_map: Tuple[Dict[str, str], Dict[str, str]] - types_map_inv: Tuple[Dict[str, str], Dict[str, str]] + suffix_map: dict[str, str] + encodings_map: dict[str, str] + types_map: tuple[dict[str, str], dict[str, str]] + types_map_inv: tuple[dict[str, str], dict[str, str]] def __init__(self, filenames: Tuple[str, ...] = ..., strict: bool = ...) -> None: ... - def guess_extension(self, type: str, strict: bool = ...) -> Optional[str]: ... - def guess_type(self, url: str, strict: bool = ...) -> Tuple[Optional[str], Optional[str]]: ... - def guess_all_extensions(self, type: str, strict: bool = ...) -> List[str]: ... + def guess_extension(self, type: str, strict: bool = ...) -> str | None: ... + def guess_type(self, url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... + def guess_all_extensions(self, type: str, strict: bool = ...) -> list[str]: ... def read(self, filename: str, strict: bool = ...) -> None: ... def readfp(self, fp: IO[str], strict: bool = ...) -> None: ... if sys.platform == "win32": diff --git a/mypy/typeshed/stdlib/mmap.pyi b/mypy/typeshed/stdlib/mmap.pyi index 0ba69e5896d7..4dd8f8cd2cdd 100644 --- a/mypy/typeshed/stdlib/mmap.pyi +++ b/mypy/typeshed/stdlib/mmap.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import ReadableBuffer -from typing import AnyStr, ContextManager, Generic, Iterable, Iterator, Optional, Sequence, Sized, Union, overload +from typing import ContextManager, Iterable, Iterator, NoReturn, Sized, overload ACCESS_DEFAULT: int ACCESS_READ: int @@ -24,11 +24,9 @@ if sys.platform != "win32": PAGESIZE: int -class _mmap(Generic[AnyStr]): +class mmap(ContextManager[mmap], Iterable[int], Sized): if sys.platform == "win32": - def __init__( - self, fileno: int, length: int, tagname: Optional[str] = ..., access: int = ..., offset: int = ... - ) -> None: ... + def __init__(self, fileno: int, length: int, tagname: str | None = ..., access: int = ..., offset: int = ...) -> None: ... else: def __init__( self, fileno: int, length: int, flags: int = ..., prot: int = ..., access: int = ..., offset: int = ... @@ -39,50 +37,33 @@ class _mmap(Generic[AnyStr]): else: def flush(self, offset: int = ..., size: int = ...) -> int: ... def move(self, dest: int, src: int, count: int) -> None: ... - def read_byte(self) -> AnyStr: ... - def readline(self) -> AnyStr: ... + def read_byte(self) -> int: ... + def readline(self) -> bytes: ... def resize(self, newsize: int) -> None: ... def seek(self, pos: int, whence: int = ...) -> None: ... def size(self) -> int: ... def tell(self) -> int: ... - def write_byte(self, byte: AnyStr) -> None: ... + def write_byte(self, byte: int) -> None: ... def __len__(self) -> int: ... - -if sys.version_info >= (3,): - class mmap(_mmap[bytes], ContextManager[mmap], Iterable[bytes], Sized): - closed: bool - if sys.version_info >= (3, 8) and sys.platform != "win32": - def madvise(self, option: int, start: int = ..., length: int = ...) -> None: ... - def find(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... - def rfind(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... - def read(self, n: Optional[int] = ...) -> bytes: ... - if sys.version_info >= (3, 6): - def write(self, bytes: ReadableBuffer) -> int: ... - else: - def write(self, bytes: ReadableBuffer) -> None: ... - @overload - def __getitem__(self, index: int) -> int: ... - @overload - def __getitem__(self, index: slice) -> bytes: ... - def __delitem__(self, index: Union[int, slice]) -> None: ... - @overload - def __setitem__(self, index: int, object: int) -> None: ... - @overload - def __setitem__(self, index: slice, object: bytes) -> None: ... - # Doesn't actually exist, but the object is actually iterable because it has __getitem__ and - # __len__, so we claim that there is also an __iter__ to help type checkers. - def __iter__(self) -> Iterator[bytes]: ... - -else: - class mmap(_mmap[bytes], Sequence[bytes]): - def find(self, string: bytes, start: int = ..., end: int = ...) -> int: ... - def rfind(self, string: bytes, start: int = ..., stop: int = ...) -> int: ... - def read(self, num: int) -> bytes: ... - def write(self, string: bytes) -> None: ... - def __getitem__(self, index: Union[int, slice]) -> bytes: ... - def __getslice__(self, i: Optional[int], j: Optional[int]) -> bytes: ... - def __delitem__(self, index: Union[int, slice]) -> None: ... - def __setitem__(self, index: Union[int, slice], object: bytes) -> None: ... + closed: bool + if sys.version_info >= (3, 8) and sys.platform != "win32": + def madvise(self, option: int, start: int = ..., length: int = ...) -> None: ... + def find(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... + def rfind(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... + def read(self, n: int | None = ...) -> bytes: ... + def write(self, bytes: ReadableBuffer) -> int: ... + @overload + def __getitem__(self, index: int) -> int: ... + @overload + def __getitem__(self, index: slice) -> bytes: ... + def __delitem__(self, index: int | slice) -> NoReturn: ... + @overload + def __setitem__(self, index: int, object: int) -> None: ... + @overload + def __setitem__(self, index: slice, object: ReadableBuffer) -> None: ... + # Doesn't actually exist, but the object is actually iterable because it has __getitem__ and + # __len__, so we claim that there is also an __iter__ to help type checkers. + def __iter__(self) -> Iterator[int]: ... if sys.version_info >= (3, 8) and sys.platform != "win32": MADV_NORMAL: int diff --git a/mypy/typeshed/stdlib/modulefinder.pyi b/mypy/typeshed/stdlib/modulefinder.pyi index 89119b6029df..e77a108e9525 100644 --- a/mypy/typeshed/stdlib/modulefinder.pyi +++ b/mypy/typeshed/stdlib/modulefinder.pyi @@ -1,51 +1,51 @@ import sys from types import CodeType -from typing import IO, Any, Container, Dict, Iterable, Iterator, List, Optional, Sequence, Tuple +from typing import IO, Any, Container, Iterable, Iterator, Sequence, Tuple LOAD_CONST: int # undocumented IMPORT_NAME: int # undocumented STORE_NAME: int # undocumented STORE_GLOBAL: int # undocumented -STORE_OPS: Tuple[int, int] # undocumented +STORE_OPS: tuple[int, int] # undocumented EXTENDED_ARG: int # undocumented -packagePathMap: Dict[str, List[str]] # undocumented +packagePathMap: dict[str, list[str]] # undocumented def AddPackagePath(packagename: str, path: str) -> None: ... -replacePackageMap: Dict[str, str] # undocumented +replacePackageMap: dict[str, str] # undocumented def ReplacePackage(oldname: str, newname: str) -> None: ... class Module: # undocumented - def __init__(self, name: str, file: Optional[str] = ..., path: Optional[str] = ...) -> None: ... + def __init__(self, name: str, file: str | None = ..., path: str | None = ...) -> None: ... def __repr__(self) -> str: ... class ModuleFinder: - modules: Dict[str, Module] - path: List[str] # undocumented - badmodules: Dict[str, Dict[str, int]] # undocumented + modules: dict[str, Module] + path: list[str] # undocumented + badmodules: dict[str, dict[str, int]] # undocumented debug: int # undocumented indent: int # undocumented excludes: Container[str] # undocumented - replace_paths: Sequence[Tuple[str, str]] # undocumented + replace_paths: Sequence[tuple[str, str]] # undocumented if sys.version_info >= (3, 8): def __init__( self, - path: Optional[List[str]] = ..., + path: list[str] | None = ..., debug: int = ..., - excludes: Optional[Container[str]] = ..., - replace_paths: Optional[Sequence[Tuple[str, str]]] = ..., + excludes: Container[str] | None = ..., + replace_paths: Sequence[tuple[str, str]] | None = ..., ) -> None: ... else: def __init__( self, - path: Optional[List[str]] = ..., + path: list[str] | None = ..., debug: int = ..., excludes: Container[str] = ..., - replace_paths: Sequence[Tuple[str, str]] = ..., + replace_paths: Sequence[tuple[str, str]] = ..., ) -> None: ... def msg(self, level: int, str: str, *args: Any) -> None: ... # undocumented def msgin(self, *args: Any) -> None: ... # undocumented @@ -53,24 +53,23 @@ class ModuleFinder: def run_script(self, pathname: str) -> None: ... def load_file(self, pathname: str) -> None: ... # undocumented def import_hook( - self, name: str, caller: Optional[Module] = ..., fromlist: Optional[List[str]] = ..., level: int = ... - ) -> Optional[Module]: ... # undocumented - def determine_parent(self, caller: Optional[Module], level: int = ...) -> Optional[Module]: ... # undocumented - def find_head_package(self, parent: Module, name: str) -> Tuple[Module, str]: ... # undocumented + self, name: str, caller: Module | None = ..., fromlist: list[str] | None = ..., level: int = ... + ) -> Module | None: ... # undocumented + def determine_parent(self, caller: Module | None, level: int = ...) -> Module | None: ... # undocumented + def find_head_package(self, parent: Module, name: str) -> tuple[Module, str]: ... # undocumented def load_tail(self, q: Module, tail: str) -> Module: ... # undocumented def ensure_fromlist(self, m: Module, fromlist: Iterable[str], recursive: int = ...) -> None: ... # undocumented def find_all_submodules(self, m: Module) -> Iterable[str]: ... # undocumented - def import_module(self, partname: str, fqname: str, parent: Module) -> Optional[Module]: ... # undocumented - def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: Tuple[str, str, str]) -> Module: ... # undocumented - if sys.version_info >= (3, 6): - def scan_opcodes(self, co: CodeType) -> Iterator[Tuple[str, Tuple[Any, ...]]]: ... # undocumented + def import_module(self, partname: str, fqname: str, parent: Module) -> Module | None: ... # undocumented + def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: tuple[str, str, str]) -> Module: ... # undocumented + def scan_opcodes(self, co: CodeType) -> Iterator[tuple[str, Tuple[Any, ...]]]: ... # undocumented def scan_code(self, co: CodeType, m: Module) -> None: ... # undocumented def load_package(self, fqname: str, pathname: str) -> Module: ... # undocumented def add_module(self, fqname: str) -> Module: ... # undocumented def find_module( - self, name: str, path: Optional[str], parent: Optional[Module] = ... - ) -> Tuple[Optional[IO[Any]], Optional[str], Tuple[str, str, int]]: ... # undocumented + self, name: str, path: str | None, parent: Module | None = ... + ) -> tuple[IO[Any] | None, str | None, tuple[str, str, int]]: ... # undocumented def report(self) -> None: ... - def any_missing(self) -> List[str]: ... # undocumented - def any_missing_maybe(self) -> Tuple[List[str], List[str]]: ... # undocumented + def any_missing(self) -> list[str]: ... # undocumented + def any_missing_maybe(self) -> tuple[list[str], list[str]]: ... # undocumented def replace_paths_in_code(self, co: CodeType) -> CodeType: ... # undocumented diff --git a/mypy/typeshed/stdlib/msilib/__init__.pyi b/mypy/typeshed/stdlib/msilib/__init__.pyi index 0442ffaaec83..4e1a7e6a7c02 100644 --- a/mypy/typeshed/stdlib/msilib/__init__.pyi +++ b/mypy/typeshed/stdlib/msilib/__init__.pyi @@ -1,6 +1,6 @@ import sys from types import ModuleType -from typing import Any, Container, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Type, Union +from typing import Any, Container, Iterable, Sequence, Tuple, Type from typing_extensions import Literal if sys.platform == "win32": @@ -25,17 +25,17 @@ if sys.platform == "win32": class Table: name: str - fields: List[Tuple[int, str, int]] + fields: list[tuple[int, str, int]] def __init__(self, name: str) -> None: ... def add_field(self, index: int, name: str, type: int) -> None: ... def sql(self) -> str: ... def create(self, db: _Database) -> None: ... class _Unspecified: ... def change_sequence( - seq: Sequence[Tuple[str, Optional[str], int]], + seq: Sequence[tuple[str, str | None, int]], action: str, - seqno: Union[int, Type[_Unspecified]] = ..., - cond: Union[str, Type[_Unspecified]] = ..., + seqno: int | Type[_Unspecified] = ..., + cond: str | Type[_Unspecified] = ..., ) -> None: ... def add_data(db: _Database, table: str, values: Iterable[Tuple[Any, ...]]) -> None: ... def add_stream(db: _Database, name: str, path: str) -> None: ... @@ -48,14 +48,14 @@ if sys.platform == "win32": class CAB: name: str - files: List[Tuple[str, str]] - filenames: Set[str] + files: list[tuple[str, str]] + filenames: set[str] index: int def __init__(self, name: str) -> None: ... def gen_id(self, file: str) -> str: ... - def append(self, full: str, file: str, logical: str) -> Tuple[int, str]: ... + def append(self, full: str, file: str, logical: str) -> tuple[int, str]: ... def commit(self, db: _Database) -> None: ... - _directories: Set[str] + _directories: set[str] class Directory: db: _Database @@ -63,11 +63,11 @@ if sys.platform == "win32": basedir: str physical: str logical: str - component: Optional[str] - short_names: Set[str] - ids: Set[str] - keyfiles: Dict[str, str] - componentflags: Optional[int] + component: str | None + short_names: set[str] + ids: set[str] + keyfiles: dict[str, str] + componentflags: int | None absolute: str def __init__( self, @@ -77,21 +77,19 @@ if sys.platform == "win32": physical: str, _logical: str, default: str, - componentflags: Optional[int] = ..., + componentflags: int | None = ..., ) -> None: ... def start_component( self, - component: Optional[str] = ..., - feature: Optional[Feature] = ..., - flags: Optional[int] = ..., - keyfile: Optional[str] = ..., - uuid: Optional[str] = ..., + component: str | None = ..., + feature: Feature | None = ..., + flags: int | None = ..., + keyfile: str | None = ..., + uuid: str | None = ..., ) -> None: ... def make_short(self, file: str) -> str: ... - def add_file( - self, file: str, src: Optional[str] = ..., version: Optional[str] = ..., language: Optional[str] = ... - ) -> str: ... - def glob(self, pattern: str, exclude: Optional[Container[str]] = ...) -> List[str]: ... + def add_file(self, file: str, src: str | None = ..., version: str | None = ..., language: str | None = ...) -> str: ... + def glob(self, pattern: str, exclude: Container[str] | None = ...) -> list[str]: ... def remove_pyc(self) -> None: ... class Binary: @@ -109,8 +107,8 @@ if sys.platform == "win32": desc: str, display: int, level: int = ..., - parent: Optional[Feature] = ..., - directory: Optional[str] = ..., + parent: Feature | None = ..., + directory: str | None = ..., attributes: int = ..., ) -> None: ... def set_current(self) -> None: ... @@ -119,7 +117,7 @@ if sys.platform == "win32": dlg: Dialog name: str def __init__(self, dlg: Dialog, name: str) -> None: ... - def event(self, event: str, argument: str, condition: str = ..., ordering: Optional[int] = ...) -> None: ... + def event(self, event: str, argument: str, condition: str = ..., ordering: int | None = ...) -> None: ... def mapping(self, event: str, attribute: str) -> None: ... def condition(self, action: str, condition: str) -> None: ... class RadioButtonGroup(Control): @@ -127,7 +125,7 @@ if sys.platform == "win32": property: str index: int def __init__(self, dlg: Dialog, name: str, property: str) -> None: ... - def add(self, name: str, x: int, y: int, w: int, h: int, text: str, value: Optional[str] = ...) -> None: ... + def add(self, name: str, x: int, y: int, w: int, h: int, text: str, value: str | None = ...) -> None: ... class Dialog: db: _Database @@ -159,38 +157,20 @@ if sys.platform == "win32": w: int, h: int, attr: int, - prop: Optional[str], - text: Optional[str], - next: Optional[str], - help: Optional[str], + prop: str | None, + text: str | None, + next: str | None, + help: str | None, ) -> Control: ... - def text(self, name: str, x: int, y: int, w: int, h: int, attr: int, text: Optional[str]) -> Control: ... - def bitmap(self, name: str, x: int, y: int, w: int, h: int, text: Optional[str]) -> Control: ... + def text(self, name: str, x: int, y: int, w: int, h: int, attr: int, text: str | None) -> Control: ... + def bitmap(self, name: str, x: int, y: int, w: int, h: int, text: str | None) -> Control: ... def line(self, name: str, x: int, y: int, w: int, h: int) -> Control: ... def pushbutton( - self, name: str, x: int, y: int, w: int, h: int, attr: int, text: Optional[str], next: Optional[str] + self, name: str, x: int, y: int, w: int, h: int, attr: int, text: str | None, next: str | None ) -> Control: ... def radiogroup( - self, - name: str, - x: int, - y: int, - w: int, - h: int, - attr: int, - prop: Optional[str], - text: Optional[str], - next: Optional[str], + self, name: str, x: int, y: int, w: int, h: int, attr: int, prop: str | None, text: str | None, next: str | None ) -> RadioButtonGroup: ... def checkbox( - self, - name: str, - x: int, - y: int, - w: int, - h: int, - attr: int, - prop: Optional[str], - text: Optional[str], - next: Optional[str], + self, name: str, x: int, y: int, w: int, h: int, attr: int, prop: str | None, text: str | None, next: str | None ) -> Control: ... diff --git a/mypy/typeshed/stdlib/msilib/schema.pyi b/mypy/typeshed/stdlib/msilib/schema.pyi index 10b65088cf80..4ad9a1783fcd 100644 --- a/mypy/typeshed/stdlib/msilib/schema.pyi +++ b/mypy/typeshed/stdlib/msilib/schema.pyi @@ -1,5 +1,4 @@ import sys -from typing import List, Optional, Tuple if sys.platform == "win32": from . import Table @@ -90,8 +89,6 @@ if sys.platform == "win32": Upgrade: Table Verb: Table - tables: List[Table] + tables: list[Table] - _Validation_records: List[ - Tuple[str, str, str, Optional[int], Optional[int], Optional[str], Optional[int], Optional[str], Optional[str], str] - ] + _Validation_records: list[tuple[str, str, str, int | None, int | None, str | None, int | None, str | None, str | None, str]] diff --git a/mypy/typeshed/stdlib/msilib/sequence.pyi b/mypy/typeshed/stdlib/msilib/sequence.pyi index e4f400d33233..123d232886f7 100644 --- a/mypy/typeshed/stdlib/msilib/sequence.pyi +++ b/mypy/typeshed/stdlib/msilib/sequence.pyi @@ -11,4 +11,4 @@ if sys.platform == "win32": InstallExecuteSequence: _SequenceType InstallUISequence: _SequenceType - tables: List[str] + tables: list[str] diff --git a/mypy/typeshed/stdlib/msilib/text.pyi b/mypy/typeshed/stdlib/msilib/text.pyi index e338b8b5ba3d..879429ecea85 100644 --- a/mypy/typeshed/stdlib/msilib/text.pyi +++ b/mypy/typeshed/stdlib/msilib/text.pyi @@ -1,9 +1,8 @@ import sys -from typing import List, Optional, Tuple if sys.platform == "win32": - ActionText: List[Tuple[str, str, Optional[str]]] - UIText: List[Tuple[str, Optional[str]]] + ActionText: list[tuple[str, str, str | None]] + UIText: list[tuple[str, str | None]] - tables: List[str] + tables: list[str] diff --git a/mypy/typeshed/stdlib/msvcrt.pyi b/mypy/typeshed/stdlib/msvcrt.pyi index ede80c9fbb66..0441ed8acd24 100644 --- a/mypy/typeshed/stdlib/msvcrt.pyi +++ b/mypy/typeshed/stdlib/msvcrt.pyi @@ -1,5 +1,4 @@ import sys -from typing import Text # This module is only available on Windows if sys.platform == "win32": @@ -14,11 +13,11 @@ if sys.platform == "win32": def get_osfhandle(__fd: int) -> int: ... def kbhit() -> bool: ... def getch() -> bytes: ... - def getwch() -> Text: ... + def getwch() -> str: ... def getche() -> bytes: ... - def getwche() -> Text: ... + def getwche() -> str: ... def putch(__char: bytes) -> None: ... - def putwch(__unicode_char: Text) -> None: ... + def putwch(__unicode_char: str) -> None: ... def ungetch(__char: bytes) -> None: ... - def ungetwch(__unicode_char: Text) -> None: ... + def ungetwch(__unicode_char: str) -> None: ... def heapmin() -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi index 161cc72c27d8..000fed79f3e4 100644 --- a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi @@ -15,10 +15,12 @@ from multiprocessing.context import ( from multiprocessing.managers import SyncManager from multiprocessing.process import active_children as active_children, current_process as current_process -# These are technically functions that return instances of these Queue classes. See #4313 for discussion +# These are technically functions that return instances of these Queue classes. +# Using them as annotations is deprecated. Either use imports from +# multiprocessing.queues or the aliases defined below. See #4266 for discussion. from multiprocessing.queues import JoinableQueue as JoinableQueue, Queue as Queue, SimpleQueue as SimpleQueue from multiprocessing.spawn import freeze_support as freeze_support -from typing import Any, Optional, Union, overload +from typing import Any, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 8): @@ -27,43 +29,63 @@ if sys.version_info >= (3, 8): if sys.platform != "win32": from multiprocessing.context import ForkContext, ForkServerContext +# The following type aliases can be used to annotate the return values of +# the corresponding functions. They are not defined at runtime. +# +# from multiprocessing import Lock +# from typing import TYPE_CHECKING +# if TYPE_CHECKING: +# from multiprocessing import _LockType +# lock: _LockType = Lock() + +_QueueType = Queue +_SimpleQueueType = SimpleQueue +_JoinableQueueType = JoinableQueue +_BarrierType = synchronize.Barrier +_BoundedSemaphoreType = synchronize.BoundedSemaphore +_ConditionType = synchronize.Condition +_EventType = synchronize.Event +_LockType = synchronize.Lock +_RLockType = synchronize.RLock +_SemaphoreType = synchronize.Semaphore + # N.B. The functions below are generated at runtime by partially applying # multiprocessing.context.BaseContext's methods, so the two signatures should # be identical (modulo self). -# Sychronization primitives +# Synchronization primitives _LockLike = Union[synchronize.Lock, synchronize.RLock] RawValue = context._default_context.RawValue RawArray = context._default_context.RawArray Value = context._default_context.Value Array = context._default_context.Array -def Barrier(parties: int, action: Optional[Callable[..., Any]] = ..., timeout: Optional[float] = ...) -> synchronize.Barrier: ... -def BoundedSemaphore(value: int = ...) -> synchronize.BoundedSemaphore: ... -def Condition(lock: Optional[_LockLike] = ...) -> synchronize.Condition: ... -def Event() -> synchronize.Event: ... -def Lock() -> synchronize.Lock: ... -def RLock() -> synchronize.RLock: ... -def Semaphore(value: int = ...) -> synchronize.Semaphore: ... +def Barrier(parties: int, action: Callable[..., Any] | None = ..., timeout: float | None = ...) -> _BarrierType: ... +def BoundedSemaphore(value: int = ...) -> _BoundedSemaphoreType: ... +def Condition(lock: _LockLike | None = ...) -> _ConditionType: ... +def Event() -> _EventType: ... +def Lock() -> _LockType: ... +def RLock() -> _RLockType: ... +def Semaphore(value: int = ...) -> _SemaphoreType: ... def Pipe(duplex: bool = ...) -> tuple[connection.Connection, connection.Connection]: ... def Pool( - processes: Optional[int] = ..., - initializer: Optional[Callable[..., Any]] = ..., + processes: int | None = ..., + initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ..., - maxtasksperchild: Optional[int] = ..., + maxtasksperchild: int | None = ..., ) -> pool.Pool: ... # ----- multiprocessing function stubs ----- def allow_connection_pickling() -> None: ... def cpu_count() -> int: ... def get_logger() -> Logger: ... -def log_to_stderr(level: Optional[Union[str, int]] = ...) -> Logger: ... +def log_to_stderr(level: str | int | None = ...) -> Logger: ... def Manager() -> SyncManager: ... def set_executable(executable: str) -> None: ... def set_forkserver_preload(module_names: list[str]) -> None: ... def get_all_start_methods() -> list[str]: ... -def get_start_method(allow_none: bool = ...) -> Optional[str]: ... -def set_start_method(method: str, force: Optional[bool] = ...) -> None: ... +def get_start_method(allow_none: bool = ...) -> str | None: ... +def set_start_method(method: str, force: bool | None = ...) -> None: ... if sys.platform != "win32": @overload diff --git a/mypy/typeshed/stdlib/multiprocessing/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/connection.pyi index 15f58a3745f3..56ea5c7c0b0b 100644 --- a/mypy/typeshed/stdlib/multiprocessing/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/connection.pyi @@ -1,7 +1,8 @@ import socket import sys import types -from typing import Any, Iterable, List, Optional, Tuple, Type, Union +from _typeshed import Self +from typing import Any, Iterable, Tuple, Type, Union if sys.version_info >= (3, 8): from typing import SupportsIndex @@ -22,15 +23,15 @@ class _ConnectionBase: def writable(self) -> bool: ... # undocumented def fileno(self) -> int: ... def close(self) -> None: ... - def send_bytes(self, buf: bytes, offset: int = ..., size: Optional[int] = ...) -> None: ... + def send_bytes(self, buf: bytes, offset: int = ..., size: int | None = ...) -> None: ... def send(self, obj: Any) -> None: ... - def recv_bytes(self, maxlength: Optional[int] = ...) -> bytes: ... + def recv_bytes(self, maxlength: int | None = ...) -> bytes: ... def recv_bytes_into(self, buf: Any, offset: int = ...) -> int: ... def recv(self) -> Any: ... - def poll(self, timeout: Optional[float] = ...) -> bool: ... - def __enter__(self) -> _ConnectionBase: ... + def poll(self, timeout: float | None = ...) -> bool: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], exc_tb: Optional[types.TracebackType] + self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... class Connection(_ConnectionBase): ... @@ -40,23 +41,23 @@ if sys.platform == "win32": class Listener: def __init__( - self, address: Optional[_Address] = ..., family: Optional[str] = ..., backlog: int = ..., authkey: Optional[bytes] = ... + self, address: _Address | None = ..., family: str | None = ..., backlog: int = ..., authkey: bytes | None = ... ) -> None: ... def accept(self) -> Connection: ... def close(self) -> None: ... @property def address(self) -> _Address: ... @property - def last_accepted(self) -> Optional[_Address]: ... - def __enter__(self) -> Listener: ... + def last_accepted(self) -> _Address | None: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], exc_tb: Optional[types.TracebackType] + self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... def deliver_challenge(connection: Connection, authkey: bytes) -> None: ... def answer_challenge(connection: Connection, authkey: bytes) -> None: ... def wait( - object_list: Iterable[Union[Connection, socket.socket, int]], timeout: Optional[float] = ... -) -> List[Union[Connection, socket.socket, int]]: ... -def Client(address: _Address, family: Optional[str] = ..., authkey: Optional[bytes] = ...) -> Connection: ... -def Pipe(duplex: bool = ...) -> Tuple[Connection, Connection]: ... + object_list: Iterable[Connection | socket.socket | int], timeout: float | None = ... +) -> list[Connection | socket.socket | int]: ... +def Client(address: _Address, family: str | None = ..., authkey: bytes | None = ...) -> Connection: ... +def Pipe(duplex: bool = ...) -> tuple[Connection, Connection]: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/context.pyi b/mypy/typeshed/stdlib/multiprocessing/context.pyi index e02bacc0a243..e65a387819bc 100644 --- a/mypy/typeshed/stdlib/multiprocessing/context.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/context.pyi @@ -5,9 +5,10 @@ from collections.abc import Callable, Iterable, Sequence from ctypes import _CData from logging import Logger from multiprocessing import queues, synchronize +from multiprocessing.pool import Pool as _Pool from multiprocessing.process import BaseProcess from multiprocessing.sharedctypes import SynchronizedArray, SynchronizedBase -from typing import Any, Optional, Type, TypeVar, Union, overload +from typing import Any, Type, TypeVar, Union, overload from typing_extensions import Literal _LockLike = Union[synchronize.Lock, synchronize.RLock] @@ -31,7 +32,7 @@ class BaseContext(object): def current_process() -> BaseProcess: ... if sys.version_info >= (3, 8): @staticmethod - def parent_process() -> Optional[BaseProcess]: ... + def parent_process() -> BaseProcess | None: ... @staticmethod def active_children() -> list[BaseProcess]: ... def cpu_count(self) -> int: ... @@ -40,10 +41,10 @@ class BaseContext(object): # TODO: change return to Pipe once a stub exists in multiprocessing.connection def Pipe(self, duplex: bool = ...) -> Any: ... def Barrier( - self, parties: int, action: Optional[Callable[..., Any]] = ..., timeout: Optional[float] = ... + self, parties: int, action: Callable[..., Any] | None = ..., timeout: float | None = ... ) -> synchronize.Barrier: ... def BoundedSemaphore(self, value: int = ...) -> synchronize.BoundedSemaphore: ... - def Condition(self, lock: Optional[_LockLike] = ...) -> synchronize.Condition: ... + def Condition(self, lock: _LockLike | None = ...) -> synchronize.Condition: ... def Event(self) -> synchronize.Event: ... def Lock(self) -> synchronize.Lock: ... def RLock(self) -> synchronize.RLock: ... @@ -53,54 +54,44 @@ class BaseContext(object): def SimpleQueue(self) -> queues.SimpleQueue[Any]: ... def Pool( self, - processes: Optional[int] = ..., - initializer: Optional[Callable[..., Any]] = ..., + processes: int | None = ..., + initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ..., - maxtasksperchild: Optional[int] = ..., - ) -> multiprocessing.pool.Pool: ... + maxtasksperchild: int | None = ..., + ) -> _Pool: ... @overload def RawValue(self, typecode_or_type: Type[_CT], *args: Any) -> _CT: ... @overload def RawValue(self, typecode_or_type: str, *args: Any) -> Any: ... @overload - def RawArray(self, typecode_or_type: Type[_CT], size_or_initializer: Union[int, Sequence[Any]]) -> ctypes.Array[_CT]: ... + def RawArray(self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... @overload - def RawArray(self, typecode_or_type: str, size_or_initializer: Union[int, Sequence[Any]]) -> Any: ... + def RawArray(self, typecode_or_type: str, size_or_initializer: int | Sequence[Any]) -> Any: ... @overload def Value(self, typecode_or_type: Type[_CT], *args: Any, lock: Literal[False]) -> _CT: ... @overload - def Value(self, typecode_or_type: Type[_CT], *args: Any, lock: Union[Literal[True], _LockLike]) -> SynchronizedBase[_CT]: ... + def Value(self, typecode_or_type: Type[_CT], *args: Any, lock: Literal[True] | _LockLike) -> SynchronizedBase[_CT]: ... @overload - def Value(self, typecode_or_type: str, *args: Any, lock: Union[Literal[True], _LockLike]) -> SynchronizedBase[Any]: ... + def Value(self, typecode_or_type: str, *args: Any, lock: Literal[True] | _LockLike) -> SynchronizedBase[Any]: ... @overload - def Value(self, typecode_or_type: Union[str, Type[_CData]], *args: Any, lock: Union[bool, _LockLike] = ...) -> Any: ... + def Value(self, typecode_or_type: str | Type[_CData], *args: Any, lock: bool | _LockLike = ...) -> Any: ... @overload - def Array( - self, typecode_or_type: Type[_CT], size_or_initializer: Union[int, Sequence[Any]], *, lock: Literal[False] - ) -> _CT: ... + def Array(self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False]) -> _CT: ... @overload def Array( - self, - typecode_or_type: Type[_CT], - size_or_initializer: Union[int, Sequence[Any]], - *, - lock: Union[Literal[True], _LockLike], + self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[True] | _LockLike ) -> SynchronizedArray[_CT]: ... @overload def Array( - self, typecode_or_type: str, size_or_initializer: Union[int, Sequence[Any]], *, lock: Union[Literal[True], _LockLike] + self, typecode_or_type: str, size_or_initializer: int | Sequence[Any], *, lock: Literal[True] | _LockLike ) -> SynchronizedArray[Any]: ... @overload def Array( - self, - typecode_or_type: Union[str, Type[_CData]], - size_or_initializer: Union[int, Sequence[Any]], - *, - lock: Union[bool, _LockLike] = ..., + self, typecode_or_type: str | Type[_CData], size_or_initializer: int | Sequence[Any], *, lock: bool | _LockLike = ... ) -> Any: ... def freeze_support(self) -> None: ... def get_logger(self) -> Logger: ... - def log_to_stderr(self, level: Optional[str] = ...) -> Logger: ... + def log_to_stderr(self, level: str | None = ...) -> Logger: ... def allow_connection_pickling(self) -> None: ... def set_executable(self, executable: str) -> None: ... def set_forkserver_preload(self, module_names: list[str]) -> None: ... @@ -123,7 +114,7 @@ class BaseContext(object): @overload def get_context(self, method: str) -> BaseContext: ... def get_start_method(self, allow_none: bool = ...) -> str: ... - def set_start_method(self, method: Optional[str], force: bool = ...) -> None: ... + def set_start_method(self, method: str | None, force: bool = ...) -> None: ... @property def reducer(self) -> str: ... @reducer.setter @@ -131,14 +122,14 @@ class BaseContext(object): def _check_available(self) -> None: ... class Process(BaseProcess): - _start_method: Optional[str] + _start_method: str | None @staticmethod def _Popen(process_obj: BaseProcess) -> DefaultContext: ... class DefaultContext(BaseContext): Process: Type[multiprocessing.Process] def __init__(self, context: BaseContext) -> None: ... - def set_start_method(self, method: Optional[str], force: bool = ...) -> None: ... + def set_start_method(self, method: str | None, force: bool = ...) -> None: ... def get_start_method(self, allow_none: bool = ...) -> str: ... def get_all_start_methods(self) -> list[str]: ... @@ -177,6 +168,6 @@ else: Process: Type[SpawnProcess] def _force_start_method(method: str) -> None: ... -def get_spawning_popen() -> Optional[Any]: ... +def get_spawning_popen() -> Any | None: ... def set_spawning_popen(popen: Any) -> None: ... def assert_spawning(obj: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi index 0089defc0099..b4d1c8404d8d 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi @@ -2,7 +2,7 @@ import array import threading import weakref from queue import Queue as Queue -from typing import Any, Callable, Iterable, List, Mapping, Optional, Sequence +from typing import Any, Callable, Iterable, Mapping, Sequence JoinableQueue = Queue Barrier = threading.Barrier @@ -18,12 +18,12 @@ class DummyProcess(threading.Thread): _parent: threading.Thread _pid: None _start_called: int - exitcode: Optional[int] + exitcode: int | None def __init__( self, group: Any = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[str] = ..., + target: Callable[..., Any] | None = ..., + name: str | None = ..., args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ..., ) -> None: ... @@ -43,10 +43,8 @@ class Value: def Array(typecode: Any, sequence: Sequence[Any], lock: Any = ...) -> array.array[Any]: ... def Manager() -> Any: ... -def Pool( - processes: Optional[int] = ..., initializer: Optional[Callable[..., Any]] = ..., initargs: Iterable[Any] = ... -) -> Any: ... -def active_children() -> List[Any]: ... +def Pool(processes: int | None = ..., initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ...) -> Any: ... +def active_children() -> list[Any]: ... def current_process() -> threading.Thread: ... def freeze_support() -> None: ... def shutdown() -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi index 01733e59c763..4ef3d095911f 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi @@ -1,11 +1,10 @@ +from _typeshed import Self from queue import Queue from types import TracebackType -from typing import Any, List, Optional, Tuple, Type, TypeVar, Union +from typing import Any, Tuple, Type, Union -families: List[None] +families: list[None] -_ConnectionT = TypeVar("_ConnectionT", bound=Connection) -_ListenerT = TypeVar("_ListenerT", bound=Listener) _Address = Union[str, Tuple[str, int]] class Connection(object): @@ -15,25 +14,25 @@ class Connection(object): recv_bytes: Any send: Any send_bytes: Any - def __enter__(self: _ConnectionT) -> _ConnectionT: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __init__(self, _in: Any, _out: Any) -> None: ... def close(self) -> None: ... def poll(self, timeout: float = ...) -> bool: ... class Listener(object): - _backlog_queue: Optional[Queue[Any]] + _backlog_queue: Queue[Any] | None @property - def address(self) -> Optional[Queue[Any]]: ... - def __enter__(self: _ListenerT) -> _ListenerT: ... + def address(self) -> Queue[Any] | None: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... - def __init__(self, address: Optional[_Address] = ..., family: Optional[int] = ..., backlog: int = ...) -> None: ... + def __init__(self, address: _Address | None = ..., family: int | None = ..., backlog: int = ...) -> None: ... def accept(self) -> Connection: ... def close(self) -> None: ... def Client(address: _Address) -> Connection: ... -def Pipe(duplex: bool = ...) -> Tuple[Connection, Connection]: ... +def Pipe(duplex: bool = ...) -> tuple[Connection, Connection]: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index 9cc671363f0b..22a33f226c0b 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -3,22 +3,7 @@ import queue import sys import threading -from typing import ( - Any, - AnyStr, - Callable, - ContextManager, - Dict, - Generic, - Iterable, - List, - Mapping, - Optional, - Sequence, - Tuple, - TypeVar, - Union, -) +from typing import Any, AnyStr, Callable, ContextManager, Generic, Iterable, Mapping, Sequence, Tuple, TypeVar from .connection import Connection from .context import BaseContext @@ -44,37 +29,31 @@ class Namespace: _Namespace = Namespace class Token(object): - typeid: Optional[Union[str, bytes]] - address: Tuple[Union[str, bytes], int] - id: Optional[Union[str, bytes, int]] - def __init__( - self, typeid: Optional[Union[bytes, str]], address: Tuple[Union[str, bytes], int], id: Optional[Union[str, bytes, int]] - ) -> None: ... + typeid: str | bytes | None + address: tuple[str | bytes, int] + id: str | bytes | int | None + def __init__(self, typeid: bytes | str | None, address: tuple[str | bytes, int], id: str | bytes | int | None) -> None: ... def __repr__(self) -> str: ... - def __getstate__( - self, - ) -> Tuple[Optional[Union[str, bytes]], Tuple[Union[str, bytes], int], Optional[Union[str, bytes, int]]]: ... - def __setstate__( - self, state: Tuple[Optional[Union[str, bytes]], Tuple[Union[str, bytes], int], Optional[Union[str, bytes, int]]] - ) -> None: ... + def __getstate__(self) -> tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]: ... + def __setstate__(self, state: tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]) -> None: ... class BaseProxy(object): - _address_to_local: Dict[Any, Any] + _address_to_local: dict[Any, Any] _mutex: Any def __init__( self, token: Any, serializer: str, manager: Any = ..., - authkey: Optional[AnyStr] = ..., + authkey: AnyStr | None = ..., exposed: Any = ..., incref: bool = ..., manager_owned: bool = ..., ) -> None: ... - def __deepcopy__(self, memo: Optional[Any]) -> Any: ... - def _callmethod(self, methodname: str, args: Tuple[Any, ...] = ..., kwds: Dict[Any, Any] = ...) -> None: ... + def __deepcopy__(self, memo: Any | None) -> Any: ... + def _callmethod(self, methodname: str, args: Tuple[Any, ...] = ..., kwds: dict[Any, Any] = ...) -> None: ... def _getvalue(self) -> Any: ... - def __reduce__(self) -> Tuple[Any, Tuple[Any, Any, str, Dict[Any, Any]]]: ... + def __reduce__(self) -> tuple[Any, tuple[Any, Any, str, dict[Any, Any]]]: ... class ValueProxy(BaseProxy, Generic[_T]): def get(self) -> _T: ... @@ -87,37 +66,37 @@ class ValueProxy(BaseProxy, Generic[_T]): class Server: address: Any def __init__( - self, registry: Dict[str, Tuple[Callable[..., Any], Any, Any, Any]], address: Any, authkey: bytes, serializer: str + self, registry: dict[str, tuple[Callable[..., Any], Any, Any, Any]], address: Any, authkey: bytes, serializer: str ) -> None: ... def serve_forever(self) -> None: ... def accept_connection(self, c: Connection, name: str) -> None: ... class BaseManager(ContextManager[BaseManager]): def __init__( - self, - address: Optional[Any] = ..., - authkey: Optional[bytes] = ..., - serializer: str = ..., - ctx: Optional[BaseContext] = ..., + self, address: Any | None = ..., authkey: bytes | None = ..., serializer: str = ..., ctx: BaseContext | None = ... ) -> None: ... def get_server(self) -> Server: ... def connect(self) -> None: ... - def start(self, initializer: Optional[Callable[..., Any]] = ..., initargs: Iterable[Any] = ...) -> None: ... + def start(self, initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ...) -> None: ... def shutdown(self) -> None: ... # only available after start() was called - def join(self, timeout: Optional[float] = ...) -> None: ... # undocumented + def join(self, timeout: float | None = ...) -> None: ... # undocumented @property def address(self) -> Any: ... @classmethod def register( cls, typeid: str, - callable: Optional[Callable[..., Any]] = ..., + callable: Callable[..., Any] | None = ..., proxytype: Any = ..., - exposed: Optional[Sequence[str]] = ..., - method_to_typeid: Optional[Mapping[str, str]] = ..., + exposed: Sequence[str] | None = ..., + method_to_typeid: Mapping[str, str] | None = ..., create_method: bool = ..., ) -> None: ... +# Conflicts with method names +_dict = dict +_list = list + class SyncManager(BaseManager, ContextManager[SyncManager]): def BoundedSemaphore(self, value: Any = ...) -> threading.BoundedSemaphore: ... def Condition(self, lock: Any = ...) -> threading.Condition: ... @@ -129,8 +108,8 @@ class SyncManager(BaseManager, ContextManager[SyncManager]): def Semaphore(self, value: Any = ...) -> threading.Semaphore: ... def Array(self, typecode: Any, sequence: Sequence[_T]) -> Sequence[_T]: ... def Value(self, typecode: Any, value: _T) -> ValueProxy[_T]: ... - def dict(self, sequence: Mapping[_KT, _VT] = ...) -> Dict[_KT, _VT]: ... - def list(self, sequence: Sequence[_T] = ...) -> List[_T]: ... + def dict(self, sequence: Mapping[_KT, _VT] = ...) -> _dict[_KT, _VT]: ... + def list(self, sequence: Sequence[_T] = ...) -> _list[_T]: ... class RemoteError(Exception): ... @@ -139,4 +118,4 @@ if sys.version_info >= (3, 8): class SharedMemoryManager(BaseManager): def get_server(self) -> SharedMemoryServer: ... def SharedMemory(self, size: int) -> _SharedMemory: ... - def ShareableList(self, sequence: Optional[Iterable[_SLT]]) -> _ShareableList[_SLT]: ... + def ShareableList(self, sequence: Iterable[_SLT] | None) -> _ShareableList[_SLT]: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/multiprocessing/pool.pyi index d8004655cacf..75583aae8012 100644 --- a/mypy/typeshed/stdlib/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/pool.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, ContextManager, Generic, Iterable, Iterator, List, Mapping, Optional, TypeVar +from _typeshed import Self +from typing import Any, Callable, ContextManager, Generic, Iterable, Iterator, List, Mapping, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -9,14 +10,19 @@ _S = TypeVar("_S") _T = TypeVar("_T") class ApplyResult(Generic[_T]): - def __init__( - self, - pool: Pool, - callback: Optional[Callable[[_T], None]] = ..., - error_callback: Optional[Callable[[BaseException], None]] = ..., - ) -> None: ... - def get(self, timeout: Optional[float] = ...) -> _T: ... - def wait(self, timeout: Optional[float] = ...) -> None: ... + if sys.version_info >= (3, 8): + def __init__( + self, pool: Pool, callback: Callable[[_T], None] | None, error_callback: Callable[[BaseException], None] | None + ) -> None: ... + else: + def __init__( + self, + cache: dict[int, ApplyResult[Any]], + callback: Callable[[_T], None] | None, + error_callback: Callable[[BaseException], None] | None, + ) -> None: ... + def get(self, timeout: float | None = ...) -> _T: ... + def wait(self, timeout: float | None = ...) -> None: ... def ready(self) -> bool: ... def successful(self) -> bool: ... if sys.version_info >= (3, 9): @@ -25,23 +31,45 @@ class ApplyResult(Generic[_T]): # alias created during issue #17805 AsyncResult = ApplyResult -class MapResult(ApplyResult[List[_T]]): ... +class MapResult(ApplyResult[List[_T]]): + if sys.version_info >= (3, 8): + def __init__( + self, + pool: Pool, + chunksize: int, + length: int, + callback: Callable[[list[_T]], None] | None, + error_callback: Callable[[BaseException], None] | None, + ) -> None: ... + else: + def __init__( + self, + cache: dict[int, ApplyResult[Any]], + chunksize: int, + length: int, + callback: Callable[[list[_T]], None] | None, + error_callback: Callable[[BaseException], None] | None, + ) -> None: ... class IMapIterator(Iterator[_T]): + if sys.version_info >= (3, 8): + def __init__(self, pool: Pool) -> None: ... + else: + def __init__(self, cache: dict[int, IMapIterator[Any]]) -> None: ... def __iter__(self: _S) -> _S: ... - def next(self, timeout: Optional[float] = ...) -> _T: ... - def __next__(self, timeout: Optional[float] = ...) -> _T: ... + def next(self, timeout: float | None = ...) -> _T: ... + def __next__(self, timeout: float | None = ...) -> _T: ... class IMapUnorderedIterator(IMapIterator[_T]): ... class Pool(ContextManager[Pool]): def __init__( self, - processes: Optional[int] = ..., - initializer: Optional[Callable[..., None]] = ..., + processes: int | None = ..., + initializer: Callable[..., None] | None = ..., initargs: Iterable[Any] = ..., - maxtasksperchild: Optional[int] = ..., - context: Optional[Any] = ..., + maxtasksperchild: int | None = ..., + context: Any | None = ..., ) -> None: ... def apply(self, func: Callable[..., _T], args: Iterable[Any] = ..., kwds: Mapping[str, Any] = ...) -> _T: ... def apply_async( @@ -49,39 +77,39 @@ class Pool(ContextManager[Pool]): func: Callable[..., _T], args: Iterable[Any] = ..., kwds: Mapping[str, Any] = ..., - callback: Optional[Callable[[_T], None]] = ..., - error_callback: Optional[Callable[[BaseException], None]] = ..., + callback: Callable[[_T], None] | None = ..., + error_callback: Callable[[BaseException], None] | None = ..., ) -> AsyncResult[_T]: ... - def map(self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: Optional[int] = ...) -> List[_T]: ... + def map(self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: int | None = ...) -> list[_T]: ... def map_async( self, func: Callable[[_S], _T], iterable: Iterable[_S], - chunksize: Optional[int] = ..., - callback: Optional[Callable[[_T], None]] = ..., - error_callback: Optional[Callable[[BaseException], None]] = ..., + chunksize: int | None = ..., + callback: Callable[[_T], None] | None = ..., + error_callback: Callable[[BaseException], None] | None = ..., ) -> MapResult[_T]: ... - def imap(self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: Optional[int] = ...) -> IMapIterator[_T]: ... + def imap(self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: int | None = ...) -> IMapIterator[_T]: ... def imap_unordered( - self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: Optional[int] = ... + self, func: Callable[[_S], _T], iterable: Iterable[_S], chunksize: int | None = ... ) -> IMapIterator[_T]: ... - def starmap(self, func: Callable[..., _T], iterable: Iterable[Iterable[Any]], chunksize: Optional[int] = ...) -> List[_T]: ... + def starmap(self, func: Callable[..., _T], iterable: Iterable[Iterable[Any]], chunksize: int | None = ...) -> list[_T]: ... def starmap_async( self, func: Callable[..., _T], iterable: Iterable[Iterable[Any]], - chunksize: Optional[int] = ..., - callback: Optional[Callable[[_T], None]] = ..., - error_callback: Optional[Callable[[BaseException], None]] = ..., - ) -> AsyncResult[List[_T]]: ... + chunksize: int | None = ..., + callback: Callable[[_T], None] | None = ..., + error_callback: Callable[[BaseException], None] | None = ..., + ) -> AsyncResult[list[_T]]: ... def close(self) -> None: ... def terminate(self) -> None: ... def join(self) -> None: ... - def __enter__(self: _PT) -> _PT: ... + def __enter__(self: Self) -> Self: ... class ThreadPool(Pool, ContextManager[ThreadPool]): def __init__( - self, processes: Optional[int] = ..., initializer: Optional[Callable[..., Any]] = ..., initargs: Iterable[Any] = ... + self, processes: int | None = ..., initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ... ) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/multiprocessing/process.pyi b/mypy/typeshed/stdlib/multiprocessing/process.pyi index f2d0b5740baf..32c22d19f6e5 100644 --- a/mypy/typeshed/stdlib/multiprocessing/process.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/process.pyi @@ -1,19 +1,20 @@ import sys -from typing import Any, Callable, List, Mapping, Optional, Tuple +from typing import Any, Callable, Mapping, Tuple class BaseProcess: name: str daemon: bool authkey: bytes + _identity: Tuple[int, ...] # undocumented def __init__( self, group: None = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[str] = ..., + target: Callable[..., Any] | None = ..., + name: str | None = ..., args: Tuple[Any, ...] = ..., kwargs: Mapping[str, Any] = ..., *, - daemon: Optional[bool] = ..., + daemon: bool | None = ..., ) -> None: ... def run(self) -> None: ... def start(self) -> None: ... @@ -21,19 +22,19 @@ class BaseProcess: if sys.version_info >= (3, 7): def kill(self) -> None: ... def close(self) -> None: ... - def join(self, timeout: Optional[float] = ...) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... def is_alive(self) -> bool: ... @property - def exitcode(self) -> Optional[int]: ... + def exitcode(self) -> int | None: ... @property - def ident(self) -> Optional[int]: ... + def ident(self) -> int | None: ... @property - def pid(self) -> Optional[int]: ... + def pid(self) -> int | None: ... @property def sentinel(self) -> int: ... def current_process() -> BaseProcess: ... -def active_children() -> List[BaseProcess]: ... +def active_children() -> list[BaseProcess]: ... if sys.version_info >= (3, 8): - def parent_process() -> Optional[BaseProcess]: ... + def parent_process() -> BaseProcess | None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/queues.pyi b/mypy/typeshed/stdlib/multiprocessing/queues.pyi index 3d61e44e67c5..1c9d76917292 100644 --- a/mypy/typeshed/stdlib/multiprocessing/queues.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/queues.pyi @@ -1,6 +1,6 @@ import queue import sys -from typing import Any, Generic, Optional, TypeVar +from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -11,8 +11,8 @@ class Queue(queue.Queue[_T]): # FIXME: `ctx` is a circular dependency and it's not actually optional. # It's marked as such to be able to use the generic Queue in __init__.pyi. def __init__(self, maxsize: int = ..., *, ctx: Any = ...) -> None: ... - def get(self, block: bool = ..., timeout: Optional[float] = ...) -> _T: ... - def put(self, obj: _T, block: bool = ..., timeout: Optional[float] = ...) -> None: ... + def get(self, block: bool = ..., timeout: float | None = ...) -> _T: ... + def put(self, obj: _T, block: bool = ..., timeout: float | None = ...) -> None: ... def qsize(self) -> int: ... def empty(self) -> bool: ... def full(self) -> bool: ... @@ -28,6 +28,8 @@ class JoinableQueue(Queue[_T]): class SimpleQueue(Generic[_T]): def __init__(self, *, ctx: Any = ...) -> None: ... + if sys.version_info >= (3, 9): + def close(self) -> None: ... def empty(self) -> bool: ... def get(self) -> _T: ... def put(self, item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi index cf8b68bfc0da..6ffc2542087a 100644 --- a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Generic, Iterable, Optional, Tuple, TypeVar +from typing import Any, Generic, Iterable, Tuple, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -9,7 +9,7 @@ _SLT = TypeVar("_SLT", int, float, bool, str, bytes, None) if sys.version_info >= (3, 8): class SharedMemory: - def __init__(self, name: Optional[str] = ..., create: bool = ..., size: int = ...) -> None: ... + def __init__(self, name: str | None = ..., create: bool = ..., size: int = ...) -> None: ... @property def buf(self) -> memoryview: ... @property @@ -20,10 +20,10 @@ if sys.version_info >= (3, 8): def unlink(self) -> None: ... class ShareableList(Generic[_SLT]): shm: SharedMemory - def __init__(self, sequence: Optional[Iterable[_SLT]] = ..., *, name: Optional[str] = ...) -> None: ... + def __init__(self, sequence: Iterable[_SLT] | None = ..., *, name: str | None = ...) -> None: ... def __getitem__(self, position: int) -> _SLT: ... def __setitem__(self, position: int, value: _SLT) -> None: ... - def __reduce__(self: _S) -> Tuple[_S, Tuple[_SLT, ...]]: ... + def __reduce__(self: _S) -> tuple[_S, Tuple[_SLT, ...]]: ... def __len__(self) -> int: ... @property def format(self) -> str: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi b/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi index 0dc5977decd7..bd9d8f089875 100644 --- a/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi @@ -3,7 +3,7 @@ from collections.abc import Callable, Iterable, Sequence from ctypes import _CData, _SimpleCData, c_char from multiprocessing.context import BaseContext from multiprocessing.synchronize import _LockLike -from typing import Any, Generic, Optional, Protocol, Type, TypeVar, Union, overload +from typing import Any, Generic, Protocol, Type, TypeVar, overload from typing_extensions import Literal _T = TypeVar("_T") @@ -14,72 +14,68 @@ def RawValue(typecode_or_type: Type[_CT], *args: Any) -> _CT: ... @overload def RawValue(typecode_or_type: str, *args: Any) -> Any: ... @overload -def RawArray(typecode_or_type: Type[_CT], size_or_initializer: Union[int, Sequence[Any]]) -> ctypes.Array[_CT]: ... +def RawArray(typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... @overload -def RawArray(typecode_or_type: str, size_or_initializer: Union[int, Sequence[Any]]) -> Any: ... +def RawArray(typecode_or_type: str, size_or_initializer: int | Sequence[Any]) -> Any: ... @overload -def Value(typecode_or_type: Type[_CT], *args: Any, lock: Literal[False], ctx: Optional[BaseContext] = ...) -> _CT: ... +def Value(typecode_or_type: Type[_CT], *args: Any, lock: Literal[False], ctx: BaseContext | None = ...) -> _CT: ... @overload def Value( - typecode_or_type: Type[_CT], *args: Any, lock: Union[Literal[True], _LockLike], ctx: Optional[BaseContext] = ... + typecode_or_type: Type[_CT], *args: Any, lock: Literal[True] | _LockLike, ctx: BaseContext | None = ... ) -> SynchronizedBase[_CT]: ... @overload def Value( - typecode_or_type: str, *args: Any, lock: Union[Literal[True], _LockLike], ctx: Optional[BaseContext] = ... + typecode_or_type: str, *args: Any, lock: Literal[True] | _LockLike, ctx: BaseContext | None = ... ) -> SynchronizedBase[Any]: ... @overload def Value( - typecode_or_type: Union[str, Type[_CData]], *args: Any, lock: Union[bool, _LockLike] = ..., ctx: Optional[BaseContext] = ... + typecode_or_type: str | Type[_CData], *args: Any, lock: bool | _LockLike = ..., ctx: BaseContext | None = ... ) -> Any: ... @overload def Array( - typecode_or_type: Type[_CT], - size_or_initializer: Union[int, Sequence[Any]], - *, - lock: Literal[False], - ctx: Optional[BaseContext] = ..., + typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False], ctx: BaseContext | None = ... ) -> _CT: ... @overload def Array( typecode_or_type: Type[_CT], - size_or_initializer: Union[int, Sequence[Any]], + size_or_initializer: int | Sequence[Any], *, - lock: Union[Literal[True], _LockLike], - ctx: Optional[BaseContext] = ..., + lock: Literal[True] | _LockLike, + ctx: BaseContext | None = ..., ) -> SynchronizedArray[_CT]: ... @overload def Array( typecode_or_type: str, - size_or_initializer: Union[int, Sequence[Any]], + size_or_initializer: int | Sequence[Any], *, - lock: Union[Literal[True], _LockLike], - ctx: Optional[BaseContext] = ..., + lock: Literal[True] | _LockLike, + ctx: BaseContext | None = ..., ) -> SynchronizedArray[Any]: ... @overload def Array( - typecode_or_type: Union[str, Type[_CData]], - size_or_initializer: Union[int, Sequence[Any]], + typecode_or_type: str | Type[_CData], + size_or_initializer: int | Sequence[Any], *, - lock: Union[bool, _LockLike] = ..., - ctx: Optional[BaseContext] = ..., + lock: bool | _LockLike = ..., + ctx: BaseContext | None = ..., ) -> Any: ... def copy(obj: _CT) -> _CT: ... @overload -def synchronized(obj: _SimpleCData[_T], lock: Optional[_LockLike] = ..., ctx: Optional[Any] = ...) -> Synchronized[_T]: ... +def synchronized(obj: _SimpleCData[_T], lock: _LockLike | None = ..., ctx: Any | None = ...) -> Synchronized[_T]: ... @overload -def synchronized(obj: ctypes.Array[c_char], lock: Optional[_LockLike] = ..., ctx: Optional[Any] = ...) -> SynchronizedString: ... +def synchronized(obj: ctypes.Array[c_char], lock: _LockLike | None = ..., ctx: Any | None = ...) -> SynchronizedString: ... @overload -def synchronized(obj: ctypes.Array[_CT], lock: Optional[_LockLike] = ..., ctx: Optional[Any] = ...) -> SynchronizedArray[_CT]: ... +def synchronized(obj: ctypes.Array[_CT], lock: _LockLike | None = ..., ctx: Any | None = ...) -> SynchronizedArray[_CT]: ... @overload -def synchronized(obj: _CT, lock: Optional[_LockLike] = ..., ctx: Optional[Any] = ...) -> SynchronizedBase[_CT]: ... +def synchronized(obj: _CT, lock: _LockLike | None = ..., ctx: Any | None = ...) -> SynchronizedBase[_CT]: ... class _AcquireFunc(Protocol): - def __call__(self, block: bool = ..., timeout: Optional[float] = ...) -> bool: ... + def __call__(self, block: bool = ..., timeout: float | None = ...) -> bool: ... class SynchronizedBase(Generic[_CT]): - acquire: _AcquireFunc = ... - release: Callable[[], None] = ... - def __init__(self, obj: Any, lock: Optional[_LockLike] = ..., ctx: Optional[Any] = ...) -> None: ... + acquire: _AcquireFunc + release: Callable[[], None] + def __init__(self, obj: Any, lock: _LockLike | None = ..., ctx: Any | None = ...) -> None: ... def __reduce__(self) -> tuple[Callable[..., Any], tuple[Any, _LockLike]]: ... def get_obj(self) -> _CT: ... def get_lock(self) -> _LockLike: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi index 0faee1754f93..34c7322e0d46 100644 --- a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi @@ -1,5 +1,5 @@ from types import ModuleType -from typing import Any, Dict, List, Mapping, Optional, Sequence +from typing import Any, Mapping, Sequence WINEXE: bool WINSERVICE: bool @@ -8,14 +8,14 @@ def set_executable(exe: str) -> None: ... def get_executable() -> str: ... def is_forking(argv: Sequence[str]) -> bool: ... def freeze_support() -> None: ... -def get_command_line(**kwds: Any) -> List[str]: ... -def spawn_main(pipe_handle: int, parent_pid: Optional[int] = ..., tracker_fd: Optional[int] = ...) -> None: ... +def get_command_line(**kwds: Any) -> list[str]: ... +def spawn_main(pipe_handle: int, parent_pid: int | None = ..., tracker_fd: int | None = ...) -> None: ... # undocumented def _main(fd: int) -> Any: ... -def get_preparation_data(name: str) -> Dict[str, Any]: ... +def get_preparation_data(name: str) -> dict[str, Any]: ... -old_main_modules: List[ModuleType] +old_main_modules: list[ModuleType] def prepare(data: Mapping[str, Any]) -> None: ... def import_main_path(main_path: str) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi index 7eefc7676b66..1741885f13bf 100644 --- a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi @@ -1,36 +1,36 @@ import sys import threading from multiprocessing.context import BaseContext -from typing import Any, Callable, ContextManager, Optional, Union +from typing import Any, Callable, ContextManager, Union _LockLike = Union[Lock, RLock] class Barrier(threading.Barrier): def __init__( - self, parties: int, action: Optional[Callable[..., Any]] = ..., timeout: Optional[float] = ..., *ctx: BaseContext + self, parties: int, action: Callable[..., Any] | None = ..., timeout: float | None = ..., *ctx: BaseContext ) -> None: ... class BoundedSemaphore(Semaphore): def __init__(self, value: int = ..., *, ctx: BaseContext) -> None: ... class Condition(ContextManager[bool]): - def __init__(self, lock: Optional[_LockLike] = ..., *, ctx: BaseContext) -> None: ... + def __init__(self, lock: _LockLike | None = ..., *, ctx: BaseContext) -> None: ... if sys.version_info >= (3, 7): def notify(self, n: int = ...) -> None: ... else: def notify(self) -> None: ... def notify_all(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... - def wait_for(self, predicate: Callable[[], bool], timeout: Optional[float] = ...) -> bool: ... - def acquire(self, block: bool = ..., timeout: Optional[float] = ...) -> bool: ... + def wait(self, timeout: float | None = ...) -> bool: ... + def wait_for(self, predicate: Callable[[], bool], timeout: float | None = ...) -> bool: ... + def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... class Event(ContextManager[bool]): - def __init__(self, lock: Optional[_LockLike] = ..., *, ctx: BaseContext) -> None: ... + def __init__(self, lock: _LockLike | None = ..., *, ctx: BaseContext) -> None: ... def is_set(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... + def wait(self, timeout: float | None = ...) -> bool: ... class Lock(SemLock): def __init__(self, *, ctx: BaseContext) -> None: ... @@ -43,5 +43,5 @@ class Semaphore(SemLock): # Not part of public API class SemLock(ContextManager[bool]): - def acquire(self, block: bool = ..., timeout: Optional[float] = ...) -> bool: ... + def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... diff --git a/mypy/typeshed/stdlib/netrc.pyi b/mypy/typeshed/stdlib/netrc.pyi index 20a0513ea54a..b8eac307740a 100644 --- a/mypy/typeshed/stdlib/netrc.pyi +++ b/mypy/typeshed/stdlib/netrc.pyi @@ -1,17 +1,17 @@ -from _typeshed import AnyPath -from typing import Dict, List, Optional, Tuple +from _typeshed import StrOrBytesPath +from typing import Optional, Tuple class NetrcParseError(Exception): - filename: Optional[str] - lineno: Optional[int] + filename: str | None + lineno: int | None msg: str - def __init__(self, msg: str, filename: Optional[AnyPath] = ..., lineno: Optional[int] = ...) -> None: ... + def __init__(self, msg: str, filename: StrOrBytesPath | None = ..., lineno: int | None = ...) -> None: ... # (login, account, password) tuple _NetrcTuple = Tuple[str, Optional[str], Optional[str]] class netrc: - hosts: Dict[str, _NetrcTuple] - macros: Dict[str, List[str]] - def __init__(self, file: Optional[AnyPath] = ...) -> None: ... - def authenticators(self, host: str) -> Optional[_NetrcTuple]: ... + hosts: dict[str, _NetrcTuple] + macros: dict[str, list[str]] + def __init__(self, file: StrOrBytesPath | None = ...) -> None: ... + def authenticators(self, host: str) -> _NetrcTuple | None: ... diff --git a/mypy/typeshed/stdlib/nis.pyi b/mypy/typeshed/stdlib/nis.pyi index bc6c2bc07256..b762ae46241c 100644 --- a/mypy/typeshed/stdlib/nis.pyi +++ b/mypy/typeshed/stdlib/nis.pyi @@ -1,9 +1,8 @@ import sys -from typing import Dict, List if sys.platform != "win32": - def cat(map: str, domain: str = ...) -> Dict[str, str]: ... + def cat(map: str, domain: str = ...) -> dict[str, str]: ... def get_default_domain() -> str: ... - def maps(domain: str = ...) -> List[str]: ... + def maps(domain: str = ...) -> list[str]: ... def match(key: str, map: str, domain: str = ...) -> str: ... class error(Exception): ... diff --git a/mypy/typeshed/stdlib/nntplib.pyi b/mypy/typeshed/stdlib/nntplib.pyi index 36fe063c8486..508b5f679bc3 100644 --- a/mypy/typeshed/stdlib/nntplib.pyi +++ b/mypy/typeshed/stdlib/nntplib.pyi @@ -2,9 +2,9 @@ import datetime import socket import ssl import sys -from typing import IO, Any, Dict, Iterable, List, NamedTuple, Optional, Tuple, TypeVar, Union +from _typeshed import Self +from typing import IO, Any, Iterable, NamedTuple, Tuple, Union -_SelfT = TypeVar("_SelfT", bound=_NNTPBase) _File = Union[IO[bytes], bytes, str, None] class NNTPError(Exception): @@ -28,10 +28,12 @@ class GroupInfo(NamedTuple): class ArticleInfo(NamedTuple): number: int message_id: str - lines: List[bytes] + lines: list[bytes] def decode_header(header_str: str) -> str: ... +_list = list # conflicts with a method named "list" + class _NNTPBase: encoding: str errors: str @@ -45,44 +47,42 @@ class _NNTPBase: authenticated: bool nntp_implementation: str nntp_version: int - def __init__(self, file: IO[bytes], host: str, readermode: Optional[bool] = ..., timeout: float = ...) -> None: ... - def __enter__(self: _SelfT) -> _SelfT: ... + def __init__(self, file: IO[bytes], host: str, readermode: bool | None = ..., timeout: float = ...) -> None: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *args: Any) -> None: ... def getwelcome(self) -> str: ... - def getcapabilities(self) -> Dict[str, List[str]]: ... + def getcapabilities(self) -> dict[str, _list[str]]: ... def set_debuglevel(self, level: int) -> None: ... def debug(self, level: int) -> None: ... - def capabilities(self) -> Tuple[str, Dict[str, List[str]]]: ... - def newgroups(self, date: Union[datetime.date, datetime.datetime], *, file: _File = ...) -> Tuple[str, List[str]]: ... - def newnews( - self, group: str, date: Union[datetime.date, datetime.datetime], *, file: _File = ... - ) -> Tuple[str, List[str]]: ... - def list(self, group_pattern: Optional[str] = ..., *, file: _File = ...) -> Tuple[str, List[str]]: ... + def capabilities(self) -> tuple[str, dict[str, _list[str]]]: ... + def newgroups(self, date: datetime.date | datetime.datetime, *, file: _File = ...) -> tuple[str, _list[str]]: ... + def newnews(self, group: str, date: datetime.date | datetime.datetime, *, file: _File = ...) -> tuple[str, _list[str]]: ... + def list(self, group_pattern: str | None = ..., *, file: _File = ...) -> tuple[str, _list[str]]: ... def description(self, group: str) -> str: ... - def descriptions(self, group_pattern: str) -> Tuple[str, Dict[str, str]]: ... - def group(self, name: str) -> Tuple[str, int, int, int, str]: ... - def help(self, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def stat(self, message_spec: Any = ...) -> Tuple[str, int, str]: ... - def next(self) -> Tuple[str, int, str]: ... - def last(self) -> Tuple[str, int, str]: ... - def head(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... - def body(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... - def article(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... + def descriptions(self, group_pattern: str) -> tuple[str, dict[str, str]]: ... + def group(self, name: str) -> tuple[str, int, int, int, str]: ... + def help(self, *, file: _File = ...) -> tuple[str, _list[str]]: ... + def stat(self, message_spec: Any = ...) -> tuple[str, int, str]: ... + def next(self) -> tuple[str, int, str]: ... + def last(self) -> tuple[str, int, str]: ... + def head(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... + def body(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... + def article(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... def slave(self) -> str: ... - def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def xover(self, start: int, end: int, *, file: _File = ...) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... + def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> tuple[str, _list[str]]: ... + def xover(self, start: int, end: int, *, file: _File = ...) -> tuple[str, _list[tuple[int, dict[str, str]]]]: ... def over( - self, message_spec: Union[None, str, List[Any], Tuple[Any, ...]], *, file: _File = ... - ) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... + self, message_spec: None | str | _list[Any] | Tuple[Any, ...], *, file: _File = ... + ) -> tuple[str, _list[tuple[int, dict[str, str]]]]: ... if sys.version_info < (3, 9): - def xgtitle(self, group: str, *, file: _File = ...) -> Tuple[str, List[Tuple[str, str]]]: ... - def xpath(self, id: Any) -> Tuple[str, str]: ... - def date(self) -> Tuple[str, datetime.datetime]: ... - def post(self, data: Union[bytes, Iterable[bytes]]) -> str: ... - def ihave(self, message_id: Any, data: Union[bytes, Iterable[bytes]]) -> str: ... + def xgtitle(self, group: str, *, file: _File = ...) -> tuple[str, _list[tuple[str, str]]]: ... + def xpath(self, id: Any) -> tuple[str, str]: ... + def date(self) -> tuple[str, datetime.datetime]: ... + def post(self, data: bytes | Iterable[bytes]) -> str: ... + def ihave(self, message_id: Any, data: bytes | Iterable[bytes]) -> str: ... def quit(self) -> str: ... - def login(self, user: Optional[str] = ..., password: Optional[str] = ..., usenetrc: bool = ...) -> None: ... - def starttls(self, context: Optional[ssl.SSLContext] = ...) -> None: ... + def login(self, user: str | None = ..., password: str | None = ..., usenetrc: bool = ...) -> None: ... + def starttls(self, context: ssl.SSLContext | None = ...) -> None: ... class NNTP(_NNTPBase): port: int @@ -91,9 +91,9 @@ class NNTP(_NNTPBase): self, host: str, port: int = ..., - user: Optional[str] = ..., - password: Optional[str] = ..., - readermode: Optional[bool] = ..., + user: str | None = ..., + password: str | None = ..., + readermode: bool | None = ..., usenetrc: bool = ..., timeout: float = ..., ) -> None: ... @@ -104,10 +104,10 @@ class NNTP_SSL(_NNTPBase): self, host: str, port: int = ..., - user: Optional[str] = ..., - password: Optional[str] = ..., - ssl_context: Optional[ssl.SSLContext] = ..., - readermode: Optional[bool] = ..., + user: str | None = ..., + password: str | None = ..., + ssl_context: ssl.SSLContext | None = ..., + readermode: bool | None = ..., usenetrc: bool = ..., timeout: float = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/ntpath.pyi b/mypy/typeshed/stdlib/ntpath.pyi index d454d7f93fbf..45d715704157 100644 --- a/mypy/typeshed/stdlib/ntpath.pyi +++ b/mypy/typeshed/stdlib/ntpath.pyi @@ -42,11 +42,11 @@ from posixpath import ( splitext as splitext, supports_unicode_filenames as supports_unicode_filenames, ) -from typing import AnyStr, Tuple, overload +from typing import AnyStr, overload altsep: str if sys.version_info < (3, 7) and sys.platform == "win32": - def splitunc(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... # deprecated + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated # Similar to posixpath, but have slightly different argument names @overload diff --git a/mypy/typeshed/stdlib/numbers.pyi b/mypy/typeshed/stdlib/numbers.pyi index 4f8a5a5d67fc..eaf53d25347a 100644 --- a/mypy/typeshed/stdlib/numbers.pyi +++ b/mypy/typeshed/stdlib/numbers.pyi @@ -1,9 +1,8 @@ # Note: these stubs are incomplete. The more complex type # signatures are currently omitted. -import sys from abc import ABCMeta, abstractmethod -from typing import Any, Optional, SupportsFloat, overload +from typing import Any, SupportsFloat, overload class Number(metaclass=ABCMeta): @abstractmethod @@ -12,10 +11,7 @@ class Number(metaclass=ABCMeta): class Complex(Number): @abstractmethod def __complex__(self) -> complex: ... - if sys.version_info >= (3, 0): - def __bool__(self) -> bool: ... - else: - def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... @property @abstractmethod def real(self) -> Any: ... @@ -36,11 +32,6 @@ class Complex(Number): def __mul__(self, other: Any) -> Any: ... @abstractmethod def __rmul__(self, other: Any) -> Any: ... - if sys.version_info < (3, 0): - @abstractmethod - def __div__(self, other): ... - @abstractmethod - def __rdiv__(self, other): ... @abstractmethod def __truediv__(self, other: Any) -> Any: ... @abstractmethod @@ -52,25 +43,22 @@ class Complex(Number): def __abs__(self) -> Real: ... def conjugate(self) -> Any: ... def __eq__(self, other: Any) -> bool: ... - if sys.version_info < (3, 0): - def __ne__(self, other: Any) -> bool: ... class Real(Complex, SupportsFloat): @abstractmethod def __float__(self) -> float: ... @abstractmethod def __trunc__(self) -> int: ... - if sys.version_info >= (3, 0): - @abstractmethod - def __floor__(self) -> int: ... - @abstractmethod - def __ceil__(self) -> int: ... - @abstractmethod - @overload - def __round__(self, ndigits: None = ...) -> int: ... - @abstractmethod - @overload - def __round__(self, ndigits: int) -> Any: ... + @abstractmethod + def __floor__(self) -> int: ... + @abstractmethod + def __ceil__(self) -> int: ... + @abstractmethod + @overload + def __round__(self, ndigits: None = ...) -> int: ... + @abstractmethod + @overload + def __round__(self, ndigits: int) -> Any: ... def __divmod__(self, other: Any) -> Any: ... def __rdivmod__(self, other: Any) -> Any: ... @abstractmethod @@ -102,15 +90,11 @@ class Rational(Real): def __float__(self) -> float: ... class Integral(Rational): - if sys.version_info >= (3, 0): - @abstractmethod - def __int__(self) -> int: ... - else: - @abstractmethod - def __long__(self) -> long: ... + @abstractmethod + def __int__(self) -> int: ... def __index__(self) -> int: ... @abstractmethod - def __pow__(self, exponent: Any, modulus: Optional[Any] = ...) -> Any: ... + def __pow__(self, exponent: Any, modulus: Any | None = ...) -> Any: ... @abstractmethod def __lshift__(self, other: Any) -> Any: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/opcode.pyi b/mypy/typeshed/stdlib/opcode.pyi index 6307c280aebe..982ddee43a63 100644 --- a/mypy/typeshed/stdlib/opcode.pyi +++ b/mypy/typeshed/stdlib/opcode.pyi @@ -1,25 +1,24 @@ import sys -from typing import Dict, List, Optional, Sequence +from typing import Sequence cmp_op: Sequence[str] -hasconst: List[int] -hasname: List[int] -hasjrel: List[int] -hasjabs: List[int] -haslocal: List[int] -hascompare: List[int] -hasfree: List[int] -opname: List[str] +hasconst: list[int] +hasname: list[int] +hasjrel: list[int] +hasjabs: list[int] +haslocal: list[int] +hascompare: list[int] +hasfree: list[int] +opname: list[str] -opmap: Dict[str, int] +opmap: dict[str, int] HAVE_ARGUMENT: int EXTENDED_ARG: int if sys.version_info >= (3, 8): - def stack_effect(__opcode: int, __oparg: Optional[int] = ..., *, jump: Optional[bool] = ...) -> int: ... + def stack_effect(__opcode: int, __oparg: int | None = ..., *, jump: bool | None = ...) -> int: ... -elif sys.version_info >= (3, 4): - def stack_effect(__opcode: int, __oparg: Optional[int] = ...) -> int: ... +else: + def stack_effect(__opcode: int, __oparg: int | None = ...) -> int: ... -if sys.version_info >= (3, 6): - hasnargs: List[int] +hasnargs: list[int] diff --git a/mypy/typeshed/stdlib/operator.pyi b/mypy/typeshed/stdlib/operator.pyi index 03510fed90fc..bb8e23733f87 100644 --- a/mypy/typeshed/stdlib/operator.pyi +++ b/mypy/typeshed/stdlib/operator.pyi @@ -1,4 +1,3 @@ -import sys from typing import ( Any, Container, @@ -12,6 +11,7 @@ from typing import ( TypeVar, overload, ) +from typing_extensions import final _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) @@ -41,11 +41,6 @@ def add(__a: Any, __b: Any) -> Any: ... def __add__(a: Any, b: Any) -> Any: ... def and_(__a: Any, __b: Any) -> Any: ... def __and__(a: Any, b: Any) -> Any: ... - -if sys.version_info < (3,): - def div(a: Any, b: Any) -> Any: ... - def __div__(a: Any, b: Any) -> Any: ... - def floordiv(__a: Any, __b: Any) -> Any: ... def __floordiv__(a: Any, b: Any) -> Any: ... def index(__a: Any) -> int: ... @@ -60,11 +55,8 @@ def mod(__a: Any, __b: Any) -> Any: ... def __mod__(a: Any, b: Any) -> Any: ... def mul(__a: Any, __b: Any) -> Any: ... def __mul__(a: Any, b: Any) -> Any: ... - -if sys.version_info >= (3, 5): - def matmul(__a: Any, __b: Any) -> Any: ... - def __matmul__(a: Any, b: Any) -> Any: ... - +def matmul(__a: Any, __b: Any) -> Any: ... +def __matmul__(a: Any, b: Any) -> Any: ... def neg(__a: Any) -> Any: ... def __neg__(a: Any) -> Any: ... def or_(__a: Any, __b: Any) -> Any: ... @@ -98,11 +90,6 @@ def __delitem__(a: MutableSequence[Any], b: int) -> None: ... def __delitem__(a: MutableSequence[Any], b: slice) -> None: ... @overload def __delitem__(a: MutableMapping[_K, Any], b: _K) -> None: ... - -if sys.version_info < (3,): - def delslice(a: MutableSequence[Any], b: int, c: int) -> None: ... - def __delslice__(a: MutableSequence[Any], b: int, c: int) -> None: ... - @overload def getitem(__a: Sequence[_T], __b: int) -> _T: ... @overload @@ -115,20 +102,7 @@ def __getitem__(a: Sequence[_T], b: int) -> _T: ... def __getitem__(a: Sequence[_T], b: slice) -> Sequence[_T]: ... @overload def __getitem__(a: Mapping[_K, _V], b: _K) -> _V: ... - -if sys.version_info < (3,): - def getslice(a: Sequence[_T], b: int, c: int) -> Sequence[_T]: ... - def __getslice__(a: Sequence[_T], b: int, c: int) -> Sequence[_T]: ... - def indexOf(__a: Sequence[_T], __b: _T) -> int: ... - -if sys.version_info < (3,): - def repeat(a: Any, b: int) -> Any: ... - def __repeat__(a: Any, b: int) -> Any: ... - -if sys.version_info < (3,): - def sequenceIncludes(a: Container[Any], b: Any) -> bool: ... - @overload def setitem(__a: MutableSequence[_T], __b: int, __c: _T) -> None: ... @overload @@ -141,40 +115,36 @@ def __setitem__(a: MutableSequence[_T], b: int, c: _T) -> None: ... def __setitem__(a: MutableSequence[_T], b: slice, c: Sequence[_T]) -> None: ... @overload def __setitem__(a: MutableMapping[_K, _V], b: _K, c: _V) -> None: ... - -if sys.version_info < (3,): - def setslice(a: MutableSequence[_T], b: int, c: int, v: Sequence[_T]) -> None: ... - def __setslice__(a: MutableSequence[_T], b: int, c: int, v: Sequence[_T]) -> None: ... - -if sys.version_info >= (3, 4): - def length_hint(__obj: Any, __default: int = ...) -> int: ... - +def length_hint(__obj: Any, __default: int = ...) -> int: ... +@final class attrgetter(Generic[_T_co]): @overload def __new__(cls, attr: str) -> attrgetter[Any]: ... @overload - def __new__(cls, attr: str, __attr2: str) -> attrgetter[Tuple[Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str) -> attrgetter[tuple[Any, Any]]: ... @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[Tuple[Any, Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[tuple[Any, Any, Any]]: ... @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[Tuple[Any, Any, Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[tuple[Any, Any, Any, Any]]: ... @overload def __new__(cls, attr: str, *attrs: str) -> attrgetter[Tuple[Any, ...]]: ... def __call__(self, obj: Any) -> _T_co: ... +@final class itemgetter(Generic[_T_co]): @overload def __new__(cls, item: Any) -> itemgetter[Any]: ... @overload - def __new__(cls, item: Any, __item2: Any) -> itemgetter[Tuple[Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any) -> itemgetter[tuple[Any, Any]]: ... @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[Tuple[Any, Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[tuple[Any, Any, Any]]: ... @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[Tuple[Any, Any, Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[tuple[Any, Any, Any, Any]]: ... @overload def __new__(cls, item: Any, *items: Any) -> itemgetter[Tuple[Any, ...]]: ... def __call__(self, obj: Any) -> _T_co: ... +@final class methodcaller: def __init__(self, __name: str, *args: Any, **kwargs: Any) -> None: ... def __call__(self, obj: Any) -> Any: ... @@ -185,11 +155,6 @@ def iand(__a: Any, __b: Any) -> Any: ... def __iand__(a: Any, b: Any) -> Any: ... def iconcat(__a: Any, __b: Any) -> Any: ... def __iconcat__(a: Any, b: Any) -> Any: ... - -if sys.version_info < (3,): - def idiv(a: Any, b: Any) -> Any: ... - def __idiv__(a: Any, b: Any) -> Any: ... - def ifloordiv(__a: Any, __b: Any) -> Any: ... def __ifloordiv__(a: Any, b: Any) -> Any: ... def ilshift(__a: Any, __b: Any) -> Any: ... @@ -198,20 +163,12 @@ def imod(__a: Any, __b: Any) -> Any: ... def __imod__(a: Any, b: Any) -> Any: ... def imul(__a: Any, __b: Any) -> Any: ... def __imul__(a: Any, b: Any) -> Any: ... - -if sys.version_info >= (3, 5): - def imatmul(__a: Any, __b: Any) -> Any: ... - def __imatmul__(a: Any, b: Any) -> Any: ... - +def imatmul(__a: Any, __b: Any) -> Any: ... +def __imatmul__(a: Any, b: Any) -> Any: ... def ior(__a: Any, __b: Any) -> Any: ... def __ior__(a: Any, b: Any) -> Any: ... def ipow(__a: Any, __b: Any) -> Any: ... def __ipow__(a: Any, b: Any) -> Any: ... - -if sys.version_info < (3,): - def irepeat(a: Any, b: int) -> Any: ... - def __irepeat__(a: Any, b: int) -> Any: ... - def irshift(__a: Any, __b: Any) -> Any: ... def __irshift__(a: Any, b: Any) -> Any: ... def isub(__a: Any, __b: Any) -> Any: ... @@ -220,9 +177,3 @@ def itruediv(__a: Any, __b: Any) -> Any: ... def __itruediv__(a: Any, b: Any) -> Any: ... def ixor(__a: Any, __b: Any) -> Any: ... def __ixor__(a: Any, b: Any) -> Any: ... - -if sys.version_info < (3,): - def isCallable(x: Any) -> bool: ... - def isMappingType(x: Any) -> bool: ... - def isNumberType(x: Any) -> bool: ... - def isSequenceType(x: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/optparse.pyi b/mypy/typeshed/stdlib/optparse.pyi index 2229807bc641..b8ea9d2fff38 100644 --- a/mypy/typeshed/stdlib/optparse.pyi +++ b/mypy/typeshed/stdlib/optparse.pyi @@ -1,133 +1,123 @@ -import sys -from typing import IO, Any, AnyStr, Callable, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Type, Union, overload +from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, Tuple, Type, overload -# See https://groups.google.com/forum/#!topic/python-ideas/gA1gdj3RZ5g -if sys.version_info >= (3,): - _Text = str -else: - _Text = Union[str, unicode] +NO_DEFAULT: Tuple[str, ...] +SUPPRESS_HELP: str +SUPPRESS_USAGE: str -NO_DEFAULT: Tuple[_Text, ...] -SUPPRESS_HELP: _Text -SUPPRESS_USAGE: _Text - -def check_builtin(option: Option, opt: Any, value: _Text) -> Any: ... -def check_choice(option: Option, opt: Any, value: _Text) -> Any: ... - -if sys.version_info < (3,): - def isbasestring(x: Any) -> bool: ... +def check_builtin(option: Option, opt: Any, value: str) -> Any: ... +def check_choice(option: Option, opt: Any, value: str) -> Any: ... class OptParseError(Exception): - msg: _Text - def __init__(self, msg: _Text) -> None: ... + msg: str + def __init__(self, msg: str) -> None: ... class BadOptionError(OptParseError): - opt_str: _Text - def __init__(self, opt_str: _Text) -> None: ... + opt_str: str + def __init__(self, opt_str: str) -> None: ... class AmbiguousOptionError(BadOptionError): - possibilities: Iterable[_Text] - def __init__(self, opt_str: _Text, possibilities: Sequence[_Text]) -> None: ... + possibilities: Iterable[str] + def __init__(self, opt_str: str, possibilities: Sequence[str]) -> None: ... class OptionError(OptParseError): - msg: _Text - option_id: _Text - def __init__(self, msg: _Text, option: Option) -> None: ... + msg: str + option_id: str + def __init__(self, msg: str, option: Option) -> None: ... class OptionConflictError(OptionError): ... class OptionValueError(OptParseError): ... class HelpFormatter: - NO_DEFAULT_VALUE: _Text - _long_opt_fmt: _Text - _short_opt_fmt: _Text + NO_DEFAULT_VALUE: str + _long_opt_fmt: str + _short_opt_fmt: str current_indent: int - default_tag: _Text + default_tag: str help_position: Any help_width: Any indent_increment: int level: int max_help_position: int - option_strings: Dict[Option, _Text] + option_strings: dict[Option, str] parser: OptionParser short_first: Any width: int - def __init__(self, indent_increment: int, max_help_position: int, width: Optional[int], short_first: int) -> None: ... + def __init__(self, indent_increment: int, max_help_position: int, width: int | None, short_first: int) -> None: ... def dedent(self) -> None: ... - def expand_default(self, option: Option) -> _Text: ... - def format_description(self, description: _Text) -> _Text: ... - def format_epilog(self, epilog: _Text) -> _Text: ... - def format_heading(self, heading: Any) -> _Text: ... - def format_option(self, option: Option) -> _Text: ... - def format_option_strings(self, option: Option) -> _Text: ... - def format_usage(self, usage: Any) -> _Text: ... + def expand_default(self, option: Option) -> str: ... + def format_description(self, description: str) -> str: ... + def format_epilog(self, epilog: str) -> str: ... + def format_heading(self, heading: Any) -> str: ... + def format_option(self, option: Option) -> str: ... + def format_option_strings(self, option: Option) -> str: ... + def format_usage(self, usage: Any) -> str: ... def indent(self) -> None: ... - def set_long_opt_delimiter(self, delim: _Text) -> None: ... + def set_long_opt_delimiter(self, delim: str) -> None: ... def set_parser(self, parser: OptionParser) -> None: ... - def set_short_opt_delimiter(self, delim: _Text) -> None: ... + def set_short_opt_delimiter(self, delim: str) -> None: ... def store_option_strings(self, parser: OptionParser) -> None: ... class IndentedHelpFormatter(HelpFormatter): def __init__( - self, indent_increment: int = ..., max_help_position: int = ..., width: Optional[int] = ..., short_first: int = ... + self, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ..., short_first: int = ... ) -> None: ... - def format_heading(self, heading: _Text) -> _Text: ... - def format_usage(self, usage: _Text) -> _Text: ... + def format_heading(self, heading: str) -> str: ... + def format_usage(self, usage: str) -> str: ... class TitledHelpFormatter(HelpFormatter): def __init__( - self, indent_increment: int = ..., max_help_position: int = ..., width: Optional[int] = ..., short_first: int = ... + self, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ..., short_first: int = ... ) -> None: ... - def format_heading(self, heading: _Text) -> _Text: ... - def format_usage(self, usage: _Text) -> _Text: ... + def format_heading(self, heading: str) -> str: ... + def format_usage(self, usage: str) -> str: ... class Option: - ACTIONS: Tuple[_Text, ...] - ALWAYS_TYPED_ACTIONS: Tuple[_Text, ...] - ATTRS: List[_Text] - CHECK_METHODS: Optional[List[Callable[..., Any]]] - CONST_ACTIONS: Tuple[_Text, ...] - STORE_ACTIONS: Tuple[_Text, ...] - TYPED_ACTIONS: Tuple[_Text, ...] - TYPES: Tuple[_Text, ...] - TYPE_CHECKER: Dict[_Text, Callable[..., Any]] - _long_opts: List[_Text] - _short_opts: List[_Text] - action: _Text - dest: Optional[_Text] + ACTIONS: Tuple[str, ...] + ALWAYS_TYPED_ACTIONS: Tuple[str, ...] + ATTRS: list[str] + CHECK_METHODS: list[Callable[..., Any]] | None + CONST_ACTIONS: Tuple[str, ...] + STORE_ACTIONS: Tuple[str, ...] + TYPED_ACTIONS: Tuple[str, ...] + TYPES: Tuple[str, ...] + TYPE_CHECKER: dict[str, Callable[..., Any]] + _long_opts: list[str] + _short_opts: list[str] + action: str + dest: str | None default: Any nargs: int type: Any - callback: Optional[Callable[..., Any]] - callback_args: Optional[Tuple[Any, ...]] - callback_kwargs: Optional[Dict[_Text, Any]] - help: Optional[_Text] - metavar: Optional[_Text] - def __init__(self, *opts: Optional[_Text], **attrs: Any) -> None: ... + callback: Callable[..., Any] | None + callback_args: Tuple[Any, ...] | None + callback_kwargs: dict[str, Any] | None + help: str | None + metavar: str | None + def __init__(self, *opts: str | None, **attrs: Any) -> None: ... def _check_action(self) -> None: ... def _check_callback(self) -> None: ... def _check_choice(self) -> None: ... def _check_const(self) -> None: ... def _check_dest(self) -> None: ... def _check_nargs(self) -> None: ... - def _check_opt_strings(self, opts: Iterable[Optional[_Text]]) -> List[_Text]: ... + def _check_opt_strings(self, opts: Iterable[str | None]) -> list[str]: ... def _check_type(self) -> None: ... - def _set_attrs(self, attrs: Dict[_Text, Any]) -> None: ... - def _set_opt_strings(self, opts: Iterable[_Text]) -> None: ... - def check_value(self, opt: _Text, value: Any) -> Any: ... - def convert_value(self, opt: _Text, value: Any) -> Any: ... - def get_opt_string(self) -> _Text: ... + def _set_attrs(self, attrs: dict[str, Any]) -> None: ... + def _set_opt_strings(self, opts: Iterable[str]) -> None: ... + def check_value(self, opt: str, value: Any) -> Any: ... + def convert_value(self, opt: str, value: Any) -> Any: ... + def get_opt_string(self) -> str: ... def process(self, opt: Any, value: Any, values: Any, parser: OptionParser) -> int: ... - def take_action(self, action: _Text, dest: _Text, opt: Any, value: Any, values: Any, parser: OptionParser) -> int: ... + def take_action(self, action: str, dest: str, opt: Any, value: Any, values: Any, parser: OptionParser) -> int: ... def takes_value(self) -> bool: ... make_option = Option class OptionContainer: - _long_opt: Dict[_Text, Option] - _short_opt: Dict[_Text, Option] - conflict_handler: _Text - defaults: Dict[_Text, Any] + _long_opt: dict[str, Option] + _short_opt: dict[str, Option] + conflict_handler: str + defaults: dict[str, Any] description: Any option_class: Type[Option] def __init__(self, option_class: Type[Option], conflict_handler: Any, description: Any) -> None: ... @@ -137,101 +127,99 @@ class OptionContainer: @overload def add_option(self, opt: Option) -> Option: ... @overload - def add_option(self, *args: Optional[_Text], **kwargs: Any) -> Any: ... + def add_option(self, *args: str | None, **kwargs: Any) -> Any: ... def add_options(self, option_list: Iterable[Option]) -> None: ... def destroy(self) -> None: ... - def format_description(self, formatter: Optional[HelpFormatter]) -> Any: ... - def format_help(self, formatter: Optional[HelpFormatter]) -> _Text: ... - def format_option_help(self, formatter: Optional[HelpFormatter]) -> _Text: ... + def format_description(self, formatter: HelpFormatter | None) -> Any: ... + def format_help(self, formatter: HelpFormatter | None) -> str: ... + def format_option_help(self, formatter: HelpFormatter | None) -> str: ... def get_description(self) -> Any: ... - def get_option(self, opt_str: _Text) -> Optional[Option]: ... - def has_option(self, opt_str: _Text) -> bool: ... - def remove_option(self, opt_str: _Text) -> None: ... + def get_option(self, opt_str: str) -> Option | None: ... + def has_option(self, opt_str: str) -> bool: ... + def remove_option(self, opt_str: str) -> None: ... def set_conflict_handler(self, handler: Any) -> None: ... def set_description(self, description: Any) -> None: ... class OptionGroup(OptionContainer): - option_list: List[Option] + option_list: list[Option] parser: OptionParser - title: _Text - def __init__(self, parser: OptionParser, title: _Text, description: Optional[_Text] = ...) -> None: ... + title: str + def __init__(self, parser: OptionParser, title: str, description: str | None = ...) -> None: ... def _create_option_list(self) -> None: ... - def set_title(self, title: _Text) -> None: ... + def set_title(self, title: str) -> None: ... class Values: - def __init__(self, defaults: Optional[Mapping[str, Any]] = ...) -> None: ... - def _update(self, dict: Mapping[_Text, Any], mode: Any) -> None: ... - def _update_careful(self, dict: Mapping[_Text, Any]) -> None: ... - def _update_loose(self, dict: Mapping[_Text, Any]) -> None: ... - def ensure_value(self, attr: _Text, value: Any) -> Any: ... - def read_file(self, filename: _Text, mode: _Text = ...) -> None: ... - def read_module(self, modname: _Text, mode: _Text = ...) -> None: ... + def __init__(self, defaults: Mapping[str, Any] | None = ...) -> None: ... + def _update(self, dict: Mapping[str, Any], mode: Any) -> None: ... + def _update_careful(self, dict: Mapping[str, Any]) -> None: ... + def _update_loose(self, dict: Mapping[str, Any]) -> None: ... + def ensure_value(self, attr: str, value: Any) -> Any: ... + def read_file(self, filename: str, mode: str = ...) -> None: ... + def read_module(self, modname: str, mode: str = ...) -> None: ... def __getattr__(self, name: str) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... class OptionParser(OptionContainer): allow_interspersed_args: bool - epilog: Optional[_Text] + epilog: str | None formatter: HelpFormatter - largs: Optional[List[_Text]] - option_groups: List[OptionGroup] - option_list: List[Option] + largs: list[str] | None + option_groups: list[OptionGroup] + option_list: list[Option] process_default_values: Any - prog: Optional[_Text] - rargs: Optional[List[Any]] - standard_option_list: List[Option] - usage: Optional[_Text] - values: Optional[Values] - version: _Text + prog: str | None + rargs: list[Any] | None + standard_option_list: list[Option] + usage: str | None + values: Values | None + version: str def __init__( self, - usage: Optional[_Text] = ..., - option_list: Optional[Iterable[Option]] = ..., + usage: str | None = ..., + option_list: Iterable[Option] | None = ..., option_class: Type[Option] = ..., - version: Optional[_Text] = ..., - conflict_handler: _Text = ..., - description: Optional[_Text] = ..., - formatter: Optional[HelpFormatter] = ..., + version: str | None = ..., + conflict_handler: str = ..., + description: str | None = ..., + formatter: HelpFormatter | None = ..., add_help_option: bool = ..., - prog: Optional[_Text] = ..., - epilog: Optional[_Text] = ..., + prog: str | None = ..., + epilog: str | None = ..., ) -> None: ... def _add_help_option(self) -> None: ... def _add_version_option(self) -> None: ... def _create_option_list(self) -> None: ... - def _get_all_options(self) -> List[Option]: ... - def _get_args(self, args: Iterable[Any]) -> List[Any]: ... + def _get_all_options(self) -> list[Option]: ... + def _get_args(self, args: Iterable[Any]) -> list[Any]: ... def _init_parsing_state(self) -> None: ... - def _match_long_opt(self, opt: _Text) -> _Text: ... + def _match_long_opt(self, opt: str) -> str: ... def _populate_option_list(self, option_list: Iterable[Option], add_help: bool = ...) -> None: ... - def _process_args(self, largs: List[Any], rargs: List[Any], values: Values) -> None: ... - def _process_long_opt(self, rargs: List[Any], values: Any) -> None: ... - def _process_short_opts(self, rargs: List[Any], values: Any) -> None: ... + def _process_args(self, largs: list[Any], rargs: list[Any], values: Values) -> None: ... + def _process_long_opt(self, rargs: list[Any], values: Any) -> None: ... + def _process_short_opts(self, rargs: list[Any], values: Any) -> None: ... @overload def add_option_group(self, __opt_group: OptionGroup) -> OptionGroup: ... @overload def add_option_group(self, *args: Any, **kwargs: Any) -> OptionGroup: ... - def check_values(self, values: Values, args: List[_Text]) -> Tuple[Values, List[_Text]]: ... + def check_values(self, values: Values, args: list[str]) -> tuple[Values, list[str]]: ... def disable_interspersed_args(self) -> None: ... def enable_interspersed_args(self) -> None: ... - def error(self, msg: _Text) -> None: ... - def exit(self, status: int = ..., msg: Optional[str] = ...) -> None: ... - def expand_prog_name(self, s: Optional[_Text]) -> Any: ... + def error(self, msg: str) -> None: ... + def exit(self, status: int = ..., msg: str | None = ...) -> None: ... + def expand_prog_name(self, s: str | None) -> Any: ... def format_epilog(self, formatter: HelpFormatter) -> Any: ... - def format_help(self, formatter: Optional[HelpFormatter] = ...) -> _Text: ... - def format_option_help(self, formatter: Optional[HelpFormatter] = ...) -> _Text: ... + def format_help(self, formatter: HelpFormatter | None = ...) -> str: ... + def format_option_help(self, formatter: HelpFormatter | None = ...) -> str: ... def get_default_values(self) -> Values: ... - def get_option_group(self, opt_str: _Text) -> Any: ... - def get_prog_name(self) -> _Text: ... - def get_usage(self) -> _Text: ... - def get_version(self) -> _Text: ... - def parse_args( - self, args: Optional[Sequence[AnyStr]] = ..., values: Optional[Values] = ... - ) -> Tuple[Values, List[AnyStr]]: ... - def print_usage(self, file: Optional[IO[str]] = ...) -> None: ... - def print_help(self, file: Optional[IO[str]] = ...) -> None: ... - def print_version(self, file: Optional[IO[str]] = ...) -> None: ... + def get_option_group(self, opt_str: str) -> Any: ... + def get_prog_name(self) -> str: ... + def get_usage(self) -> str: ... + def get_version(self) -> str: ... + def parse_args(self, args: Sequence[AnyStr] | None = ..., values: Values | None = ...) -> tuple[Values, list[AnyStr]]: ... + def print_usage(self, file: IO[str] | None = ...) -> None: ... + def print_help(self, file: IO[str] | None = ...) -> None: ... + def print_version(self, file: IO[str] | None = ...) -> None: ... def set_default(self, dest: Any, value: Any) -> None: ... def set_defaults(self, **kwargs: Any) -> None: ... def set_process_default_values(self, process: Any) -> None: ... - def set_usage(self, usage: _Text) -> None: ... + def set_usage(self, usage: str) -> None: ... diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index 4500a748d574..d65681a46c3f 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -1,12 +1,14 @@ import sys from _typeshed import ( - AnyPath, FileDescriptorLike, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, OpenBinaryModeWriting, OpenTextMode, + Self, + StrOrBytesPath, + StrPath, ) from builtins import OSError from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper as _TextIOWrapper @@ -19,7 +21,6 @@ from typing import ( BinaryIO, Callable, ContextManager, - Dict, Generic, Iterable, Iterator, @@ -27,17 +28,15 @@ from typing import ( Mapping, MutableMapping, NoReturn, - Optional, Protocol, Sequence, - Set, Tuple, TypeVar, Union, overload, runtime_checkable, ) -from typing_extensions import Literal +from typing_extensions import Literal, final from . import path as _path @@ -56,10 +55,10 @@ error = OSError supports_bytes_environ: bool -supports_dir_fd: Set[Callable[..., Any]] -supports_fd: Set[Callable[..., Any]] -supports_effective_ids: Set[Callable[..., Any]] -supports_follow_symlinks: Set[Callable[..., Any]] +supports_dir_fd: set[Callable[..., Any]] +supports_fd: set[Callable[..., Any]] +supports_effective_ids: set[Callable[..., Any]] +supports_follow_symlinks: set[Callable[..., Any]] if sys.platform != "win32": # Unix only @@ -169,7 +168,7 @@ sep: str if sys.platform == "win32": altsep: str else: - altsep: Optional[str] + altsep: str | None extsep: str pathsep: str defpath: str @@ -212,7 +211,7 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): unsetenv: Callable[[AnyStr, AnyStr], None], ) -> None: ... def setdefault(self, key: AnyStr, value: AnyStr) -> AnyStr: ... # type: ignore - def copy(self) -> Dict[AnyStr, AnyStr]: ... + def copy(self) -> dict[AnyStr, AnyStr]: ... def __delitem__(self, key: AnyStr) -> None: ... def __getitem__(self, key: AnyStr) -> AnyStr: ... def __setitem__(self, key: AnyStr, value: AnyStr) -> None: ... @@ -224,9 +223,9 @@ if sys.platform != "win32": environb: _Environ[bytes] if sys.platform != "win32": - confstr_names: Dict[str, int] - pathconf_names: Dict[str, int] - sysconf_names: Dict[str, int] + confstr_names: dict[str, int] + pathconf_names: dict[str, int] + sysconf_names: dict[str, int] EX_OK: int EX_USAGE: int @@ -262,6 +261,7 @@ if sys.platform != "win32": TMP_MAX: int # Undocumented, but used by tempfile # ----- os classes (structures) ----- +@final class stat_result: # For backward compatibility, the return value of stat() is also # accessible as a tuple of at least 10 integers giving the most important @@ -310,10 +310,11 @@ class stat_result: class PathLike(Protocol[_AnyStr_co]): def __fspath__(self) -> _AnyStr_co: ... -_FdOrAnyPath = Union[int, AnyPath] +_FdOrAnyPath = Union[int, StrOrBytesPath] +@final class DirEntry(Generic[AnyStr]): - # This is what the scandir interator yields + # This is what the scandir iterator yields # The constructor is hidden name: AnyStr @@ -332,8 +333,9 @@ if sys.platform != "win32": _Tuple11Int = Tuple[int, int, int, int, int, int, int, int, int, int, int] if sys.version_info >= (3, 7): # f_fsid was added in https://github.com/python/cpython/pull/4571 + @final class statvfs_result(_Tuple10Int): # Unix only - def __new__(cls, seq: Union[_Tuple10Int, _Tuple11Int], dict: Dict[str, int] = ...) -> statvfs_result: ... + def __new__(cls, seq: _Tuple10Int | _Tuple11Int, dict: dict[str, int] = ...) -> statvfs_result: ... n_fields: int n_sequence_fields: int n_unnamed_fields: int @@ -348,7 +350,7 @@ if sys.platform != "win32": f_favail: int f_flag: int f_namemax: int - f_fsid: int = ... + f_fsid: int else: class statvfs_result(_Tuple10Int): # Unix only n_fields: int @@ -367,17 +369,15 @@ if sys.platform != "win32": f_namemax: int # ----- os function stubs ----- -def fsencode(filename: Union[str, bytes, PathLike[Any]]) -> bytes: ... -def fsdecode(filename: Union[str, bytes, PathLike[Any]]) -> str: ... +def fsencode(filename: StrOrBytesPath) -> bytes: ... +def fsdecode(filename: StrOrBytesPath) -> str: ... @overload def fspath(path: str) -> str: ... @overload def fspath(path: bytes) -> bytes: ... @overload def fspath(path: PathLike[AnyStr]) -> AnyStr: ... -def get_exec_path(env: Optional[Mapping[str, str]] = ...) -> List[str]: ... - -# NOTE: get_exec_path(): returns List[bytes] when env not None +def get_exec_path(env: Mapping[str, str] | None = ...) -> list[str]: ... def getlogin() -> str: ... def getpid() -> int: ... def getppid() -> int: ... @@ -390,16 +390,16 @@ if sys.platform != "win32": def getegid() -> int: ... def geteuid() -> int: ... def getgid() -> int: ... - def getgrouplist(__user: str, __group: int) -> List[int]: ... - def getgroups() -> List[int]: ... # Unix only, behaves differently on Mac + def getgrouplist(__user: str, __group: int) -> list[int]: ... + def getgroups() -> list[int]: ... # Unix only, behaves differently on Mac def initgroups(__username: str, __gid: int) -> None: ... def getpgid(pid: int) -> int: ... def getpgrp() -> int: ... def getpriority(which: int, who: int) -> int: ... def setpriority(which: int, who: int, priority: int) -> None: ... if sys.platform != "darwin": - def getresuid() -> Tuple[int, int, int]: ... - def getresgid() -> Tuple[int, int, int]: ... + def getresuid() -> tuple[int, int, int]: ... + def getresgid() -> tuple[int, int, int]: ... def getuid() -> int: ... def setegid(__egid: int) -> None: ... def seteuid(__euid: int) -> None: ... @@ -419,20 +419,20 @@ if sys.platform != "win32": def uname() -> uname_result: ... @overload -def getenv(key: str) -> Optional[str]: ... +def getenv(key: str) -> str | None: ... @overload -def getenv(key: str, default: _T) -> Union[str, _T]: ... +def getenv(key: str, default: _T) -> str | _T: ... if sys.platform != "win32": @overload - def getenvb(key: bytes) -> Optional[bytes]: ... + def getenvb(key: bytes) -> bytes | None: ... @overload - def getenvb(key: bytes, default: _T) -> Union[bytes, _T]: ... + def getenvb(key: bytes, default: _T) -> bytes | _T: ... -def putenv(__name: Union[bytes, str], __value: Union[bytes, str]) -> None: ... +def putenv(__name: bytes | str, __value: bytes | str) -> None: ... if sys.platform != "win32": - def unsetenv(__name: Union[bytes, str]) -> None: ... + def unsetenv(__name: bytes | str) -> None: ... _Opener = Callable[[str, int], int] @@ -441,11 +441,11 @@ def fdopen( fd: int, mode: OpenTextMode = ..., buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> _TextIOWrapper: ... @overload def fdopen( @@ -456,7 +456,7 @@ def fdopen( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> FileIO: ... @overload def fdopen( @@ -467,7 +467,7 @@ def fdopen( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedRandom: ... @overload def fdopen( @@ -478,7 +478,7 @@ def fdopen( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedWriter: ... @overload def fdopen( @@ -489,7 +489,7 @@ def fdopen( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BufferedReader: ... @overload def fdopen( @@ -500,22 +500,22 @@ def fdopen( errors: None = ..., newline: None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> BinaryIO: ... @overload def fdopen( fd: int, mode: str, buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., closefd: bool = ..., - opener: Optional[_Opener] = ..., + opener: _Opener | None = ..., ) -> IO[Any]: ... def close(fd: int) -> None: ... def closerange(__fd_low: int, __fd_high: int) -> None: ... -def device_encoding(fd: int) -> Optional[str]: ... +def device_encoding(fd: int) -> str | None: ... def dup(__fd: int) -> int: ... if sys.version_info >= (3, 7): @@ -527,8 +527,8 @@ else: def fstat(fd: int) -> stat_result: ... def fsync(fd: FileDescriptorLike) -> None: ... def lseek(__fd: int, __position: int, __how: int) -> int: ... -def open(path: AnyPath, flags: int, mode: int = ..., *, dir_fd: Optional[int] = ...) -> int: ... -def pipe() -> Tuple[int, int]: ... +def open(path: StrOrBytesPath, flags: int, mode: int = ..., *, dir_fd: int | None = ...) -> int: ... +def pipe() -> tuple[int, int]: ... def read(__fd: int, __length: int) -> bytes: ... if sys.platform != "win32": @@ -537,22 +537,22 @@ if sys.platform != "win32": def fchown(fd: int, uid: int, gid: int) -> None: ... if sys.platform != "darwin": def fdatasync(fd: FileDescriptorLike) -> None: ... # Unix only, not Mac - def fpathconf(__fd: int, __name: Union[str, int]) -> int: ... + def fpathconf(__fd: int, __name: str | int) -> int: ... def fstatvfs(__fd: int) -> statvfs_result: ... def ftruncate(__fd: int, __length: int) -> None: ... def get_blocking(__fd: int) -> bool: ... def set_blocking(__fd: int, __blocking: bool) -> None: ... def isatty(__fd: int) -> bool: ... def lockf(__fd: int, __command: int, __length: int) -> None: ... - def openpty() -> Tuple[int, int]: ... # some flavors of Unix + def openpty() -> tuple[int, int]: ... # some flavors of Unix if sys.platform != "darwin": - def pipe2(flags: int) -> Tuple[int, int]: ... # some flavors of Unix + def pipe2(flags: int) -> tuple[int, int]: ... # some flavors of Unix def posix_fallocate(fd: int, offset: int, length: int) -> None: ... def posix_fadvise(fd: int, offset: int, length: int, advice: int) -> None: ... def pread(__fd: int, __length: int, __offset: int) -> bytes: ... def pwrite(__fd: int, __buffer: bytes, __offset: int) -> int: ... @overload - def sendfile(out_fd: int, in_fd: int, offset: Optional[int], count: int) -> int: ... + def sendfile(out_fd: int, in_fd: int, offset: int | None, count: int) -> int: ... @overload def sendfile( out_fd: int, @@ -566,6 +566,7 @@ if sys.platform != "win32": def readv(__fd: int, __buffers: Sequence[bytearray]) -> int: ... def writev(__fd: int, __buffers: Sequence[bytes]) -> int: ... +@final class terminal_size(Tuple[int, int]): columns: int lines: int @@ -582,7 +583,7 @@ if sys.platform != "win32": def write(__fd: int, __data: bytes) -> int: ... def access( - path: _FdOrAnyPath, mode: int, *, dir_fd: Optional[int] = ..., effective_ids: bool = ..., follow_symlinks: bool = ... + path: _FdOrAnyPath, mode: int, *, dir_fd: int | None = ..., effective_ids: bool = ..., follow_symlinks: bool = ... ) -> bool: ... def chdir(path: _FdOrAnyPath) -> None: ... @@ -591,46 +592,51 @@ if sys.platform != "win32": def getcwd() -> str: ... def getcwdb() -> bytes: ... -def chmod(path: _FdOrAnyPath, mode: int, *, dir_fd: Optional[int] = ..., follow_symlinks: bool = ...) -> None: ... +def chmod(path: _FdOrAnyPath, mode: int, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> None: ... if sys.platform != "win32": - def chflags(path: AnyPath, flags: int, follow_symlinks: bool = ...) -> None: ... # some flavors of Unix + def chflags(path: StrOrBytesPath, flags: int, follow_symlinks: bool = ...) -> None: ... # some flavors of Unix def chown( - path: _FdOrAnyPath, uid: int, gid: int, *, dir_fd: Optional[int] = ..., follow_symlinks: bool = ... + path: _FdOrAnyPath, uid: int, gid: int, *, dir_fd: int | None = ..., follow_symlinks: bool = ... ) -> None: ... # Unix only if sys.platform != "win32": # Unix only - def chroot(path: AnyPath) -> None: ... - def lchflags(path: AnyPath, flags: int) -> None: ... - def lchmod(path: AnyPath, mode: int) -> None: ... - def lchown(path: AnyPath, uid: int, gid: int) -> None: ... + def chroot(path: StrOrBytesPath) -> None: ... + def lchflags(path: StrOrBytesPath, flags: int) -> None: ... + def lchmod(path: StrOrBytesPath, mode: int) -> None: ... + def lchown(path: StrOrBytesPath, uid: int, gid: int) -> None: ... def link( - src: AnyPath, dst: AnyPath, *, src_dir_fd: Optional[int] = ..., dst_dir_fd: Optional[int] = ..., follow_symlinks: bool = ... + src: StrOrBytesPath, + dst: StrOrBytesPath, + *, + src_dir_fd: int | None = ..., + dst_dir_fd: int | None = ..., + follow_symlinks: bool = ..., ) -> None: ... -def lstat(path: AnyPath, *, dir_fd: Optional[int] = ...) -> stat_result: ... -def mkdir(path: AnyPath, mode: int = ..., *, dir_fd: Optional[int] = ...) -> None: ... +def lstat(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> stat_result: ... +def mkdir(path: StrOrBytesPath, mode: int = ..., *, dir_fd: int | None = ...) -> None: ... if sys.platform != "win32": - def mkfifo(path: AnyPath, mode: int = ..., *, dir_fd: Optional[int] = ...) -> None: ... # Unix only + def mkfifo(path: StrOrBytesPath, mode: int = ..., *, dir_fd: int | None = ...) -> None: ... # Unix only -def makedirs(name: AnyPath, mode: int = ..., exist_ok: bool = ...) -> None: ... +def makedirs(name: StrOrBytesPath, mode: int = ..., exist_ok: bool = ...) -> None: ... if sys.platform != "win32": - def mknod(path: AnyPath, mode: int = ..., device: int = ..., *, dir_fd: Optional[int] = ...) -> None: ... + def mknod(path: StrOrBytesPath, mode: int = ..., device: int = ..., *, dir_fd: int | None = ...) -> None: ... def major(__device: int) -> int: ... def minor(__device: int) -> int: ... def makedev(__major: int, __minor: int) -> int: ... - def pathconf(path: _FdOrAnyPath, name: Union[str, int]) -> int: ... # Unix only + def pathconf(path: _FdOrAnyPath, name: str | int) -> int: ... # Unix only -def readlink(path: Union[AnyStr, PathLike[AnyStr]], *, dir_fd: Optional[int] = ...) -> AnyStr: ... -def remove(path: AnyPath, *, dir_fd: Optional[int] = ...) -> None: ... -def removedirs(name: AnyPath) -> None: ... -def rename(src: AnyPath, dst: AnyPath, *, src_dir_fd: Optional[int] = ..., dst_dir_fd: Optional[int] = ...) -> None: ... -def renames(old: AnyPath, new: AnyPath) -> None: ... -def replace(src: AnyPath, dst: AnyPath, *, src_dir_fd: Optional[int] = ..., dst_dir_fd: Optional[int] = ...) -> None: ... -def rmdir(path: AnyPath, *, dir_fd: Optional[int] = ...) -> None: ... +def readlink(path: AnyStr | PathLike[AnyStr], *, dir_fd: int | None = ...) -> AnyStr: ... +def remove(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... +def removedirs(name: StrOrBytesPath) -> None: ... +def rename(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = ..., dst_dir_fd: int | None = ...) -> None: ... +def renames(old: StrOrBytesPath, new: StrOrBytesPath) -> None: ... +def replace(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = ..., dst_dir_fd: int | None = ...) -> None: ... +def rmdir(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... class _ScandirIterator(Iterator[DirEntry[AnyStr]], ContextManager[_ScandirIterator[AnyStr]]): def __next__(self) -> DirEntry[AnyStr]: ... @@ -642,15 +648,15 @@ if sys.version_info >= (3, 7): @overload def scandir(path: int) -> _ScandirIterator[str]: ... @overload - def scandir(path: Union[AnyStr, PathLike[AnyStr]]) -> _ScandirIterator[AnyStr]: ... + def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... else: @overload def scandir(path: None = ...) -> _ScandirIterator[str]: ... @overload - def scandir(path: Union[AnyStr, PathLike[AnyStr]]) -> _ScandirIterator[AnyStr]: ... + def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... -def stat(path: _FdOrAnyPath, *, dir_fd: Optional[int] = ..., follow_symlinks: bool = ...) -> stat_result: ... +def stat(path: _FdOrAnyPath, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> stat_result: ... if sys.version_info < (3, 7): @overload @@ -661,82 +667,82 @@ if sys.version_info < (3, 7): if sys.platform != "win32": def statvfs(path: _FdOrAnyPath) -> statvfs_result: ... # Unix only -def symlink(src: AnyPath, dst: AnyPath, target_is_directory: bool = ..., *, dir_fd: Optional[int] = ...) -> None: ... +def symlink(src: StrOrBytesPath, dst: StrOrBytesPath, target_is_directory: bool = ..., *, dir_fd: int | None = ...) -> None: ... if sys.platform != "win32": def sync() -> None: ... # Unix only def truncate(path: _FdOrAnyPath, length: int) -> None: ... # Unix only up to version 3.4 -def unlink(path: AnyPath, *, dir_fd: Optional[int] = ...) -> None: ... +def unlink(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... def utime( path: _FdOrAnyPath, - times: Optional[Union[Tuple[int, int], Tuple[float, float]]] = ..., + times: tuple[int, int] | tuple[float, float] | None = ..., *, - ns: Tuple[int, int] = ..., - dir_fd: Optional[int] = ..., + ns: tuple[int, int] = ..., + dir_fd: int | None = ..., follow_symlinks: bool = ..., ) -> None: ... _OnError = Callable[[OSError], Any] def walk( - top: Union[AnyStr, PathLike[AnyStr]], topdown: bool = ..., onerror: Optional[_OnError] = ..., followlinks: bool = ... -) -> Iterator[Tuple[AnyStr, List[AnyStr], List[AnyStr]]]: ... + top: AnyStr | PathLike[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... +) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]: ... if sys.platform != "win32": if sys.version_info >= (3, 7): @overload def fwalk( - top: Union[str, PathLike[str]] = ..., + top: StrPath = ..., topdown: bool = ..., - onerror: Optional[_OnError] = ..., + onerror: _OnError | None = ..., *, follow_symlinks: bool = ..., - dir_fd: Optional[int] = ..., - ) -> Iterator[Tuple[str, List[str], List[str], int]]: ... + dir_fd: int | None = ..., + ) -> Iterator[tuple[str, list[str], list[str], int]]: ... @overload def fwalk( top: bytes, topdown: bool = ..., - onerror: Optional[_OnError] = ..., + onerror: _OnError | None = ..., *, follow_symlinks: bool = ..., - dir_fd: Optional[int] = ..., - ) -> Iterator[Tuple[bytes, List[bytes], List[bytes], int]]: ... + dir_fd: int | None = ..., + ) -> Iterator[tuple[bytes, list[bytes], list[bytes], int]]: ... else: def fwalk( - top: Union[str, PathLike[str]] = ..., + top: StrPath = ..., topdown: bool = ..., - onerror: Optional[_OnError] = ..., + onerror: _OnError | None = ..., *, follow_symlinks: bool = ..., - dir_fd: Optional[int] = ..., - ) -> Iterator[Tuple[str, List[str], List[str], int]]: ... + dir_fd: int | None = ..., + ) -> Iterator[tuple[str, list[str], list[str], int]]: ... if sys.platform == "linux": - def getxattr(path: _FdOrAnyPath, attribute: AnyPath, *, follow_symlinks: bool = ...) -> bytes: ... - def listxattr(path: Optional[_FdOrAnyPath] = ..., *, follow_symlinks: bool = ...) -> List[str]: ... - def removexattr(path: _FdOrAnyPath, attribute: AnyPath, *, follow_symlinks: bool = ...) -> None: ... + def getxattr(path: _FdOrAnyPath, attribute: StrOrBytesPath, *, follow_symlinks: bool = ...) -> bytes: ... + def listxattr(path: _FdOrAnyPath | None = ..., *, follow_symlinks: bool = ...) -> list[str]: ... + def removexattr(path: _FdOrAnyPath, attribute: StrOrBytesPath, *, follow_symlinks: bool = ...) -> None: ... def setxattr( - path: _FdOrAnyPath, attribute: AnyPath, value: bytes, flags: int = ..., *, follow_symlinks: bool = ... + path: _FdOrAnyPath, attribute: StrOrBytesPath, value: bytes, flags: int = ..., *, follow_symlinks: bool = ... ) -> None: ... def abort() -> NoReturn: ... # These are defined as execl(file, *args) but the first *arg is mandatory. -def execl(file: AnyPath, __arg0: AnyPath, *args: AnyPath) -> NoReturn: ... -def execlp(file: AnyPath, __arg0: AnyPath, *args: AnyPath) -> NoReturn: ... +def execl(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: StrOrBytesPath) -> NoReturn: ... +def execlp(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: StrOrBytesPath) -> NoReturn: ... # These are: execle(file, *args, env) but env is pulled from the last element of the args. -def execle(file: AnyPath, __arg0: AnyPath, *args: Any) -> NoReturn: ... -def execlpe(file: AnyPath, __arg0: AnyPath, *args: Any) -> NoReturn: ... +def execle(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: Any) -> NoReturn: ... +def execlpe(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: Any) -> NoReturn: ... # The docs say `args: tuple or list of strings` # The implementation enforces tuple or list so we can't use Sequence. # Not separating out PathLike[str] and PathLike[bytes] here because it doesn't make much difference # in practice, and doing so would explode the number of combinations in this already long union. -# All these combinations are necessary due to List being invariant. +# All these combinations are necessary due to list being invariant. _ExecVArgs = Union[ - Tuple[AnyPath, ...], + Tuple[StrOrBytesPath, ...], List[bytes], List[str], List[PathLike[Any]], @@ -747,17 +753,17 @@ _ExecVArgs = Union[ ] _ExecEnv = Union[Mapping[bytes, Union[bytes, str]], Mapping[str, Union[bytes, str]]] -def execv(__path: AnyPath, __argv: _ExecVArgs) -> NoReturn: ... +def execv(__path: StrOrBytesPath, __argv: _ExecVArgs) -> NoReturn: ... def execve(path: _FdOrAnyPath, argv: _ExecVArgs, env: _ExecEnv) -> NoReturn: ... -def execvp(file: AnyPath, args: _ExecVArgs) -> NoReturn: ... -def execvpe(file: AnyPath, args: _ExecVArgs, env: _ExecEnv) -> NoReturn: ... +def execvp(file: StrOrBytesPath, args: _ExecVArgs) -> NoReturn: ... +def execvpe(file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> NoReturn: ... def _exit(status: int) -> NoReturn: ... def kill(__pid: int, __signal: int) -> None: ... if sys.platform != "win32": # Unix only def fork() -> int: ... - def forkpty() -> Tuple[int, int]: ... # some flavors of Unix + def forkpty() -> tuple[int, int]: ... # some flavors of Unix def killpg(__pgid: int, __signal: int) -> None: ... def nice(__increment: int) -> int: ... if sys.platform != "darwin": @@ -765,39 +771,39 @@ if sys.platform != "win32": class _wrap_close(_TextIOWrapper): def __init__(self, stream: _TextIOWrapper, proc: Popen[str]) -> None: ... - def close(self) -> Optional[int]: ... # type: ignore + def close(self) -> int | None: ... # type: ignore def popen(cmd: str, mode: str = ..., buffering: int = ...) -> _wrap_close: ... -def spawnl(mode: int, file: AnyPath, arg0: AnyPath, *args: AnyPath) -> int: ... -def spawnle(mode: int, file: AnyPath, arg0: AnyPath, *args: Any) -> int: ... # Imprecise sig +def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... +def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise sig if sys.platform != "win32": - def spawnv(mode: int, file: AnyPath, args: _ExecVArgs) -> int: ... - def spawnve(mode: int, file: AnyPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... else: - def spawnv(__mode: int, __path: AnyPath, __argv: _ExecVArgs) -> int: ... - def spawnve(__mode: int, __path: AnyPath, __argv: _ExecVArgs, __env: _ExecEnv) -> int: ... + def spawnv(__mode: int, __path: StrOrBytesPath, __argv: _ExecVArgs) -> int: ... + def spawnve(__mode: int, __path: StrOrBytesPath, __argv: _ExecVArgs, __env: _ExecEnv) -> int: ... -def system(command: AnyPath) -> int: ... +def system(command: StrOrBytesPath) -> int: ... def times() -> times_result: ... -def waitpid(__pid: int, __options: int) -> Tuple[int, int]: ... +def waitpid(__pid: int, __options: int) -> tuple[int, int]: ... if sys.platform == "win32": - def startfile(path: AnyPath, operation: Optional[str] = ...) -> None: ... + def startfile(path: StrOrBytesPath, operation: str | None = ...) -> None: ... else: # Unix only - def spawnlp(mode: int, file: AnyPath, arg0: AnyPath, *args: AnyPath) -> int: ... - def spawnlpe(mode: int, file: AnyPath, arg0: AnyPath, *args: Any) -> int: ... # Imprecise signature - def spawnvp(mode: int, file: AnyPath, args: _ExecVArgs) -> int: ... - def spawnvpe(mode: int, file: AnyPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... - def wait() -> Tuple[int, int]: ... # Unix only + def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... + def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature + def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... + def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... + def wait() -> tuple[int, int]: ... # Unix only if sys.platform != "darwin": from posix import waitid_result def waitid(idtype: int, ident: int, options: int) -> waitid_result: ... - def wait3(options: int) -> Tuple[int, int, Any]: ... - def wait4(pid: int, options: int) -> Tuple[int, int, Any]: ... + def wait3(options: int) -> tuple[int, int, Any]: ... + def wait4(pid: int, options: int) -> tuple[int, int, Any]: ... def WCOREDUMP(__status: int) -> bool: ... def WIFCONTINUED(status: int) -> bool: ... def WIFSTOPPED(status: int) -> bool: ... @@ -806,6 +812,8 @@ else: def WEXITSTATUS(status: int) -> int: ... def WSTOPSIG(status: int) -> int: ... def WTERMSIG(status: int) -> int: ... + if sys.version_info >= (3, 8): + from posix import posix_spawn as posix_spawn, posix_spawnp as posix_spawnp if sys.platform != "win32": from posix import sched_param @@ -819,15 +827,15 @@ if sys.platform != "win32": def sched_setparam(pid: int, param: sched_param) -> None: ... # some flavors of Unix def sched_getparam(pid: int) -> sched_param: ... # some flavors of Unix def sched_setaffinity(pid: int, mask: Iterable[int]) -> None: ... # some flavors of Unix - def sched_getaffinity(pid: int) -> Set[int]: ... # some flavors of Unix + def sched_getaffinity(pid: int) -> set[int]: ... # some flavors of Unix -def cpu_count() -> Optional[int]: ... +def cpu_count() -> int | None: ... if sys.platform != "win32": # Unix only - def confstr(__name: Union[str, int]) -> Optional[str]: ... - def getloadavg() -> Tuple[float, float, float]: ... - def sysconf(__name: Union[str, int]) -> int: ... + def confstr(__name: str | int) -> str | None: ... + def getloadavg() -> tuple[float, float, float]: ... + def sysconf(__name: str | int) -> int: ... if sys.platform == "linux": def getrandom(size: int, flags: int = ...) -> bytes: ... @@ -837,18 +845,18 @@ def urandom(__size: int) -> bytes: ... if sys.version_info >= (3, 7) and sys.platform != "win32": def register_at_fork( *, - before: Optional[Callable[..., Any]] = ..., - after_in_parent: Optional[Callable[..., Any]] = ..., - after_in_child: Optional[Callable[..., Any]] = ..., + before: Callable[..., Any] | None = ..., + after_in_parent: Callable[..., Any] | None = ..., + after_in_child: Callable[..., Any] | None = ..., ) -> None: ... if sys.version_info >= (3, 8): if sys.platform == "win32": class _AddedDllDirectory: - path: Optional[str] - def __init__(self, path: Optional[str], cookie: _T, remove_dll_directory: Callable[[_T], Any]) -> None: ... + path: str | None + def __init__(self, path: str | None, cookie: _T, remove_dll_directory: Callable[[_T], Any]) -> None: ... def close(self) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *args: Any) -> None: ... def add_dll_directory(path: str) -> _AddedDllDirectory: ... if sys.platform == "linux": diff --git a/mypy/typeshed/stdlib/ossaudiodev.pyi b/mypy/typeshed/stdlib/ossaudiodev.pyi index af3e2c210930..f221c95b8036 100644 --- a/mypy/typeshed/stdlib/ossaudiodev.pyi +++ b/mypy/typeshed/stdlib/ossaudiodev.pyi @@ -1,4 +1,4 @@ -from typing import Any, List, overload +from typing import Any, overload from typing_extensions import Literal AFMT_AC3: int @@ -114,8 +114,8 @@ SOUND_MIXER_TREBLE: int SOUND_MIXER_VIDEO: int SOUND_MIXER_VOLUME: int -control_labels: List[str] -control_names: List[str] +control_labels: list[str] +control_names: list[str] # TODO: oss_audio_device return type @overload diff --git a/mypy/typeshed/stdlib/parser.pyi b/mypy/typeshed/stdlib/parser.pyi index 799f25cf6a48..aecf3244ca8d 100644 --- a/mypy/typeshed/stdlib/parser.pyi +++ b/mypy/typeshed/stdlib/parser.pyi @@ -1,22 +1,22 @@ -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from types import CodeType -from typing import Any, List, Sequence, Text, Tuple +from typing import Any, Sequence, Tuple -def expr(source: Text) -> STType: ... -def suite(source: Text) -> STType: ... +def expr(source: str) -> STType: ... +def suite(source: str) -> STType: ... def sequence2st(sequence: Sequence[Any]) -> STType: ... def tuple2st(sequence: Sequence[Any]) -> STType: ... -def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... -def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... -def compilest(st: STType, filename: AnyPath = ...) -> CodeType: ... +def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... +def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any, ...]: ... +def compilest(st: STType, filename: StrOrBytesPath = ...) -> CodeType: ... def isexpr(st: STType) -> bool: ... def issuite(st: STType) -> bool: ... class ParserError(Exception): ... class STType: - def compile(self, filename: AnyPath = ...) -> CodeType: ... + def compile(self, filename: StrOrBytesPath = ...) -> CodeType: ... def isexpr(self) -> bool: ... def issuite(self) -> bool: ... - def tolist(self, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... - def totuple(self, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... + def tolist(self, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... + def totuple(self, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/pathlib.pyi b/mypy/typeshed/stdlib/pathlib.pyi index b4624c3bea73..7d5f7ff2dba8 100644 --- a/mypy/typeshed/stdlib/pathlib.pyi +++ b/mypy/typeshed/stdlib/pathlib.pyi @@ -1,9 +1,17 @@ import sys -from _typeshed import OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, OpenBinaryModeWriting, OpenTextMode, StrPath +from _typeshed import ( + OpenBinaryMode, + OpenBinaryModeReading, + OpenBinaryModeUpdating, + OpenBinaryModeWriting, + OpenTextMode, + Self, + StrPath, +) from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from os import PathLike, stat_result from types import TracebackType -from typing import IO, Any, BinaryIO, Generator, List, Optional, Sequence, Tuple, Type, TypeVar, Union, overload +from typing import IO, Any, BinaryIO, Generator, Sequence, Tuple, Type, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 9): @@ -18,7 +26,7 @@ class PurePath(PathLike[str]): anchor: str name: str suffix: str - suffixes: List[str] + suffixes: list[str] stem: str def __new__(cls: Type[_P], *args: StrPath) -> _P: ... def __hash__(self) -> int: ... @@ -54,14 +62,18 @@ class PureWindowsPath(PurePath): ... class Path(PurePath): def __new__(cls: Type[_P], *args: StrPath, **kwargs: Any) -> _P: ... - def __enter__(self: _P) -> _P: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... @classmethod def cwd(cls: Type[_P]) -> _P: ... - def stat(self) -> stat_result: ... - def chmod(self, mode: int) -> None: ... + if sys.version_info >= (3, 10): + def stat(self, *, follow_symlinks: bool = ...) -> stat_result: ... + def chmod(self, mode: int, *, follow_symlinks: bool = ...) -> None: ... + else: + def stat(self) -> stat_result: ... + def chmod(self, mode: int) -> None: ... def exists(self) -> bool: ... def glob(self: _P, pattern: str) -> Generator[_P, None, None]: ... def group(self) -> str: ... @@ -80,14 +92,15 @@ class Path(PurePath): def mkdir(self, mode: int = ..., parents: bool = ..., exist_ok: bool = ...) -> None: ... # Adapted from builtins.open # Text mode: always returns a TextIOWrapper + # The Traversable .open in stdlib/importlib/abc.pyi should be kept in sync with this. @overload def open( self, mode: OpenTextMode = ..., buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., ) -> TextIOWrapper: ... # Unbuffered binary mode: returns a FileIO @overload @@ -130,26 +143,23 @@ class Path(PurePath): # Fallback if mode is not specified @overload def open( - self, - mode: str, - buffering: int = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + self, mode: str, buffering: int = ..., encoding: str | None = ..., errors: str | None = ..., newline: str | None = ... ) -> IO[Any]: ... def owner(self) -> str: ... if sys.version_info >= (3, 9): def readlink(self: _P) -> _P: ... if sys.version_info >= (3, 8): - def rename(self: _P, target: Union[str, PurePath]) -> _P: ... - def replace(self: _P, target: Union[str, PurePath]) -> _P: ... + def rename(self: _P, target: str | PurePath) -> _P: ... + def replace(self: _P, target: str | PurePath) -> _P: ... else: - def rename(self, target: Union[str, PurePath]) -> None: ... - def replace(self, target: Union[str, PurePath]) -> None: ... + def rename(self, target: str | PurePath) -> None: ... + def replace(self, target: str | PurePath) -> None: ... def resolve(self: _P, strict: bool = ...) -> _P: ... def rglob(self: _P, pattern: str) -> Generator[_P, None, None]: ... def rmdir(self) -> None: ... - def symlink_to(self, target: Union[str, Path], target_is_directory: bool = ...) -> None: ... + def symlink_to(self, target: str | Path, target_is_directory: bool = ...) -> None: ... + if sys.version_info >= (3, 10): + def hardlink_to(self, target: str | Path) -> None: ... def touch(self, mode: int = ..., exist_ok: bool = ...) -> None: ... if sys.version_info >= (3, 8): def unlink(self, missing_ok: bool = ...) -> None: ... @@ -160,12 +170,17 @@ class Path(PurePath): def absolute(self: _P) -> _P: ... def expanduser(self: _P) -> _P: ... def read_bytes(self) -> bytes: ... - def read_text(self, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> str: ... - def samefile(self, other_path: Union[str, bytes, int, Path]) -> bool: ... + def read_text(self, encoding: str | None = ..., errors: str | None = ...) -> str: ... + def samefile(self, other_path: str | bytes | int | Path) -> bool: ... def write_bytes(self, data: bytes) -> int: ... - def write_text(self, data: str, encoding: Optional[str] = ..., errors: Optional[str] = ...) -> int: ... + if sys.version_info >= (3, 10): + def write_text( + self, data: str, encoding: str | None = ..., errors: str | None = ..., newline: str | None = ... + ) -> int: ... + else: + def write_text(self, data: str, encoding: str | None = ..., errors: str | None = ...) -> int: ... if sys.version_info >= (3, 8): - def link_to(self, target: Union[StrPath, bytes]) -> None: ... + def link_to(self, target: StrPath | bytes) -> None: ... class PosixPath(Path, PurePosixPath): ... class WindowsPath(Path, PureWindowsPath): ... diff --git a/mypy/typeshed/stdlib/pdb.pyi b/mypy/typeshed/stdlib/pdb.pyi index 2750e9ea0f4b..83bd32d76450 100644 --- a/mypy/typeshed/stdlib/pdb.pyi +++ b/mypy/typeshed/stdlib/pdb.pyi @@ -4,7 +4,7 @@ from bdb import Bdb from cmd import Cmd from inspect import _SourceObjectType from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, ClassVar, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, TypeVar, Union +from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, Sequence, TypeVar _T = TypeVar("_T") @@ -12,112 +12,93 @@ line_prefix: str # undocumented class Restart(Exception): ... -def run(statement: str, globals: Optional[Dict[str, Any]] = ..., locals: Optional[Mapping[str, Any]] = ...) -> None: ... -def runeval(expression: str, globals: Optional[Dict[str, Any]] = ..., locals: Optional[Mapping[str, Any]] = ...) -> Any: ... -def runctx(statement: str, globals: Dict[str, Any], locals: Mapping[str, Any]) -> None: ... -def runcall(func: Callable[..., _T], *args: Any, **kwds: Any) -> Optional[_T]: ... +def run(statement: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... +def runeval(expression: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> Any: ... +def runctx(statement: str, globals: dict[str, Any], locals: Mapping[str, Any]) -> None: ... +def runcall(func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... if sys.version_info >= (3, 7): - def set_trace(*, header: Optional[str] = ...) -> None: ... + def set_trace(*, header: str | None = ...) -> None: ... else: def set_trace() -> None: ... -def post_mortem(t: Optional[TracebackType] = ...) -> None: ... +def post_mortem(t: TracebackType | None = ...) -> None: ... def pm() -> None: ... class Pdb(Bdb, Cmd): # Everything here is undocumented, except for __init__ - commands_resuming: ClassVar[List[str]] + commands_resuming: ClassVar[list[str]] - aliases: Dict[str, str] + aliases: dict[str, str] mainpyfile: str _wait_for_mainpyfile: bool - rcLines: List[str] - commands: Dict[int, List[str]] - commands_doprompt: Dict[int, bool] - commands_silent: Dict[int, bool] + rcLines: list[str] + commands: dict[int, list[str]] + commands_doprompt: dict[int, bool] + commands_silent: dict[int, bool] commands_defining: bool - commands_bnum: Optional[int] - lineno: Optional[int] - stack: List[Tuple[FrameType, int]] + commands_bnum: int | None + lineno: int | None + stack: list[tuple[FrameType, int]] curindex: int - curframe: Optional[FrameType] + curframe: FrameType | None curframe_locals: Mapping[str, Any] - - if sys.version_info >= (3, 6): - def __init__( - self, - completekey: str = ..., - stdin: Optional[IO[str]] = ..., - stdout: Optional[IO[str]] = ..., - skip: Optional[Iterable[str]] = ..., - nosigint: bool = ..., - readrc: bool = ..., - ) -> None: ... - elif sys.version_info >= (3, 2): - def __init__( - self, - completekey: str = ..., - stdin: Optional[IO[str]] = ..., - stdout: Optional[IO[str]] = ..., - skip: Optional[Iterable[str]] = ..., - nosigint: bool = ..., - ) -> None: ... - else: - def __init__( - self, - completekey: str = ..., - stdin: Optional[IO[str]] = ..., - stdout: Optional[IO[str]] = ..., - skip: Optional[Iterable[str]] = ..., - ) -> None: ... + def __init__( + self, + completekey: str = ..., + stdin: IO[str] | None = ..., + stdout: IO[str] | None = ..., + skip: Iterable[str] | None = ..., + nosigint: bool = ..., + readrc: bool = ..., + ) -> None: ... def forget(self) -> None: ... - def setup(self, f: Optional[FrameType], tb: Optional[TracebackType]) -> None: ... + def setup(self, f: FrameType | None, tb: TracebackType | None) -> None: ... def execRcLines(self) -> None: ... def bp_commands(self, frame: FrameType) -> bool: ... - def interaction(self, frame: Optional[FrameType], traceback: Optional[TracebackType]) -> None: ... + def interaction(self, frame: FrameType | None, traceback: TracebackType | None) -> None: ... def displayhook(self, obj: object) -> None: ... def handle_command_def(self, line: str) -> bool: ... def defaultFile(self) -> str: ... - def lineinfo(self, identifier: str) -> Union[Tuple[None, None, None], Tuple[str, str, int]]: ... + def lineinfo(self, identifier: str) -> tuple[None, None, None] | tuple[str, str, int]: ... def checkline(self, filename: str, lineno: int) -> int: ... def _getval(self, arg: str) -> object: ... def print_stack_trace(self) -> None: ... - def print_stack_entry(self, frame_lineno: Tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... - def lookupmodule(self, filename: str) -> Optional[str]: ... + def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... + def lookupmodule(self, filename: str) -> str | None: ... def _runscript(self, filename: str) -> None: ... - def do_commands(self, arg: str) -> Optional[bool]: ... - def do_break(self, arg: str, temporary: bool = ...) -> Optional[bool]: ... - def do_tbreak(self, arg: str) -> Optional[bool]: ... - def do_enable(self, arg: str) -> Optional[bool]: ... - def do_disable(self, arg: str) -> Optional[bool]: ... - def do_condition(self, arg: str) -> Optional[bool]: ... - def do_ignore(self, arg: str) -> Optional[bool]: ... - def do_clear(self, arg: str) -> Optional[bool]: ... - def do_where(self, arg: str) -> Optional[bool]: ... - def do_up(self, arg: str) -> Optional[bool]: ... - def do_down(self, arg: str) -> Optional[bool]: ... - def do_until(self, arg: str) -> Optional[bool]: ... - def do_step(self, arg: str) -> Optional[bool]: ... - def do_next(self, arg: str) -> Optional[bool]: ... - def do_run(self, arg: str) -> Optional[bool]: ... - def do_return(self, arg: str) -> Optional[bool]: ... - def do_continue(self, arg: str) -> Optional[bool]: ... - def do_jump(self, arg: str) -> Optional[bool]: ... - def do_debug(self, arg: str) -> Optional[bool]: ... - def do_quit(self, arg: str) -> Optional[bool]: ... - def do_EOF(self, arg: str) -> Optional[bool]: ... - def do_args(self, arg: str) -> Optional[bool]: ... - def do_retval(self, arg: str) -> Optional[bool]: ... - def do_p(self, arg: str) -> Optional[bool]: ... - def do_pp(self, arg: str) -> Optional[bool]: ... - def do_list(self, arg: str) -> Optional[bool]: ... - def do_whatis(self, arg: str) -> Optional[bool]: ... - def do_alias(self, arg: str) -> Optional[bool]: ... - def do_unalias(self, arg: str) -> Optional[bool]: ... - def do_help(self, arg: str) -> Optional[bool]: ... + def do_commands(self, arg: str) -> bool | None: ... + def do_break(self, arg: str, temporary: bool = ...) -> bool | None: ... + def do_tbreak(self, arg: str) -> bool | None: ... + def do_enable(self, arg: str) -> bool | None: ... + def do_disable(self, arg: str) -> bool | None: ... + def do_condition(self, arg: str) -> bool | None: ... + def do_ignore(self, arg: str) -> bool | None: ... + def do_clear(self, arg: str) -> bool | None: ... + def do_where(self, arg: str) -> bool | None: ... + def do_up(self, arg: str) -> bool | None: ... + def do_down(self, arg: str) -> bool | None: ... + def do_until(self, arg: str) -> bool | None: ... + def do_step(self, arg: str) -> bool | None: ... + def do_next(self, arg: str) -> bool | None: ... + def do_run(self, arg: str) -> bool | None: ... + def do_return(self, arg: str) -> bool | None: ... + def do_continue(self, arg: str) -> bool | None: ... + def do_jump(self, arg: str) -> bool | None: ... + def do_debug(self, arg: str) -> bool | None: ... + def do_quit(self, arg: str) -> bool | None: ... + def do_EOF(self, arg: str) -> bool | None: ... + def do_args(self, arg: str) -> bool | None: ... + def do_retval(self, arg: str) -> bool | None: ... + def do_p(self, arg: str) -> bool | None: ... + def do_pp(self, arg: str) -> bool | None: ... + def do_list(self, arg: str) -> bool | None: ... + def do_whatis(self, arg: str) -> bool | None: ... + def do_alias(self, arg: str) -> bool | None: ... + def do_unalias(self, arg: str) -> bool | None: ... + def do_help(self, arg: str) -> bool | None: ... do_b = do_break do_cl = do_clear do_w = do_where @@ -140,111 +121,54 @@ class Pdb(Bdb, Cmd): do_h = do_help def help_exec(self) -> None: ... def help_pdb(self) -> None: ... - if sys.version_info < (3, 2): - def help_help(self) -> None: ... - def help_h(self) -> None: ... - def help_where(self) -> None: ... - def help_w(self) -> None: ... - def help_down(self) -> None: ... - def help_d(self) -> None: ... - def help_up(self) -> None: ... - def help_u(self) -> None: ... - def help_break(self) -> None: ... - def help_b(self) -> None: ... - def help_clear(self) -> None: ... - def help_cl(self) -> None: ... - def help_tbreak(self) -> None: ... - def help_enable(self) -> None: ... - def help_disable(self) -> None: ... - def help_ignore(self) -> None: ... - def help_condition(self) -> None: ... - def help_step(self) -> None: ... - def help_s(self) -> None: ... - def help_until(self) -> None: ... - def help_unt(self) -> None: ... - def help_next(self) -> None: ... - def help_n(self) -> None: ... - def help_return(self) -> None: ... - def help_r(self) -> None: ... - def help_continue(self) -> None: ... - def help_cont(self) -> None: ... - def help_c(self) -> None: ... - def help_jump(self) -> None: ... - def help_j(self) -> None: ... - def help_debug(self) -> None: ... - def help_list(self) -> None: ... - def help_l(self) -> None: ... - def help_args(self) -> None: ... - def help_a(self) -> None: ... - def help_p(self) -> None: ... - def help_pp(self) -> None: ... - def help_run(self) -> None: ... - def help_quit(self) -> None: ... - def help_q(self) -> None: ... - def help_whatis(self) -> None: ... - def help_EOF(self) -> None: ... - def help_alias(self) -> None: ... - def help_unalias(self) -> None: ... - def help_commands(self) -> None: ... - help_bt = help_w - help_restart = help_run - help_exit = help_q - - if sys.version_info >= (3, 2): - def sigint_handler(self, signum: signal.Signals, frame: FrameType) -> None: ... - def message(self, msg: str) -> None: ... - def error(self, msg: str) -> None: ... - def _select_frame(self, number: int) -> None: ... - def _getval_except(self, arg: str, frame: Optional[FrameType] = ...) -> object: ... - def _print_lines( - self, lines: Sequence[str], start: int, breaks: Sequence[int] = ..., frame: Optional[FrameType] = ... - ) -> None: ... - def _cmdloop(self) -> None: ... - def do_display(self, arg: str) -> Optional[bool]: ... - def do_interact(self, arg: str) -> Optional[bool]: ... - def do_longlist(self, arg: str) -> Optional[bool]: ... - def do_source(self, arg: str) -> Optional[bool]: ... - def do_undisplay(self, arg: str) -> Optional[bool]: ... - do_ll = do_longlist - - if sys.version_info >= (3, 3): - def _complete_location(self, text: str, line: str, begidx: int, endidx: int) -> List[str]: ... - def _complete_bpnumber(self, text: str, line: str, begidx: int, endidx: int) -> List[str]: ... - def _complete_expression(self, text: str, line: str, begidx: int, endidx: int) -> List[str]: ... - def complete_undisplay(self, text: str, line: str, begidx: int, endidx: int) -> List[str]: ... - def complete_unalias(self, text: str, line: str, begidx: int, endidx: int) -> List[str]: ... - complete_commands = _complete_bpnumber - complete_break = _complete_location - complete_b = _complete_location - complete_tbreak = _complete_location - complete_enable = _complete_bpnumber - complete_disable = _complete_bpnumber - complete_condition = _complete_bpnumber - complete_ignore = _complete_bpnumber - complete_clear = _complete_location - complete_cl = _complete_location - complete_debug = _complete_expression - complete_print = _complete_expression - complete_p = _complete_expression - complete_pp = _complete_expression - complete_source = _complete_expression - complete_whatis = _complete_expression - complete_display = _complete_expression + def sigint_handler(self, signum: signal.Signals, frame: FrameType) -> None: ... + def message(self, msg: str) -> None: ... + def error(self, msg: str) -> None: ... + def _select_frame(self, number: int) -> None: ... + def _getval_except(self, arg: str, frame: FrameType | None = ...) -> object: ... + def _print_lines( + self, lines: Sequence[str], start: int, breaks: Sequence[int] = ..., frame: FrameType | None = ... + ) -> None: ... + def _cmdloop(self) -> None: ... + def do_display(self, arg: str) -> bool | None: ... + def do_interact(self, arg: str) -> bool | None: ... + def do_longlist(self, arg: str) -> bool | None: ... + def do_source(self, arg: str) -> bool | None: ... + def do_undisplay(self, arg: str) -> bool | None: ... + do_ll = do_longlist + def _complete_location(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: ... + def _complete_bpnumber(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: ... + def _complete_expression(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: ... + def complete_undisplay(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: ... + def complete_unalias(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: ... + complete_commands = _complete_bpnumber + complete_break = _complete_location + complete_b = _complete_location + complete_tbreak = _complete_location + complete_enable = _complete_bpnumber + complete_disable = _complete_bpnumber + complete_condition = _complete_bpnumber + complete_ignore = _complete_bpnumber + complete_clear = _complete_location + complete_cl = _complete_location + complete_debug = _complete_expression + complete_print = _complete_expression + complete_p = _complete_expression + complete_pp = _complete_expression + complete_source = _complete_expression + complete_whatis = _complete_expression + complete_display = _complete_expression if sys.version_info >= (3, 7): def _runmodule(self, module_name: str) -> None: ... - if sys.version_info >= (3,) and sys.version_info < (3, 4): - do_print = do_p # undocumented -def find_function(funcname: str, filename: str) -> Optional[Tuple[str, str, int]]: ... +def find_function(funcname: str, filename: str) -> tuple[str, str, int] | None: ... def main() -> None: ... def help() -> None: ... - -if sys.version_info >= (3, 2): - def getsourcelines(obj: _SourceObjectType) -> Tuple[List[str], int]: ... - def lasti2lineno(code: CodeType, lasti: int) -> int: ... +def getsourcelines(obj: _SourceObjectType) -> tuple[list[str], int]: ... +def lasti2lineno(code: CodeType, lasti: int) -> int: ... class _rstr(str): def __repr__(self) -> _rstr: ... diff --git a/mypy/typeshed/stdlib/pickle.pyi b/mypy/typeshed/stdlib/pickle.pyi index ddf8a4401399..cef1ffe9eb9b 100644 --- a/mypy/typeshed/stdlib/pickle.pyi +++ b/mypy/typeshed/stdlib/pickle.pyi @@ -1,14 +1,22 @@ import sys -from typing import IO, Any, Callable, Iterable, Iterator, Mapping, Optional, Tuple, Type, Union +from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Optional, Protocol, Tuple, Type, Union +from typing_extensions import final HIGHEST_PROTOCOL: int -if sys.version_info >= (3, 0): - DEFAULT_PROTOCOL: int +DEFAULT_PROTOCOL: int bytes_types: Tuple[Type[Any], ...] # undocumented +class _ReadableFileobj(Protocol): + def read(self, __n: int) -> bytes: ... + def readline(self) -> bytes: ... + +class _WritableFileobj(Protocol): + def write(self, __b: bytes) -> Any: ... + if sys.version_info >= (3, 8): # TODO: holistic design for buffer interface (typing.Buffer?) + @final class PickleBuffer: # buffer must be a buffer-providing object def __init__(self, buffer: Any) -> None: ... @@ -17,38 +25,32 @@ if sys.version_info >= (3, 8): _BufferCallback = Optional[Callable[[PickleBuffer], Any]] def dump( obj: Any, - file: IO[bytes], - protocol: Optional[int] = ..., + file: _WritableFileobj, + protocol: int | None = ..., *, fix_imports: bool = ..., buffer_callback: _BufferCallback = ..., ) -> None: ... def dumps( - obj: Any, protocol: Optional[int] = ..., *, fix_imports: bool = ..., buffer_callback: _BufferCallback = ... + obj: Any, protocol: int | None = ..., *, fix_imports: bool = ..., buffer_callback: _BufferCallback = ... ) -> bytes: ... def load( - file: IO[bytes], + file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ..., - buffers: Optional[Iterable[Any]] = ..., + buffers: Iterable[Any] | None = ..., ) -> Any: ... def loads( - __data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ..., buffers: Optional[Iterable[Any]] = ... + __data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ..., buffers: Iterable[Any] | None = ... ) -> Any: ... -elif sys.version_info >= (3, 0): - def dump(obj: Any, file: IO[bytes], protocol: Optional[int] = ..., *, fix_imports: bool = ...) -> None: ... - def dumps(obj: Any, protocol: Optional[int] = ..., *, fix_imports: bool = ...) -> bytes: ... - def load(file: IO[bytes], *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... - def loads(data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... - else: - def dump(obj: Any, file: IO[bytes], protocol: Optional[int] = ...) -> None: ... - def dumps(obj: Any, protocol: Optional[int] = ...) -> bytes: ... - def load(file: IO[bytes]) -> Any: ... - def loads(string: bytes) -> Any: ... + def dump(obj: Any, file: _WritableFileobj, protocol: int | None = ..., *, fix_imports: bool = ...) -> None: ... + def dumps(obj: Any, protocol: int | None = ..., *, fix_imports: bool = ...) -> bytes: ... + def load(file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... + def loads(data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... class PickleError(Exception): ... class PicklingError(PickleError): ... @@ -64,46 +66,46 @@ _reducedtype = Union[ class Pickler: fast: bool - if sys.version_info >= (3, 3): - dispatch_table: Mapping[type, Callable[[Any], _reducedtype]] + dispatch_table: Mapping[type, Callable[[Any], _reducedtype]] + bin: bool # undocumented + dispatch: ClassVar[dict[type, Callable[[Unpickler, Any], None]]] # undocumented, _Pickler only if sys.version_info >= (3, 8): def __init__( self, - file: IO[bytes], - protocol: Optional[int] = ..., + file: _WritableFileobj, + protocol: int | None = ..., *, fix_imports: bool = ..., buffer_callback: _BufferCallback = ..., ) -> None: ... def reducer_override(self, obj: Any) -> Any: ... - elif sys.version_info >= (3, 0): - def __init__(self, file: IO[bytes], protocol: Optional[int] = ..., *, fix_imports: bool = ...) -> None: ... else: - def __init__(self, file: IO[bytes], protocol: Optional[int] = ...) -> None: ... + def __init__(self, file: _WritableFileobj, protocol: int | None = ..., *, fix_imports: bool = ...) -> None: ... def dump(self, __obj: Any) -> None: ... def clear_memo(self) -> None: ... def persistent_id(self, obj: Any) -> Any: ... class Unpickler: + dispatch: ClassVar[dict[int, Callable[[Unpickler], None]]] # undocumented, _Unpickler only + if sys.version_info >= (3, 8): def __init__( self, - file: IO[bytes], + file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ..., - buffers: Optional[Iterable[Any]] = ..., + buffers: Iterable[Any] | None = ..., ) -> None: ... - elif sys.version_info >= (3, 0): - def __init__(self, file: IO[bytes], *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> None: ... else: - def __init__(self, file: IO[bytes]) -> None: ... + def __init__( + self, file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ... + ) -> None: ... def load(self) -> Any: ... def find_class(self, __module_name: str, __global_name: str) -> Any: ... - if sys.version_info >= (3, 0): - def persistent_load(self, pid: Any) -> Any: ... + def persistent_load(self, pid: Any) -> Any: ... MARK: bytes STOP: bytes @@ -164,23 +166,31 @@ NEWFALSE: bytes LONG1: bytes LONG4: bytes -if sys.version_info >= (3, 0): - # protocol 3 - BINBYTES: bytes - SHORT_BINBYTES: bytes - -if sys.version_info >= (3, 4): - # protocol 4 - SHORT_BINUNICODE: bytes - BINUNICODE8: bytes - BINBYTES8: bytes - EMPTY_SET: bytes - ADDITEMS: bytes - FROZENSET: bytes - NEWOBJ_EX: bytes - STACK_GLOBAL: bytes - MEMOIZE: bytes - FRAME: bytes +# protocol 3 +BINBYTES: bytes +SHORT_BINBYTES: bytes + +# protocol 4 +SHORT_BINUNICODE: bytes +BINUNICODE8: bytes +BINBYTES8: bytes +EMPTY_SET: bytes +ADDITEMS: bytes +FROZENSET: bytes +NEWOBJ_EX: bytes +STACK_GLOBAL: bytes +MEMOIZE: bytes +FRAME: bytes + +if sys.version_info >= (3, 8): + # Protocol 5 + BYTEARRAY8: bytes + NEXT_BUFFER: bytes + READONLY_BUFFER: bytes def encode_long(x: int) -> bytes: ... # undocumented def decode_long(data: bytes) -> int: ... # undocumented + +# pure-Python implementations +_Pickler = Pickler # undocumented +_Unpickler = Unpickler # undocumented diff --git a/mypy/typeshed/stdlib/pickletools.pyi b/mypy/typeshed/stdlib/pickletools.pyi index ec279524bc50..9fa51a3848ee 100644 --- a/mypy/typeshed/stdlib/pickletools.pyi +++ b/mypy/typeshed/stdlib/pickletools.pyi @@ -1,18 +1,13 @@ -import sys -from typing import IO, Any, Callable, Iterator, List, MutableMapping, Optional, Text, Tuple, Type, Union +from typing import IO, Any, Callable, Iterator, MutableMapping, Tuple, Type _Reader = Callable[[IO[bytes]], Any] - -if sys.version_info >= (3, 0): - bytes_types: Tuple[Type[Any], ...] +bytes_types: Tuple[Type[Any], ...] UP_TO_NEWLINE: int TAKEN_FROM_ARGUMENT1: int TAKEN_FROM_ARGUMENT4: int -if sys.version_info >= (3, 3): - TAKEN_FROM_ARGUMENT4U: int -if sys.version_info >= (3, 4): - TAKEN_FROM_ARGUMENT8U: int +TAKEN_FROM_ARGUMENT4U: int +TAKEN_FROM_ARGUMENT8U: int class ArgumentDescriptor(object): name: str @@ -33,15 +28,15 @@ def read_int4(f: IO[bytes]) -> int: ... int4: ArgumentDescriptor -if sys.version_info >= (3, 3): - def read_uint4(f: IO[bytes]) -> int: ... - uint4: ArgumentDescriptor +def read_uint4(f: IO[bytes]) -> int: ... + +uint4: ArgumentDescriptor -if sys.version_info >= (3, 5): - def read_uint8(f: IO[bytes]) -> int: ... - uint8: ArgumentDescriptor +def read_uint8(f: IO[bytes]) -> int: ... -def read_stringnl(f: IO[bytes], decode: bool = ..., stripquotes: bool = ...) -> Union[bytes, Text]: ... +uint8: ArgumentDescriptor + +def read_stringnl(f: IO[bytes], decode: bool = ..., stripquotes: bool = ...) -> bytes | str: ... stringnl: ArgumentDescriptor @@ -49,7 +44,7 @@ def read_stringnl_noescape(f: IO[bytes]) -> str: ... stringnl_noescape: ArgumentDescriptor -def read_stringnl_noescape_pair(f: IO[bytes]) -> Text: ... +def read_stringnl_noescape_pair(f: IO[bytes]) -> str: ... stringnl_noescape_pair: ArgumentDescriptor @@ -61,31 +56,33 @@ def read_string4(f: IO[bytes]) -> str: ... string4: ArgumentDescriptor -if sys.version_info >= (3, 3): - def read_bytes1(f: IO[bytes]) -> bytes: ... - bytes1: ArgumentDescriptor - def read_bytes4(f: IO[bytes]) -> bytes: ... - bytes4: ArgumentDescriptor +def read_bytes1(f: IO[bytes]) -> bytes: ... + +bytes1: ArgumentDescriptor + +def read_bytes4(f: IO[bytes]) -> bytes: ... + +bytes4: ArgumentDescriptor + +def read_bytes8(f: IO[bytes]) -> bytes: ... -if sys.version_info >= (3, 4): - def read_bytes8(f: IO[bytes]) -> bytes: ... - bytes8: ArgumentDescriptor +bytes8: ArgumentDescriptor -def read_unicodestringnl(f: IO[bytes]) -> Text: ... +def read_unicodestringnl(f: IO[bytes]) -> str: ... unicodestringnl: ArgumentDescriptor -if sys.version_info >= (3, 4): - def read_unicodestring1(f: IO[bytes]) -> Text: ... - unicodestring1: ArgumentDescriptor +def read_unicodestring1(f: IO[bytes]) -> str: ... -def read_unicodestring4(f: IO[bytes]) -> Text: ... +unicodestring1: ArgumentDescriptor + +def read_unicodestring4(f: IO[bytes]) -> str: ... unicodestring4: ArgumentDescriptor -if sys.version_info >= (3, 4): - def read_unicodestring8(f: IO[bytes]) -> Text: ... - unicodestring8: ArgumentDescriptor +def read_unicodestring8(f: IO[bytes]) -> str: ... + +unicodestring8: ArgumentDescriptor def read_decimalnl_short(f: IO[bytes]) -> int: ... def read_decimalnl_long(f: IO[bytes]) -> int: ... @@ -111,28 +108,25 @@ long4: ArgumentDescriptor class StackObject(object): name: str - obtype: Union[Type[Any], Tuple[Type[Any], ...]] + obtype: Type[Any] | Tuple[Type[Any], ...] doc: str - def __init__(self, name: str, obtype: Union[Type[Any], Tuple[Type[Any], ...]], doc: str) -> None: ... + def __init__(self, name: str, obtype: Type[Any] | Tuple[Type[Any], ...], doc: str) -> None: ... pyint: StackObject pylong: StackObject pyinteger_or_bool: StackObject pybool: StackObject pyfloat: StackObject -if sys.version_info >= (3, 4): - pybytes_or_str: StackObject +pybytes_or_str: StackObject pystring: StackObject -if sys.version_info >= (3, 0): - pybytes: StackObject +pybytes: StackObject pyunicode: StackObject pynone: StackObject pytuple: StackObject pylist: StackObject pydict: StackObject -if sys.version_info >= (3, 4): - pyset: StackObject - pyfrozenset: StackObject +pyset: StackObject +pyfrozenset: StackObject anyobject: StackObject markobject: StackObject stackslice: StackObject @@ -140,40 +134,30 @@ stackslice: StackObject class OpcodeInfo(object): name: str code: str - arg: Optional[ArgumentDescriptor] - stack_before: List[StackObject] - stack_after: List[StackObject] + arg: ArgumentDescriptor | None + stack_before: list[StackObject] + stack_after: list[StackObject] proto: int doc: str def __init__( self, name: str, code: str, - arg: Optional[ArgumentDescriptor], - stack_before: List[StackObject], - stack_after: List[StackObject], + arg: ArgumentDescriptor | None, + stack_before: list[StackObject], + stack_after: list[StackObject], proto: int, doc: str, ) -> None: ... -opcodes: List[OpcodeInfo] - -def genops(pickle: Union[bytes, IO[bytes]]) -> Iterator[Tuple[OpcodeInfo, Optional[Any], Optional[int]]]: ... -def optimize(p: Union[bytes, IO[bytes]]) -> bytes: ... - -if sys.version_info >= (3, 2): - def dis( - pickle: Union[bytes, IO[bytes]], - out: Optional[IO[str]] = ..., - memo: Optional[MutableMapping[int, Any]] = ..., - indentlevel: int = ..., - annotate: int = ..., - ) -> None: ... - -else: - def dis( - pickle: Union[bytes, IO[bytes]], - out: Optional[IO[str]] = ..., - memo: Optional[MutableMapping[int, Any]] = ..., - indentlevel: int = ..., - ) -> None: ... +opcodes: list[OpcodeInfo] + +def genops(pickle: bytes | IO[bytes]) -> Iterator[tuple[OpcodeInfo, Any | None, int | None]]: ... +def optimize(p: bytes | IO[bytes]) -> bytes: ... +def dis( + pickle: bytes | IO[bytes], + out: IO[str] | None = ..., + memo: MutableMapping[int, Any] | None = ..., + indentlevel: int = ..., + annotate: int = ..., +) -> None: ... diff --git a/mypy/typeshed/stdlib/pkgutil.pyi b/mypy/typeshed/stdlib/pkgutil.pyi index 0935e922562e..e0f392fd91d8 100644 --- a/mypy/typeshed/stdlib/pkgutil.pyi +++ b/mypy/typeshed/stdlib/pkgutil.pyi @@ -1,41 +1,31 @@ import sys from _typeshed import SupportsRead -from typing import IO, Any, Callable, Iterable, Iterator, List, NamedTuple, Optional, Tuple, Union +from importlib.abc import Loader, MetaPathFinder, PathEntryFinder +from typing import IO, Any, Callable, Iterable, Iterator, NamedTuple -if sys.version_info >= (3,): - from importlib.abc import Loader, MetaPathFinder, PathEntryFinder -else: - Loader = Any - MetaPathFinder = Any - PathEntryFinder = Any +class ModuleInfo(NamedTuple): + module_finder: MetaPathFinder | PathEntryFinder + name: str + ispkg: bool -if sys.version_info >= (3, 6): - class ModuleInfo(NamedTuple): - module_finder: Union[MetaPathFinder, PathEntryFinder] - name: str - ispkg: bool - _ModuleInfoLike = ModuleInfo -else: - _ModuleInfoLike = Tuple[Union[MetaPathFinder, PathEntryFinder], str, bool] - -def extend_path(path: List[str], name: str) -> List[str]: ... +def extend_path(path: list[str], name: str) -> list[str]: ... class ImpImporter: - def __init__(self, path: Optional[str] = ...) -> None: ... + def __init__(self, path: str | None = ...) -> None: ... class ImpLoader: - def __init__(self, fullname: str, file: IO[str], filename: str, etc: Tuple[str, str, int]) -> None: ... + def __init__(self, fullname: str, file: IO[str], filename: str, etc: tuple[str, str, int]) -> None: ... -def find_loader(fullname: str) -> Optional[Loader]: ... -def get_importer(path_item: str) -> Optional[PathEntryFinder]: ... +def find_loader(fullname: str) -> Loader | None: ... +def get_importer(path_item: str) -> PathEntryFinder | None: ... def get_loader(module_or_name: str) -> Loader: ... -def iter_importers(fullname: str = ...) -> Iterator[Union[MetaPathFinder, PathEntryFinder]]: ... -def iter_modules(path: Optional[Iterable[str]] = ..., prefix: str = ...) -> Iterator[_ModuleInfoLike]: ... +def iter_importers(fullname: str = ...) -> Iterator[MetaPathFinder | PathEntryFinder]: ... +def iter_modules(path: Iterable[str] | None = ..., prefix: str = ...) -> Iterator[ModuleInfo]: ... def read_code(stream: SupportsRead[bytes]) -> Any: ... # undocumented def walk_packages( - path: Optional[Iterable[str]] = ..., prefix: str = ..., onerror: Optional[Callable[[str], None]] = ... -) -> Iterator[_ModuleInfoLike]: ... -def get_data(package: str, resource: str) -> Optional[bytes]: ... + path: Iterable[str] | None = ..., prefix: str = ..., onerror: Callable[[str], None] | None = ... +) -> Iterator[ModuleInfo]: ... +def get_data(package: str, resource: str) -> bytes | None: ... if sys.version_info >= (3, 9): def resolve_name(name: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/platform.pyi b/mypy/typeshed/stdlib/platform.pyi index 217882224d74..7db2d59ff7ea 100644 --- a/mypy/typeshed/stdlib/platform.pyi +++ b/mypy/typeshed/stdlib/platform.pyi @@ -4,15 +4,13 @@ if sys.version_info < (3, 8): import os DEV_NULL = os.devnull -from typing import NamedTuple, Optional, Tuple +from typing import NamedTuple, Tuple if sys.version_info >= (3, 8): - def libc_ver( - executable: Optional[str] = ..., lib: str = ..., version: str = ..., chunksize: int = ... - ) -> Tuple[str, str]: ... + def libc_ver(executable: str | None = ..., lib: str = ..., version: str = ..., chunksize: int = ...) -> tuple[str, str]: ... else: - def libc_ver(executable: str = ..., lib: str = ..., version: str = ..., chunksize: int = ...) -> Tuple[str, str]: ... + def libc_ver(executable: str = ..., lib: str = ..., version: str = ..., chunksize: int = ...) -> tuple[str, str]: ... if sys.version_info < (3, 8): def linux_distribution( @@ -21,25 +19,25 @@ if sys.version_info < (3, 8): id: str = ..., supported_dists: Tuple[str, ...] = ..., full_distribution_name: bool = ..., - ) -> Tuple[str, str, str]: ... + ) -> tuple[str, str, str]: ... def dist( distname: str = ..., version: str = ..., id: str = ..., supported_dists: Tuple[str, ...] = ... - ) -> Tuple[str, str, str]: ... + ) -> tuple[str, str, str]: ... -def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> Tuple[str, str, str, str]: ... +def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> tuple[str, str, str, str]: ... if sys.version_info >= (3, 8): def win32_edition() -> str: ... def win32_is_iot() -> bool: ... def mac_ver( - release: str = ..., versioninfo: Tuple[str, str, str] = ..., machine: str = ... -) -> Tuple[str, Tuple[str, str, str], str]: ... + release: str = ..., versioninfo: tuple[str, str, str] = ..., machine: str = ... +) -> tuple[str, tuple[str, str, str], str]: ... def java_ver( - release: str = ..., vendor: str = ..., vminfo: Tuple[str, str, str] = ..., osinfo: Tuple[str, str, str] = ... -) -> Tuple[str, str, Tuple[str, str, str], Tuple[str, str, str]]: ... -def system_alias(system: str, release: str, version: str) -> Tuple[str, str, str]: ... -def architecture(executable: str = ..., bits: str = ..., linkage: str = ...) -> Tuple[str, str]: ... + release: str = ..., vendor: str = ..., vminfo: tuple[str, str, str] = ..., osinfo: tuple[str, str, str] = ... +) -> tuple[str, str, tuple[str, str, str], tuple[str, str, str]]: ... +def system_alias(system: str, release: str, version: str) -> tuple[str, str, str]: ... +def architecture(executable: str = ..., bits: str = ..., linkage: str = ...) -> tuple[str, str]: ... class uname_result(NamedTuple): system: str @@ -58,9 +56,9 @@ def machine() -> str: ... def processor() -> str: ... def python_implementation() -> str: ... def python_version() -> str: ... -def python_version_tuple() -> Tuple[str, str, str]: ... +def python_version_tuple() -> tuple[str, str, str]: ... def python_branch() -> str: ... def python_revision() -> str: ... -def python_build() -> Tuple[str, str]: ... +def python_build() -> tuple[str, str]: ... def python_compiler() -> str: ... def platform(aliased: bool = ..., terse: bool = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/plistlib.pyi b/mypy/typeshed/stdlib/plistlib.pyi index 5aadae9fc97b..07b6963746be 100644 --- a/mypy/typeshed/stdlib/plistlib.pyi +++ b/mypy/typeshed/stdlib/plistlib.pyi @@ -1,56 +1,59 @@ import sys -from typing import IO, Any, Dict as DictT, Mapping, MutableMapping, Optional, Text, Type, Union +from datetime import datetime +from enum import Enum +from typing import IO, Any, Dict as _Dict, Mapping, MutableMapping, Tuple, Type -if sys.version_info >= (3,): - from enum import Enum - class PlistFormat(Enum): - FMT_XML: int - FMT_BINARY: int - FMT_XML = PlistFormat.FMT_XML - FMT_BINARY = PlistFormat.FMT_BINARY +class PlistFormat(Enum): + FMT_XML: int + FMT_BINARY: int -_Path = Union[str, Text] +FMT_XML = PlistFormat.FMT_XML +FMT_BINARY = PlistFormat.FMT_BINARY if sys.version_info >= (3, 9): - def load(fp: IO[bytes], *, fmt: Optional[PlistFormat] = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... - def loads(value: bytes, *, fmt: Optional[PlistFormat] = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... + def load(fp: IO[bytes], *, fmt: PlistFormat | None = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... + def loads(value: bytes, *, fmt: PlistFormat | None = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... -elif sys.version_info >= (3, 4): +else: def load( fp: IO[bytes], *, - fmt: Optional[PlistFormat] = ..., + fmt: PlistFormat | None = ..., use_builtin_types: bool = ..., dict_type: Type[MutableMapping[str, Any]] = ..., ) -> Any: ... def loads( value: bytes, *, - fmt: Optional[PlistFormat] = ..., + fmt: PlistFormat | None = ..., use_builtin_types: bool = ..., dict_type: Type[MutableMapping[str, Any]] = ..., ) -> Any: ... -if sys.version_info >= (3, 4): - def dump( - value: Mapping[str, Any], fp: IO[bytes], *, fmt: PlistFormat = ..., sort_keys: bool = ..., skipkeys: bool = ... - ) -> None: ... - def dumps(value: Mapping[str, Any], *, fmt: PlistFormat = ..., skipkeys: bool = ..., sort_keys: bool = ...) -> bytes: ... +def dump( + value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + fp: IO[bytes], + *, + fmt: PlistFormat = ..., + sort_keys: bool = ..., + skipkeys: bool = ..., +) -> None: ... +def dumps( + value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + *, + fmt: PlistFormat = ..., + skipkeys: bool = ..., + sort_keys: bool = ..., +) -> bytes: ... if sys.version_info < (3, 9): - def readPlist(pathOrFile: Union[_Path, IO[bytes]]) -> Any: ... - def writePlist(value: Mapping[str, Any], pathOrFile: Union[_Path, IO[bytes]]) -> None: ... + def readPlist(pathOrFile: str | IO[bytes]) -> Any: ... + def writePlist(value: Mapping[str, Any], pathOrFile: str | IO[bytes]) -> None: ... def readPlistFromBytes(data: bytes) -> Any: ... def writePlistToBytes(value: Mapping[str, Any]) -> bytes: ... -if sys.version_info < (3,): - def readPlistFromResource(path: _Path, restype: str = ..., resid: int = ...) -> Any: ... - def writePlistToResource(rootObject: Mapping[str, Any], path: _Path, restype: str = ..., resid: int = ...) -> None: ... - def readPlistFromString(data: str) -> Any: ... - def writePlistToString(rootObject: Mapping[str, Any]) -> str: ... - if sys.version_info < (3, 7): - class Dict(DictT[str, Any]): + class Dict(_Dict[str, Any]): def __getattr__(self, attr: str) -> Any: ... def __setattr__(self, attr: str, value: Any) -> None: ... def __delattr__(self, attr: str) -> None: ... diff --git a/mypy/typeshed/stdlib/poplib.pyi b/mypy/typeshed/stdlib/poplib.pyi index 2c08f3586c0f..28fba4ce951f 100644 --- a/mypy/typeshed/stdlib/poplib.pyi +++ b/mypy/typeshed/stdlib/poplib.pyi @@ -1,7 +1,6 @@ import socket import ssl -import sys -from typing import Any, BinaryIO, Dict, List, Optional, Pattern, Text, Tuple, overload +from typing import Any, BinaryIO, List, Pattern, Tuple, overload _LongResp = Tuple[bytes, List[bytes], int] @@ -13,61 +12,49 @@ CR: bytes LF: bytes CRLF: bytes -class POP3: - if sys.version_info >= (3, 0): - encoding: Text +_list = list # conflicts with a method named "list" - host: Text +class POP3: + encoding: str + host: str port: int sock: socket.socket file: BinaryIO welcome: bytes - def __init__(self, host: Text, port: int = ..., timeout: float = ...) -> None: ... + def __init__(self, host: str, port: int = ..., timeout: float = ...) -> None: ... def getwelcome(self) -> bytes: ... def set_debuglevel(self, level: int) -> None: ... - def user(self, user: Text) -> bytes: ... - def pass_(self, pswd: Text) -> bytes: ... - def stat(self) -> Tuple[int, int]: ... - def list(self, which: Optional[Any] = ...) -> _LongResp: ... + def user(self, user: str) -> bytes: ... + def pass_(self, pswd: str) -> bytes: ... + def stat(self) -> tuple[int, int]: ... + def list(self, which: Any | None = ...) -> _LongResp: ... def retr(self, which: Any) -> _LongResp: ... def dele(self, which: Any) -> bytes: ... def noop(self) -> bytes: ... def rset(self) -> bytes: ... def quit(self) -> bytes: ... def close(self) -> None: ... - def rpop(self, user: Text) -> bytes: ... - timestamp: Pattern[Text] - - if sys.version_info < (3, 0): - def apop(self, user: Text, secret: Text) -> bytes: ... - else: - def apop(self, user: Text, password: Text) -> bytes: ... + def rpop(self, user: str) -> bytes: ... + timestamp: Pattern[str] + def apop(self, user: str, password: str) -> bytes: ... def top(self, which: Any, howmuch: int) -> _LongResp: ... @overload def uidl(self) -> _LongResp: ... @overload def uidl(self, which: Any) -> bytes: ... - if sys.version_info >= (3, 5): - def utf8(self) -> bytes: ... - if sys.version_info >= (3, 4): - def capa(self) -> Dict[Text, List[Text]]: ... - def stls(self, context: Optional[ssl.SSLContext] = ...) -> bytes: ... + def utf8(self) -> bytes: ... + def capa(self) -> dict[str, _list[str]]: ... + def stls(self, context: ssl.SSLContext | None = ...) -> bytes: ... class POP3_SSL(POP3): - if sys.version_info >= (3, 0): - def __init__( - self, - host: Text, - port: int = ..., - keyfile: Optional[Text] = ..., - certfile: Optional[Text] = ..., - timeout: float = ..., - context: Optional[ssl.SSLContext] = ..., - ) -> None: ... - else: - def __init__( - self, host: Text, port: int = ..., keyfile: Optional[Text] = ..., certfile: Optional[Text] = ..., timeout: float = ... - ) -> None: ... - if sys.version_info >= (3, 4): - # "context" is actually the last argument, but that breaks LSP and it doesn't really matter because all the arguments are ignored - def stls(self, context: Any = ..., keyfile: Any = ..., certfile: Any = ...) -> bytes: ... + def __init__( + self, + host: str, + port: int = ..., + keyfile: str | None = ..., + certfile: str | None = ..., + timeout: float = ..., + context: ssl.SSLContext | None = ..., + ) -> None: ... + # "context" is actually the last argument, but that breaks LSP and it doesn't really matter because all the arguments are ignored + def stls(self, context: Any = ..., keyfile: Any = ..., certfile: Any = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/posix.pyi b/mypy/typeshed/stdlib/posix.pyi index 2499463647cd..14cea87cde29 100644 --- a/mypy/typeshed/stdlib/posix.pyi +++ b/mypy/typeshed/stdlib/posix.pyi @@ -1,7 +1,10 @@ import sys -from os import PathLike, stat_result as stat_result -from typing import Dict, List, NamedTuple, Optional, overload +from _typeshed import StrOrBytesPath +from os import PathLike, _ExecEnv, _ExecVArgs, stat_result as stat_result +from typing import Any, Iterable, NamedTuple, Sequence, Tuple, overload +from typing_extensions import final +@final class uname_result(NamedTuple): sysname: str nodename: str @@ -9,6 +12,7 @@ class uname_result(NamedTuple): version: str machine: str +@final class times_result(NamedTuple): user: float system: float @@ -158,15 +162,43 @@ XATTR_REPLACE: int XATTR_SIZE_MAX: int @overload -def listdir(path: Optional[str] = ...) -> List[str]: ... +def listdir(path: str | None = ...) -> list[str]: ... @overload -def listdir(path: bytes) -> List[bytes]: ... +def listdir(path: bytes) -> list[bytes]: ... @overload -def listdir(path: int) -> List[str]: ... +def listdir(path: int) -> list[str]: ... @overload -def listdir(path: PathLike[str]) -> List[str]: ... +def listdir(path: PathLike[str]) -> list[str]: ... + +if sys.platform != "win32" and sys.version_info >= (3, 8): + def posix_spawn( + path: StrOrBytesPath, + argv: _ExecVArgs, + env: _ExecEnv, + *, + file_actions: Sequence[Tuple[Any, ...]] | None = ..., + setpgroup: int | None = ..., + resetids: bool = ..., + setsid: bool = ..., + setsigmask: Iterable[int] = ..., + setsigdef: Iterable[int] = ..., + scheduler: tuple[Any, sched_param] | None = ..., + ) -> int: ... + def posix_spawnp( + path: StrOrBytesPath, + argv: _ExecVArgs, + env: _ExecEnv, + *, + file_actions: Sequence[Tuple[Any, ...]] | None = ..., + setpgroup: int | None = ..., + resetids: bool = ..., + setsid: bool = ..., + setsigmask: Iterable[int] = ..., + setsigdef: Iterable[int] = ..., + scheduler: tuple[Any, sched_param] | None = ..., + ) -> int: ... if sys.platform == "win32": - environ: Dict[str, str] + environ: dict[str, str] else: - environ: Dict[bytes, bytes] + environ: dict[bytes, bytes] diff --git a/mypy/typeshed/stdlib/posixpath.pyi b/mypy/typeshed/stdlib/posixpath.pyi index 98176eaa03ec..ae3d0d5cc65f 100644 --- a/mypy/typeshed/stdlib/posixpath.pyi +++ b/mypy/typeshed/stdlib/posixpath.pyi @@ -1,5 +1,5 @@ import sys -from _typeshed import AnyPath, BytesPath, StrPath +from _typeshed import BytesPath, StrOrBytesPath, StrPath from genericpath import ( commonprefix as commonprefix, exists as exists, @@ -14,14 +14,14 @@ from genericpath import ( samestat as samestat, ) from os import PathLike -from typing import AnyStr, Optional, Sequence, Tuple, overload +from typing import AnyStr, Sequence, overload supports_unicode_filenames: bool # aliases (also in os) curdir: str pardir: str sep: str -altsep: Optional[str] +altsep: str | None extsep: str pathsep: str defpath: str @@ -78,22 +78,22 @@ else: def realpath(filename: AnyStr) -> AnyStr: ... @overload -def relpath(path: BytesPath, start: Optional[BytesPath] = ...) -> bytes: ... +def relpath(path: BytesPath, start: BytesPath | None = ...) -> bytes: ... @overload -def relpath(path: StrPath, start: Optional[StrPath] = ...) -> str: ... +def relpath(path: StrPath, start: StrPath | None = ...) -> str: ... @overload -def split(p: PathLike[AnyStr]) -> Tuple[AnyStr, AnyStr]: ... +def split(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... @overload -def splitdrive(p: PathLike[AnyStr]) -> Tuple[AnyStr, AnyStr]: ... +def splitdrive(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... @overload -def splitext(p: PathLike[AnyStr]) -> Tuple[AnyStr, AnyStr]: ... +def splitext(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def isabs(s: AnyPath) -> bool: ... -def islink(path: AnyPath) -> bool: ... -def ismount(path: AnyPath) -> bool: ... -def lexists(path: AnyPath) -> bool: ... +def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def isabs(s: StrOrBytesPath) -> bool: ... +def islink(path: StrOrBytesPath | int) -> bool: ... +def ismount(path: StrOrBytesPath | int) -> bool: ... +def lexists(path: StrOrBytesPath | int) -> bool: ... diff --git a/mypy/typeshed/stdlib/pprint.pyi b/mypy/typeshed/stdlib/pprint.pyi index 9484f92eca46..9e343feb49bc 100644 --- a/mypy/typeshed/stdlib/pprint.pyi +++ b/mypy/typeshed/stdlib/pprint.pyi @@ -1,12 +1,12 @@ import sys -from typing import IO, Any, Dict, Optional, Tuple +from typing import IO, Any if sys.version_info >= (3, 10): def pformat( object: object, indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., @@ -18,27 +18,22 @@ elif sys.version_info >= (3, 8): object: object, indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., ) -> str: ... -elif sys.version_info >= (3, 4): - def pformat( - object: object, indent: int = ..., width: int = ..., depth: Optional[int] = ..., *, compact: bool = ... - ) -> str: ... - else: - def pformat(object: object, indent: int = ..., width: int = ..., depth: Optional[int] = ...) -> str: ... + def pformat(object: object, indent: int = ..., width: int = ..., depth: int | None = ..., *, compact: bool = ...) -> str: ... if sys.version_info >= (3, 10): def pp( object: object, - stream: Optional[IO[str]] = ..., + stream: IO[str] | None = ..., indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., @@ -48,10 +43,10 @@ if sys.version_info >= (3, 10): elif sys.version_info >= (3, 8): def pp( object: object, - stream: Optional[IO[str]] = ..., + stream: IO[str] | None = ..., indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., @@ -60,10 +55,10 @@ elif sys.version_info >= (3, 8): if sys.version_info >= (3, 10): def pprint( object: object, - stream: Optional[IO[str]] = ..., + stream: IO[str] | None = ..., indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., @@ -73,31 +68,26 @@ if sys.version_info >= (3, 10): elif sys.version_info >= (3, 8): def pprint( object: object, - stream: Optional[IO[str]] = ..., + stream: IO[str] | None = ..., indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., ) -> None: ... -elif sys.version_info >= (3, 4): +else: def pprint( object: object, - stream: Optional[IO[str]] = ..., + stream: IO[str] | None = ..., indent: int = ..., width: int = ..., - depth: Optional[int] = ..., + depth: int | None = ..., *, compact: bool = ..., ) -> None: ... -else: - def pprint( - object: object, stream: Optional[IO[str]] = ..., indent: int = ..., width: int = ..., depth: Optional[int] = ... - ) -> None: ... - def isreadable(object: object) -> bool: ... def isrecursive(object: object) -> bool: ... def saferepr(object: object) -> str: ... @@ -108,8 +98,8 @@ class PrettyPrinter: self, indent: int = ..., width: int = ..., - depth: Optional[int] = ..., - stream: Optional[IO[str]] = ..., + depth: int | None = ..., + stream: IO[str] | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., @@ -120,28 +110,24 @@ class PrettyPrinter: self, indent: int = ..., width: int = ..., - depth: Optional[int] = ..., - stream: Optional[IO[str]] = ..., + depth: int | None = ..., + stream: IO[str] | None = ..., *, compact: bool = ..., sort_dicts: bool = ..., ) -> None: ... - elif sys.version_info >= (3, 4): + else: def __init__( self, indent: int = ..., width: int = ..., - depth: Optional[int] = ..., - stream: Optional[IO[str]] = ..., + depth: int | None = ..., + stream: IO[str] | None = ..., *, compact: bool = ..., ) -> None: ... - else: - def __init__( - self, indent: int = ..., width: int = ..., depth: Optional[int] = ..., stream: Optional[IO[str]] = ... - ) -> None: ... def pformat(self, object: object) -> str: ... def pprint(self, object: object) -> None: ... def isreadable(self, object: object) -> bool: ... def isrecursive(self, object: object) -> bool: ... - def format(self, object: object, context: Dict[int, Any], maxlevels: int, level: int) -> Tuple[str, bool, bool]: ... + def format(self, object: object, context: dict[int, Any], maxlevels: int, level: int) -> tuple[str, bool, bool]: ... diff --git a/mypy/typeshed/stdlib/profile.pyi b/mypy/typeshed/stdlib/profile.pyi index cc769b604a71..cb0cbf7c9388 100644 --- a/mypy/typeshed/stdlib/profile.pyi +++ b/mypy/typeshed/stdlib/profile.pyi @@ -1,9 +1,9 @@ -from _typeshed import AnyPath -from typing import Any, Callable, Dict, Optional, Tuple, TypeVar, Union +from _typeshed import StrOrBytesPath +from typing import Any, Callable, Tuple, TypeVar -def run(statement: str, filename: Optional[str] = ..., sort: Union[str, int] = ...) -> None: ... +def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( - statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: Optional[str] = ..., sort: Union[str, int] = ... + statement: str, globals: dict[str, Any], locals: dict[str, Any], filename: str | None = ..., sort: str | int = ... ) -> None: ... _SelfT = TypeVar("_SelfT", bound=Profile) @@ -13,15 +13,15 @@ _Label = Tuple[str, int, str] class Profile: bias: int stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented - def __init__(self, timer: Optional[Callable[[], float]] = ..., bias: Optional[int] = ...) -> None: ... + def __init__(self, timer: Callable[[], float] | None = ..., bias: int | None = ...) -> None: ... def set_cmd(self, cmd: str) -> None: ... def simulate_call(self, name: str) -> None: ... def simulate_cmd_complete(self) -> None: ... - def print_stats(self, sort: Union[str, int] = ...) -> None: ... - def dump_stats(self, file: AnyPath) -> None: ... + def print_stats(self, sort: str | int = ...) -> None: ... + def dump_stats(self, file: StrOrBytesPath) -> None: ... def create_stats(self) -> None: ... def snapshot_stats(self) -> None: ... def run(self: _SelfT, cmd: str) -> _SelfT: ... - def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... + def runctx(self: _SelfT, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> _SelfT: ... def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... def calibrate(self, m: int, verbose: int = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/pstats.pyi b/mypy/typeshed/stdlib/pstats.pyi index 9c74aeb9c3de..e8256f9f98ab 100644 --- a/mypy/typeshed/stdlib/pstats.pyi +++ b/mypy/typeshed/stdlib/pstats.pyi @@ -1,8 +1,8 @@ import sys -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from cProfile import Profile as _cProfile from profile import Profile -from typing import IO, Any, Dict, Iterable, List, Optional, Text, Tuple, TypeVar, Union, overload +from typing import IO, Any, Iterable, Tuple, TypeVar, Union, overload _Selector = Union[str, float, int] _T = TypeVar("_T", bound=Stats) @@ -21,19 +21,19 @@ if sys.version_info >= (3, 7): TIME: str class Stats: - sort_arg_dict_default: Dict[str, Tuple[Any, str]] + sort_arg_dict_default: dict[str, tuple[Any, str]] def __init__( self: _T, - __arg: Union[None, str, Text, Profile, _cProfile] = ..., - *args: Union[None, str, Text, Profile, _cProfile, _T], - stream: Optional[IO[Any]] = ..., + __arg: None | str | Profile | _cProfile = ..., + *args: None | str | Profile | _cProfile | _T, + stream: IO[Any] | None = ..., ) -> None: ... - def init(self, arg: Union[None, str, Text, Profile, _cProfile]) -> None: ... - def load_stats(self, arg: Union[None, str, Text, Profile, _cProfile]) -> None: ... + def init(self, arg: None | str | Profile | _cProfile) -> None: ... + def load_stats(self, arg: None | str | Profile | _cProfile) -> None: ... def get_top_level_stats(self) -> None: ... - def add(self: _T, *arg_list: Union[None, str, Text, Profile, _cProfile, _T]) -> _T: ... - def dump_stats(self, filename: AnyPath) -> None: ... - def get_sort_arg_defs(self) -> Dict[str, Tuple[Tuple[Tuple[int, int], ...], str]]: ... + def add(self: _T, *arg_list: None | str | Profile | _cProfile | _T) -> _T: ... + def dump_stats(self, filename: StrOrBytesPath) -> None: ... + def get_sort_arg_defs(self) -> dict[str, tuple[Tuple[tuple[int, int], ...], str]]: ... @overload def sort_stats(self: _T, field: int) -> _T: ... @overload @@ -41,12 +41,12 @@ class Stats: def reverse_order(self: _T) -> _T: ... def strip_dirs(self: _T) -> _T: ... def calc_callees(self) -> None: ... - def eval_print_amount(self, sel: _Selector, list: List[str], msg: str) -> Tuple[List[str], str]: ... - def get_print_list(self, sel_list: Iterable[_Selector]) -> Tuple[int, List[str]]: ... + def eval_print_amount(self, sel: _Selector, list: list[str], msg: str) -> tuple[list[str], str]: ... + def get_print_list(self, sel_list: Iterable[_Selector]) -> tuple[int, list[str]]: ... def print_stats(self: _T, *amount: _Selector) -> _T: ... def print_callees(self: _T, *amount: _Selector) -> _T: ... def print_callers(self: _T, *amount: _Selector) -> _T: ... def print_call_heading(self, name_size: int, column_title: str) -> None: ... - def print_call_line(self, name_size: int, source: str, call_dict: Dict[str, Any], arrow: str = ...) -> None: ... + def print_call_line(self, name_size: int, source: str, call_dict: dict[str, Any], arrow: str = ...) -> None: ... def print_title(self) -> None: ... def print_line(self, func: str) -> None: ... diff --git a/mypy/typeshed/stdlib/pty.pyi b/mypy/typeshed/stdlib/pty.pyi index f31e2c61ca9b..f943cebdb157 100644 --- a/mypy/typeshed/stdlib/pty.pyi +++ b/mypy/typeshed/stdlib/pty.pyi @@ -1,5 +1,4 @@ -import sys -from typing import Callable, Iterable, Tuple, Union +from typing import Callable, Iterable _Reader = Callable[[int], bytes] @@ -9,13 +8,8 @@ STDERR_FILENO: int CHILD: int -def openpty() -> Tuple[int, int]: ... -def master_open() -> Tuple[int, str]: ... +def openpty() -> tuple[int, int]: ... +def master_open() -> tuple[int, str]: ... def slave_open(tty_name: str) -> int: ... -def fork() -> Tuple[int, int]: ... - -if sys.version_info >= (3, 4): - def spawn(argv: Union[str, Iterable[str]], master_read: _Reader = ..., stdin_read: _Reader = ...) -> int: ... - -else: - def spawn(argv: Union[str, Iterable[str]], master_read: _Reader = ..., stdin_read: _Reader = ...) -> None: ... +def fork() -> tuple[int, int]: ... +def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/pwd.pyi b/mypy/typeshed/stdlib/pwd.pyi index 83020c1576dd..2b931248edda 100644 --- a/mypy/typeshed/stdlib/pwd.pyi +++ b/mypy/typeshed/stdlib/pwd.pyi @@ -1,4 +1,4 @@ -from typing import List, Tuple +from typing import ClassVar, Tuple class struct_passwd(Tuple[str, str, int, int, str, str, str]): pw_name: str @@ -9,6 +9,10 @@ class struct_passwd(Tuple[str, str, int, int, str, str, str]): pw_dir: str pw_shell: str -def getpwall() -> List[struct_passwd]: ... + n_fields: ClassVar[int] + n_sequence_fields: ClassVar[int] + n_unnamed_fields: ClassVar[int] + +def getpwall() -> list[struct_passwd]: ... def getpwuid(__uid: int) -> struct_passwd: ... def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/py_compile.pyi b/mypy/typeshed/stdlib/py_compile.pyi index 49473b17708e..1df818509d0e 100644 --- a/mypy/typeshed/stdlib/py_compile.pyi +++ b/mypy/typeshed/stdlib/py_compile.pyi @@ -1,7 +1,5 @@ import sys -from typing import AnyStr, List, Optional, Text, Type, Union - -_EitherStr = Union[bytes, Text] +from typing import AnyStr, Type class PyCompileError(Exception): exc_type_name: str @@ -13,40 +11,35 @@ class PyCompileError(Exception): if sys.version_info >= (3, 7): import enum class PycInvalidationMode(enum.Enum): - TIMESTAMP: int = ... - CHECKED_HASH: int = ... - UNCHECKED_HASH: int = ... + TIMESTAMP: int + CHECKED_HASH: int + UNCHECKED_HASH: int def _get_default_invalidation_mode() -> PycInvalidationMode: ... if sys.version_info >= (3, 8): def compile( file: AnyStr, - cfile: Optional[AnyStr] = ..., - dfile: Optional[AnyStr] = ..., + cfile: AnyStr | None = ..., + dfile: AnyStr | None = ..., doraise: bool = ..., optimize: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., + invalidation_mode: PycInvalidationMode | None = ..., quiet: int = ..., - ) -> Optional[AnyStr]: ... + ) -> AnyStr | None: ... elif sys.version_info >= (3, 7): def compile( file: AnyStr, - cfile: Optional[AnyStr] = ..., - dfile: Optional[AnyStr] = ..., + cfile: AnyStr | None = ..., + dfile: AnyStr | None = ..., doraise: bool = ..., optimize: int = ..., - invalidation_mode: Optional[PycInvalidationMode] = ..., - ) -> Optional[AnyStr]: ... - -elif sys.version_info >= (3, 2): - def compile( - file: AnyStr, cfile: Optional[AnyStr] = ..., dfile: Optional[AnyStr] = ..., doraise: bool = ..., optimize: int = ... - ) -> Optional[AnyStr]: ... + invalidation_mode: PycInvalidationMode | None = ..., + ) -> AnyStr | None: ... else: def compile( - file: _EitherStr, cfile: Optional[_EitherStr] = ..., dfile: Optional[_EitherStr] = ..., doraise: bool = ... - ) -> None: ... + file: AnyStr, cfile: AnyStr | None = ..., dfile: AnyStr | None = ..., doraise: bool = ..., optimize: int = ... + ) -> AnyStr | None: ... -def main(args: Optional[List[Text]] = ...) -> int: ... +def main(args: list[str] | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/pyclbr.pyi b/mypy/typeshed/stdlib/pyclbr.pyi index 665ea43c0d4a..10d106b4f511 100644 --- a/mypy/typeshed/stdlib/pyclbr.pyi +++ b/mypy/typeshed/stdlib/pyclbr.pyi @@ -1,26 +1,20 @@ import sys -from typing import Dict, List, Optional, Sequence, Union +from typing import Sequence class Class: module: str name: str - super: Optional[List[Union[Class, str]]] - methods: Dict[str, int] + super: list[Class | str] | None + methods: dict[str, int] file: int lineno: int if sys.version_info >= (3, 7): def __init__( - self, - module: str, - name: str, - super: Optional[List[Union[Class, str]]], - file: str, - lineno: int, - parent: Optional[Class] = ..., + self, module: str, name: str, super: list[Class | str] | None, file: str, lineno: int, parent: Class | None = ... ) -> None: ... else: - def __init__(self, module: str, name: str, super: Optional[List[Union[Class, str]]], file: str, lineno: int) -> None: ... + def __init__(self, module: str, name: str, super: list[Class | str] | None, file: str, lineno: int) -> None: ... class Function: module: str @@ -29,9 +23,9 @@ class Function: lineno: int if sys.version_info >= (3, 7): - def __init__(self, module: str, name: str, file: str, lineno: int, parent: Optional[Function] = ...) -> None: ... + def __init__(self, module: str, name: str, file: str, lineno: int, parent: Function | None = ...) -> None: ... else: def __init__(self, module: str, name: str, file: str, lineno: int) -> None: ... -def readmodule(module: str, path: Optional[Sequence[str]] = ...) -> Dict[str, Class]: ... -def readmodule_ex(module: str, path: Optional[Sequence[str]] = ...) -> Dict[str, Union[Class, Function, List[str]]]: ... +def readmodule(module: str, path: Sequence[str] | None = ...) -> dict[str, Class]: ... +def readmodule_ex(module: str, path: Sequence[str] | None = ...) -> dict[str, Class | Function | list[str]]: ... diff --git a/mypy/typeshed/stdlib/pydoc.pyi b/mypy/typeshed/stdlib/pydoc.pyi index 39252dd9f725..97e71f389616 100644 --- a/mypy/typeshed/stdlib/pydoc.pyi +++ b/mypy/typeshed/stdlib/pydoc.pyi @@ -1,28 +1,7 @@ -import sys from _typeshed import SupportsWrite +from reprlib import Repr from types import MethodType, ModuleType, TracebackType -from typing import ( - IO, - Any, - AnyStr, - Callable, - Container, - Dict, - List, - Mapping, - MutableMapping, - NoReturn, - Optional, - Text, - Tuple, - Type, - Union, -) - -if sys.version_info >= (3,): - from reprlib import Repr -else: - from repr import Repr +from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, Optional, Tuple, Type # the return type of sys.exc_info(), used by ErrorDuringImport.__init__ _Exc_Info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] @@ -32,26 +11,26 @@ __date__: str __version__: str __credits__: str -def pathdirs() -> List[str]: ... -def getdoc(object: object) -> Text: ... -def splitdoc(doc: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def pathdirs() -> list[str]: ... +def getdoc(object: object) -> str: ... +def splitdoc(doc: AnyStr) -> tuple[AnyStr, AnyStr]: ... def classname(object: object, modname: str) -> str: ... def isdata(object: object) -> bool: ... def replace(text: AnyStr, *pairs: AnyStr) -> AnyStr: ... def cram(text: str, maxlen: int) -> str: ... def stripid(text: str) -> str: ... def allmethods(cl: type) -> MutableMapping[str, MethodType]: ... -def visiblename(name: str, all: Optional[Container[str]] = ..., obj: Optional[object] = ...) -> bool: ... -def classify_class_attrs(object: object) -> List[Tuple[str, str, type, str]]: ... +def visiblename(name: str, all: Container[str] | None = ..., obj: object | None = ...) -> bool: ... +def classify_class_attrs(object: object) -> list[tuple[str, str, type, str]]: ... def ispackage(path: str) -> bool: ... -def source_synopsis(file: IO[AnyStr]) -> Optional[AnyStr]: ... -def synopsis(filename: str, cache: MutableMapping[str, Tuple[int, str]] = ...) -> Optional[str]: ... +def source_synopsis(file: IO[AnyStr]) -> AnyStr | None: ... +def synopsis(filename: str, cache: MutableMapping[str, tuple[int, str]] = ...) -> str | None: ... class ErrorDuringImport(Exception): filename: str - exc: Optional[Type[BaseException]] - value: Optional[BaseException] - tb: Optional[TracebackType] + exc: Type[BaseException] | None + value: BaseException | None + tb: TracebackType | None def __init__(self, filename: str, exc_info: _Exc_Info) -> None: ... def importfile(path: str) -> ModuleType: ... @@ -59,15 +38,15 @@ def safeimport(path: str, forceload: bool = ..., cache: MutableMapping[str, Modu class Doc: PYTHONDOCS: str - def document(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def fail(self, object: object, name: Optional[str] = ..., *args: Any) -> NoReturn: ... - def docmodule(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def docclass(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def docroutine(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def docother(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def docproperty(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def docdata(self, object: object, name: Optional[str] = ..., *args: Any) -> str: ... - def getdocloc(self, object: object, basedir: str = ...) -> Optional[str]: ... + def document(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def fail(self, object: object, name: str | None = ..., *args: Any) -> NoReturn: ... + def docmodule(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docclass(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docroutine(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docother(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docproperty(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def docdata(self, object: object, name: str | None = ..., *args: Any) -> str: ... + def getdocloc(self, object: object, basedir: str = ...) -> str | None: ... class HTMLRepr(Repr): maxlist: int @@ -79,8 +58,8 @@ class HTMLRepr(Repr): def escape(self, text: str) -> str: ... def repr(self, object: object) -> str: ... def repr1(self, x: object, level: complex) -> str: ... - def repr_string(self, x: Text, level: complex) -> str: ... - def repr_str(self, x: Text, level: complex) -> str: ... + def repr_string(self, x: str, level: complex) -> str: ... + def repr_str(self, x: str, level: complex) -> str: ... def repr_instance(self, x: object, level: complex) -> str: ... def repr_unicode(self, x: AnyStr, level: complex) -> str: ... @@ -97,34 +76,34 @@ class HTMLDoc(Doc): contents: str, width: int = ..., prelude: str = ..., - marginalia: Optional[str] = ..., + marginalia: str | None = ..., gap: str = ..., ) -> str: ... def bigsection(self, title: str, *args: Any) -> str: ... def preformat(self, text: str) -> str: ... - def multicolumn(self, list: List[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... + def multicolumn(self, list: list[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... def grey(self, text: str) -> str: ... def namelink(self, name: str, *dicts: MutableMapping[str, str]) -> str: ... def classlink(self, object: object, modname: str) -> str: ... def modulelink(self, object: object) -> str: ... - def modpkglink(self, modpkginfo: Tuple[str, str, bool, bool]) -> str: ... + def modpkglink(self, modpkginfo: tuple[str, str, bool, bool]) -> str: ... def markup( self, text: str, - escape: Optional[Callable[[str], str]] = ..., + escape: Callable[[str], str] | None = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., ) -> str: ... def formattree( - self, tree: List[Union[Tuple[type, Tuple[type, ...]], List[Any]]], modname: str, parent: Optional[type] = ... + self, tree: list[tuple[type, Tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ... ) -> str: ... - def docmodule(self, object: object, name: Optional[str] = ..., mod: Optional[str] = ..., *ignored: Any) -> str: ... + def docmodule(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... def docclass( self, object: object, - name: Optional[str] = ..., - mod: Optional[str] = ..., + name: str | None = ..., + mod: str | None = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., *ignored: Any, @@ -133,22 +112,22 @@ class HTMLDoc(Doc): def docroutine( self, object: object, - name: Optional[str] = ..., - mod: Optional[str] = ..., + name: str | None = ..., + mod: str | None = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., - cl: Optional[type] = ..., + cl: type | None = ..., *ignored: Any, ) -> str: ... def docproperty( - self, object: object, name: Optional[str] = ..., mod: Optional[str] = ..., cl: Optional[Any] = ..., *ignored: Any + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... - def docother(self, object: object, name: Optional[str] = ..., mod: Optional[Any] = ..., *ignored: Any) -> str: ... + def docother(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... def docdata( - self, object: object, name: Optional[str] = ..., mod: Optional[Any] = ..., cl: Optional[Any] = ..., *ignored: Any + self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... - def index(self, dir: str, shadowed: Optional[MutableMapping[str, bool]] = ...) -> str: ... + def index(self, dir: str, shadowed: MutableMapping[str, bool] | None = ...) -> str: ... def filelink(self, url: str, path: str) -> str: ... class TextRepr(Repr): @@ -169,32 +148,28 @@ class TextDoc(Doc): def indent(self, text: str, prefix: str = ...) -> str: ... def section(self, title: str, contents: str) -> str: ... def formattree( - self, - tree: List[Union[Tuple[type, Tuple[type, ...]], List[Any]]], - modname: str, - parent: Optional[type] = ..., - prefix: str = ..., + self, tree: list[tuple[type, Tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ..., prefix: str = ... ) -> str: ... - def docmodule(self, object: object, name: Optional[str] = ..., mod: Optional[Any] = ..., *ignored: Any) -> str: ... - def docclass(self, object: object, name: Optional[str] = ..., mod: Optional[str] = ..., *ignored: Any) -> str: ... + def docmodule(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... + def docclass(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... def formatvalue(self, object: object) -> str: ... def docroutine( - self, object: object, name: Optional[str] = ..., mod: Optional[str] = ..., cl: Optional[Any] = ..., *ignored: Any + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... def docproperty( - self, object: object, name: Optional[str] = ..., mod: Optional[Any] = ..., cl: Optional[Any] = ..., *ignored: Any + self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... def docdata( - self, object: object, name: Optional[str] = ..., mod: Optional[str] = ..., cl: Optional[Any] = ..., *ignored: Any + self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... def docother( self, object: object, - name: Optional[str] = ..., - mod: Optional[str] = ..., - parent: Optional[str] = ..., - maxlen: Optional[int] = ..., - doc: Optional[Any] = ..., + name: str | None = ..., + mod: str | None = ..., + parent: str | None = ..., + maxlen: int | None = ..., + doc: Any | None = ..., *ignored: Any, ) -> str: ... @@ -213,27 +188,27 @@ html: HTMLDoc class _OldStyleClass: ... -def resolve(thing: Union[str, object], forceload: bool = ...) -> Optional[Tuple[object, str]]: ... -def render_doc(thing: Union[str, object], title: str = ..., forceload: bool = ..., renderer: Optional[Doc] = ...) -> str: ... -def doc( - thing: Union[str, object], title: str = ..., forceload: bool = ..., output: Optional[SupportsWrite[str]] = ... -) -> None: ... -def writedoc(thing: Union[str, object], forceload: bool = ...) -> None: ... -def writedocs(dir: str, pkgpath: str = ..., done: Optional[Any] = ...) -> None: ... +def resolve(thing: str | object, forceload: bool = ...) -> tuple[object, str] | None: ... +def render_doc(thing: str | object, title: str = ..., forceload: bool = ..., renderer: Doc | None = ...) -> str: ... +def doc(thing: str | object, title: str = ..., forceload: bool = ..., output: SupportsWrite[str] | None = ...) -> None: ... +def writedoc(thing: str | object, forceload: bool = ...) -> None: ... +def writedocs(dir: str, pkgpath: str = ..., done: Any | None = ...) -> None: ... + +_list = list # "list" conflicts with method name class Helper: - keywords: Dict[str, Union[str, Tuple[str, str]]] - symbols: Dict[str, str] - topics: Dict[str, Union[str, Tuple[str, ...]]] - def __init__(self, input: Optional[IO[str]] = ..., output: Optional[IO[str]] = ...) -> None: ... + keywords: dict[str, str | tuple[str, str]] + symbols: dict[str, str] + topics: dict[str, str | Tuple[str, ...]] + def __init__(self, input: IO[str] | None = ..., output: IO[str] | None = ...) -> None: ... input: IO[str] output: IO[str] - def __call__(self, request: Union[str, Helper, object] = ...) -> None: ... + def __call__(self, request: str | Helper | object = ...) -> None: ... def interact(self) -> None: ... def getline(self, prompt: str) -> str: ... def help(self, request: Any) -> None: ... def intro(self) -> None: ... - def list(self, items: List[str], columns: int = ..., width: int = ...) -> None: ... + def list(self, items: _list[str], columns: int = ..., width: int = ...) -> None: ... def listkeywords(self) -> None: ... def listsymbols(self) -> None: ... def listtopics(self) -> None: ... @@ -256,18 +231,12 @@ class ModuleScanner: quit: bool def run( self, - callback: Callable[[Optional[str], str, str], None], - key: Optional[Any] = ..., - completer: Optional[Callable[[], None]] = ..., - onerror: Optional[Callable[[str], None]] = ..., + callback: Callable[[str | None, str, str], None], + key: Any | None = ..., + completer: Callable[[], None] | None = ..., + onerror: Callable[[str], None] | None = ..., ) -> None: ... def apropos(key: str) -> None: ... def ispath(x: Any) -> bool: ... def cli() -> None: ... - -if sys.version_info < (3,): - def serve( - port: int, callback: Optional[Callable[[Any], None]] = ..., completer: Optional[Callable[[], None]] = ... - ) -> None: ... - def gui() -> None: ... diff --git a/mypy/typeshed/stdlib/pydoc_data/topics.pyi b/mypy/typeshed/stdlib/pydoc_data/topics.pyi index 1c48f4022fd6..091d34300106 100644 --- a/mypy/typeshed/stdlib/pydoc_data/topics.pyi +++ b/mypy/typeshed/stdlib/pydoc_data/topics.pyi @@ -1,3 +1 @@ -from typing import Dict - -topics: Dict[str, str] +topics: dict[str, str] diff --git a/mypy/typeshed/stdlib/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/pyexpat/__init__.pyi index 65f6b0e9f7de..6a3d6cd56791 100644 --- a/mypy/typeshed/stdlib/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/pyexpat/__init__.pyi @@ -1,12 +1,13 @@ import pyexpat.errors as errors import pyexpat.model as model from _typeshed import SupportsRead -from typing import Any, Callable, Dict, List, Optional, Text, Tuple, Union +from typing import Any, Callable, Optional, Tuple +from typing_extensions import final EXPAT_VERSION: str # undocumented -version_info: Tuple[int, int, int] # undocumented +version_info: tuple[int, int, int] # undocumented native_encoding: str # undocumented -features: List[Tuple[str, int]] # undocumented +features: list[tuple[str, int]] # undocumented class ExpatError(Exception): code: int @@ -21,13 +22,14 @@ XML_PARAM_ENTITY_PARSING_ALWAYS: int _Model = Tuple[int, int, Optional[str], Tuple[Any, ...]] +@final class XMLParserType(object): - def Parse(self, __data: Union[Text, bytes], __isfinal: bool = ...) -> int: ... + def Parse(self, __data: str | bytes, __isfinal: bool = ...) -> int: ... def ParseFile(self, __file: SupportsRead[bytes]) -> int: ... - def SetBase(self, __base: Text) -> None: ... - def GetBase(self) -> Optional[str]: ... - def GetInputContext(self) -> Optional[bytes]: ... - def ExternalEntityParserCreate(self, __context: Optional[Text], __encoding: Text = ...) -> XMLParserType: ... + def SetBase(self, __base: str) -> None: ... + def GetBase(self) -> str | None: ... + def GetInputContext(self) -> bytes | None: ... + def ExternalEntityParserCreate(self, __context: str | None, __encoding: str = ...) -> XMLParserType: ... def SetParamEntityParsing(self, __flag: int) -> int: ... def UseForeignDTD(self, __flag: bool = ...) -> None: ... buffer_size: int @@ -43,37 +45,33 @@ class XMLParserType(object): CurrentByteIndex: int CurrentColumnNumber: int CurrentLineNumber: int - XmlDeclHandler: Optional[Callable[[str, Optional[str], int], Any]] - StartDoctypeDeclHandler: Optional[Callable[[str, Optional[str], Optional[str], bool], Any]] - EndDoctypeDeclHandler: Optional[Callable[[], Any]] - ElementDeclHandler: Optional[Callable[[str, _Model], Any]] - AttlistDeclHandler: Optional[Callable[[str, str, str, Optional[str], bool], Any]] - StartElementHandler: Optional[ - Union[ - Callable[[str, Dict[str, str]], Any], - Callable[[str, List[str]], Any], - Callable[[str, Union[Dict[str, str]], List[str]], Any], - ] - ] - EndElementHandler: Optional[Callable[[str], Any]] - ProcessingInstructionHandler: Optional[Callable[[str, str], Any]] - CharacterDataHandler: Optional[Callable[[str], Any]] - UnparsedEntityDeclHandler: Optional[Callable[[str, Optional[str], str, Optional[str], str], Any]] - EntityDeclHandler: Optional[Callable[[str, bool, Optional[str], Optional[str], str, Optional[str], Optional[str]], Any]] - NotationDeclHandler: Optional[Callable[[str, Optional[str], str, Optional[str]], Any]] - StartNamespaceDeclHandler: Optional[Callable[[str, str], Any]] - EndNamespaceDeclHandler: Optional[Callable[[str], Any]] - CommentHandler: Optional[Callable[[str], Any]] - StartCdataSectionHandler: Optional[Callable[[], Any]] - EndCdataSectionHandler: Optional[Callable[[], Any]] - DefaultHandler: Optional[Callable[[str], Any]] - DefaultHandlerExpand: Optional[Callable[[str], Any]] - NotStandaloneHandler: Optional[Callable[[], int]] - ExternalEntityRefHandler: Optional[Callable[[str, Optional[str], Optional[str], Optional[str]], int]] + XmlDeclHandler: Callable[[str, str | None, int], Any] | None + StartDoctypeDeclHandler: Callable[[str, str | None, str | None, bool], Any] | None + EndDoctypeDeclHandler: Callable[[], Any] | None + ElementDeclHandler: Callable[[str, _Model], Any] | None + AttlistDeclHandler: Callable[[str, str, str, str | None, bool], Any] | None + StartElementHandler: Callable[[str, dict[str, str]], Any] | Callable[[str, list[str]], Any] | Callable[ + [str, dict[str, str], list[str]], Any + ] | None + EndElementHandler: Callable[[str], Any] | None + ProcessingInstructionHandler: Callable[[str, str], Any] | None + CharacterDataHandler: Callable[[str], Any] | None + UnparsedEntityDeclHandler: Callable[[str, str | None, str, str | None, str], Any] | None + EntityDeclHandler: Callable[[str, bool, str | None, str | None, str, str | None, str | None], Any] | None + NotationDeclHandler: Callable[[str, str | None, str, str | None], Any] | None + StartNamespaceDeclHandler: Callable[[str, str], Any] | None + EndNamespaceDeclHandler: Callable[[str], Any] | None + CommentHandler: Callable[[str], Any] | None + StartCdataSectionHandler: Callable[[], Any] | None + EndCdataSectionHandler: Callable[[], Any] | None + DefaultHandler: Callable[[str], Any] | None + DefaultHandlerExpand: Callable[[str], Any] | None + NotStandaloneHandler: Callable[[], int] | None + ExternalEntityRefHandler: Callable[[str, str | None, str | None, str | None], int] | None def ErrorString(__code: int) -> str: ... # intern is undocumented def ParserCreate( - encoding: Optional[Text] = ..., namespace_separator: Optional[Text] = ..., intern: Optional[Dict[str, Any]] = ... + encoding: str | None = ..., namespace_separator: str | None = ..., intern: dict[str, Any] | None = ... ) -> XMLParserType: ... diff --git a/mypy/typeshed/stdlib/pyexpat/errors.pyi b/mypy/typeshed/stdlib/pyexpat/errors.pyi index 6cde43e3b61f..61826e12da00 100644 --- a/mypy/typeshed/stdlib/pyexpat/errors.pyi +++ b/mypy/typeshed/stdlib/pyexpat/errors.pyi @@ -1,9 +1,5 @@ -import sys -from typing import Dict - -if sys.version_info >= (3, 2): - codes: Dict[str, int] - messages: Dict[int, str] +codes: dict[str, int] +messages: dict[int, str] XML_ERROR_ABORTED: str XML_ERROR_ASYNC_ENTITY: str diff --git a/mypy/typeshed/stdlib/queue.pyi b/mypy/typeshed/stdlib/queue.pyi index 82fde5989d34..9671155b7eb6 100644 --- a/mypy/typeshed/stdlib/queue.pyi +++ b/mypy/typeshed/stdlib/queue.pyi @@ -1,6 +1,6 @@ import sys from threading import Condition, Lock -from typing import Any, Generic, Optional, TypeVar +from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -23,10 +23,10 @@ class Queue(Generic[_T]): def _init(self, maxsize: int) -> None: ... def empty(self) -> bool: ... def full(self) -> bool: ... - def get(self, block: bool = ..., timeout: Optional[float] = ...) -> _T: ... + def get(self, block: bool = ..., timeout: float | None = ...) -> _T: ... def get_nowait(self) -> _T: ... def _get(self) -> _T: ... - def put(self, item: _T, block: bool = ..., timeout: Optional[float] = ...) -> None: ... + def put(self, item: _T, block: bool = ..., timeout: float | None = ...) -> None: ... def put_nowait(self, item: _T) -> None: ... def _put(self, item: _T) -> None: ... def join(self) -> None: ... @@ -43,9 +43,9 @@ if sys.version_info >= (3, 7): class SimpleQueue(Generic[_T]): def __init__(self) -> None: ... def empty(self) -> bool: ... - def get(self, block: bool = ..., timeout: Optional[float] = ...) -> _T: ... + def get(self, block: bool = ..., timeout: float | None = ...) -> _T: ... def get_nowait(self) -> _T: ... - def put(self, item: _T, block: bool = ..., timeout: Optional[float] = ...) -> None: ... + def put(self, item: _T, block: bool = ..., timeout: float | None = ...) -> None: ... def put_nowait(self, item: _T) -> None: ... def qsize(self) -> int: ... if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/random.pyi b/mypy/typeshed/stdlib/random.pyi index 0f1e280490ac..73c29d2f78c3 100644 --- a/mypy/typeshed/stdlib/random.pyi +++ b/mypy/typeshed/stdlib/random.pyi @@ -1,7 +1,8 @@ import _random import sys -from collections.abc import Callable, Iterable, MutableSequence, Sequence, Set -from typing import Any, NoReturn, Optional, Tuple, TypeVar, Union +from collections.abc import Callable, Iterable, MutableSequence, Sequence, Set as AbstractSet +from fractions import Fraction +from typing import Any, NoReturn, Tuple, TypeVar _T = TypeVar("_T") @@ -11,7 +12,7 @@ class Random(_random.Random): def getstate(self) -> Tuple[Any, ...]: ... def setstate(self, state: Tuple[Any, ...]) -> None: ... def getrandbits(self, __k: int) -> int: ... - def randrange(self, start: int, stop: Optional[int] = ..., step: int = ...) -> int: ... + def randrange(self, start: int, stop: int | None = ..., step: int = ...) -> int: ... def randint(self, a: int, b: int) -> int: ... if sys.version_info >= (3, 9): def randbytes(self, n: int) -> bytes: ... @@ -19,21 +20,19 @@ class Random(_random.Random): def choices( self, population: Sequence[_T], - weights: Optional[Sequence[float]] = ..., + weights: Sequence[float | Fraction] | None = ..., *, - cum_weights: Optional[Sequence[float]] = ..., + cum_weights: Sequence[float | Fraction] | None = ..., k: int = ..., ) -> list[_T]: ... - def shuffle(self, x: MutableSequence[Any], random: Optional[Callable[[], float]] = ...) -> None: ... + def shuffle(self, x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... if sys.version_info >= (3, 9): - def sample( - self, population: Union[Sequence[_T], Set[_T]], k: int, *, counts: Optional[Iterable[_T]] = ... - ) -> list[_T]: ... + def sample(self, population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ...) -> list[_T]: ... else: - def sample(self, population: Union[Sequence[_T], Set[_T]], k: int) -> list[_T]: ... + def sample(self, population: Sequence[_T] | AbstractSet[_T], k: int) -> list[_T]: ... def random(self) -> float: ... def uniform(self, a: float, b: float) -> float: ... - def triangular(self, low: float = ..., high: float = ..., mode: Optional[float] = ...) -> float: ... + def triangular(self, low: float = ..., high: float = ..., mode: float | None = ...) -> float: ... def betavariate(self, alpha: float, beta: float) -> float: ... def expovariate(self, lambd: float) -> float: ... def gammavariate(self, alpha: float, beta: float) -> float: ... @@ -54,7 +53,7 @@ def seed(a: Any = ..., version: int = ...) -> None: ... def getstate() -> object: ... def setstate(state: object) -> None: ... def getrandbits(__k: int) -> int: ... -def randrange(start: int, stop: Union[None, int] = ..., step: int = ...) -> int: ... +def randrange(start: int, stop: None | int = ..., step: int = ...) -> int: ... def randint(a: int, b: int) -> int: ... if sys.version_info >= (3, 9): @@ -62,23 +61,19 @@ if sys.version_info >= (3, 9): def choice(seq: Sequence[_T]) -> _T: ... def choices( - population: Sequence[_T], - weights: Optional[Sequence[float]] = ..., - *, - cum_weights: Optional[Sequence[float]] = ..., - k: int = ..., + population: Sequence[_T], weights: Sequence[float] | None = ..., *, cum_weights: Sequence[float] | None = ..., k: int = ... ) -> list[_T]: ... -def shuffle(x: MutableSequence[Any], random: Optional[Callable[[], float]] = ...) -> None: ... +def shuffle(x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... if sys.version_info >= (3, 9): - def sample(population: Union[Sequence[_T], Set[_T]], k: int, *, counts: Optional[Iterable[_T]] = ...) -> list[_T]: ... + def sample(population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ...) -> list[_T]: ... else: - def sample(population: Union[Sequence[_T], Set[_T]], k: int) -> list[_T]: ... + def sample(population: Sequence[_T] | AbstractSet[_T], k: int) -> list[_T]: ... def random() -> float: ... def uniform(a: float, b: float) -> float: ... -def triangular(low: float = ..., high: float = ..., mode: Optional[float] = ...) -> float: ... +def triangular(low: float = ..., high: float = ..., mode: float | None = ...) -> float: ... def betavariate(alpha: float, beta: float) -> float: ... def expovariate(lambd: float) -> float: ... def gammavariate(alpha: float, beta: float) -> float: ... diff --git a/mypy/typeshed/stdlib/re.pyi b/mypy/typeshed/stdlib/re.pyi index 3f2490ae4e11..01a60d170c50 100644 --- a/mypy/typeshed/stdlib/re.pyi +++ b/mypy/typeshed/stdlib/re.pyi @@ -1,7 +1,7 @@ import enum import sys from sre_constants import error as error -from typing import Any, AnyStr, Callable, Iterator, List, Optional, Tuple, Union, overload +from typing import Any, AnyStr, Callable, Iterator, Union, overload # ----- re variables and constants ----- if sys.version_info >= (3, 7): @@ -56,27 +56,27 @@ def compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]: ... @overload def compile(pattern: Pattern[AnyStr], flags: _FlagsType = ...) -> Pattern[AnyStr]: ... @overload -def search(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def search(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload -def search(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def search(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload -def match(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def match(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload -def match(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def match(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... # New in Python 3.4 @overload -def fullmatch(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def fullmatch(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload -def fullmatch(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Optional[Match[AnyStr]]: ... +def fullmatch(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload -def split(pattern: AnyStr, string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> List[Union[AnyStr, Any]]: ... +def split(pattern: AnyStr, string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> list[AnyStr | Any]: ... @overload -def split(pattern: Pattern[AnyStr], string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> List[Union[AnyStr, Any]]: ... +def split(pattern: Pattern[AnyStr], string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> list[AnyStr | Any]: ... @overload -def findall(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> List[Any]: ... +def findall(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> list[Any]: ... @overload -def findall(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> List[Any]: ... +def findall(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> list[Any]: ... # Return an iterator yielding match objects over all non-overlapping matches # for the RE pattern in string. The string is scanned left-to-right, and @@ -99,19 +99,19 @@ def sub( pattern: Pattern[AnyStr], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... ) -> AnyStr: ... @overload -def subn(pattern: AnyStr, repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ...) -> Tuple[AnyStr, int]: ... +def subn(pattern: AnyStr, repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ...) -> tuple[AnyStr, int]: ... @overload def subn( pattern: AnyStr, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... @overload def subn( pattern: Pattern[AnyStr], repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... @overload def subn( pattern: Pattern[AnyStr], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... def escape(pattern: AnyStr) -> AnyStr: ... def purge() -> None: ... -def template(pattern: Union[AnyStr, Pattern[AnyStr]], flags: _FlagsType = ...) -> Pattern[AnyStr]: ... +def template(pattern: AnyStr | Pattern[AnyStr], flags: _FlagsType = ...) -> Pattern[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/readline.pyi b/mypy/typeshed/stdlib/readline.pyi index 8f28a2b2b760..2de749b2c216 100644 --- a/mypy/typeshed/stdlib/readline.pyi +++ b/mypy/typeshed/stdlib/readline.pyi @@ -1,21 +1,17 @@ -import sys -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from typing import Callable, Optional, Sequence _CompleterT = Optional[Callable[[str, int], Optional[str]]] _CompDispT = Optional[Callable[[str, Sequence[str], int], None]] def parse_and_bind(__string: str) -> None: ... -def read_init_file(__filename: Optional[AnyPath] = ...) -> None: ... +def read_init_file(__filename: StrOrBytesPath | None = ...) -> None: ... def get_line_buffer() -> str: ... def insert_text(__string: str) -> None: ... def redisplay() -> None: ... -def read_history_file(__filename: Optional[AnyPath] = ...) -> None: ... -def write_history_file(__filename: Optional[AnyPath] = ...) -> None: ... - -if sys.version_info >= (3, 5): - def append_history_file(__nelements: int, __filename: Optional[AnyPath] = ...) -> None: ... - +def read_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... +def write_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... +def append_history_file(__nelements: int, __filename: StrOrBytesPath | None = ...) -> None: ... def get_history_length() -> int: ... def set_history_length(__length: int) -> None: ... def clear_history() -> None: ... @@ -24,12 +20,9 @@ def get_history_item(__index: int) -> str: ... def remove_history_item(__pos: int) -> None: ... def replace_history_item(__pos: int, __line: str) -> None: ... def add_history(__string: str) -> None: ... - -if sys.version_info >= (3, 6): - def set_auto_history(__enabled: bool) -> None: ... - -def set_startup_hook(__function: Optional[Callable[[], None]] = ...) -> None: ... -def set_pre_input_hook(__function: Optional[Callable[[], None]] = ...) -> None: ... +def set_auto_history(__enabled: bool) -> None: ... +def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... +def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... def set_completer(__function: _CompleterT = ...) -> None: ... def get_completer() -> _CompleterT: ... def get_completion_type() -> int: ... diff --git a/mypy/typeshed/stdlib/reprlib.pyi b/mypy/typeshed/stdlib/reprlib.pyi index 39828ffc9f29..4d400554a4ff 100644 --- a/mypy/typeshed/stdlib/reprlib.pyi +++ b/mypy/typeshed/stdlib/reprlib.pyi @@ -1,5 +1,6 @@ from array import array -from typing import Any, Callable, Deque, Dict, FrozenSet, List, Set, Tuple +from collections import deque +from typing import Any, Callable, Tuple _ReprFunc = Callable[[Any], str] @@ -21,12 +22,12 @@ class Repr: def repr(self, x: Any) -> str: ... def repr1(self, x: Any, level: int) -> str: ... def repr_tuple(self, x: Tuple[Any, ...], level: int) -> str: ... - def repr_list(self, x: List[Any], level: int) -> str: ... + def repr_list(self, x: list[Any], level: int) -> str: ... def repr_array(self, x: array[Any], level: int) -> str: ... - def repr_set(self, x: Set[Any], level: int) -> str: ... - def repr_frozenset(self, x: FrozenSet[Any], level: int) -> str: ... - def repr_deque(self, x: Deque[Any], level: int) -> str: ... - def repr_dict(self, x: Dict[Any, Any], level: int) -> str: ... + def repr_set(self, x: set[Any], level: int) -> str: ... + def repr_frozenset(self, x: frozenset[Any], level: int) -> str: ... + def repr_deque(self, x: deque[Any], level: int) -> str: ... + def repr_dict(self, x: dict[Any, Any], level: int) -> str: ... def repr_str(self, x: str, level: int) -> str: ... def repr_int(self, x: int, level: int) -> str: ... def repr_instance(self, x: Any, level: int) -> str: ... diff --git a/mypy/typeshed/stdlib/resource.pyi b/mypy/typeshed/stdlib/resource.pyi index ff17bc1a0e44..d7124edcc2fa 100644 --- a/mypy/typeshed/stdlib/resource.pyi +++ b/mypy/typeshed/stdlib/resource.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Dict, Tuple, overload +from typing import Any, Tuple, overload RLIMIT_AS: int RLIMIT_CORE: int @@ -26,7 +26,7 @@ if sys.platform == "linux": _Tuple16 = Tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] class struct_rusage(_Tuple16): - def __new__(cls, sequence: _Tuple16, dict: Dict[str, Any] = ...) -> struct_rusage: ... + def __new__(cls, sequence: _Tuple16, dict: dict[str, Any] = ...) -> struct_rusage: ... ru_utime: float ru_stime: float ru_maxrss: int @@ -45,14 +45,14 @@ class struct_rusage(_Tuple16): ru_nivcsw: int def getpagesize() -> int: ... -def getrlimit(__resource: int) -> Tuple[int, int]: ... +def getrlimit(__resource: int) -> tuple[int, int]: ... def getrusage(__who: int) -> struct_rusage: ... -def setrlimit(__resource: int, __limits: Tuple[int, int]) -> None: ... +def setrlimit(__resource: int, __limits: tuple[int, int]) -> None: ... if sys.platform == "linux": @overload - def prlimit(pid: int, resource: int, limits: Tuple[int, int]) -> Tuple[int, int]: ... + def prlimit(pid: int, resource: int, limits: tuple[int, int]) -> tuple[int, int]: ... @overload - def prlimit(pid: int, resource: int) -> Tuple[int, int]: ... + def prlimit(pid: int, resource: int) -> tuple[int, int]: ... error = OSError diff --git a/mypy/typeshed/stdlib/rlcompleter.pyi b/mypy/typeshed/stdlib/rlcompleter.pyi index 3733cc13110c..f971c424213d 100644 --- a/mypy/typeshed/stdlib/rlcompleter.pyi +++ b/mypy/typeshed/stdlib/rlcompleter.pyi @@ -1,11 +1,5 @@ -import sys -from typing import Any, Dict, Optional, Union - -if sys.version_info >= (3,): - _Text = str -else: - _Text = Union[str, unicode] +from typing import Any class Completer: - def __init__(self, namespace: Optional[Dict[str, Any]] = ...) -> None: ... - def complete(self, text: _Text, state: int) -> Optional[str]: ... + def __init__(self, namespace: dict[str, Any] | None = ...) -> None: ... + def complete(self, text: str, state: int) -> str | None: ... diff --git a/mypy/typeshed/stdlib/runpy.pyi b/mypy/typeshed/stdlib/runpy.pyi index d40c3668ad2f..371fa9d07cf8 100644 --- a/mypy/typeshed/stdlib/runpy.pyi +++ b/mypy/typeshed/stdlib/runpy.pyi @@ -1,22 +1,21 @@ +from _typeshed import Self from types import ModuleType -from typing import Any, Dict, Optional, TypeVar - -_T = TypeVar("_T") +from typing import Any class _TempModule: - mod_name: str = ... - module: ModuleType = ... + mod_name: str + module: ModuleType def __init__(self, mod_name: str) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *args: Any) -> None: ... class _ModifiedArgv0: - value: Any = ... + value: Any def __init__(self, value: Any) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self) -> None: ... def __exit__(self, *args: Any) -> None: ... def run_module( - mod_name: str, init_globals: Optional[Dict[str, Any]] = ..., run_name: Optional[str] = ..., alter_sys: bool = ... -) -> Dict[str, Any]: ... -def run_path(path_name: str, init_globals: Optional[Dict[str, Any]] = ..., run_name: Optional[str] = ...) -> Dict[str, Any]: ... + mod_name: str, init_globals: dict[str, Any] | None = ..., run_name: str | None = ..., alter_sys: bool = ... +) -> dict[str, Any]: ... +def run_path(path_name: str, init_globals: dict[str, Any] | None = ..., run_name: str | None = ...) -> dict[str, Any]: ... diff --git a/mypy/typeshed/stdlib/sched.pyi b/mypy/typeshed/stdlib/sched.pyi index 21d81e16ec60..cb96dc2bbf4a 100644 --- a/mypy/typeshed/stdlib/sched.pyi +++ b/mypy/typeshed/stdlib/sched.pyi @@ -1,39 +1,32 @@ -import sys -from typing import Any, Callable, Dict, List, NamedTuple, Optional, Text, Tuple +from typing import Any, Callable, NamedTuple, Tuple class Event(NamedTuple): time: float priority: Any action: Callable[..., Any] argument: Tuple[Any, ...] - kwargs: Dict[Text, Any] + kwargs: dict[str, Any] class scheduler: - if sys.version_info >= (3, 3): - def __init__(self, timefunc: Callable[[], float] = ..., delayfunc: Callable[[float], None] = ...) -> None: ... - def enterabs( - self, - time: float, - priority: Any, - action: Callable[..., Any], - argument: Tuple[Any, ...] = ..., - kwargs: Dict[str, Any] = ..., - ) -> Event: ... - def enter( - self, - delay: float, - priority: Any, - action: Callable[..., Any], - argument: Tuple[Any, ...] = ..., - kwargs: Dict[str, Any] = ..., - ) -> Event: ... - def run(self, blocking: bool = ...) -> Optional[float]: ... - else: - def __init__(self, timefunc: Callable[[], float], delayfunc: Callable[[float], None]) -> None: ... - def enterabs(self, time: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... - def enter(self, delay: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... - def run(self) -> None: ... + def __init__(self, timefunc: Callable[[], float] = ..., delayfunc: Callable[[float], None] = ...) -> None: ... + def enterabs( + self, + time: float, + priority: Any, + action: Callable[..., Any], + argument: Tuple[Any, ...] = ..., + kwargs: dict[str, Any] = ..., + ) -> Event: ... + def enter( + self, + delay: float, + priority: Any, + action: Callable[..., Any], + argument: Tuple[Any, ...] = ..., + kwargs: dict[str, Any] = ..., + ) -> Event: ... + def run(self, blocking: bool = ...) -> float | None: ... def cancel(self, event: Event) -> None: ... def empty(self) -> bool: ... @property - def queue(self) -> List[Event]: ... + def queue(self) -> list[Event]: ... diff --git a/mypy/typeshed/stdlib/secrets.pyi b/mypy/typeshed/stdlib/secrets.pyi index 84b2fea8379a..6752a30f431e 100644 --- a/mypy/typeshed/stdlib/secrets.pyi +++ b/mypy/typeshed/stdlib/secrets.pyi @@ -1,12 +1,12 @@ from hmac import compare_digest as compare_digest from random import SystemRandom as SystemRandom -from typing import Optional, Sequence, TypeVar +from typing import Sequence, TypeVar _T = TypeVar("_T") def randbelow(exclusive_upper_bound: int) -> int: ... def randbits(k: int) -> int: ... def choice(seq: Sequence[_T]) -> _T: ... -def token_bytes(nbytes: Optional[int] = ...) -> bytes: ... -def token_hex(nbytes: Optional[int] = ...) -> str: ... -def token_urlsafe(nbytes: Optional[int] = ...) -> str: ... +def token_bytes(nbytes: int | None = ...) -> bytes: ... +def token_hex(nbytes: int | None = ...) -> str: ... +def token_urlsafe(nbytes: int | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/select.pyi b/mypy/typeshed/stdlib/select.pyi index e0cf3bdd4d75..0329dbaa2c11 100644 --- a/mypy/typeshed/stdlib/select.pyi +++ b/mypy/typeshed/stdlib/select.pyi @@ -1,7 +1,7 @@ import sys -from _typeshed import FileDescriptorLike +from _typeshed import FileDescriptorLike, Self from types import TracebackType -from typing import Any, Iterable, List, Optional, Tuple, Type +from typing import Any, Iterable, Type if sys.platform != "win32": PIPE_BUF: int @@ -22,16 +22,13 @@ class poll: def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... def unregister(self, fd: FileDescriptorLike) -> None: ... - def poll(self, timeout: Optional[float] = ...) -> List[Tuple[int, int]]: ... + def poll(self, timeout: float | None = ...) -> list[tuple[int, int]]: ... def select( - __rlist: Iterable[Any], __wlist: Iterable[Any], __xlist: Iterable[Any], __timeout: Optional[float] = ... -) -> Tuple[List[Any], List[Any], List[Any]]: ... + __rlist: Iterable[Any], __wlist: Iterable[Any], __xlist: Iterable[Any], __timeout: float | None = ... +) -> tuple[list[Any], list[Any], list[Any]]: ... -if sys.version_info >= (3, 3): - error = OSError -else: - class error(Exception): ... +error = OSError if sys.platform != "linux" and sys.platform != "win32": # BSD only @@ -57,8 +54,8 @@ if sys.platform != "linux" and sys.platform != "win32": def __init__(self) -> None: ... def close(self) -> None: ... def control( - self, __changelist: Optional[Iterable[kevent]], __maxevents: int, __timeout: Optional[float] = ... - ) -> List[kevent]: ... + self, __changelist: Iterable[kevent] | None, __maxevents: int, __timeout: float | None = ... + ) -> list[kevent]: ... def fileno(self) -> int: ... @classmethod def fromfd(cls, __fd: FileDescriptorLike) -> kqueue: ... @@ -103,25 +100,21 @@ if sys.platform != "linux" and sys.platform != "win32": if sys.platform == "linux": class epoll(object): - if sys.version_info >= (3, 3): - def __init__(self, sizehint: int = ..., flags: int = ...) -> None: ... - else: - def __init__(self, sizehint: int = ...) -> None: ... - if sys.version_info >= (3, 4): - def __enter__(self) -> epoll: ... - def __exit__( - self, - exc_type: Optional[Type[BaseException]] = ..., - exc_val: Optional[BaseException] = ..., - exc_tb: Optional[TracebackType] = ..., - ) -> None: ... + def __init__(self, sizehint: int = ..., flags: int = ...) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, + exc_type: Type[BaseException] | None = ..., + exc_val: BaseException | None = ..., + exc_tb: TracebackType | None = ..., + ) -> None: ... def close(self) -> None: ... closed: bool def fileno(self) -> int: ... def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... def unregister(self, fd: FileDescriptorLike) -> None: ... - def poll(self, timeout: Optional[float] = ..., maxevents: int = ...) -> List[Tuple[int, int]]: ... + def poll(self, timeout: float | None = ..., maxevents: int = ...) -> list[tuple[int, int]]: ... @classmethod def fromfd(cls, __fd: FileDescriptorLike) -> epoll: ... EPOLLERR: int @@ -139,14 +132,12 @@ if sys.platform == "linux": EPOLL_RDHUP: int if sys.platform != "linux" and sys.platform != "darwin" and sys.platform != "win32": - if sys.version_info >= (3, 3): - # Solaris only - class devpoll: - if sys.version_info >= (3, 4): - def close(self) -> None: ... - closed: bool - def fileno(self) -> int: ... - def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... - def modify(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... - def unregister(self, fd: FileDescriptorLike) -> None: ... - def poll(self, timeout: Optional[float] = ...) -> List[Tuple[int, int]]: ... + # Solaris only + class devpoll: + def close(self) -> None: ... + closed: bool + def fileno(self) -> int: ... + def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... + def modify(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... + def unregister(self, fd: FileDescriptorLike) -> None: ... + def poll(self, timeout: float | None = ...) -> list[tuple[int, int]]: ... diff --git a/mypy/typeshed/stdlib/selectors.pyi b/mypy/typeshed/stdlib/selectors.pyi index 94690efadbf8..c3fe7ec47ace 100644 --- a/mypy/typeshed/stdlib/selectors.pyi +++ b/mypy/typeshed/stdlib/selectors.pyi @@ -1,7 +1,7 @@ import sys -from _typeshed import FileDescriptor, FileDescriptorLike +from _typeshed import FileDescriptor, FileDescriptorLike, Self from abc import ABCMeta, abstractmethod -from typing import Any, List, Mapping, NamedTuple, Optional, Tuple +from typing import Any, Mapping, NamedTuple _EventMask = int @@ -21,25 +21,25 @@ class BaseSelector(metaclass=ABCMeta): def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... def modify(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... @abstractmethod - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def close(self) -> None: ... def get_key(self, fileobj: FileDescriptorLike) -> SelectorKey: ... @abstractmethod def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... - def __enter__(self) -> BaseSelector: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *args: Any) -> None: ... class SelectSelector(BaseSelector): def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... if sys.platform != "win32": class PollSelector(BaseSelector): def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... if sys.platform == "linux": @@ -47,25 +47,25 @@ if sys.platform == "linux": def fileno(self) -> int: ... def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... class DevpollSelector(BaseSelector): def fileno(self) -> int: ... def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... class KqueueSelector(BaseSelector): def fileno(self) -> int: ... def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... class DefaultSelector(BaseSelector): def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... def unregister(self, fileobj: FileDescriptorLike) -> SelectorKey: ... - def select(self, timeout: Optional[float] = ...) -> List[Tuple[SelectorKey, _EventMask]]: ... + def select(self, timeout: float | None = ...) -> list[tuple[SelectorKey, _EventMask]]: ... def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... diff --git a/mypy/typeshed/stdlib/shelve.pyi b/mypy/typeshed/stdlib/shelve.pyi index ed062f62b49b..90b2aafa4f03 100644 --- a/mypy/typeshed/stdlib/shelve.pyi +++ b/mypy/typeshed/stdlib/shelve.pyi @@ -1,34 +1,39 @@ -import collections.abc -from typing import Any, Dict, Iterator, Optional, Tuple +from _typeshed import Self +from collections.abc import Iterator, MutableMapping +from types import TracebackType +from typing import Type, TypeVar, overload -class Shelf(collections.abc.MutableMapping[Any, Any]): +_T = TypeVar("_T") +_VT = TypeVar("_VT") + +class Shelf(MutableMapping[str, _VT]): def __init__( - self, dict: Dict[bytes, Any], protocol: Optional[int] = ..., writeback: bool = ..., keyencoding: str = ... + self, dict: MutableMapping[bytes, bytes], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... ) -> None: ... def __iter__(self) -> Iterator[str]: ... def __len__(self) -> int: ... - def __contains__(self, key: Any) -> bool: ... # key should be str, but it would conflict with superclass's type signature - def get(self, key: str, default: Any = ...) -> Any: ... - def __getitem__(self, key: str) -> Any: ... - def __setitem__(self, key: str, value: Any) -> None: ... + @overload + def get(self, key: str) -> _VT | None: ... + @overload + def get(self, key: str, default: _T) -> _VT | _T: ... + def __getitem__(self, key: str) -> _VT: ... + def __setitem__(self, key: str, value: _VT) -> None: ... def __delitem__(self, key: str) -> None: ... - def __enter__(self) -> Shelf: ... - def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> None: ... def close(self) -> None: ... - def __del__(self) -> None: ... def sync(self) -> None: ... -class BsdDbShelf(Shelf): - def __init__( - self, dict: Dict[bytes, Any], protocol: Optional[int] = ..., writeback: bool = ..., keyencoding: str = ... - ) -> None: ... - def set_location(self, key: Any) -> Tuple[str, Any]: ... - def next(self) -> Tuple[str, Any]: ... - def previous(self) -> Tuple[str, Any]: ... - def first(self) -> Tuple[str, Any]: ... - def last(self) -> Tuple[str, Any]: ... +class BsdDbShelf(Shelf[_VT]): + def set_location(self, key: str) -> tuple[str, _VT]: ... + def next(self) -> tuple[str, _VT]: ... + def previous(self) -> tuple[str, _VT]: ... + def first(self) -> tuple[str, _VT]: ... + def last(self) -> tuple[str, _VT]: ... -class DbfilenameShelf(Shelf): - def __init__(self, filename: str, flag: str = ..., protocol: Optional[int] = ..., writeback: bool = ...) -> None: ... +class DbfilenameShelf(Shelf[_VT]): + def __init__(self, filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> None: ... -def open(filename: str, flag: str = ..., protocol: Optional[int] = ..., writeback: bool = ...) -> DbfilenameShelf: ... +def open(filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> Shelf[object]: ... diff --git a/mypy/typeshed/stdlib/shlex.pyi b/mypy/typeshed/stdlib/shlex.pyi index 741f516dcfdc..dfe554b0a773 100644 --- a/mypy/typeshed/stdlib/shlex.pyi +++ b/mypy/typeshed/stdlib/shlex.pyi @@ -1,7 +1,7 @@ import sys -from typing import Any, Iterable, List, Optional, TextIO, Tuple, TypeVar, Union +from typing import Any, Iterable, TextIO, TypeVar -def split(s: str, comments: bool = ..., posix: bool = ...) -> List[str]: ... +def split(s: str, comments: bool = ..., posix: bool = ...) -> list[str]: ... if sys.version_info >= (3, 8): def join(split_command: Iterable[str]) -> str: ... @@ -28,18 +28,18 @@ class shlex(Iterable[str]): punctuation_chars: str def __init__( self, - instream: Optional[Union[str, TextIO]] = ..., - infile: Optional[str] = ..., + instream: str | TextIO | None = ..., + infile: str | None = ..., posix: bool = ..., - punctuation_chars: Union[bool, str] = ..., + punctuation_chars: bool | str = ..., ) -> None: ... def get_token(self) -> str: ... def push_token(self, tok: str) -> None: ... def read_token(self) -> str: ... - def sourcehook(self, newfile: str) -> Tuple[str, TextIO]: ... + def sourcehook(self, newfile: str) -> tuple[str, TextIO]: ... # TODO argument types def push_source(self, newstream: Any, newfile: Any = ...) -> None: ... def pop_source(self) -> None: ... - def error_leader(self, infile: Optional[str] = ..., lineno: Optional[int] = ...) -> None: ... + def error_leader(self, infile: str | None = ..., lineno: int | None = ...) -> None: ... def __iter__(self: _SLT) -> _SLT: ... def __next__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/shutil.pyi b/mypy/typeshed/stdlib/shutil.pyi index c0779d871c14..f4c492caccaf 100644 --- a/mypy/typeshed/stdlib/shutil.pyi +++ b/mypy/typeshed/stdlib/shutil.pyi @@ -1,170 +1,107 @@ import os import sys -from _typeshed import StrPath, SupportsRead, SupportsWrite -from typing import ( - Any, - AnyStr, - Callable, - Iterable, - List, - NamedTuple, - Optional, - Sequence, - Set, - Tuple, - Type, - TypeVar, - Union, - overload, -) - -if sys.version_info >= (3, 6): - _AnyStr = str - _AnyPath = TypeVar("_AnyPath", str, os.PathLike[str]) - # Return value of some functions that may either return a path-like object that was passed in or - # a string - _PathReturn = Any -elif sys.version_info >= (3,): - _AnyStr = str - _AnyPath = str - _PathReturn = str -else: - _AnyStr = TypeVar("_AnyStr", str, unicode) - _AnyPath = TypeVar("_AnyPath", str, unicode) - _PathReturn = Type[None] - -if sys.version_info >= (3,): - class Error(OSError): ... - class SameFileError(Error): ... - class SpecialFileError(OSError): ... - class ExecError(OSError): ... - class ReadError(OSError): ... - class RegistryError(Exception): ... - -else: - class Error(EnvironmentError): ... - class SpecialFileError(EnvironmentError): ... - class ExecError(EnvironmentError): ... +from _typeshed import StrOrBytesPath, StrPath, SupportsRead, SupportsWrite +from typing import Any, AnyStr, Callable, Iterable, NamedTuple, Sequence, TypeVar, Union, overload -def copyfileobj(fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...) -> None: ... - -if sys.version_info >= (3,): - def copyfile(src: StrPath, dst: _AnyPath, *, follow_symlinks: bool = ...) -> _AnyPath: ... - def copymode(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... - def copystat(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... - def copy(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... - def copy2(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +_PathT = TypeVar("_PathT", str, os.PathLike[str]) +# Return value of some functions that may either return a path-like object that was passed in or +# a string +_PathReturn = Any -else: - def copyfile(src: StrPath, dst: StrPath) -> None: ... - def copymode(src: StrPath, dst: StrPath) -> None: ... - def copystat(src: StrPath, dst: StrPath) -> None: ... - def copy(src: StrPath, dst: StrPath) -> _PathReturn: ... - def copy2(src: StrPath, dst: StrPath) -> _PathReturn: ... +class Error(OSError): ... +class SameFileError(Error): ... +class SpecialFileError(OSError): ... +class ExecError(OSError): ... +class ReadError(OSError): ... +class RegistryError(Exception): ... -def ignore_patterns(*patterns: StrPath) -> Callable[[Any, List[_AnyStr]], Set[_AnyStr]]: ... +def copyfileobj(fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...) -> None: ... +def copyfile(src: StrPath, dst: _PathT, *, follow_symlinks: bool = ...) -> _PathT: ... +def copymode(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... +def copystat(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... +def copy(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +def copy2(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +def ignore_patterns(*patterns: StrPath) -> Callable[[Any, list[str]], set[str]]: ... if sys.version_info >= (3, 8): def copytree( src: StrPath, dst: StrPath, symlinks: bool = ..., - ignore: Union[None, Callable[[str, List[str]], Iterable[str]], Callable[[StrPath, List[str]], Iterable[str]]] = ..., + ignore: None | Callable[[str, list[str]], Iterable[str]] | Callable[[StrPath, list[str]], Iterable[str]] = ..., copy_function: Callable[[str, str], None] = ..., ignore_dangling_symlinks: bool = ..., dirs_exist_ok: bool = ..., ) -> _PathReturn: ... -elif sys.version_info >= (3,): +else: def copytree( src: StrPath, dst: StrPath, symlinks: bool = ..., - ignore: Union[None, Callable[[str, List[str]], Iterable[str]], Callable[[StrPath, List[str]], Iterable[str]]] = ..., + ignore: None | Callable[[str, list[str]], Iterable[str]] | Callable[[StrPath, list[str]], Iterable[str]] = ..., copy_function: Callable[[str, str], None] = ..., ignore_dangling_symlinks: bool = ..., ) -> _PathReturn: ... -else: - def copytree( - src: AnyStr, - dst: AnyStr, - symlinks: bool = ..., - ignore: Union[None, Callable[[AnyStr, List[AnyStr]], Iterable[AnyStr]]] = ..., - ) -> _PathReturn: ... - -if sys.version_info >= (3,): - def rmtree( - path: Union[bytes, StrPath], ignore_errors: bool = ..., onerror: Optional[Callable[[Any, Any, Any], Any]] = ... - ) -> None: ... - -else: - def rmtree( - path: _AnyPath, ignore_errors: bool = ..., onerror: Optional[Callable[[Any, _AnyPath, Any], Any]] = ... - ) -> None: ... +def rmtree(path: bytes | StrPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... _CopyFn = Union[Callable[[str, str], None], Callable[[StrPath, StrPath], None]] if sys.version_info >= (3, 9): def move(src: StrPath, dst: StrPath, copy_function: _CopyFn = ...) -> _PathReturn: ... -elif sys.version_info >= (3, 5): +else: # See https://bugs.python.org/issue32689 def move(src: str, dst: StrPath, copy_function: _CopyFn = ...) -> _PathReturn: ... -else: - def move(src: StrPath, dst: StrPath) -> _PathReturn: ... +class _ntuple_diskusage(NamedTuple): + total: int + used: int + free: int -if sys.version_info >= (3,): - class _ntuple_diskusage(NamedTuple): - total: int - used: int - free: int - def disk_usage(path: StrPath) -> _ntuple_diskusage: ... - def chown(path: StrPath, user: Optional[Union[str, int]] = ..., group: Optional[Union[str, int]] = ...) -> None: ... +def disk_usage(path: int | StrOrBytesPath) -> _ntuple_diskusage: ... +def chown(path: StrPath, user: str | int | None = ..., group: str | int | None = ...) -> None: ... if sys.version_info >= (3, 8): @overload - def which(cmd: StrPath, mode: int = ..., path: Optional[StrPath] = ...) -> Optional[str]: ... + def which(cmd: StrPath, mode: int = ..., path: StrPath | None = ...) -> str | None: ... @overload - def which(cmd: bytes, mode: int = ..., path: Optional[StrPath] = ...) -> Optional[bytes]: ... + def which(cmd: bytes, mode: int = ..., path: StrPath | None = ...) -> bytes | None: ... -elif sys.version_info >= (3,): - def which(cmd: StrPath, mode: int = ..., path: Optional[StrPath] = ...) -> Optional[str]: ... +else: + def which(cmd: StrPath, mode: int = ..., path: StrPath | None = ...) -> str | None: ... def make_archive( - base_name: _AnyStr, + base_name: str, format: str, - root_dir: Optional[StrPath] = ..., - base_dir: Optional[StrPath] = ..., + root_dir: StrPath | None = ..., + base_dir: StrPath | None = ..., verbose: bool = ..., dry_run: bool = ..., - owner: Optional[str] = ..., - group: Optional[str] = ..., - logger: Optional[Any] = ..., -) -> _AnyStr: ... -def get_archive_formats() -> List[Tuple[str, str]]: ... + owner: str | None = ..., + group: str | None = ..., + logger: Any | None = ..., +) -> str: ... +def get_archive_formats() -> list[tuple[str, str]]: ... def register_archive_format( name: str, function: Callable[..., Any], - extra_args: Optional[Sequence[Union[Tuple[str, Any], List[Any]]]] = ..., + extra_args: Sequence[tuple[str, Any] | list[Any]] | None = ..., description: str = ..., ) -> None: ... def unregister_archive_format(name: str) -> None: ... -if sys.version_info >= (3,): - if sys.version_info >= (3, 7): - def unpack_archive(filename: StrPath, extract_dir: Optional[StrPath] = ..., format: Optional[str] = ...) -> None: ... - else: - # See http://bugs.python.org/issue30218 - def unpack_archive(filename: str, extract_dir: Optional[StrPath] = ..., format: Optional[str] = ...) -> None: ... - def register_unpack_format( - name: str, - extensions: List[str], - function: Any, - extra_args: Optional[Sequence[Tuple[str, Any]]] = ..., - description: str = ..., - ) -> None: ... - def unregister_unpack_format(name: str) -> None: ... - def get_unpack_formats() -> List[Tuple[str, List[str], str]]: ... - def get_terminal_size(fallback: Tuple[int, int] = ...) -> os.terminal_size: ... +if sys.version_info >= (3, 7): + def unpack_archive(filename: StrPath, extract_dir: StrPath | None = ..., format: str | None = ...) -> None: ... + +else: + # See http://bugs.python.org/issue30218 + def unpack_archive(filename: str, extract_dir: StrPath | None = ..., format: str | None = ...) -> None: ... + +def register_unpack_format( + name: str, extensions: list[str], function: Any, extra_args: Sequence[tuple[str, Any]] | None = ..., description: str = ... +) -> None: ... +def unregister_unpack_format(name: str) -> None: ... +def get_unpack_formats() -> list[tuple[str, list[str], str]]: ... +def get_terminal_size(fallback: tuple[int, int] = ...) -> os.terminal_size: ... diff --git a/mypy/typeshed/stdlib/signal.pyi b/mypy/typeshed/stdlib/signal.pyi index aa0bbf2bffd1..d617e24f227f 100644 --- a/mypy/typeshed/stdlib/signal.pyi +++ b/mypy/typeshed/stdlib/signal.pyi @@ -1,7 +1,7 @@ import sys from enum import IntEnum from types import FrameType -from typing import Any, Callable, Iterable, Optional, Set, Tuple, Union +from typing import Any, Callable, Iterable, Optional, Tuple, Union if sys.platform != "win32": class ItimerError(IOError): ... @@ -80,7 +80,7 @@ if sys.platform != "win32": SIG_SETMASK = Sigmasks.SIG_SETMASK _SIGNUM = Union[int, Signals] -_HANDLER = Union[Callable[[Signals, FrameType], Any], int, Handlers, None] +_HANDLER = Union[Callable[[int, Optional[FrameType]], Any], int, Handlers, None] SIGABRT: Signals if sys.platform != "win32": @@ -161,19 +161,19 @@ if sys.platform != "win32": def default_int_handler(signum: int, frame: FrameType) -> None: ... if sys.platform != "win32": - def getitimer(__which: int) -> Tuple[float, float]: ... + def getitimer(__which: int) -> tuple[float, float]: ... def getsignal(__signalnum: _SIGNUM) -> _HANDLER: ... if sys.version_info >= (3, 8): - def strsignal(__signalnum: _SIGNUM) -> Optional[str]: ... - def valid_signals() -> Set[Signals]: ... + def strsignal(__signalnum: _SIGNUM) -> str | None: ... + def valid_signals() -> set[Signals]: ... def raise_signal(__signalnum: _SIGNUM) -> None: ... if sys.platform != "win32": def pause() -> None: ... def pthread_kill(__thread_id: int, __signalnum: int) -> None: ... - def pthread_sigmask(__how: int, __mask: Iterable[int]) -> Set[_SIGNUM]: ... + def pthread_sigmask(__how: int, __mask: Iterable[int]) -> set[_SIGNUM]: ... if sys.version_info >= (3, 7): def set_wakeup_fd(fd: int, *, warn_on_full_buffer: bool = ...) -> int: ... @@ -182,7 +182,7 @@ else: def set_wakeup_fd(fd: int) -> int: ... if sys.platform != "win32": - def setitimer(__which: int, __seconds: float, __interval: float = ...) -> Tuple[float, float]: ... + def setitimer(__which: int, __seconds: float, __interval: float = ...) -> tuple[float, float]: ... def siginterrupt(__signalnum: int, __flag: bool) -> None: ... def signal(__signalnum: _SIGNUM, __handler: _HANDLER) -> _HANDLER: ... @@ -191,5 +191,5 @@ if sys.platform != "win32": def sigpending() -> Any: ... def sigwait(__sigset: Iterable[int]) -> _SIGNUM: ... if sys.platform != "darwin": - def sigtimedwait(sigset: Iterable[int], timeout: float) -> Optional[struct_siginfo]: ... + def sigtimedwait(sigset: Iterable[int], timeout: float) -> struct_siginfo | None: ... def sigwaitinfo(sigset: Iterable[int]) -> struct_siginfo: ... diff --git a/mypy/typeshed/stdlib/site.pyi b/mypy/typeshed/stdlib/site.pyi index db7bbefcc794..a73d188a7e5c 100644 --- a/mypy/typeshed/stdlib/site.pyi +++ b/mypy/typeshed/stdlib/site.pyi @@ -1,12 +1,27 @@ -from typing import Iterable, List, Optional +from _typeshed import StrPath +from typing import Iterable -PREFIXES: List[str] -ENABLE_USER_SITE: Optional[bool] -USER_SITE: Optional[str] -USER_BASE: Optional[str] +PREFIXES: list[str] +ENABLE_USER_SITE: bool | None +USER_SITE: str | None +USER_BASE: str | None def main() -> None: ... -def addsitedir(sitedir: str, known_paths: Optional[Iterable[str]] = ...) -> None: ... -def getsitepackages(prefixes: Optional[Iterable[str]] = ...) -> List[str]: ... +def abs_paths() -> None: ... # undocumented +def addpackage(sitedir: StrPath, name: StrPath, known_paths: set[str] | None) -> set[str] | None: ... # undocumented +def addsitedir(sitedir: str, known_paths: set[str] | None = ...) -> None: ... +def addsitepackages(known_paths: set[str] | None, prefixes: Iterable[str] | None = ...) -> set[str] | None: ... # undocumented +def addusersitepackages(known_paths: set[str] | None) -> set[str] | None: ... # undocumented +def check_enableusersite() -> bool | None: ... # undocumented +def enablerlcompleter() -> None: ... # undocumented +def execsitecustomize() -> None: ... # undocumented +def execusercustomize() -> None: ... # undocumented +def getsitepackages(prefixes: Iterable[str] | None = ...) -> list[str]: ... def getuserbase() -> str: ... def getusersitepackages() -> str: ... +def makepath(*paths: StrPath) -> tuple[str, str]: ... # undocumented +def removeduppaths() -> set[str]: ... # undocumented +def setcopyright() -> None: ... # undocumented +def sethelper() -> None: ... # undocumented +def setquit() -> None: ... # undocumented +def venv(known_paths: set[str] | None) -> set[str] | None: ... # undocumented diff --git a/mypy/typeshed/stdlib/smtpd.pyi b/mypy/typeshed/stdlib/smtpd.pyi index 92f078a063f6..2b6020524827 100644 --- a/mypy/typeshed/stdlib/smtpd.pyi +++ b/mypy/typeshed/stdlib/smtpd.pyi @@ -1,8 +1,8 @@ import asynchat import asyncore import socket -import sys -from typing import Any, DefaultDict, List, Optional, Text, Tuple, Type, Union +from collections import defaultdict +from typing import Any, Tuple, Type _Address = Tuple[str, int] # (host, port) @@ -10,41 +10,37 @@ class SMTPChannel(asynchat.async_chat): COMMAND: int DATA: int - if sys.version_info >= (3,): - command_size_limits: DefaultDict[str, int] - smtp_server: SMTPServer - conn: socket.socket - addr: Any - received_lines: List[Text] - smtp_state: int - seen_greeting: str - mailfrom: str - rcpttos: List[str] - received_data: str - fqdn: str - peer: str + command_size_limits: defaultdict[str, int] + smtp_server: SMTPServer + conn: socket.socket + addr: Any + received_lines: list[str] + smtp_state: int + seen_greeting: str + mailfrom: str + rcpttos: list[str] + received_data: str + fqdn: str + peer: str - command_size_limit: int - data_size_limit: int + command_size_limit: int + data_size_limit: int - enable_SMTPUTF8: bool - @property - def max_command_size_limit(self) -> int: ... - if sys.version_info >= (3,): - def __init__( - self, - server: SMTPServer, - conn: socket.socket, - addr: Any, - data_size_limit: int = ..., - map: Optional[asyncore._maptype] = ..., - enable_SMTPUTF8: bool = ..., - decode_data: bool = ..., - ) -> None: ... - else: - def __init__(self, server: SMTPServer, conn: socket.socket, addr: Any, data_size_limit: int = ...) -> None: ... + enable_SMTPUTF8: bool + @property + def max_command_size_limit(self) -> int: ... + def __init__( + self, + server: SMTPServer, + conn: socket.socket, + addr: Any, + data_size_limit: int = ..., + map: asyncore._maptype | None = ..., + enable_SMTPUTF8: bool = ..., + decode_data: bool = ..., + ) -> None: ... # base asynchat.async_chat.push() accepts bytes - def push(self, msg: Text) -> None: ... # type: ignore + def push(self, msg: str) -> None: ... # type: ignore def collect_incoming_data(self, data: bytes) -> None: ... def found_terminator(self) -> None: ... def smtp_HELO(self, arg: str) -> None: ... @@ -54,43 +50,38 @@ class SMTPChannel(asynchat.async_chat): def smtp_RCPT(self, arg: str) -> None: ... def smtp_RSET(self, arg: str) -> None: ... def smtp_DATA(self, arg: str) -> None: ... - if sys.version_info >= (3, 3): - def smtp_EHLO(self, arg: str) -> None: ... - def smtp_HELP(self, arg: str) -> None: ... - def smtp_VRFY(self, arg: str) -> None: ... - def smtp_EXPN(self, arg: str) -> None: ... + def smtp_EHLO(self, arg: str) -> None: ... + def smtp_HELP(self, arg: str) -> None: ... + def smtp_VRFY(self, arg: str) -> None: ... + def smtp_EXPN(self, arg: str) -> None: ... class SMTPServer(asyncore.dispatcher): channel_class: Type[SMTPChannel] data_size_limit: int enable_SMTPUTF8: bool - - if sys.version_info >= (3,): - def __init__( - self, - localaddr: _Address, - remoteaddr: _Address, - data_size_limit: int = ..., - map: Optional[asyncore._maptype] = ..., - enable_SMTPUTF8: bool = ..., - decode_data: bool = ..., - ) -> None: ... - else: - def __init__(self, localaddr: _Address, remoteaddr: _Address, data_size_limit: int = ...) -> None: ... + def __init__( + self, + localaddr: _Address, + remoteaddr: _Address, + data_size_limit: int = ..., + map: asyncore._maptype | None = ..., + enable_SMTPUTF8: bool = ..., + decode_data: bool = ..., + ) -> None: ... def handle_accepted(self, conn: socket.socket, addr: Any) -> None: ... def process_message( - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: Union[bytes, str], **kwargs: Any - ) -> Optional[str]: ... + self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str, **kwargs: Any + ) -> str | None: ... class DebuggingServer(SMTPServer): ... class PureProxy(SMTPServer): def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: Union[bytes, str] - ) -> Optional[str]: ... + self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str + ) -> str | None: ... class MailmanProxy(PureProxy): def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: Union[bytes, str] - ) -> Optional[str]: ... + self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str + ) -> str | None: ... diff --git a/mypy/typeshed/stdlib/smtplib.pyi b/mypy/typeshed/stdlib/smtplib.pyi index 48a35f8e3b67..5dbdf5d44c29 100644 --- a/mypy/typeshed/stdlib/smtplib.pyi +++ b/mypy/typeshed/stdlib/smtplib.pyi @@ -1,8 +1,9 @@ +from _typeshed import Self from email.message import Message as _Message from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Dict, Optional, Pattern, Protocol, Sequence, Tuple, Type, Union, overload +from typing import Any, Dict, Pattern, Protocol, Sequence, Tuple, Type, Union, overload _Reply = Tuple[int, bytes] _SendErrs = Dict[str, _Reply] @@ -22,20 +23,20 @@ class SMTPServerDisconnected(SMTPException): ... class SMTPResponseException(SMTPException): smtp_code: int - smtp_error: Union[bytes, str] - args: Union[Tuple[int, Union[bytes, str]], Tuple[int, bytes, str]] - def __init__(self, code: int, msg: Union[bytes, str]) -> None: ... + smtp_error: bytes | str + args: tuple[int, bytes | str] | tuple[int, bytes, str] + def __init__(self, code: int, msg: bytes | str) -> None: ... class SMTPSenderRefused(SMTPResponseException): smtp_code: int smtp_error: bytes sender: str - args: Tuple[int, bytes, str] + args: tuple[int, bytes, str] def __init__(self, code: int, msg: bytes, sender: str) -> None: ... class SMTPRecipientsRefused(SMTPException): recipients: _SendErrs - args: Tuple[_SendErrs] + args: tuple[_SendErrs] def __init__(self, recipients: _SendErrs) -> None: ... class SMTPDataError(SMTPResponseException): ... @@ -48,40 +49,40 @@ def quotedata(data: str) -> str: ... class _AuthObject(Protocol): @overload - def __call__(self, challenge: None = ...) -> Optional[str]: ... + def __call__(self, challenge: None = ...) -> str | None: ... @overload def __call__(self, challenge: bytes) -> str: ... class SMTP: - debuglevel: int = ... - sock: Optional[socket] = ... + debuglevel: int + sock: socket | None # Type of file should match what socket.makefile() returns - file: Optional[Any] = ... - helo_resp: Optional[bytes] = ... - ehlo_msg: str = ... - ehlo_resp: Optional[bytes] = ... - does_esmtp: bool = ... - default_port: int = ... + file: Any | None + helo_resp: bytes | None + ehlo_msg: str + ehlo_resp: bytes | None + does_esmtp: bool + default_port: int timeout: float - esmtp_features: Dict[str, str] + esmtp_features: dict[str, str] command_encoding: str - source_address: Optional[_SourceAddress] + source_address: _SourceAddress | None local_hostname: str def __init__( self, host: str = ..., port: int = ..., - local_hostname: Optional[str] = ..., + local_hostname: str | None = ..., timeout: float = ..., - source_address: Optional[_SourceAddress] = ..., + source_address: _SourceAddress | None = ..., ) -> None: ... - def __enter__(self) -> SMTP: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None ) -> None: ... def set_debuglevel(self, debuglevel: int) -> None: ... - def connect(self, host: str = ..., port: int = ..., source_address: Optional[_SourceAddress] = ...) -> _Reply: ... - def send(self, s: Union[bytes, str]) -> None: ... + def connect(self, host: str = ..., port: int = ..., source_address: _SourceAddress | None = ...) -> _Reply: ... + def send(self, s: bytes | str) -> None: ... def putcmd(self, cmd: str, args: str = ...) -> None: ... def getreply(self) -> _Reply: ... def docmd(self, cmd: str, args: str = ...) -> _Reply: ... @@ -93,7 +94,7 @@ class SMTP: def noop(self) -> _Reply: ... def mail(self, sender: str, options: Sequence[str] = ...) -> _Reply: ... def rcpt(self, recip: str, options: Sequence[str] = ...) -> _Reply: ... - def data(self, msg: Union[bytes, str]) -> _Reply: ... + def data(self, msg: bytes | str) -> _Reply: ... def verify(self, address: str) -> _Reply: ... vrfy = verify def expn(self, address: str) -> _Reply: ... @@ -105,25 +106,23 @@ class SMTP: def auth_cram_md5(self, challenge: None = ...) -> None: ... @overload def auth_cram_md5(self, challenge: bytes) -> str: ... - def auth_plain(self, challenge: Optional[bytes] = ...) -> str: ... - def auth_login(self, challenge: Optional[bytes] = ...) -> str: ... + def auth_plain(self, challenge: bytes | None = ...) -> str: ... + def auth_login(self, challenge: bytes | None = ...) -> str: ... def login(self, user: str, password: str, *, initial_response_ok: bool = ...) -> _Reply: ... - def starttls( - self, keyfile: Optional[str] = ..., certfile: Optional[str] = ..., context: Optional[SSLContext] = ... - ) -> _Reply: ... + def starttls(self, keyfile: str | None = ..., certfile: str | None = ..., context: SSLContext | None = ...) -> _Reply: ... def sendmail( self, from_addr: str, - to_addrs: Union[str, Sequence[str]], - msg: Union[bytes, str], + to_addrs: str | Sequence[str], + msg: bytes | str, mail_options: Sequence[str] = ..., rcpt_options: Sequence[str] = ..., ) -> _SendErrs: ... def send_message( self, msg: _Message, - from_addr: Optional[str] = ..., - to_addrs: Optional[Union[str, Sequence[str]]] = ..., + from_addr: str | None = ..., + to_addrs: str | Sequence[str] | None = ..., mail_options: Sequence[str] = ..., rcpt_options: Sequence[str] = ..., ) -> _SendErrs: ... @@ -131,29 +130,25 @@ class SMTP: def quit(self) -> _Reply: ... class SMTP_SSL(SMTP): - default_port: int = ... - keyfile: Optional[str] - certfile: Optional[str] + default_port: int + keyfile: str | None + certfile: str | None context: SSLContext def __init__( self, host: str = ..., port: int = ..., - local_hostname: Optional[str] = ..., - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., + local_hostname: str | None = ..., + keyfile: str | None = ..., + certfile: str | None = ..., timeout: float = ..., - source_address: Optional[_SourceAddress] = ..., - context: Optional[SSLContext] = ..., + source_address: _SourceAddress | None = ..., + context: SSLContext | None = ..., ) -> None: ... LMTP_PORT: int class LMTP(SMTP): def __init__( - self, - host: str = ..., - port: int = ..., - local_hostname: Optional[str] = ..., - source_address: Optional[_SourceAddress] = ..., + self, host: str = ..., port: int = ..., local_hostname: str | None = ..., source_address: _SourceAddress | None = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/sndhdr.pyi b/mypy/typeshed/stdlib/sndhdr.pyi index ef025ac571a7..84d6441a83b1 100644 --- a/mypy/typeshed/stdlib/sndhdr.pyi +++ b/mypy/typeshed/stdlib/sndhdr.pyi @@ -1,17 +1,12 @@ -import sys -from _typeshed import AnyPath -from typing import NamedTuple, Optional, Tuple, Union +from _typeshed import StrOrBytesPath +from typing import NamedTuple -if sys.version_info >= (3, 5): - class SndHeaders(NamedTuple): - filetype: str - framerate: int - nchannels: int - nframes: int - sampwidth: Union[int, str] - _SndHeaders = SndHeaders -else: - _SndHeaders = Tuple[str, int, int, int, Union[int, str]] +class SndHeaders(NamedTuple): + filetype: str + framerate: int + nchannels: int + nframes: int + sampwidth: int | str -def what(filename: AnyPath) -> Optional[_SndHeaders]: ... -def whathdr(filename: AnyPath) -> Optional[_SndHeaders]: ... +def what(filename: StrOrBytesPath) -> SndHeaders | None: ... +def whathdr(filename: StrOrBytesPath) -> SndHeaders | None: ... diff --git a/mypy/typeshed/stdlib/socket.pyi b/mypy/typeshed/stdlib/socket.pyi index e3f5d9b35bef..1f5ae6eb76c8 100644 --- a/mypy/typeshed/stdlib/socket.pyi +++ b/mypy/typeshed/stdlib/socket.pyi @@ -1,45 +1,432 @@ import sys -from typing import Any, BinaryIO, Iterable, List, Optional, Text, TextIO, Tuple, TypeVar, Union, overload +from _typeshed import ReadableBuffer, Self, WriteableBuffer +from collections.abc import Iterable +from enum import IntEnum, IntFlag +from io import RawIOBase +from typing import Any, BinaryIO, TextIO, TypeVar, overload from typing_extensions import Literal -# ----- Constants ----- -# Some socket families are listed in the "Socket families" section of the docs, -# but not the "Constants" section. These are listed at the end of the list of -# constants. -# -# Besides those and the first few constants listed, the constants are listed in -# documentation order. +# Ideally, we'd just do "from _socket import *". Unfortunately, socket +# overrides some definitions from _socket incompatibly. mypy incorrectly +# prefers the definitions from _socket over those defined here. +import _socket +from _socket import ( + _FD, + CMSG_LEN as CMSG_LEN, + CMSG_SPACE as CMSG_SPACE, + EAI_ADDRFAMILY as EAI_ADDRFAMILY, + EAI_AGAIN as EAI_AGAIN, + EAI_BADFLAGS as EAI_BADFLAGS, + EAI_BADHINTS as EAI_BADHINTS, + EAI_FAIL as EAI_FAIL, + EAI_FAMILY as EAI_FAMILY, + EAI_MAX as EAI_MAX, + EAI_MEMORY as EAI_MEMORY, + EAI_NODATA as EAI_NODATA, + EAI_NONAME as EAI_NONAME, + EAI_OVERFLOW as EAI_OVERFLOW, + EAI_PROTOCOL as EAI_PROTOCOL, + EAI_SERVICE as EAI_SERVICE, + EAI_SOCKTYPE as EAI_SOCKTYPE, + EAI_SYSTEM as EAI_SYSTEM, + INADDR_ALLHOSTS_GROUP as INADDR_ALLHOSTS_GROUP, + INADDR_ANY as INADDR_ANY, + INADDR_BROADCAST as INADDR_BROADCAST, + INADDR_LOOPBACK as INADDR_LOOPBACK, + INADDR_MAX_LOCAL_GROUP as INADDR_MAX_LOCAL_GROUP, + INADDR_NONE as INADDR_NONE, + INADDR_UNSPEC_GROUP as INADDR_UNSPEC_GROUP, + IP_ADD_MEMBERSHIP as IP_ADD_MEMBERSHIP, + IP_DEFAULT_MULTICAST_LOOP as IP_DEFAULT_MULTICAST_LOOP, + IP_DEFAULT_MULTICAST_TTL as IP_DEFAULT_MULTICAST_TTL, + IP_DROP_MEMBERSHIP as IP_DROP_MEMBERSHIP, + IP_HDRINCL as IP_HDRINCL, + IP_MAX_MEMBERSHIPS as IP_MAX_MEMBERSHIPS, + IP_MULTICAST_IF as IP_MULTICAST_IF, + IP_MULTICAST_LOOP as IP_MULTICAST_LOOP, + IP_MULTICAST_TTL as IP_MULTICAST_TTL, + IP_OPTIONS as IP_OPTIONS, + IP_RECVDSTADDR as IP_RECVDSTADDR, + IP_RECVOPTS as IP_RECVOPTS, + IP_RECVRETOPTS as IP_RECVRETOPTS, + IP_RETOPTS as IP_RETOPTS, + IP_TOS as IP_TOS, + IP_TRANSPARENT as IP_TRANSPARENT, + IP_TTL as IP_TTL, + IPPORT_RESERVED as IPPORT_RESERVED, + IPPORT_USERRESERVED as IPPORT_USERRESERVED, + IPPROTO_AH as IPPROTO_AH, + IPPROTO_BIP as IPPROTO_BIP, + IPPROTO_DSTOPTS as IPPROTO_DSTOPTS, + IPPROTO_EGP as IPPROTO_EGP, + IPPROTO_EON as IPPROTO_EON, + IPPROTO_ESP as IPPROTO_ESP, + IPPROTO_FRAGMENT as IPPROTO_FRAGMENT, + IPPROTO_GGP as IPPROTO_GGP, + IPPROTO_GRE as IPPROTO_GRE, + IPPROTO_HELLO as IPPROTO_HELLO, + IPPROTO_HOPOPTS as IPPROTO_HOPOPTS, + IPPROTO_ICMP as IPPROTO_ICMP, + IPPROTO_ICMPV6 as IPPROTO_ICMPV6, + IPPROTO_IDP as IPPROTO_IDP, + IPPROTO_IGMP as IPPROTO_IGMP, + IPPROTO_IP as IPPROTO_IP, + IPPROTO_IPCOMP as IPPROTO_IPCOMP, + IPPROTO_IPIP as IPPROTO_IPIP, + IPPROTO_IPV4 as IPPROTO_IPV4, + IPPROTO_IPV6 as IPPROTO_IPV6, + IPPROTO_MAX as IPPROTO_MAX, + IPPROTO_MOBILE as IPPROTO_MOBILE, + IPPROTO_ND as IPPROTO_ND, + IPPROTO_NONE as IPPROTO_NONE, + IPPROTO_PIM as IPPROTO_PIM, + IPPROTO_PUP as IPPROTO_PUP, + IPPROTO_RAW as IPPROTO_RAW, + IPPROTO_ROUTING as IPPROTO_ROUTING, + IPPROTO_RSVP as IPPROTO_RSVP, + IPPROTO_SCTP as IPPROTO_SCTP, + IPPROTO_TCP as IPPROTO_TCP, + IPPROTO_TP as IPPROTO_TP, + IPPROTO_UDP as IPPROTO_UDP, + IPPROTO_VRRP as IPPROTO_VRRP, + IPPROTO_XTP as IPPROTO_XTP, + IPV6_CHECKSUM as IPV6_CHECKSUM, + IPV6_DONTFRAG as IPV6_DONTFRAG, + IPV6_DSTOPTS as IPV6_DSTOPTS, + IPV6_HOPLIMIT as IPV6_HOPLIMIT, + IPV6_HOPOPTS as IPV6_HOPOPTS, + IPV6_JOIN_GROUP as IPV6_JOIN_GROUP, + IPV6_LEAVE_GROUP as IPV6_LEAVE_GROUP, + IPV6_MULTICAST_HOPS as IPV6_MULTICAST_HOPS, + IPV6_MULTICAST_IF as IPV6_MULTICAST_IF, + IPV6_MULTICAST_LOOP as IPV6_MULTICAST_LOOP, + IPV6_NEXTHOP as IPV6_NEXTHOP, + IPV6_PATHMTU as IPV6_PATHMTU, + IPV6_PKTINFO as IPV6_PKTINFO, + IPV6_RECVDSTOPTS as IPV6_RECVDSTOPTS, + IPV6_RECVHOPLIMIT as IPV6_RECVHOPLIMIT, + IPV6_RECVHOPOPTS as IPV6_RECVHOPOPTS, + IPV6_RECVPATHMTU as IPV6_RECVPATHMTU, + IPV6_RECVPKTINFO as IPV6_RECVPKTINFO, + IPV6_RECVRTHDR as IPV6_RECVRTHDR, + IPV6_RECVTCLASS as IPV6_RECVTCLASS, + IPV6_RTHDR as IPV6_RTHDR, + IPV6_RTHDR_TYPE_0 as IPV6_RTHDR_TYPE_0, + IPV6_RTHDRDSTOPTS as IPV6_RTHDRDSTOPTS, + IPV6_TCLASS as IPV6_TCLASS, + IPV6_UNICAST_HOPS as IPV6_UNICAST_HOPS, + IPV6_USE_MIN_MTU as IPV6_USE_MIN_MTU, + IPV6_V6ONLY as IPV6_V6ONLY, + IPX_TYPE as IPX_TYPE, + LOCAL_PEERCRED as LOCAL_PEERCRED, + NI_DGRAM as NI_DGRAM, + NI_MAXHOST as NI_MAXHOST, + NI_MAXSERV as NI_MAXSERV, + NI_NAMEREQD as NI_NAMEREQD, + NI_NOFQDN as NI_NOFQDN, + NI_NUMERICHOST as NI_NUMERICHOST, + NI_NUMERICSERV as NI_NUMERICSERV, + SCM_CREDENTIALS as SCM_CREDENTIALS, + SCM_CREDS as SCM_CREDS, + SCM_RIGHTS as SCM_RIGHTS, + SHUT_RD as SHUT_RD, + SHUT_RDWR as SHUT_RDWR, + SHUT_WR as SHUT_WR, + SO_ACCEPTCONN as SO_ACCEPTCONN, + SO_BINDTODEVICE as SO_BINDTODEVICE, + SO_BROADCAST as SO_BROADCAST, + SO_DEBUG as SO_DEBUG, + SO_DONTROUTE as SO_DONTROUTE, + SO_ERROR as SO_ERROR, + SO_EXCLUSIVEADDRUSE as SO_EXCLUSIVEADDRUSE, + SO_KEEPALIVE as SO_KEEPALIVE, + SO_LINGER as SO_LINGER, + SO_MARK as SO_MARK, + SO_OOBINLINE as SO_OOBINLINE, + SO_PASSCRED as SO_PASSCRED, + SO_PEERCRED as SO_PEERCRED, + SO_PRIORITY as SO_PRIORITY, + SO_RCVBUF as SO_RCVBUF, + SO_RCVLOWAT as SO_RCVLOWAT, + SO_RCVTIMEO as SO_RCVTIMEO, + SO_REUSEADDR as SO_REUSEADDR, + SO_REUSEPORT as SO_REUSEPORT, + SO_SETFIB as SO_SETFIB, + SO_SNDBUF as SO_SNDBUF, + SO_SNDLOWAT as SO_SNDLOWAT, + SO_SNDTIMEO as SO_SNDTIMEO, + SO_TYPE as SO_TYPE, + SO_USELOOPBACK as SO_USELOOPBACK, + SOL_ATALK as SOL_ATALK, + SOL_AX25 as SOL_AX25, + SOL_HCI as SOL_HCI, + SOL_IP as SOL_IP, + SOL_IPX as SOL_IPX, + SOL_NETROM as SOL_NETROM, + SOL_ROSE as SOL_ROSE, + SOL_SOCKET as SOL_SOCKET, + SOL_TCP as SOL_TCP, + SOL_UDP as SOL_UDP, + SOMAXCONN as SOMAXCONN, + TCP_CORK as TCP_CORK, + TCP_DEFER_ACCEPT as TCP_DEFER_ACCEPT, + TCP_FASTOPEN as TCP_FASTOPEN, + TCP_INFO as TCP_INFO, + TCP_KEEPCNT as TCP_KEEPCNT, + TCP_KEEPIDLE as TCP_KEEPIDLE, + TCP_KEEPINTVL as TCP_KEEPINTVL, + TCP_LINGER2 as TCP_LINGER2, + TCP_MAXSEG as TCP_MAXSEG, + TCP_NODELAY as TCP_NODELAY, + TCP_QUICKACK as TCP_QUICKACK, + TCP_SYNCNT as TCP_SYNCNT, + TCP_WINDOW_CLAMP as TCP_WINDOW_CLAMP, + SocketType as SocketType, + _Address as _Address, + _RetAddress as _RetAddress, + dup as dup, + error as error, + gaierror as gaierror, + getdefaulttimeout as getdefaulttimeout, + gethostbyaddr as gethostbyaddr, + gethostbyname as gethostbyname, + gethostbyname_ex as gethostbyname_ex, + gethostname as gethostname, + getnameinfo as getnameinfo, + getprotobyname as getprotobyname, + getservbyname as getservbyname, + getservbyport as getservbyport, + has_ipv6 as has_ipv6, + herror as herror, + htonl as htonl, + htons as htons, + inet_aton as inet_aton, + inet_ntoa as inet_ntoa, + inet_ntop as inet_ntop, + inet_pton as inet_pton, + ntohl as ntohl, + ntohs as ntohs, + setdefaulttimeout as setdefaulttimeout, + timeout as timeout, +) -# Constants defined by Python (i.e. not OS constants re-exported from C) -has_ipv6: bool -SocketType: Any -if sys.version_info >= (3,): - SocketIO: Any - -# Re-exported errno -EAGAIN: int +if sys.version_info >= (3, 7): + from _socket import close as close +if sys.platform != "win32": + from _socket import sethostname as sethostname +if sys.platform != "win32" or sys.version_info >= (3, 8): + from _socket import if_indextoname as if_indextoname, if_nameindex as if_nameindex, if_nametoindex as if_nametoindex +if sys.platform == "linux": + from _socket import ( + ALG_OP_DECRYPT as ALG_OP_DECRYPT, + ALG_OP_ENCRYPT as ALG_OP_ENCRYPT, + ALG_OP_SIGN as ALG_OP_SIGN, + ALG_OP_VERIFY as ALG_OP_VERIFY, + ALG_SET_AEAD_ASSOCLEN as ALG_SET_AEAD_ASSOCLEN, + ALG_SET_AEAD_AUTHSIZE as ALG_SET_AEAD_AUTHSIZE, + ALG_SET_IV as ALG_SET_IV, + ALG_SET_KEY as ALG_SET_KEY, + ALG_SET_OP as ALG_SET_OP, + ALG_SET_PUBKEY as ALG_SET_PUBKEY, + CAN_BCM as CAN_BCM, + CAN_BCM_RX_CHANGED as CAN_BCM_RX_CHANGED, + CAN_BCM_RX_DELETE as CAN_BCM_RX_DELETE, + CAN_BCM_RX_READ as CAN_BCM_RX_READ, + CAN_BCM_RX_SETUP as CAN_BCM_RX_SETUP, + CAN_BCM_RX_STATUS as CAN_BCM_RX_STATUS, + CAN_BCM_RX_TIMEOUT as CAN_BCM_RX_TIMEOUT, + CAN_BCM_TX_DELETE as CAN_BCM_TX_DELETE, + CAN_BCM_TX_EXPIRED as CAN_BCM_TX_EXPIRED, + CAN_BCM_TX_READ as CAN_BCM_TX_READ, + CAN_BCM_TX_SEND as CAN_BCM_TX_SEND, + CAN_BCM_TX_SETUP as CAN_BCM_TX_SETUP, + CAN_BCM_TX_STATUS as CAN_BCM_TX_STATUS, + CAN_EFF_FLAG as CAN_EFF_FLAG, + CAN_EFF_MASK as CAN_EFF_MASK, + CAN_ERR_FLAG as CAN_ERR_FLAG, + CAN_ERR_MASK as CAN_ERR_MASK, + CAN_RAW as CAN_RAW, + CAN_RAW_ERR_FILTER as CAN_RAW_ERR_FILTER, + CAN_RAW_FD_FRAMES as CAN_RAW_FD_FRAMES, + CAN_RAW_FILTER as CAN_RAW_FILTER, + CAN_RAW_LOOPBACK as CAN_RAW_LOOPBACK, + CAN_RAW_RECV_OWN_MSGS as CAN_RAW_RECV_OWN_MSGS, + CAN_RTR_FLAG as CAN_RTR_FLAG, + CAN_SFF_MASK as CAN_SFF_MASK, + PACKET_BROADCAST as PACKET_BROADCAST, + PACKET_FASTROUTE as PACKET_FASTROUTE, + PACKET_HOST as PACKET_HOST, + PACKET_LOOPBACK as PACKET_LOOPBACK, + PACKET_MULTICAST as PACKET_MULTICAST, + PACKET_OTHERHOST as PACKET_OTHERHOST, + PACKET_OUTGOING as PACKET_OUTGOING, + PF_CAN as PF_CAN, + PF_PACKET as PF_PACKET, + PF_RDS as PF_RDS, + RDS_CANCEL_SENT_TO as RDS_CANCEL_SENT_TO, + RDS_CMSG_RDMA_ARGS as RDS_CMSG_RDMA_ARGS, + RDS_CMSG_RDMA_DEST as RDS_CMSG_RDMA_DEST, + RDS_CMSG_RDMA_MAP as RDS_CMSG_RDMA_MAP, + RDS_CMSG_RDMA_STATUS as RDS_CMSG_RDMA_STATUS, + RDS_CMSG_RDMA_UPDATE as RDS_CMSG_RDMA_UPDATE, + RDS_CONG_MONITOR as RDS_CONG_MONITOR, + RDS_FREE_MR as RDS_FREE_MR, + RDS_GET_MR as RDS_GET_MR, + RDS_GET_MR_FOR_DEST as RDS_GET_MR_FOR_DEST, + RDS_RDMA_DONTWAIT as RDS_RDMA_DONTWAIT, + RDS_RDMA_FENCE as RDS_RDMA_FENCE, + RDS_RDMA_INVALIDATE as RDS_RDMA_INVALIDATE, + RDS_RDMA_NOTIFY_ME as RDS_RDMA_NOTIFY_ME, + RDS_RDMA_READWRITE as RDS_RDMA_READWRITE, + RDS_RDMA_SILENT as RDS_RDMA_SILENT, + RDS_RDMA_USE_ONCE as RDS_RDMA_USE_ONCE, + RDS_RECVERR as RDS_RECVERR, + SOL_ALG as SOL_ALG, + SOL_CAN_BASE as SOL_CAN_BASE, + SOL_CAN_RAW as SOL_CAN_RAW, + SOL_RDS as SOL_RDS, + SOL_TIPC as SOL_TIPC, + TIPC_ADDR_ID as TIPC_ADDR_ID, + TIPC_ADDR_NAME as TIPC_ADDR_NAME, + TIPC_ADDR_NAMESEQ as TIPC_ADDR_NAMESEQ, + TIPC_CFG_SRV as TIPC_CFG_SRV, + TIPC_CLUSTER_SCOPE as TIPC_CLUSTER_SCOPE, + TIPC_CONN_TIMEOUT as TIPC_CONN_TIMEOUT, + TIPC_CRITICAL_IMPORTANCE as TIPC_CRITICAL_IMPORTANCE, + TIPC_DEST_DROPPABLE as TIPC_DEST_DROPPABLE, + TIPC_HIGH_IMPORTANCE as TIPC_HIGH_IMPORTANCE, + TIPC_IMPORTANCE as TIPC_IMPORTANCE, + TIPC_LOW_IMPORTANCE as TIPC_LOW_IMPORTANCE, + TIPC_MEDIUM_IMPORTANCE as TIPC_MEDIUM_IMPORTANCE, + TIPC_NODE_SCOPE as TIPC_NODE_SCOPE, + TIPC_PUBLISHED as TIPC_PUBLISHED, + TIPC_SRC_DROPPABLE as TIPC_SRC_DROPPABLE, + TIPC_SUB_CANCEL as TIPC_SUB_CANCEL, + TIPC_SUB_PORTS as TIPC_SUB_PORTS, + TIPC_SUB_SERVICE as TIPC_SUB_SERVICE, + TIPC_SUBSCR_TIMEOUT as TIPC_SUBSCR_TIMEOUT, + TIPC_TOP_SRV as TIPC_TOP_SRV, + TIPC_WAIT_FOREVER as TIPC_WAIT_FOREVER, + TIPC_WITHDRAWN as TIPC_WITHDRAWN, + TIPC_ZONE_SCOPE as TIPC_ZONE_SCOPE, + ) +if sys.platform == "linux" and sys.version_info >= (3, 7): + from _socket import ( + CAN_ISOTP as CAN_ISOTP, + IOCTL_VM_SOCKETS_GET_LOCAL_CID as IOCTL_VM_SOCKETS_GET_LOCAL_CID, + SO_VM_SOCKETS_BUFFER_MAX_SIZE as SO_VM_SOCKETS_BUFFER_MAX_SIZE, + SO_VM_SOCKETS_BUFFER_MIN_SIZE as SO_VM_SOCKETS_BUFFER_MIN_SIZE, + SO_VM_SOCKETS_BUFFER_SIZE as SO_VM_SOCKETS_BUFFER_SIZE, + TCP_NOTSENT_LOWAT as TCP_NOTSENT_LOWAT, + VM_SOCKETS_INVALID_VERSION as VM_SOCKETS_INVALID_VERSION, + VMADDR_CID_ANY as VMADDR_CID_ANY, + VMADDR_CID_HOST as VMADDR_CID_HOST, + VMADDR_PORT_ANY as VMADDR_PORT_ANY, + ) +if sys.platform == "linux" and sys.version_info >= (3, 8): + from _socket import ( + CAN_BCM_CAN_FD_FRAME as CAN_BCM_CAN_FD_FRAME, + CAN_BCM_RX_ANNOUNCE_RESUME as CAN_BCM_RX_ANNOUNCE_RESUME, + CAN_BCM_RX_CHECK_DLC as CAN_BCM_RX_CHECK_DLC, + CAN_BCM_RX_FILTER_ID as CAN_BCM_RX_FILTER_ID, + CAN_BCM_RX_NO_AUTOTIMER as CAN_BCM_RX_NO_AUTOTIMER, + CAN_BCM_RX_RTR_FRAME as CAN_BCM_RX_RTR_FRAME, + CAN_BCM_SETTIMER as CAN_BCM_SETTIMER, + CAN_BCM_STARTTIMER as CAN_BCM_STARTTIMER, + CAN_BCM_TX_ANNOUNCE as CAN_BCM_TX_ANNOUNCE, + CAN_BCM_TX_COUNTEVT as CAN_BCM_TX_COUNTEVT, + CAN_BCM_TX_CP_CAN_ID as CAN_BCM_TX_CP_CAN_ID, + CAN_BCM_TX_RESET_MULTI_IDX as CAN_BCM_TX_RESET_MULTI_IDX, + ) +if sys.platform == "linux" and sys.version_info >= (3, 9): + from _socket import ( + CAN_J1939 as CAN_J1939, + CAN_RAW_JOIN_FILTERS as CAN_RAW_JOIN_FILTERS, + J1939_EE_INFO_NONE as J1939_EE_INFO_NONE, + J1939_EE_INFO_TX_ABORT as J1939_EE_INFO_TX_ABORT, + J1939_FILTER_MAX as J1939_FILTER_MAX, + J1939_IDLE_ADDR as J1939_IDLE_ADDR, + J1939_MAX_UNICAST_ADDR as J1939_MAX_UNICAST_ADDR, + J1939_NLA_BYTES_ACKED as J1939_NLA_BYTES_ACKED, + J1939_NLA_PAD as J1939_NLA_PAD, + J1939_NO_ADDR as J1939_NO_ADDR, + J1939_NO_NAME as J1939_NO_NAME, + J1939_NO_PGN as J1939_NO_PGN, + J1939_PGN_ADDRESS_CLAIMED as J1939_PGN_ADDRESS_CLAIMED, + J1939_PGN_ADDRESS_COMMANDED as J1939_PGN_ADDRESS_COMMANDED, + J1939_PGN_MAX as J1939_PGN_MAX, + J1939_PGN_PDU1_MAX as J1939_PGN_PDU1_MAX, + J1939_PGN_REQUEST as J1939_PGN_REQUEST, + SCM_J1939_DEST_ADDR as SCM_J1939_DEST_ADDR, + SCM_J1939_DEST_NAME as SCM_J1939_DEST_NAME, + SCM_J1939_ERRQUEUE as SCM_J1939_ERRQUEUE, + SCM_J1939_PRIO as SCM_J1939_PRIO, + SO_J1939_ERRQUEUE as SO_J1939_ERRQUEUE, + SO_J1939_FILTER as SO_J1939_FILTER, + SO_J1939_PROMISC as SO_J1939_PROMISC, + SO_J1939_SEND_PRIO as SO_J1939_SEND_PRIO, + ) +if sys.platform == "win32": + from _socket import ( + RCVALL_IPLEVEL as RCVALL_IPLEVEL, + RCVALL_MAX as RCVALL_MAX, + RCVALL_OFF as RCVALL_OFF, + RCVALL_ON as RCVALL_ON, + RCVALL_SOCKETLEVELONLY as RCVALL_SOCKETLEVELONLY, + SIO_KEEPALIVE_VALS as SIO_KEEPALIVE_VALS, + SIO_LOOPBACK_FAST_PATH as SIO_LOOPBACK_FAST_PATH, + SIO_RCVALL as SIO_RCVALL, + ) + +_T = TypeVar("_T") + +# Re-exported from errno EBADF: int -EINTR: int +EAGAIN: int EWOULDBLOCK: int -# Constants re-exported from C +class AddressFamily(IntEnum): + AF_UNIX: int + AF_INET: int + AF_INET6: int + AF_AAL5: int + AF_ALG: int + AF_APPLETALK: int + AF_ASH: int + AF_ATMPVC: int + AF_ATMSVC: int + AF_AX25: int + AF_BLUETOOTH: int + AF_BRIDGE: int + AF_CAN: int + AF_DECnet: int + AF_ECONET: int + AF_IPX: int + AF_IRDA: int + AF_KEY: int + AF_LINK: int + AF_LLC: int + AF_NETBEUI: int + AF_NETLINK: int + AF_NETROM: int + AF_PACKET: int + AF_PPPOX: int + AF_QIPCRTR: int + AF_RDS: int + AF_ROSE: int + AF_ROUTE: int + AF_SECURITY: int + AF_SNA: int + AF_SYSTEM: int + AF_TIPC: int + AF_UNSPEC: int + AF_VSOCK: int + AF_WANPIPE: int + AF_X25: int -# Per socketmodule.c, only these three families are portable AF_UNIX: AddressFamily AF_INET: AddressFamily AF_INET6: AddressFamily - -SOCK_STREAM: SocketKind -SOCK_DGRAM: SocketKind -SOCK_RAW: SocketKind -SOCK_RDM: SocketKind -SOCK_SEQPACKET: SocketKind - -if sys.platform == "linux" and sys.version_info >= (3,): - SOCK_CLOEXEC: SocketKind - SOCK_NONBLOCK: SocketKind - -# Address families not mentioned in the docs AF_AAL5: AddressFamily AF_APPLETALK: AddressFamily AF_ASH: AddressFamily @@ -64,124 +451,49 @@ AF_SYSTEM: AddressFamily AF_UNSPEC: AddressFamily AF_WANPIPE: AddressFamily AF_X25: AddressFamily +if sys.platform == "linux": + AF_CAN: AddressFamily + AF_PACKET: AddressFamily + AF_RDS: AddressFamily + AF_TIPC: AddressFamily + AF_ALG: AddressFamily + AF_NETLINK: AddressFamily + if sys.version_info >= (3, 7): + AF_VSOCK: AddressFamily + if sys.version_info >= (3, 8): + AF_QIPCRTR: AddressFamily +AF_LINK: AddressFamily # availability: BSD, macOS +if sys.platform != "win32" and sys.platform != "darwin": + AF_BLUETOOTH: AddressFamily + +class SocketKind(IntEnum): + SOCK_STREAM: int + SOCK_DGRAM: int + SOCK_RAW: int + SOCK_RDM: int + SOCK_SEQPACKET: int + SOCK_CLOEXEC: int + SOCK_NONBLOCK: int + +SOCK_STREAM: SocketKind +SOCK_DGRAM: SocketKind +SOCK_RAW: SocketKind +SOCK_RDM: SocketKind +SOCK_SEQPACKET: SocketKind +if sys.platform == "linux": + SOCK_CLOEXEC: SocketKind + SOCK_NONBLOCK: SocketKind + +class MsgFlag(IntFlag): + MSG_CTRUNC: int + MSG_DONTROUTE: int + MSG_DONTWAIT: int + MSG_EOR: int + MSG_OOB: int + MSG_PEEK: int + MSG_TRUNC: int + MSG_WAITALL: int -# The "many constants" referenced by the docs -SOMAXCONN: int -AI_ADDRCONFIG: AddressInfo -AI_ALL: AddressInfo -AI_CANONNAME: AddressInfo -AI_DEFAULT: AddressInfo -AI_MASK: AddressInfo -AI_NUMERICHOST: AddressInfo -AI_NUMERICSERV: AddressInfo -AI_PASSIVE: AddressInfo -AI_V4MAPPED: AddressInfo -AI_V4MAPPED_CFG: AddressInfo -EAI_ADDRFAMILY: int -EAI_AGAIN: int -EAI_BADFLAGS: int -EAI_BADHINTS: int -EAI_FAIL: int -EAI_FAMILY: int -EAI_MAX: int -EAI_MEMORY: int -EAI_NODATA: int -EAI_NONAME: int -EAI_OVERFLOW: int -EAI_PROTOCOL: int -EAI_SERVICE: int -EAI_SOCKTYPE: int -EAI_SYSTEM: int -INADDR_ALLHOSTS_GROUP: int -INADDR_ANY: int -INADDR_BROADCAST: int -INADDR_LOOPBACK: int -INADDR_MAX_LOCAL_GROUP: int -INADDR_NONE: int -INADDR_UNSPEC_GROUP: int -IPPORT_RESERVED: int -IPPORT_USERRESERVED: int -IPPROTO_AH: int -IPPROTO_BIP: int -IPPROTO_DSTOPTS: int -IPPROTO_EGP: int -IPPROTO_EON: int -IPPROTO_ESP: int -IPPROTO_FRAGMENT: int -IPPROTO_GGP: int -IPPROTO_GRE: int -IPPROTO_HELLO: int -IPPROTO_HOPOPTS: int -IPPROTO_ICMP: int -IPPROTO_ICMPV6: int -IPPROTO_IDP: int -IPPROTO_IGMP: int -IPPROTO_IP: int -IPPROTO_IPCOMP: int -IPPROTO_IPIP: int -IPPROTO_IPV4: int -IPPROTO_IPV6: int -IPPROTO_MAX: int -IPPROTO_MOBILE: int -IPPROTO_ND: int -IPPROTO_NONE: int -IPPROTO_PIM: int -IPPROTO_PUP: int -IPPROTO_RAW: int -IPPROTO_ROUTING: int -IPPROTO_RSVP: int -IPPROTO_SCTP: int -IPPROTO_TCP: int -IPPROTO_TP: int -IPPROTO_UDP: int -IPPROTO_VRRP: int -IPPROTO_XTP: int -IPV6_CHECKSUM: int -IPV6_DONTFRAG: int -IPV6_DSTOPTS: int -IPV6_HOPLIMIT: int -IPV6_HOPOPTS: int -IPV6_JOIN_GROUP: int -IPV6_LEAVE_GROUP: int -IPV6_MULTICAST_HOPS: int -IPV6_MULTICAST_IF: int -IPV6_MULTICAST_LOOP: int -IPV6_NEXTHOP: int -IPV6_PATHMTU: int -IPV6_PKTINFO: int -IPV6_RECVDSTOPTS: int -IPV6_RECVHOPLIMIT: int -IPV6_RECVHOPOPTS: int -IPV6_RECVPATHMTU: int -IPV6_RECVPKTINFO: int -IPV6_RECVRTHDR: int -IPV6_RECVTCLASS: int -IPV6_RTHDR: int -IPV6_RTHDRDSTOPTS: int -IPV6_RTHDR_TYPE_0: int -IPV6_TCLASS: int -IPV6_UNICAST_HOPS: int -IPV6_USE_MIN_MTU: int -IPV6_V6ONLY: int -IPX_TYPE: int -IP_ADD_MEMBERSHIP: int -IP_DEFAULT_MULTICAST_LOOP: int -IP_DEFAULT_MULTICAST_TTL: int -IP_DROP_MEMBERSHIP: int -IP_HDRINCL: int -IP_MAX_MEMBERSHIPS: int -IP_MULTICAST_IF: int -IP_MULTICAST_LOOP: int -IP_MULTICAST_TTL: int -IP_OPTIONS: int -IP_RECVDSTADDR: int -IP_RECVOPTS: int -IP_RECVRETOPTS: int -IP_RETOPTS: int -IP_TOS: int -IP_TRANSPARENT: int -IP_TTL: int -LOCAL_PEERCRED: int MSG_BCAST: MsgFlag MSG_BTAG: MsgFlag MSG_CMSG_CLOEXEC: MsgFlag @@ -202,608 +514,117 @@ MSG_OOB: MsgFlag MSG_PEEK: MsgFlag MSG_TRUNC: MsgFlag MSG_WAITALL: MsgFlag -NI_DGRAM: int -NI_MAXHOST: int -NI_MAXSERV: int -NI_NAMEREQD: int -NI_NOFQDN: int -NI_NUMERICHOST: int -NI_NUMERICSERV: int -SCM_CREDENTIALS: int -SCM_CREDS: int -SCM_RIGHTS: int -SHUT_RD: int -SHUT_RDWR: int -SHUT_WR: int -SOL_ATALK: int -SOL_AX25: int -SOL_HCI: int -SOL_IP: int -SOL_IPX: int -SOL_NETROM: int -SOL_ROSE: int -SOL_SOCKET: int -SOL_TCP: int -SOL_UDP: int -SO_ACCEPTCONN: int -SO_BINDTODEVICE: int -SO_BROADCAST: int -SO_DEBUG: int -SO_DONTROUTE: int -SO_ERROR: int -SO_EXCLUSIVEADDRUSE: int -SO_KEEPALIVE: int -SO_LINGER: int -SO_MARK: int -SO_OOBINLINE: int -SO_PASSCRED: int -SO_PEERCRED: int -SO_PRIORITY: int -SO_RCVBUF: int -SO_RCVLOWAT: int -SO_RCVTIMEO: int -SO_REUSEADDR: int -SO_REUSEPORT: int -SO_SETFIB: int -SO_SNDBUF: int -SO_SNDLOWAT: int -SO_SNDTIMEO: int -SO_TYPE: int -SO_USELOOPBACK: int -TCP_CORK: int -TCP_DEFER_ACCEPT: int -TCP_FASTOPEN: int -TCP_INFO: int -TCP_KEEPCNT: int -TCP_KEEPIDLE: int -TCP_KEEPINTVL: int -TCP_LINGER2: int -TCP_MAXSEG: int -TCP_NODELAY: int -TCP_QUICKACK: int -TCP_SYNCNT: int -TCP_WINDOW_CLAMP: int -if sys.version_info >= (3, 7): - TCP_NOTSENT_LOWAT: int - -# Specifically-documented constants - -if sys.platform == "linux" and sys.version_info >= (3,): - AF_CAN: AddressFamily - PF_CAN: int - SOL_CAN_BASE: int - SOL_CAN_RAW: int - CAN_EFF_FLAG: int - CAN_EFF_MASK: int - CAN_ERR_FLAG: int - CAN_ERR_MASK: int - CAN_RAW: int - CAN_RAW_ERR_FILTER: int - CAN_RAW_FILTER: int - CAN_RAW_LOOPBACK: int - CAN_RAW_RECV_OWN_MSGS: int - CAN_RTR_FLAG: int - CAN_SFF_MASK: int - CAN_BCM: int - CAN_BCM_TX_SETUP: int - CAN_BCM_TX_DELETE: int - CAN_BCM_TX_READ: int - CAN_BCM_TX_SEND: int - CAN_BCM_RX_SETUP: int - CAN_BCM_RX_DELETE: int - CAN_BCM_RX_READ: int - CAN_BCM_TX_STATUS: int - CAN_BCM_TX_EXPIRED: int - CAN_BCM_RX_STATUS: int - CAN_BCM_RX_TIMEOUT: int - CAN_BCM_RX_CHANGED: int - - CAN_RAW_FD_FRAMES: int - -if sys.platform == "linux" and sys.version_info >= (3, 8): - CAN_BCM_SETTIMER: int - CAN_BCM_STARTTIMER: int - CAN_BCM_TX_COUNTEVT: int - CAN_BCM_TX_ANNOUNCE: int - CAN_BCM_TX_CP_CAN_ID: int - CAN_BCM_RX_FILTER_ID: int - CAN_BCM_RX_CHECK_DLC: int - CAN_BCM_RX_NO_AUTOTIMER: int - CAN_BCM_RX_ANNOUNCE_RESUME: int - CAN_BCM_TX_RESET_MULTI_IDX: int - CAN_BCM_RX_RTR_FRAME: int - CAN_BCM_CAN_FD_FRAME: int - -if sys.platform == "linux" and sys.version_info >= (3, 7): - CAN_ISOTP: int +class AddressInfo(IntFlag): + AI_ADDRCONFIG: int + AI_ALL: int + AI_CANONNAME: int + AI_NUMERICHOST: int + AI_NUMERICSERV: int + AI_PASSIVE: int + AI_V4MAPPED: int -if sys.platform == "linux" and sys.version_info >= (3, 9): - CAN_J1939: int - - J1939_MAX_UNICAST_ADDR: int - J1939_IDLE_ADDR: int - J1939_NO_ADDR: int - J1939_NO_NAME: int - J1939_PGN_REQUEST: int - J1939_PGN_ADDRESS_CLAIMED: int - J1939_PGN_ADDRESS_COMMANDED: int - J1939_PGN_PDU1_MAX: int - J1939_PGN_MAX: int - J1939_NO_PGN: int - - SO_J1939_FILTER: int - SO_J1939_PROMISC: int - SO_J1939_SEND_PRIO: int - SO_J1939_ERRQUEUE: int - - SCM_J1939_DEST_ADDR: int - SCM_J1939_DEST_NAME: int - SCM_J1939_PRIO: int - SCM_J1939_ERRQUEUE: int - - J1939_NLA_PAD: int - J1939_NLA_BYTES_ACKED: int - - J1939_EE_INFO_NONE: int - J1939_EE_INFO_TX_ABORT: int - - J1939_FILTER_MAX: int - -if sys.platform == "linux": - AF_PACKET: AddressFamily - PF_PACKET: int - PACKET_BROADCAST: int - PACKET_FASTROUTE: int - PACKET_HOST: int - PACKET_LOOPBACK: int - PACKET_MULTICAST: int - PACKET_OTHERHOST: int - PACKET_OUTGOING: int - -if sys.platform == "linux" and sys.version_info >= (3,): - AF_RDS: AddressFamily - PF_RDS: int - SOL_RDS: int - RDS_CANCEL_SENT_TO: int - RDS_CMSG_RDMA_ARGS: int - RDS_CMSG_RDMA_DEST: int - RDS_CMSG_RDMA_MAP: int - RDS_CMSG_RDMA_STATUS: int - RDS_CMSG_RDMA_UPDATE: int - RDS_CONG_MONITOR: int - RDS_FREE_MR: int - RDS_GET_MR: int - RDS_GET_MR_FOR_DEST: int - RDS_RDMA_DONTWAIT: int - RDS_RDMA_FENCE: int - RDS_RDMA_INVALIDATE: int - RDS_RDMA_NOTIFY_ME: int - RDS_RDMA_READWRITE: int - RDS_RDMA_SILENT: int - RDS_RDMA_USE_ONCE: int - RDS_RECVERR: int +AI_ADDRCONFIG: AddressInfo +AI_ALL: AddressInfo +AI_CANONNAME: AddressInfo +AI_DEFAULT: AddressInfo +AI_MASK: AddressInfo +AI_NUMERICHOST: AddressInfo +AI_NUMERICSERV: AddressInfo +AI_PASSIVE: AddressInfo +AI_V4MAPPED: AddressInfo +AI_V4MAPPED_CFG: AddressInfo if sys.platform == "win32": - SIO_RCVALL: int - SIO_KEEPALIVE_VALS: int - if sys.version_info >= (3, 6): - SIO_LOOPBACK_FAST_PATH: int - RCVALL_IPLEVEL: int - RCVALL_MAX: int - RCVALL_OFF: int - RCVALL_ON: int - RCVALL_SOCKETLEVELONLY: int - -if sys.platform == "linux": - AF_TIPC: AddressFamily - SOL_TIPC: int - TIPC_ADDR_ID: int - TIPC_ADDR_NAME: int - TIPC_ADDR_NAMESEQ: int - TIPC_CFG_SRV: int - TIPC_CLUSTER_SCOPE: int - TIPC_CONN_TIMEOUT: int - TIPC_CRITICAL_IMPORTANCE: int - TIPC_DEST_DROPPABLE: int - TIPC_HIGH_IMPORTANCE: int - TIPC_IMPORTANCE: int - TIPC_LOW_IMPORTANCE: int - TIPC_MEDIUM_IMPORTANCE: int - TIPC_NODE_SCOPE: int - TIPC_PUBLISHED: int - TIPC_SRC_DROPPABLE: int - TIPC_SUBSCR_TIMEOUT: int - TIPC_SUB_CANCEL: int - TIPC_SUB_PORTS: int - TIPC_SUB_SERVICE: int - TIPC_TOP_SRV: int - TIPC_WAIT_FOREVER: int - TIPC_WITHDRAWN: int - TIPC_ZONE_SCOPE: int - -if sys.platform == "linux" and sys.version_info >= (3, 6): - AF_ALG: AddressFamily - SOL_ALG: int - ALG_OP_DECRYPT: int - ALG_OP_ENCRYPT: int - ALG_OP_SIGN: int - ALG_OP_VERIFY: int - ALG_SET_AEAD_ASSOCLEN: int - ALG_SET_AEAD_AUTHSIZE: int - ALG_SET_IV: int - ALG_SET_KEY: int - ALG_SET_OP: int - ALG_SET_PUBKEY: int - -if sys.platform == "linux" and sys.version_info >= (3, 7): - AF_VSOCK: AddressFamily - IOCTL_VM_SOCKETS_GET_LOCAL_CID: int - VMADDR_CID_ANY: int - VMADDR_CID_HOST: int - VMADDR_PORT_ANY: int - SO_VM_SOCKETS_BUFFER_MAX_SIZE: int - SO_VM_SOCKETS_BUFFER_SIZE: int - SO_VM_SOCKETS_BUFFER_MIN_SIZE: int - VM_SOCKETS_INVALID_VERSION: int - -AF_LINK: AddressFamily # Availability: BSD, macOS - -# BDADDR_* and HCI_* listed with other bluetooth constants below - -if sys.version_info >= (3, 6): - SO_DOMAIN: int - SO_PASSSEC: int - SO_PEERSEC: int - SO_PROTOCOL: int - TCP_CONGESTION: int - TCP_USER_TIMEOUT: int - -if sys.platform == "linux" and sys.version_info >= (3, 8): - AF_QIPCRTR: AddressFamily - -# Semi-documented constants -# (Listed under "Socket families" in the docs, but not "Constants") - -if sys.platform == "linux": - # Netlink is defined by Linux - AF_NETLINK: AddressFamily - NETLINK_ARPD: int - NETLINK_CRYPTO: int - NETLINK_DNRTMSG: int - NETLINK_FIREWALL: int - NETLINK_IP6_FW: int - NETLINK_NFLOG: int - NETLINK_ROUTE6: int - NETLINK_ROUTE: int - NETLINK_SKIP: int - NETLINK_TAPBASE: int - NETLINK_TCPDIAG: int - NETLINK_USERSOCK: int - NETLINK_W1: int - NETLINK_XFRM: int - -if sys.platform != "win32" and sys.platform != "darwin": - # Linux and some BSD support is explicit in the docs - # Windows and macOS do not support in practice - AF_BLUETOOTH: AddressFamily - BTPROTO_HCI: int - BTPROTO_L2CAP: int - BTPROTO_RFCOMM: int - BTPROTO_SCO: int # not in FreeBSD - - BDADDR_ANY: str - BDADDR_LOCAL: str - - HCI_FILTER: int # not in NetBSD or DragonFlyBSD - # not in FreeBSD, NetBSD, or DragonFlyBSD - HCI_TIME_STAMP: int - HCI_DATA_DIR: int - -if sys.platform == "darwin": - # PF_SYSTEM is defined by macOS - PF_SYSTEM: int - SYSPROTO_CONTROL: int - -# enum versions of above flags -if sys.version_info >= (3, 4): - from enum import IntEnum - class AddressFamily(IntEnum): - AF_UNIX: int - AF_INET: int - AF_INET6: int - AF_AAL5: int - AF_ALG: int - AF_APPLETALK: int - AF_ASH: int - AF_ATMPVC: int - AF_ATMSVC: int - AF_AX25: int - AF_BLUETOOTH: int - AF_BRIDGE: int - AF_CAN: int - AF_DECnet: int - AF_ECONET: int - AF_IPX: int - AF_IRDA: int - AF_KEY: int - AF_LINK: int - AF_LLC: int - AF_NETBEUI: int - AF_NETLINK: int - AF_NETROM: int - AF_PACKET: int - AF_PPPOX: int - AF_QIPCRTR: int - AF_RDS: int - AF_ROSE: int - AF_ROUTE: int - AF_SECURITY: int - AF_SNA: int - AF_SYSTEM: int - AF_TIPC: int - AF_UNSPEC: int - AF_VSOCK: int - AF_WANPIPE: int - AF_X25: int - class SocketKind(IntEnum): - SOCK_STREAM: int - SOCK_DGRAM: int - SOCK_RAW: int - SOCK_RDM: int - SOCK_SEQPACKET: int - SOCK_CLOEXEC: int - SOCK_NONBLOCK: int - -else: - AddressFamily = int - SocketKind = int - -if sys.version_info >= (3, 6): - from enum import IntFlag - class AddressInfo(IntFlag): - AI_ADDRCONFIG: int - AI_ALL: int - AI_CANONNAME: int - AI_NUMERICHOST: int - AI_NUMERICSERV: int - AI_PASSIVE: int - AI_V4MAPPED: int - class MsgFlag(IntFlag): - MSG_CTRUNC: int - MSG_DONTROUTE: int - MSG_DONTWAIT: int - MSG_EOR: int - MSG_OOB: int - MSG_PEEK: int - MSG_TRUNC: int - MSG_WAITALL: int - -else: - AddressInfo = int - MsgFlag = int - -# ----- Exceptions ----- - -if sys.version_info < (3,): - class error(IOError): ... - -else: - error = OSError - -class herror(error): - def __init__(self, herror: int = ..., string: str = ...) -> None: ... - -class gaierror(error): - def __init__(self, error: int = ..., string: str = ...) -> None: ... - -class timeout(error): - def __init__(self, error: int = ..., string: str = ...) -> None: ... - -# ----- Classes ----- - -# Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, -# AF_NETLINK, AF_TIPC) or strings (AF_UNIX). -_Address = Union[Tuple[Any, ...], str] -_RetAddress = Any -# TODO Most methods allow bytes as address objects - -_WriteBuffer = Union[bytearray, memoryview] - -_CMSG = Tuple[int, int, bytes] -_SelfT = TypeVar("_SelfT", bound=socket) - -class socket: - family: int - type: int - proto: int - - if sys.version_info < (3,): - def __init__(self, family: int = ..., type: int = ..., proto: int = ...) -> None: ... - else: - def __init__(self, family: int = ..., type: int = ..., proto: int = ..., fileno: Optional[int] = ...) -> None: ... - def __enter__(self: _SelfT) -> _SelfT: ... - def __exit__(self, *args: Any) -> None: ... - # --- methods --- - def accept(self) -> Tuple[socket, _RetAddress]: ... - def bind(self, address: Union[_Address, bytes]) -> None: ... - def close(self) -> None: ... - def connect(self, address: Union[_Address, bytes]) -> None: ... - def connect_ex(self, address: Union[_Address, bytes]) -> int: ... - def detach(self) -> int: ... - def dup(self) -> socket: ... - def fileno(self) -> int: ... - if sys.version_info >= (3, 4): - def get_inheritable(self) -> bool: ... - def getpeername(self) -> _RetAddress: ... - def getsockname(self) -> _RetAddress: ... - @overload - def getsockopt(self, level: int, optname: int) -> int: ... - @overload - def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... - if sys.version_info >= (3, 7): - def getblocking(self) -> bool: ... - def gettimeout(self) -> Optional[float]: ... - if sys.platform == "win32" and sys.version_info >= (3, 6): - def ioctl(self, control: int, option: Union[int, Tuple[int, int, int], bool]) -> None: ... - elif sys.platform == "win32": - def ioctl(self, control: int, option: Union[int, Tuple[int, int, int]]) -> None: ... - if sys.version_info >= (3, 5): - def listen(self, __backlog: int = ...) -> None: ... - else: - def listen(self, __backlog: int) -> None: ... + errorTab: dict[int, str] # undocumented + +class socket(_socket.socket): + def __init__( + self, family: AddressFamily | int = ..., type: SocketKind | int = ..., proto: int = ..., fileno: int | None = ... + ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: object) -> None: ... + def dup(self: _T) -> _T: ... # noqa: F811 + def accept(self) -> tuple[socket, _RetAddress]: ... # Note that the makefile's documented windows-specific behavior is not represented - if sys.version_info >= (3,): - # mode strings with duplicates are intentionally excluded - @overload - def makefile( - self, - mode: Literal["r", "w", "rw", "wr", ""] = ..., - buffering: Optional[int] = ..., - *, - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., - ) -> TextIO: ... - @overload - def makefile( - self, - mode: Literal["b", "rb", "br", "wb", "bw", "rwb", "rbw", "wrb", "wbr", "brw", "bwr"], - buffering: Optional[int] = ..., - *, - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., - ) -> BinaryIO: ... - else: - def makefile(self, mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... - def recv(self, bufsize: int, flags: int = ...) -> bytes: ... - def recvfrom(self, bufsize: int, flags: int = ...) -> Tuple[bytes, _RetAddress]: ... - if sys.version_info >= (3, 3) and sys.platform != "win32": - def recvmsg(self, __bufsize: int, __ancbufsize: int = ..., __flags: int = ...) -> Tuple[bytes, List[_CMSG], int, Any]: ... - def recvmsg_into( - self, __buffers: Iterable[_WriteBuffer], __ancbufsize: int = ..., __flags: int = ... - ) -> Tuple[int, List[_CMSG], int, Any]: ... - def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> Tuple[int, _RetAddress]: ... - def recv_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> int: ... - def send(self, data: bytes, flags: int = ...) -> int: ... - def sendall(self, data: bytes, flags: int = ...) -> None: ... # return type: None on success + # mode strings with duplicates are intentionally excluded @overload - def sendto(self, data: bytes, address: _Address) -> int: ... + def makefile( + self, + mode: Literal["r", "w", "rw", "wr", ""] = ..., + buffering: int | None = ..., + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> TextIO: ... @overload - def sendto(self, data: bytes, flags: int, address: _Address) -> int: ... - if sys.version_info >= (3, 3) and sys.platform != "win32": - def sendmsg( - self, __buffers: Iterable[bytes], __ancdata: Iterable[_CMSG] = ..., __flags: int = ..., __address: _Address = ... - ) -> int: ... - if sys.platform == "linux" and sys.version_info >= (3, 6): - def sendmsg_afalg( - self, msg: Iterable[bytes] = ..., *, op: int, iv: Any = ..., assoclen: int = ..., flags: int = ... + def makefile( + self, + mode: Literal["b", "rb", "br", "wb", "bw", "rwb", "rbw", "wrb", "wbr", "brw", "bwr"], + buffering: int | None = ..., + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> BinaryIO: ... + def sendfile(self, file: BinaryIO, offset: int = ..., count: int | None = ...) -> int: ... + @property + def family(self) -> AddressFamily: ... # type: ignore + @property + def type(self) -> SocketKind: ... # type: ignore + def get_inheritable(self) -> bool: ... + def set_inheritable(self, inheritable: bool) -> None: ... + +def fromfd(fd: _FD, family: AddressFamily | int, type: SocketKind | int, proto: int = ...) -> socket: ... + +if sys.platform != "win32": + if sys.version_info >= (3, 9): + # flags and address appear to be unused in send_fds and recv_fds + def send_fds( + sock: socket, buffers: Iterable[bytes], fds: bytes | Iterable[int], flags: int = ..., address: None = ... ) -> int: ... - if sys.version_info >= (3,): - def sendfile(self, file: BinaryIO, offset: int = ..., count: Optional[int] = ...) -> int: ... - def set_inheritable(self, inheritable: bool) -> None: ... - def setblocking(self, flag: bool) -> None: ... - def settimeout(self, value: Optional[float]) -> None: ... - if sys.version_info < (3, 6): - def setsockopt(self, level: int, optname: int, value: Union[int, bytes]) -> None: ... - else: - @overload - def setsockopt(self, level: int, optname: int, value: Union[int, bytes]) -> None: ... - @overload - def setsockopt(self, level: int, optname: int, value: None, optlen: int) -> None: ... - if sys.platform == "win32": - def share(self, process_id: int) -> bytes: ... - def shutdown(self, how: int) -> None: ... + def recv_fds(sock: socket, bufsize: int, maxfds: int, flags: int = ...) -> tuple[bytes, list[int], int, Any]: ... -# ----- Functions ----- +if sys.platform == "win32": + def fromshare(info: bytes) -> socket: ... -if sys.version_info >= (3, 7): - def close(fd: int) -> None: ... +if sys.platform == "win32": + def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> tuple[socket, socket]: ... +else: + def socketpair( # type: ignore + family: int | AddressFamily | None = ..., type: SocketType | int = ..., proto: int = ... + ) -> tuple[socket, socket]: ... + +class SocketIO(RawIOBase): + def __init__(self, sock: socket, mode: Literal["r", "w", "rw", "rb", "wb", "rwb"]) -> None: ... + def readinto(self, b: WriteableBuffer) -> int | None: ... + def write(self, b: ReadableBuffer) -> int | None: ... + @property + def name(self) -> int: ... # return value is really "int" + @property + def mode(self) -> Literal["rb", "wb", "rwb"]: ... + +def getfqdn(name: str = ...) -> str: ... def create_connection( - address: Tuple[Optional[str], int], - timeout: Optional[float] = ..., - source_address: Optional[Tuple[Union[bytearray, bytes, Text], int]] = ..., + address: tuple[str | None, int], + timeout: float | None = ..., # noqa: F811 + source_address: tuple[bytearray | bytes | str, int] | None = ..., ) -> socket: ... if sys.version_info >= (3, 8): + def has_dualstack_ipv6() -> bool: ... def create_server( - address: _Address, *, family: int = ..., backlog: Optional[int] = ..., reuse_port: bool = ..., dualstack_ipv6: bool = ... + address: _Address, *, family: int = ..., backlog: int | None = ..., reuse_port: bool = ..., dualstack_ipv6: bool = ... ) -> socket: ... - def has_dualstack_ipv6() -> bool: ... - -def fromfd(fd: int, family: int, type: int, proto: int = ...) -> socket: ... - -if sys.platform == "win32" and sys.version_info >= (3, 3): - def fromshare(info: bytes) -> socket: ... # the 5th tuple item is an address -if sys.version_info >= (3,): - def getaddrinfo( - host: Optional[Union[bytearray, bytes, Text]], - port: Union[str, int, None], - family: int = ..., - type: int = ..., - proto: int = ..., - flags: int = ..., - ) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int]]]]: ... - -else: - def getaddrinfo( - host: Optional[Union[bytearray, bytes, Text]], - port: Union[str, int, None], - family: int = ..., - socktype: int = ..., - proto: int = ..., - flags: int = ..., - ) -> List[Tuple[AddressFamily, SocketKind, int, str, Tuple[Any, ...]]]: ... - -def getfqdn(name: str = ...) -> str: ... -def gethostbyname(hostname: str) -> str: ... -def gethostbyname_ex(hostname: str) -> Tuple[str, List[str], List[str]]: ... -def gethostname() -> str: ... -def gethostbyaddr(ip_address: str) -> Tuple[str, List[str], List[str]]: ... -def getnameinfo(sockaddr: Union[Tuple[str, int], Tuple[str, int, int, int]], flags: int) -> Tuple[str, str]: ... -def getprotobyname(protocolname: str) -> int: ... -def getservbyname(servicename: str, protocolname: str = ...) -> int: ... -def getservbyport(port: int, protocolname: str = ...) -> str: ... - -if sys.platform == "win32": - def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... - -else: - def socketpair(family: Optional[int] = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... - -def ntohl(x: int) -> int: ... # param & ret val are 32-bit ints -def ntohs(x: int) -> int: ... # param & ret val are 16-bit ints -def htonl(x: int) -> int: ... # param & ret val are 32-bit ints -def htons(x: int) -> int: ... # param & ret val are 16-bit ints -def inet_aton(ip_string: str) -> bytes: ... # ret val 4 bytes in length -def inet_ntoa(packed_ip: bytes) -> str: ... -def inet_pton(address_family: int, ip_string: str) -> bytes: ... -def inet_ntop(address_family: int, packed_ip: bytes) -> str: ... - -if sys.version_info >= (3, 9): - if sys.platform != "win32": - # flags and address appear to be unused in send_fds and recv_fds - def send_fds( - sock: socket, buffers: Iterable[bytes], fds: Union[bytes, Iterable[int]], flags: int = ..., address: None = ... - ) -> int: ... - def recv_fds(sock: socket, bufsize: int, maxfds: int, flags: int = ...) -> Tuple[bytes, List[int], int, Any]: ... - -if sys.version_info >= (3, 3): - def CMSG_LEN(length: int) -> int: ... - def CMSG_SPACE(length: int) -> int: ... - -def getdefaulttimeout() -> Optional[float]: ... -def setdefaulttimeout(timeout: Optional[float]) -> None: ... - -if sys.version_info >= (3, 3): - if sys.platform != "win32": - def sethostname(name: str) -> None: ... - # Windows added these in 3.8, but didn't have them before - if sys.platform != "win32" or sys.version_info >= (3, 8): - def if_nameindex() -> List[Tuple[int, str]]: ... - def if_nametoindex(name: str) -> int: ... - def if_indextoname(index: int) -> str: ... +def getaddrinfo( + host: bytearray | bytes | str | None, + port: str | int | None, + family: int = ..., + type: int = ..., + proto: int = ..., + flags: int = ..., +) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... diff --git a/mypy/typeshed/stdlib/socketserver.pyi b/mypy/typeshed/stdlib/socketserver.pyi index f0617e393b7e..6f5eeefb84fd 100644 --- a/mypy/typeshed/stdlib/socketserver.pyi +++ b/mypy/typeshed/stdlib/socketserver.pyi @@ -1,90 +1,109 @@ import sys import types -from socket import SocketType -from typing import Any, BinaryIO, Callable, ClassVar, List, Optional, Tuple, Type, TypeVar, Union +from _typeshed import Self +from socket import socket as _socket +from typing import Any, BinaryIO, Callable, ClassVar, Tuple, Type, TypeVar, Union _T = TypeVar("_T") +_RequestType = Union[_socket, Tuple[bytes, _socket]] +_AddressType = Union[Tuple[str, int], str] class BaseServer: address_family: int RequestHandlerClass: Callable[..., BaseRequestHandler] - server_address: Tuple[str, int] - socket: SocketType + server_address: tuple[str, int] + socket: _socket allow_reuse_address: bool request_queue_size: int socket_type: int - timeout: Optional[float] + timeout: float | None def __init__(self, server_address: Any, RequestHandlerClass: Callable[..., BaseRequestHandler]) -> None: ... def fileno(self) -> int: ... def handle_request(self) -> None: ... def serve_forever(self, poll_interval: float = ...) -> None: ... def shutdown(self) -> None: ... def server_close(self) -> None: ... - def finish_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... - def get_request(self) -> Tuple[SocketType, Tuple[str, int]]: ... - def handle_error(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def finish_request(self, request: _RequestType, client_address: _AddressType) -> None: ... + def get_request(self) -> tuple[Any, Any]: ... + def handle_error(self, request: _RequestType, client_address: _AddressType) -> None: ... def handle_timeout(self) -> None: ... - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... def server_activate(self) -> None: ... def server_bind(self) -> None: ... - def verify_request(self, request: bytes, client_address: Tuple[str, int]) -> bool: ... - def __enter__(self: _T) -> _T: ... + def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[types.TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... def service_actions(self) -> None: ... + def shutdown_request(self, request: _RequestType) -> None: ... # undocumented + def close_request(self, request: _RequestType) -> None: ... # undocumented class TCPServer(BaseServer): def __init__( self, - server_address: Tuple[str, int], + server_address: tuple[str, int], RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... + def get_request(self) -> tuple[_socket, Any]: ... + def finish_request(self, request: _RequestType, client_address: _AddressType) -> None: ... + def handle_error(self, request: _RequestType, client_address: _AddressType) -> None: ... + def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... + def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... + def shutdown_request(self, request: _RequestType) -> None: ... # undocumented + def close_request(self, request: _RequestType) -> None: ... # undocumented class UDPServer(BaseServer): def __init__( self, - server_address: Tuple[str, int], + server_address: tuple[str, int], RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... + def get_request(self) -> tuple[tuple[bytes, _socket], Any]: ... + def finish_request(self, request: _RequestType, client_address: _AddressType) -> None: ... + def handle_error(self, request: _RequestType, client_address: _AddressType) -> None: ... + def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... + def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... + def shutdown_request(self, request: _RequestType) -> None: ... # undocumented + def close_request(self, request: _RequestType) -> None: ... # undocumented if sys.platform != "win32": class UnixStreamServer(BaseServer): def __init__( self, - server_address: Union[str, bytes], + server_address: str | bytes, RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... class UnixDatagramServer(BaseServer): def __init__( self, - server_address: Union[str, bytes], + server_address: str | bytes, RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... if sys.platform != "win32": class ForkingMixIn: - timeout: Optional[float] # undocumented - active_children: Optional[List[int]] # undocumented + timeout: float | None # undocumented + active_children: set[int] | None # undocumented max_children: int # undocumented if sys.version_info >= (3, 7): block_on_close: bool def collect_children(self, *, blocking: bool = ...) -> None: ... # undocumented def handle_timeout(self) -> None: ... # undocumented def service_actions(self) -> None: ... # undocumented - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... def server_close(self) -> None: ... class ThreadingMixIn: daemon_threads: bool if sys.version_info >= (3, 7): block_on_close: bool - def process_request_thread(self, request: bytes, client_address: Tuple[str, int]) -> None: ... # undocumented - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request_thread(self, request: _RequestType, client_address: _AddressType) -> None: ... # undocumented + def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... def server_close(self) -> None: ... if sys.platform != "win32": @@ -100,30 +119,30 @@ if sys.platform != "win32": class BaseRequestHandler: # Those are technically of types, respectively: - # * Union[SocketType, Tuple[bytes, SocketType]] - # * Union[Tuple[str, int], str] + # * _RequestType + # * _AddressType # But there are some concerns that having unions here would cause # too much inconvenience to people using it (see # https://github.com/python/typeshed/pull/384#issuecomment-234649696) request: Any client_address: Any server: BaseServer - def __init__(self, request: Any, client_address: Any, server: BaseServer) -> None: ... + def __init__(self, request: _RequestType, client_address: _AddressType, server: BaseServer) -> None: ... def setup(self) -> None: ... def handle(self) -> None: ... def finish(self) -> None: ... class StreamRequestHandler(BaseRequestHandler): - rbufsize: ClassVar[int] # Undocumented - wbufsize: ClassVar[int] # Undocumented - timeout: ClassVar[Optional[float]] # Undocumented - disable_nagle_algorithm: ClassVar[bool] # Undocumented - connection: SocketType # Undocumented + rbufsize: ClassVar[int] # undocumented + wbufsize: ClassVar[int] # undocumented + timeout: ClassVar[float | None] # undocumented + disable_nagle_algorithm: ClassVar[bool] # undocumented + connection: _socket # undocumented rfile: BinaryIO wfile: BinaryIO class DatagramRequestHandler(BaseRequestHandler): - packet: SocketType # Undocumented - socket: SocketType # Undocumented + packet: _socket # undocumented + socket: _socket # undocumented rfile: BinaryIO wfile: BinaryIO diff --git a/mypy/typeshed/stdlib/spwd.pyi b/mypy/typeshed/stdlib/spwd.pyi index 8a6656194614..0f8d36fee945 100644 --- a/mypy/typeshed/stdlib/spwd.pyi +++ b/mypy/typeshed/stdlib/spwd.pyi @@ -1,4 +1,4 @@ -from typing import List, NamedTuple +from typing import NamedTuple class struct_spwd(NamedTuple): sp_namp: str @@ -11,5 +11,5 @@ class struct_spwd(NamedTuple): sp_expire: int sp_flag: int -def getspall() -> List[struct_spwd]: ... +def getspall() -> list[struct_spwd]: ... def getspnam(__arg: str) -> struct_spwd: ... diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index 74caa0e64cf1..e2e45d538da9 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -1,7 +1,7 @@ -import os import sys +from _typeshed import Self, StrOrBytesPath from datetime import date, datetime, time -from typing import Any, Callable, Generator, Iterable, Iterator, List, Optional, Protocol, Text, Tuple, Type, TypeVar, Union +from typing import Any, Callable, Generator, Iterable, Iterator, Protocol, Type, TypeVar _T = TypeVar("_T") @@ -16,12 +16,9 @@ def DateFromTicks(ticks: float) -> Date: ... def TimeFromTicks(ticks: float) -> Time: ... def TimestampFromTicks(ticks: float) -> Timestamp: ... -version_info: Tuple[int, int, int] -sqlite_version_info: Tuple[int, int, int] -if sys.version_info >= (3,): - Binary = memoryview -else: - Binary = buffer +version_info: tuple[int, int, int] +sqlite_version_info: tuple[int, int, int] +Binary = memoryview # The remaining definitions are imported from _sqlite3. @@ -38,6 +35,8 @@ SQLITE_CREATE_TEMP_TRIGGER: int SQLITE_CREATE_TEMP_VIEW: int SQLITE_CREATE_TRIGGER: int SQLITE_CREATE_VIEW: int +if sys.version_info >= (3, 7): + SQLITE_CREATE_VTABLE: int SQLITE_DELETE: int SQLITE_DENY: int SQLITE_DETACH: int @@ -49,12 +48,31 @@ SQLITE_DROP_TEMP_TRIGGER: int SQLITE_DROP_TEMP_VIEW: int SQLITE_DROP_TRIGGER: int SQLITE_DROP_VIEW: int +if sys.version_info >= (3, 7): + SQLITE_DROP_VTABLE: int + SQLITE_FUNCTION: int SQLITE_IGNORE: int SQLITE_INSERT: int SQLITE_OK: int +if sys.version_info >= (3, 11): + SQLITE_LIMIT_LENGTH: int + SQLITE_LIMIT_SQL_LENGTH: int + SQLITE_LIMIT_COLUMN: int + SQLITE_LIMIT_EXPR_DEPTH: int + SQLITE_LIMIT_COMPOUND_SELECT: int + SQLITE_LIMIT_VDBE_OP: int + SQLITE_LIMIT_FUNCTION_ARG: int + SQLITE_LIMIT_ATTACHED: int + SQLITE_LIMIT_LIKE_PATTERN_LENGTH: int + SQLITE_LIMIT_VARIABLE_NUMBER: int + SQLITE_LIMIT_TRIGGER_DEPTH: int + SQLITE_LIMIT_WORKER_THREADS: int SQLITE_PRAGMA: int SQLITE_READ: int SQLITE_REINDEX: int +if sys.version_info >= (3, 7): + SQLITE_RECURSIVE: int + SQLITE_SAVEPOINT: int SQLITE_SELECT: int SQLITE_TRANSACTION: int SQLITE_UPDATE: int @@ -69,42 +87,31 @@ def complete_statement(sql: str) -> bool: ... if sys.version_info >= (3, 7): def connect( - database: Union[bytes, Text, os.PathLike[Text]], - timeout: float = ..., - detect_types: int = ..., - isolation_level: Optional[str] = ..., - check_same_thread: bool = ..., - factory: Optional[Type[Connection]] = ..., - cached_statements: int = ..., - uri: bool = ..., - ) -> Connection: ... - -elif sys.version_info >= (3, 4): - def connect( - database: Union[bytes, Text], + database: StrOrBytesPath, timeout: float = ..., detect_types: int = ..., - isolation_level: Optional[str] = ..., + isolation_level: str | None = ..., check_same_thread: bool = ..., - factory: Optional[Type[Connection]] = ..., + factory: Type[Connection] | None = ..., cached_statements: int = ..., uri: bool = ..., ) -> Connection: ... else: def connect( - database: Union[bytes, Text], + database: bytes | str, timeout: float = ..., detect_types: int = ..., - isolation_level: Optional[str] = ..., + isolation_level: str | None = ..., check_same_thread: bool = ..., - factory: Optional[Type[Connection]] = ..., + factory: Type[Connection] | None = ..., cached_statements: int = ..., + uri: bool = ..., ) -> Connection: ... def enable_callback_tracebacks(__enable: bool) -> None: ... def enable_shared_cache(enable: int) -> None: ... -def register_adapter(__type: Type[_T], __caster: Callable[[_T], Union[int, float, str, bytes]]) -> None: ... +def register_adapter(__type: Type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... if sys.version_info < (3, 8): @@ -142,11 +149,11 @@ class Connection(object): def create_function(self, name: str, narg: int, func: Any, *, deterministic: bool = ...) -> None: ... else: def create_function(self, name: str, num_params: int, func: Any) -> None: ... - def cursor(self, cursorClass: Optional[type] = ...) -> Cursor: ... + def cursor(self, cursorClass: type | None = ...) -> Cursor: ... def execute(self, sql: str, parameters: Iterable[Any] = ...) -> Cursor: ... # TODO: please check in executemany() if seq_of_parameters type is possible like this def executemany(self, __sql: str, __parameters: Iterable[Iterable[Any]]) -> Cursor: ... - def executescript(self, __sql_script: Union[bytes, Text]) -> Cursor: ... + def executescript(self, __sql_script: bytes | str) -> Cursor: ... def interrupt(self, *args: Any, **kwargs: Any) -> None: ... def iterdump(self, *args: Any, **kwargs: Any) -> Generator[str, None, None]: ... def rollback(self, *args: Any, **kwargs: Any) -> None: ... @@ -167,13 +174,13 @@ class Connection(object): target: Connection, *, pages: int = ..., - progress: Optional[Callable[[int, int, int], object]] = ..., + progress: Callable[[int, int, int], object] | None = ..., name: str = ..., sleep: float = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __enter__(self) -> Connection: ... - def __exit__(self, t: Optional[type], exc: Optional[BaseException], tb: Optional[Any]) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: type | None, exc: BaseException | None, tb: Any | None) -> None: ... class Cursor(Iterator[Any]): arraysize: Any @@ -181,7 +188,7 @@ class Cursor(Iterator[Any]): description: Any lastrowid: Any row_factory: Any - rowcount: Any + rowcount: int # TODO: Cursor class accepts exactly 1 argument # required type is sqlite3.Connection (which is imported as _Connection) # however, the name of the __init__ variable is unknown @@ -189,17 +196,14 @@ class Cursor(Iterator[Any]): def close(self, *args: Any, **kwargs: Any) -> None: ... def execute(self, __sql: str, __parameters: Iterable[Any] = ...) -> Cursor: ... def executemany(self, __sql: str, __seq_of_parameters: Iterable[Iterable[Any]]) -> Cursor: ... - def executescript(self, __sql_script: Union[bytes, Text]) -> Cursor: ... - def fetchall(self) -> List[Any]: ... - def fetchmany(self, size: Optional[int] = ...) -> List[Any]: ... + def executescript(self, __sql_script: bytes | str) -> Cursor: ... + def fetchall(self) -> list[Any]: ... + def fetchmany(self, size: int | None = ...) -> list[Any]: ... def fetchone(self) -> Any: ... def setinputsizes(self, *args: Any, **kwargs: Any) -> None: ... def setoutputsize(self, *args: Any, **kwargs: Any) -> None: ... def __iter__(self) -> Cursor: ... - if sys.version_info >= (3, 0): - def __next__(self) -> Any: ... - else: - def next(self) -> Any: ... + def __next__(self) -> Any: ... class DataError(DatabaseError): ... class DatabaseError(Error): ... @@ -210,73 +214,7 @@ class InternalError(DatabaseError): ... class NotSupportedError(DatabaseError): ... class OperationalError(DatabaseError): ... -if sys.version_info >= (3,): - OptimizedUnicode = str -else: - class OptimizedUnicode(object): - maketrans: Any - def __init__(self, *args, **kwargs): ... - def capitalize(self, *args, **kwargs): ... - def casefold(self, *args, **kwargs): ... - def center(self, *args, **kwargs): ... - def count(self, *args, **kwargs): ... - def encode(self, *args, **kwargs): ... - def endswith(self, *args, **kwargs): ... - def expandtabs(self, *args, **kwargs): ... - def find(self, *args, **kwargs): ... - def format(self, *args, **kwargs): ... - def format_map(self, *args, **kwargs): ... - def index(self, *args, **kwargs): ... - def isalnum(self, *args, **kwargs): ... - def isalpha(self, *args, **kwargs): ... - def isdecimal(self, *args, **kwargs): ... - def isdigit(self, *args, **kwargs): ... - def isidentifier(self, *args, **kwargs): ... - def islower(self, *args, **kwargs): ... - def isnumeric(self, *args, **kwargs): ... - def isprintable(self, *args, **kwargs): ... - def isspace(self, *args, **kwargs): ... - def istitle(self, *args, **kwargs): ... - def isupper(self, *args, **kwargs): ... - def join(self, *args, **kwargs): ... - def ljust(self, *args, **kwargs): ... - def lower(self, *args, **kwargs): ... - def lstrip(self, *args, **kwargs): ... - def partition(self, *args, **kwargs): ... - def replace(self, *args, **kwargs): ... - def rfind(self, *args, **kwargs): ... - def rindex(self, *args, **kwargs): ... - def rjust(self, *args, **kwargs): ... - def rpartition(self, *args, **kwargs): ... - def rsplit(self, *args, **kwargs): ... - def rstrip(self, *args, **kwargs): ... - def split(self, *args, **kwargs): ... - def splitlines(self, *args, **kwargs): ... - def startswith(self, *args, **kwargs): ... - def strip(self, *args, **kwargs): ... - def swapcase(self, *args, **kwargs): ... - def title(self, *args, **kwargs): ... - def translate(self, *args, **kwargs): ... - def upper(self, *args, **kwargs): ... - def zfill(self, *args, **kwargs): ... - def __add__(self, other): ... - def __contains__(self, *args, **kwargs): ... - def __eq__(self, other): ... - def __format__(self, *args, **kwargs): ... - def __ge__(self, other): ... - def __getitem__(self, index): ... - def __getnewargs__(self, *args, **kwargs): ... - def __gt__(self, other): ... - def __hash__(self): ... - def __iter__(self): ... - def __le__(self, other): ... - def __len__(self, *args, **kwargs): ... - def __lt__(self, other): ... - def __mod__(self, other): ... - def __mul__(self, other): ... - def __ne__(self, other): ... - def __rmod__(self, other): ... - def __rmul__(self, other): ... +OptimizedUnicode = str class PrepareProtocol(object): def __init__(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/sre_compile.pyi b/mypy/typeshed/stdlib/sre_compile.pyi index 9b50b75d8c31..aac8c0242764 100644 --- a/mypy/typeshed/stdlib/sre_compile.pyi +++ b/mypy/typeshed/stdlib/sre_compile.pyi @@ -1,5 +1,5 @@ -import sys from sre_constants import ( + SRE_FLAG_ASCII as SRE_FLAG_ASCII, SRE_FLAG_DEBUG as SRE_FLAG_DEBUG, SRE_FLAG_DOTALL as SRE_FLAG_DOTALL, SRE_FLAG_IGNORECASE as SRE_FLAG_IGNORECASE, @@ -11,21 +11,13 @@ from sre_constants import ( SRE_INFO_CHARSET as SRE_INFO_CHARSET, SRE_INFO_LITERAL as SRE_INFO_LITERAL, SRE_INFO_PREFIX as SRE_INFO_PREFIX, + _NamedIntConstant, ) from sre_parse import SubPattern -from typing import Any, List, Pattern, Tuple, Type, Union - -if sys.version_info >= (3,): - from sre_constants import SRE_FLAG_ASCII as SRE_FLAG_ASCII +from typing import Any, Pattern MAXCODE: int -if sys.version_info < (3, 0): - STRING_TYPES: Tuple[Type[str], Type[unicode]] - _IsStringType = int -else: - from sre_constants import _NamedIntConstant - def dis(code: List[_NamedIntConstant]) -> None: ... - _IsStringType = bool -def isstring(obj: Any) -> _IsStringType: ... -def compile(p: Union[str, bytes, SubPattern], flags: int = ...) -> Pattern[Any]: ... +def dis(code: list[_NamedIntConstant]) -> None: ... +def isstring(obj: Any) -> bool: ... +def compile(p: str | bytes | SubPattern, flags: int = ...) -> Pattern[Any]: ... diff --git a/mypy/typeshed/stdlib/sre_constants.pyi b/mypy/typeshed/stdlib/sre_constants.pyi index 07a308e6f67b..4658d0e4b175 100644 --- a/mypy/typeshed/stdlib/sre_constants.pyi +++ b/mypy/typeshed/stdlib/sre_constants.pyi @@ -1,30 +1,30 @@ import sys -from typing import Any, Dict, List, Optional, Union +from typing import Any MAGIC: int class error(Exception): msg: str - pattern: Optional[Union[str, bytes]] - pos: Optional[int] + pattern: str | bytes | None + pos: int | None lineno: int colno: int - def __init__(self, msg: str, pattern: Optional[Union[str, bytes]] = ..., pos: Optional[int] = ...) -> None: ... + def __init__(self, msg: str, pattern: str | bytes | None = ..., pos: int | None = ...) -> None: ... class _NamedIntConstant(int): name: Any def __new__(cls, value: int, name: str) -> _NamedIntConstant: ... MAXREPEAT: _NamedIntConstant -OPCODES: List[_NamedIntConstant] -ATCODES: List[_NamedIntConstant] -CHCODES: List[_NamedIntConstant] -OP_IGNORE: Dict[_NamedIntConstant, _NamedIntConstant] -AT_MULTILINE: Dict[_NamedIntConstant, _NamedIntConstant] -AT_LOCALE: Dict[_NamedIntConstant, _NamedIntConstant] -AT_UNICODE: Dict[_NamedIntConstant, _NamedIntConstant] -CH_LOCALE: Dict[_NamedIntConstant, _NamedIntConstant] -CH_UNICODE: Dict[_NamedIntConstant, _NamedIntConstant] +OPCODES: list[_NamedIntConstant] +ATCODES: list[_NamedIntConstant] +CHCODES: list[_NamedIntConstant] +OP_IGNORE: dict[_NamedIntConstant, _NamedIntConstant] +AT_MULTILINE: dict[_NamedIntConstant, _NamedIntConstant] +AT_LOCALE: dict[_NamedIntConstant, _NamedIntConstant] +AT_UNICODE: dict[_NamedIntConstant, _NamedIntConstant] +CH_LOCALE: dict[_NamedIntConstant, _NamedIntConstant] +CH_UNICODE: dict[_NamedIntConstant, _NamedIntConstant] SRE_FLAG_TEMPLATE: int SRE_FLAG_IGNORECASE: int SRE_FLAG_LOCALE: int diff --git a/mypy/typeshed/stdlib/sre_parse.pyi b/mypy/typeshed/stdlib/sre_parse.pyi index 4c7b6157d8a9..2d00bedc2c81 100644 --- a/mypy/typeshed/stdlib/sre_parse.pyi +++ b/mypy/typeshed/stdlib/sre_parse.pyi @@ -1,26 +1,26 @@ import sys from sre_constants import _NamedIntConstant as _NIC, error as _Error -from typing import Any, Dict, FrozenSet, Iterable, List, Match, Optional, Pattern as _Pattern, Tuple, Union, overload +from typing import Any, Iterable, List, Match, Optional, Pattern as _Pattern, Tuple, Union, overload SPECIAL_CHARS: str REPEAT_CHARS: str -DIGITS: FrozenSet[str] -OCTDIGITS: FrozenSet[str] -HEXDIGITS: FrozenSet[str] -ASCIILETTERS: FrozenSet[str] -WHITESPACE: FrozenSet[str] -ESCAPES: Dict[str, Tuple[_NIC, int]] -CATEGORIES: Dict[str, Union[Tuple[_NIC, _NIC], Tuple[_NIC, List[Tuple[_NIC, _NIC]]]]] -FLAGS: Dict[str, int] +DIGITS: frozenset[str] +OCTDIGITS: frozenset[str] +HEXDIGITS: frozenset[str] +ASCIILETTERS: frozenset[str] +WHITESPACE: frozenset[str] +ESCAPES: dict[str, tuple[_NIC, int]] +CATEGORIES: dict[str, tuple[_NIC, _NIC] | tuple[_NIC, list[tuple[_NIC, _NIC]]]] +FLAGS: dict[str, int] GLOBAL_FLAGS: int class Verbose(Exception): ... class _State: flags: int - groupdict: Dict[str, int] - groupwidths: List[Optional[int]] - lookbehindgroups: Optional[int] + groupdict: dict[str, int] + groupwidths: list[int | None] + lookbehindgroups: int | None def __init__(self) -> None: ... @property def groups(self) -> int: ... @@ -42,20 +42,20 @@ _AvType = Union[_OpInType, _OpBranchType, Iterable[SubPattern], _OpGroupRefExist _CodeType = Tuple[_NIC, _AvType] class SubPattern: - data: List[_CodeType] - width: Optional[int] + data: list[_CodeType] + width: int | None if sys.version_info >= (3, 8): state: State - def __init__(self, state: State, data: Optional[List[_CodeType]] = ...) -> None: ... + def __init__(self, state: State, data: list[_CodeType] | None = ...) -> None: ... else: pattern: Pattern - def __init__(self, pattern: Pattern, data: Optional[List[_CodeType]] = ...) -> None: ... + def __init__(self, pattern: Pattern, data: list[_CodeType] | None = ...) -> None: ... def dump(self, level: int = ...) -> None: ... def __len__(self) -> int: ... - def __delitem__(self, index: Union[int, slice]) -> None: ... - def __getitem__(self, index: Union[int, slice]) -> Union[SubPattern, _CodeType]: ... - def __setitem__(self, index: Union[int, slice], code: _CodeType) -> None: ... + def __delitem__(self, index: int | slice) -> None: ... + def __getitem__(self, index: int | slice) -> SubPattern | _CodeType: ... + def __setitem__(self, index: int | slice, code: _CodeType) -> None: ... def insert(self, index: int, code: _CodeType) -> None: ... def append(self, code: _CodeType) -> None: ... def getwidth(self) -> int: ... @@ -65,10 +65,10 @@ class Tokenizer: string: Any decoded_string: str index: int - next: Optional[str] + next: str | None def __init__(self, string: Any) -> None: ... def match(self, char: str) -> bool: ... - def get(self) -> Optional[str]: ... + def get(self) -> str | None: ... def getwhile(self, n: int, charset: Iterable[str]) -> str: ... if sys.version_info >= (3, 8): def getuntil(self, terminator: str, name: str) -> str: ... @@ -80,19 +80,19 @@ class Tokenizer: def seek(self, index: int) -> None: ... def error(self, msg: str, offset: int = ...) -> _Error: ... -def fix_flags(src: Union[str, bytes], flags: int) -> int: ... +def fix_flags(src: str | bytes, flags: int) -> int: ... _TemplateType = Tuple[List[Tuple[int, int]], List[Optional[str]]] _TemplateByteType = Tuple[List[Tuple[int, int]], List[Optional[bytes]]] if sys.version_info >= (3, 8): - def parse(str: str, flags: int = ..., state: Optional[State] = ...) -> SubPattern: ... + def parse(str: str, flags: int = ..., state: State | None = ...) -> SubPattern: ... @overload def parse_template(source: str, state: _Pattern[Any]) -> _TemplateType: ... @overload def parse_template(source: bytes, state: _Pattern[Any]) -> _TemplateByteType: ... else: - def parse(str: str, flags: int = ..., pattern: Optional[Pattern] = ...) -> SubPattern: ... + def parse(str: str, flags: int = ..., pattern: Pattern | None = ...) -> SubPattern: ... @overload def parse_template(source: str, pattern: _Pattern[Any]) -> _TemplateType: ... @overload diff --git a/mypy/typeshed/stdlib/ssl.pyi b/mypy/typeshed/stdlib/ssl.pyi index 838211d959e5..689b083d764c 100644 --- a/mypy/typeshed/stdlib/ssl.pyi +++ b/mypy/typeshed/stdlib/ssl.pyi @@ -1,11 +1,9 @@ +import enum import socket import sys -from _typeshed import StrPath -from typing import Any, Callable, ClassVar, Dict, Iterable, List, NamedTuple, Optional, Set, Text, Tuple, Type, Union, overload -from typing_extensions import Literal - -if sys.version_info >= (3, 4): - import enum +from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer +from typing import Any, Callable, ClassVar, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Type, Union, overload +from typing_extensions import Literal, TypedDict _PCTRTT = Tuple[Tuple[str, str], ...] _PCTRTTT = Tuple[_PCTRTT, ...] @@ -14,11 +12,20 @@ _PeerCertRetType = Union[_PeerCertRetDictType, bytes, None] _EnumRetType = List[Tuple[bytes, str, Union[Set[str], bool]]] _PasswordType = Union[Callable[[], Union[str, bytes]], str, bytes] -if sys.version_info >= (3, 5): - _SC1ArgT = Union[SSLSocket, SSLObject] -else: - _SC1ArgT = SSLSocket -_SrvnmeCbType = Callable[[_SC1ArgT, Optional[str], SSLSocket], Optional[int]] +_SrvnmeCbType = Callable[[Union[SSLSocket, SSLObject], Optional[str], SSLSocket], Optional[int]] + +class _Cipher(TypedDict): + aead: bool + alg_bits: int + auth: str + description: str + digest: str | None + id: int + kea: str + name: str + protocol: str + strength_bits: int + symmetric: str class SSLError(OSError): library: str @@ -40,18 +47,22 @@ else: def wrap_socket( sock: socket.socket, - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., + keyfile: StrOrBytesPath | None = ..., + certfile: StrOrBytesPath | None = ..., server_side: bool = ..., cert_reqs: int = ..., ssl_version: int = ..., - ca_certs: Optional[str] = ..., + ca_certs: str | None = ..., do_handshake_on_connect: bool = ..., suppress_ragged_eofs: bool = ..., - ciphers: Optional[str] = ..., + ciphers: str | None = ..., ) -> SSLSocket: ... def create_default_context( - purpose: Any = ..., *, cafile: Optional[str] = ..., capath: Optional[str] = ..., cadata: Union[Text, bytes, None] = ... + purpose: Purpose = ..., + *, + cafile: StrOrBytesPath | None = ..., + capath: StrOrBytesPath | None = ..., + cadata: str | bytes | None = ..., ) -> SSLContext: ... if sys.version_info >= (3, 7): @@ -60,40 +71,38 @@ if sys.version_info >= (3, 7): *, cert_reqs: int = ..., check_hostname: bool = ..., - purpose: Any = ..., - certfile: Optional[str] = ..., - keyfile: Optional[str] = ..., - cafile: Optional[str] = ..., - capath: Optional[str] = ..., - cadata: Union[Text, bytes, None] = ..., + purpose: Purpose = ..., + certfile: StrOrBytesPath | None = ..., + keyfile: StrOrBytesPath | None = ..., + cafile: StrOrBytesPath | None = ..., + capath: StrOrBytesPath | None = ..., + cadata: str | bytes | None = ..., ) -> SSLContext: ... else: def _create_unverified_context( protocol: int = ..., *, - cert_reqs: Optional[int] = ..., + cert_reqs: int | None = ..., check_hostname: bool = ..., - purpose: Any = ..., - certfile: Optional[str] = ..., - keyfile: Optional[str] = ..., - cafile: Optional[str] = ..., - capath: Optional[str] = ..., - cadata: Union[Text, bytes, None] = ..., + purpose: Purpose = ..., + certfile: StrOrBytesPath | None = ..., + keyfile: StrOrBytesPath | None = ..., + cafile: StrOrBytesPath | None = ..., + capath: StrOrBytesPath | None = ..., + cadata: str | bytes | None = ..., ) -> SSLContext: ... _create_default_https_context: Callable[..., SSLContext] -if sys.version_info >= (3, 3): - def RAND_bytes(__num: int) -> bytes: ... - def RAND_pseudo_bytes(__num: int) -> Tuple[bytes, bool]: ... - +def RAND_bytes(__num: int) -> bytes: ... +def RAND_pseudo_bytes(__num: int) -> tuple[bytes, bool]: ... def RAND_status() -> bool: ... def RAND_egd(path: str) -> None: ... def RAND_add(__s: bytes, __entropy: float) -> None: ... def match_hostname(cert: _PeerCertRetType, hostname: str) -> None: ... def cert_time_to_seconds(cert_time: str) -> int: ... -def get_server_certificate(addr: Tuple[str, int], ssl_version: int = ..., ca_certs: Optional[str] = ...) -> str: ... +def get_server_certificate(addr: tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... def DER_cert_to_PEM_cert(der_cert_bytes: bytes) -> str: ... def PEM_cert_to_DER_cert(pem_cert_string: str) -> bytes: ... @@ -111,72 +120,83 @@ if sys.platform == "win32": def enum_certificates(store_name: str) -> _EnumRetType: ... def enum_crls(store_name: str) -> _EnumRetType: ... -CERT_NONE: int -CERT_OPTIONAL: int -CERT_REQUIRED: int - -VERIFY_DEFAULT: int -VERIFY_CRL_CHECK_LEAF: int -VERIFY_CRL_CHECK_CHAIN: int -VERIFY_X509_STRICT: int -VERIFY_X509_TRUSTED_FIRST: int - -PROTOCOL_SSLv23: int -PROTOCOL_SSLv2: int -PROTOCOL_SSLv3: int -PROTOCOL_TLSv1: int -PROTOCOL_TLSv1_1: int -PROTOCOL_TLSv1_2: int -PROTOCOL_TLS: int -if sys.version_info >= (3, 6): +class VerifyMode(enum.IntEnum): + CERT_NONE: int + CERT_OPTIONAL: int + CERT_REQUIRED: int + +CERT_NONE: VerifyMode +CERT_OPTIONAL: VerifyMode +CERT_REQUIRED: VerifyMode + +class VerifyFlags(enum.IntFlag): + VERIFY_DEFAULT: int + VERIFY_CRL_CHECK_LEAF: int + VERIFY_CRL_CHECK_CHAIN: int + VERIFY_X509_STRICT: int + VERIFY_X509_TRUSTED_FIRST: int + +VERIFY_DEFAULT: VerifyFlags +VERIFY_CRL_CHECK_LEAF: VerifyFlags +VERIFY_CRL_CHECK_CHAIN: VerifyFlags +VERIFY_X509_STRICT: VerifyFlags +VERIFY_X509_TRUSTED_FIRST: VerifyFlags + +class _SSLMethod(enum.IntEnum): + PROTOCOL_SSLv23: int + PROTOCOL_SSLv2: int + PROTOCOL_SSLv3: int + PROTOCOL_TLSv1: int + PROTOCOL_TLSv1_1: int + PROTOCOL_TLSv1_2: int + PROTOCOL_TLS: int PROTOCOL_TLS_CLIENT: int PROTOCOL_TLS_SERVER: int -if sys.version_info >= (3, 6): - class Options(enum.IntFlag): - OP_ALL: int - OP_NO_SSLv2: int - OP_NO_SSLv3: int - OP_NO_TLSv1: int - OP_NO_TLSv1_1: int - OP_NO_TLSv1_2: int - OP_NO_TLSv1_3: int - OP_CIPHER_SERVER_PREFERENCE: int - OP_SINGLE_DH_USE: int - OP_SINGLE_ECDH_USE: int - OP_NO_COMPRESSION: int - OP_NO_TICKET: int - if sys.version_info >= (3, 7): - OP_NO_RENEGOTIATION: int - if sys.version_info >= (3, 8): - OP_ENABLE_MIDDLEBOX_COMPAT: int - OP_ALL: Options - OP_NO_SSLv2: Options - OP_NO_SSLv3: Options - OP_NO_TLSv1: Options - OP_NO_TLSv1_1: Options - OP_NO_TLSv1_2: Options - OP_NO_TLSv1_3: Options - OP_CIPHER_SERVER_PREFERENCE: Options - OP_SINGLE_DH_USE: Options - OP_SINGLE_ECDH_USE: Options - OP_NO_COMPRESSION: Options - OP_NO_TICKET: Options - if sys.version_info >= (3, 7): - OP_NO_RENEGOTIATION: Options - if sys.version_info >= (3, 8): - OP_ENABLE_MIDDLEBOX_COMPAT: Options -else: +PROTOCOL_SSLv23: _SSLMethod +PROTOCOL_SSLv2: _SSLMethod +PROTOCOL_SSLv3: _SSLMethod +PROTOCOL_TLSv1: _SSLMethod +PROTOCOL_TLSv1_1: _SSLMethod +PROTOCOL_TLSv1_2: _SSLMethod +PROTOCOL_TLS: _SSLMethod +PROTOCOL_TLS_CLIENT: _SSLMethod +PROTOCOL_TLS_SERVER: _SSLMethod + +class Options(enum.IntFlag): OP_ALL: int OP_NO_SSLv2: int OP_NO_SSLv3: int OP_NO_TLSv1: int OP_NO_TLSv1_1: int OP_NO_TLSv1_2: int + OP_NO_TLSv1_3: int OP_CIPHER_SERVER_PREFERENCE: int OP_SINGLE_DH_USE: int OP_SINGLE_ECDH_USE: int OP_NO_COMPRESSION: int + OP_NO_TICKET: int + if sys.version_info >= (3, 7): + OP_NO_RENEGOTIATION: int + if sys.version_info >= (3, 8): + OP_ENABLE_MIDDLEBOX_COMPAT: int + +OP_ALL: Options +OP_NO_SSLv2: Options +OP_NO_SSLv3: Options +OP_NO_TLSv1: Options +OP_NO_TLSv1_1: Options +OP_NO_TLSv1_2: Options +OP_NO_TLSv1_3: Options +OP_CIPHER_SERVER_PREFERENCE: Options +OP_SINGLE_DH_USE: Options +OP_SINGLE_ECDH_USE: Options +OP_NO_COMPRESSION: Options +OP_NO_TICKET: Options +if sys.version_info >= (3, 7): + OP_NO_RENEGOTIATION: Options +if sys.version_info >= (3, 8): + OP_ENABLE_MIDDLEBOX_COMPAT: Options if sys.version_info >= (3, 7): HAS_NEVER_CHECK_COMMON_NAME: bool @@ -190,118 +210,146 @@ HAS_ALPN: bool HAS_ECDH: bool HAS_SNI: bool HAS_NPN: bool -CHANNEL_BINDING_TYPES: List[str] +CHANNEL_BINDING_TYPES: list[str] OPENSSL_VERSION: str -OPENSSL_VERSION_INFO: Tuple[int, int, int, int, int] +OPENSSL_VERSION_INFO: tuple[int, int, int, int, int] OPENSSL_VERSION_NUMBER: int -ALERT_DESCRIPTION_HANDSHAKE_FAILURE: int -ALERT_DESCRIPTION_INTERNAL_ERROR: int -ALERT_DESCRIPTION_ACCESS_DENIED: int -ALERT_DESCRIPTION_BAD_CERTIFICATE: int -ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE: int -ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE: int -ALERT_DESCRIPTION_BAD_RECORD_MAC: int -ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: int -ALERT_DESCRIPTION_CERTIFICATE_REVOKED: int -ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: int -ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE: int -ALERT_DESCRIPTION_CLOSE_NOTIFY: int -ALERT_DESCRIPTION_DECODE_ERROR: int -ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: int -ALERT_DESCRIPTION_DECRYPT_ERROR: int -ALERT_DESCRIPTION_ILLEGAL_PARAMETER: int -ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: int -ALERT_DESCRIPTION_NO_RENEGOTIATION: int -ALERT_DESCRIPTION_PROTOCOL_VERSION: int -ALERT_DESCRIPTION_RECORD_OVERFLOW: int -ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: int -ALERT_DESCRIPTION_UNKNOWN_CA: int -ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY: int -ALERT_DESCRIPTION_UNRECOGNIZED_NAME: int -ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: int -ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: int -ALERT_DESCRIPTION_USER_CANCELLED: int +class AlertDescription(enum.IntEnum): + ALERT_DESCRIPTION_ACCESS_DENIED: int + ALERT_DESCRIPTION_BAD_CERTIFICATE: int + ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE: int + ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE: int + ALERT_DESCRIPTION_BAD_RECORD_MAC: int + ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: int + ALERT_DESCRIPTION_CERTIFICATE_REVOKED: int + ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: int + ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE: int + ALERT_DESCRIPTION_CLOSE_NOTIFY: int + ALERT_DESCRIPTION_DECODE_ERROR: int + ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: int + ALERT_DESCRIPTION_DECRYPT_ERROR: int + ALERT_DESCRIPTION_HANDSHAKE_FAILURE: int + ALERT_DESCRIPTION_ILLEGAL_PARAMETER: int + ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: int + ALERT_DESCRIPTION_INTERNAL_ERROR: int + ALERT_DESCRIPTION_NO_RENEGOTIATION: int + ALERT_DESCRIPTION_PROTOCOL_VERSION: int + ALERT_DESCRIPTION_RECORD_OVERFLOW: int + ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: int + ALERT_DESCRIPTION_UNKNOWN_CA: int + ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY: int + ALERT_DESCRIPTION_UNRECOGNIZED_NAME: int + ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: int + ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: int + ALERT_DESCRIPTION_USER_CANCELLED: int + +ALERT_DESCRIPTION_HANDSHAKE_FAILURE: AlertDescription +ALERT_DESCRIPTION_INTERNAL_ERROR: AlertDescription +ALERT_DESCRIPTION_ACCESS_DENIED: AlertDescription +ALERT_DESCRIPTION_BAD_CERTIFICATE: AlertDescription +ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE: AlertDescription +ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE: AlertDescription +ALERT_DESCRIPTION_BAD_RECORD_MAC: AlertDescription +ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: AlertDescription +ALERT_DESCRIPTION_CERTIFICATE_REVOKED: AlertDescription +ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: AlertDescription +ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE: AlertDescription +ALERT_DESCRIPTION_CLOSE_NOTIFY: AlertDescription +ALERT_DESCRIPTION_DECODE_ERROR: AlertDescription +ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: AlertDescription +ALERT_DESCRIPTION_DECRYPT_ERROR: AlertDescription +ALERT_DESCRIPTION_ILLEGAL_PARAMETER: AlertDescription +ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: AlertDescription +ALERT_DESCRIPTION_NO_RENEGOTIATION: AlertDescription +ALERT_DESCRIPTION_PROTOCOL_VERSION: AlertDescription +ALERT_DESCRIPTION_RECORD_OVERFLOW: AlertDescription +ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: AlertDescription +ALERT_DESCRIPTION_UNKNOWN_CA: AlertDescription +ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY: AlertDescription +ALERT_DESCRIPTION_UNRECOGNIZED_NAME: AlertDescription +ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: AlertDescription +ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: AlertDescription +ALERT_DESCRIPTION_USER_CANCELLED: AlertDescription class _ASN1Object(NamedTuple): nid: int shortname: str longname: str oid: str + @classmethod + def fromnid(cls: Type[Self], nid: int) -> Self: ... + @classmethod + def fromname(cls: Type[Self], name: str) -> Self: ... -if sys.version_info >= (3, 4): - class Purpose(_ASN1Object, enum.Enum): - SERVER_AUTH: _ASN1Object - CLIENT_AUTH: _ASN1Object - -else: - class Purpose(_ASN1Object): - SERVER_AUTH: ClassVar[Purpose] - CLIENT_AUTH: ClassVar[Purpose] +class Purpose(_ASN1Object, enum.Enum): + SERVER_AUTH: _ASN1Object + CLIENT_AUTH: _ASN1Object class SSLSocket(socket.socket): context: SSLContext server_side: bool - server_hostname: Optional[str] - if sys.version_info >= (3, 6): - session: Optional[SSLSession] - session_reused: Optional[bool] + server_hostname: str | None + session: SSLSession | None + session_reused: bool | None if sys.version_info < (3, 7): def __init__( self, - sock: Optional[socket.socket] = ..., - keyfile: Optional[str] = ..., - certfile: Optional[str] = ..., + sock: socket.socket | None = ..., + keyfile: str | None = ..., + certfile: str | None = ..., server_side: bool = ..., cert_reqs: int = ..., ssl_version: int = ..., - ca_certs: Optional[str] = ..., + ca_certs: str | None = ..., do_handshake_on_connect: bool = ..., family: int = ..., type: int = ..., proto: int = ..., - fileno: Optional[int] = ..., + fileno: int | None = ..., suppress_ragged_eofs: bool = ..., - npn_protocols: Optional[Iterable[str]] = ..., - ciphers: Optional[str] = ..., - server_hostname: Optional[str] = ..., - _context: Optional[SSLContext] = ..., - _session: Optional[Any] = ..., + npn_protocols: Iterable[str] | None = ..., + ciphers: str | None = ..., + server_hostname: str | None = ..., + _context: SSLContext | None = ..., + _session: Any | None = ..., ) -> None: ... else: def __init__(self, *args: Any, **kwargs: Any) -> None: ... - def connect(self, addr: Union[socket._Address, bytes]) -> None: ... - def connect_ex(self, addr: Union[socket._Address, bytes]) -> int: ... + def connect(self, addr: socket._Address | bytes) -> None: ... + def connect_ex(self, addr: socket._Address | bytes) -> int: ... def recv(self, buflen: int = ..., flags: int = ...) -> bytes: ... - def recv_into(self, buffer: socket._WriteBuffer, nbytes: Optional[int] = ..., flags: int = ...) -> int: ... + def recv_into(self, buffer: WriteableBuffer, nbytes: int | None = ..., flags: int = ...) -> int: ... def recvfrom(self, buflen: int = ..., flags: int = ...) -> tuple[bytes, socket._RetAddress]: ... def recvfrom_into( - self, buffer: socket._WriteBuffer, nbytes: Optional[int] = ..., flags: int = ... + self, buffer: WriteableBuffer, nbytes: int | None = ..., flags: int = ... ) -> tuple[int, socket._RetAddress]: ... + def send(self, data: ReadableBuffer, flags: int = ...) -> int: ... + def sendall(self, data: ReadableBuffer, flags: int = ...) -> None: ... @overload - def sendto(self, data: bytes, flags_or_addr: socket._Address) -> int: ... + def sendto(self, data: ReadableBuffer, flags_or_addr: socket._Address) -> int: ... @overload - def sendto(self, data: bytes, flags_or_addr: Union[int, socket._Address], addr: Optional[socket._Address] = ...) -> int: ... - def read(self, len: int = ..., buffer: Optional[bytearray] = ...) -> bytes: ... + def sendto(self, data: ReadableBuffer, flags_or_addr: int | socket._Address, addr: socket._Address | None = ...) -> int: ... + def shutdown(self, how: int) -> None: ... + def read(self, len: int = ..., buffer: bytearray | None = ...) -> bytes: ... def write(self, data: bytes) -> int: ... def do_handshake(self, block: bool = ...) -> None: ... # block is undocumented @overload - def getpeercert(self, binary_form: Literal[False] = ...) -> Optional[_PeerCertRetDictType]: ... + def getpeercert(self, binary_form: Literal[False] = ...) -> _PeerCertRetDictType | None: ... @overload - def getpeercert(self, binary_form: Literal[True]) -> Optional[bytes]: ... + def getpeercert(self, binary_form: Literal[True]) -> bytes | None: ... @overload def getpeercert(self, binary_form: bool) -> _PeerCertRetType: ... - def cipher(self) -> Optional[Tuple[str, str, int]]: ... - if sys.version_info >= (3, 5): - def shared_ciphers(self) -> Optional[List[Tuple[str, str, int]]]: ... - def compression(self) -> Optional[str]: ... - def get_channel_binding(self, cb_type: str = ...) -> Optional[bytes]: ... - def selected_alpn_protocol(self) -> Optional[str]: ... - def selected_npn_protocol(self) -> Optional[str]: ... - def accept(self) -> Tuple[SSLSocket, socket._RetAddress]: ... + def cipher(self) -> tuple[str, str, int] | None: ... + def shared_ciphers(self) -> list[tuple[str, str, int]] | None: ... + def compression(self) -> str | None: ... + def get_channel_binding(self, cb_type: str = ...) -> bytes | None: ... + def selected_alpn_protocol(self) -> str | None: ... + def selected_npn_protocol(self) -> str | None: ... + def accept(self) -> tuple[SSLSocket, socket._RetAddress]: ... def unwrap(self) -> socket.socket: ... - def version(self) -> Optional[str]: ... + def version(self) -> str | None: ... def pending(self) -> int: ... if sys.version_info >= (3, 8): def verify_client_post_handshake(self) -> None: ... @@ -318,154 +366,127 @@ if sys.version_info >= (3, 7): class SSLContext: check_hostname: bool - if sys.version_info >= (3, 6): - options: Options - else: - options: int + options: Options + verify_flags: VerifyFlags + verify_mode: VerifyMode + @property + def protocol(self) -> _SSLMethod: ... + if sys.version_info >= (3, 7): + hostname_checks_common_name: bool + maximum_version: TLSVersion + minimum_version: TLSVersion + sni_callback: Callable[[SSLObject, str, SSLContext], None | int] | None + sslobject_class: ClassVar[Type[SSLObject]] + sslsocket_class: ClassVar[Type[SSLSocket]] if sys.version_info >= (3, 8): + keylog_filename: str post_handshake_auth: bool - if sys.version_info >= (3, 5): - def __new__(cls, protocol: int = ..., *args: Any, **kwargs: Any) -> SSLContext: ... - else: - def __new__(cls, protocol: int, *args: Any, **kwargs: Any) -> SSLContext: ... - @property - def protocol(self) -> int: ... - verify_flags: int - verify_mode: int - if sys.version_info >= (3, 5): - def __init__(self, protocol: int = ...) -> None: ... - else: - def __init__(self, protocol: int) -> None: ... - def cert_store_stats(self) -> Dict[str, int]: ... + def __new__(cls, protocol: int = ..., *args: Any, **kwargs: Any) -> SSLContext: ... + def __init__(self, protocol: int = ...) -> None: ... + def cert_store_stats(self) -> dict[str, int]: ... def load_cert_chain( - self, certfile: StrPath, keyfile: Optional[StrPath] = ..., password: Optional[_PasswordType] = ... + self, certfile: StrOrBytesPath, keyfile: StrOrBytesPath | None = ..., password: _PasswordType | None = ... ) -> None: ... def load_default_certs(self, purpose: Purpose = ...) -> None: ... def load_verify_locations( - self, cafile: Optional[StrPath] = ..., capath: Optional[StrPath] = ..., cadata: Union[Text, bytes, None] = ... + self, cafile: StrOrBytesPath | None = ..., capath: StrOrBytesPath | None = ..., cadata: str | bytes | None = ... ) -> None: ... - def get_ca_certs(self, binary_form: bool = ...) -> Union[List[_PeerCertRetDictType], List[bytes]]: ... + def get_ca_certs(self, binary_form: bool = ...) -> list[_PeerCertRetDictType] | list[bytes]: ... + def get_ciphers(self) -> list[_Cipher]: ... def set_default_verify_paths(self) -> None: ... def set_ciphers(self, __cipherlist: str) -> None: ... def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None: ... - if sys.version_info >= (3, 7): - sni_callback: Optional[Callable[[SSLObject, str, SSLContext], Union[None, int]]] - sslobject_class: Type[SSLObject] def set_npn_protocols(self, npn_protocols: Iterable[str]) -> None: ... if sys.version_info >= (3, 7): - def set_servername_callback(self, server_name_callback: Optional[_SrvnmeCbType]) -> None: ... + def set_servername_callback(self, server_name_callback: _SrvnmeCbType | None) -> None: ... else: - def set_servername_callback(self, __method: Optional[_SrvnmeCbType]) -> None: ... + def set_servername_callback(self, __method: _SrvnmeCbType | None) -> None: ... def load_dh_params(self, __path: str) -> None: ... def set_ecdh_curve(self, __name: str) -> None: ... - if sys.version_info >= (3, 6): - def wrap_socket( - self, - sock: socket.socket, - server_side: bool = ..., - do_handshake_on_connect: bool = ..., - suppress_ragged_eofs: bool = ..., - server_hostname: Optional[str] = ..., - session: Optional[SSLSession] = ..., - ) -> SSLSocket: ... - else: - def wrap_socket( - self, - sock: socket.socket, - server_side: bool = ..., - do_handshake_on_connect: bool = ..., - suppress_ragged_eofs: bool = ..., - server_hostname: Optional[str] = ..., - ) -> SSLSocket: ... - if sys.version_info >= (3, 6): - def wrap_bio( - self, - incoming: MemoryBIO, - outgoing: MemoryBIO, - server_side: bool = ..., - server_hostname: Optional[str] = ..., - session: Optional[SSLSession] = ..., - ) -> SSLObject: ... - elif sys.version_info >= (3, 5): - def wrap_bio( - self, incoming: MemoryBIO, outgoing: MemoryBIO, server_side: bool = ..., server_hostname: Optional[str] = ... - ) -> SSLObject: ... - def session_stats(self) -> Dict[str, int]: ... + def wrap_socket( + self, + sock: socket.socket, + server_side: bool = ..., + do_handshake_on_connect: bool = ..., + suppress_ragged_eofs: bool = ..., + server_hostname: str | None = ..., + session: SSLSession | None = ..., + ) -> SSLSocket: ... + def wrap_bio( + self, + incoming: MemoryBIO, + outgoing: MemoryBIO, + server_side: bool = ..., + server_hostname: str | None = ..., + session: SSLSession | None = ..., + ) -> SSLObject: ... + def session_stats(self) -> dict[str, int]: ... + +class SSLObject: + context: SSLContext + server_side: bool + server_hostname: str | None + session: SSLSession | None + session_reused: bool if sys.version_info >= (3, 7): - hostname_checks_common_name: bool - maximum_version: TLSVersion - minimum_version: TLSVersion + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + else: + def __init__(self, sslobj: Any, owner: SSLSocket | SSLObject | None = ..., session: Any | None = ...) -> None: ... + def read(self, len: int = ..., buffer: bytearray | None = ...) -> bytes: ... + def write(self, data: bytes) -> int: ... + @overload + def getpeercert(self, binary_form: Literal[False] = ...) -> _PeerCertRetDictType | None: ... + @overload + def getpeercert(self, binary_form: Literal[True]) -> bytes | None: ... + @overload + def getpeercert(self, binary_form: bool) -> _PeerCertRetType: ... + def selected_alpn_protocol(self) -> str | None: ... + def selected_npn_protocol(self) -> str | None: ... + def cipher(self) -> tuple[str, str, int] | None: ... + def shared_ciphers(self) -> list[tuple[str, str, int]] | None: ... + def compression(self) -> str | None: ... + def pending(self) -> int: ... + def do_handshake(self) -> None: ... + def unwrap(self) -> None: ... + def version(self) -> str | None: ... + def get_channel_binding(self, cb_type: str = ...) -> bytes | None: ... + if sys.version_info >= (3, 8): + def verify_client_post_handshake(self) -> None: ... -if sys.version_info >= (3, 5): - class SSLObject: - context: SSLContext - server_side: bool - server_hostname: Optional[str] - if sys.version_info >= (3, 6): - session: Optional[SSLSession] - session_reused: bool - if sys.version_info >= (3, 7): - def __init__(self, *args: Any, **kwargs: Any) -> None: ... - else: - def __init__( - self, sslobj: Any, owner: Optional[Union[SSLSocket, SSLObject]] = ..., session: Optional[Any] = ... - ) -> None: ... - def read(self, len: int = ..., buffer: Optional[bytearray] = ...) -> bytes: ... - def write(self, data: bytes) -> int: ... - @overload - def getpeercert(self, binary_form: Literal[False] = ...) -> Optional[_PeerCertRetDictType]: ... - @overload - def getpeercert(self, binary_form: Literal[True]) -> Optional[bytes]: ... - @overload - def getpeercert(self, binary_form: bool) -> _PeerCertRetType: ... - def selected_alpn_protocol(self) -> Optional[str]: ... - def selected_npn_protocol(self) -> Optional[str]: ... - def cipher(self) -> Optional[Tuple[str, str, int]]: ... - def shared_ciphers(self) -> Optional[List[Tuple[str, str, int]]]: ... - def compression(self) -> Optional[str]: ... - def pending(self) -> int: ... - def do_handshake(self) -> None: ... - def unwrap(self) -> None: ... - def version(self) -> Optional[str]: ... - def get_channel_binding(self, cb_type: str = ...) -> Optional[bytes]: ... - if sys.version_info >= (3, 8): - def verify_client_post_handshake(self) -> None: ... - class MemoryBIO: - pending: int - eof: bool - def read(self, __size: int = ...) -> bytes: ... - def write(self, __buf: bytes) -> int: ... - def write_eof(self) -> None: ... - -if sys.version_info >= (3, 6): - class SSLSession: - id: bytes - time: int - timeout: int - ticket_lifetime_hint: int - has_ticket: bool - class VerifyFlags(enum.IntFlag): - VERIFY_DEFAULT: int - VERIFY_CRL_CHECK_LEAF: int - VERIFY_CRL_CHECK_CHAIN: int - VERIFY_X509_STRICT: int - VERIFY_X509_TRUSTED_FIRST: int - class VerifyMode(enum.IntEnum): - CERT_NONE: int - CERT_OPTIONAL: int - CERT_REQUIRED: int - -# TODO below documented in cpython but not in docs.python.org -# taken from python 3.4 -SSL_ERROR_EOF: int -SSL_ERROR_INVALID_ERROR_CODE: int -SSL_ERROR_SSL: int -SSL_ERROR_SYSCALL: int -SSL_ERROR_WANT_CONNECT: int -SSL_ERROR_WANT_READ: int -SSL_ERROR_WANT_WRITE: int -SSL_ERROR_WANT_X509_LOOKUP: int -SSL_ERROR_ZERO_RETURN: int +class MemoryBIO: + pending: int + eof: bool + def read(self, __size: int = ...) -> bytes: ... + def write(self, __buf: bytes) -> int: ... + def write_eof(self) -> None: ... + +class SSLSession: + id: bytes + time: int + timeout: int + ticket_lifetime_hint: int + has_ticket: bool + +class SSLErrorNumber(enum.IntEnum): + SSL_ERROR_EOF: int + SSL_ERROR_INVALID_ERROR_CODE: int + SSL_ERROR_SSL: int + SSL_ERROR_SYSCALL: int + SSL_ERROR_WANT_CONNECT: int + SSL_ERROR_WANT_READ: int + SSL_ERROR_WANT_WRITE: int + SSL_ERROR_WANT_X509_LOOKUP: int + SSL_ERROR_ZERO_RETURN: int + +SSL_ERROR_EOF: SSLErrorNumber # undocumented +SSL_ERROR_INVALID_ERROR_CODE: SSLErrorNumber # undocumented +SSL_ERROR_SSL: SSLErrorNumber # undocumented +SSL_ERROR_SYSCALL: SSLErrorNumber # undocumented +SSL_ERROR_WANT_CONNECT: SSLErrorNumber # undocumented +SSL_ERROR_WANT_READ: SSLErrorNumber # undocumented +SSL_ERROR_WANT_WRITE: SSLErrorNumber # undocumented +SSL_ERROR_WANT_X509_LOOKUP: SSLErrorNumber # undocumented +SSL_ERROR_ZERO_RETURN: SSLErrorNumber # undocumented def get_protocol_name(protocol_code: int) -> str: ... diff --git a/mypy/typeshed/stdlib/stat.pyi b/mypy/typeshed/stdlib/stat.pyi index 6fd2bc0814f0..d6450fe77817 100644 --- a/mypy/typeshed/stdlib/stat.pyi +++ b/mypy/typeshed/stdlib/stat.pyi @@ -9,6 +9,9 @@ def S_ISLNK(mode: int) -> bool: ... def S_ISSOCK(mode: int) -> bool: ... def S_IMODE(mode: int) -> int: ... def S_IFMT(mode: int) -> int: ... +def S_ISDOOR(mode: int) -> int: ... +def S_ISPORT(mode: int) -> int: ... +def S_ISWHT(mode: int) -> int: ... def filemode(mode: int) -> str: ... ST_MODE: int @@ -29,6 +32,9 @@ S_IFBLK: int S_IFDIR: int S_IFCHR: int S_IFIFO: int +S_IFDOOR: int +S_IFPORT: int +S_IFWHT: int S_ISUID: int S_ISGID: int S_ISVTX: int diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index 4435bf8a001b..ec3574ab12b1 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import SupportsLessThanT from decimal import Decimal from fractions import Fraction -from typing import Any, Hashable, Iterable, List, NamedTuple, Optional, Sequence, SupportsFloat, Type, TypeVar, Union +from typing import Any, Hashable, Iterable, NamedTuple, Sequence, SupportsFloat, Type, TypeVar, Union _T = TypeVar("_T") # Most functions in this module accept homogeneous collections of one of these types @@ -21,7 +21,7 @@ if sys.version_info >= (3, 8): def mean(data: Iterable[_NumberT]) -> _NumberT: ... if sys.version_info >= (3, 10): - def harmonic_mean(data: Iterable[_NumberT], weights: Optional[Iterable[_Number]] = ...) -> _NumberT: ... + def harmonic_mean(data: Iterable[_NumberT], weights: Iterable[_Number] | None = ...) -> _NumberT: ... else: def harmonic_mean(data: Iterable[_NumberT]) -> _NumberT: ... @@ -33,16 +33,16 @@ def median_grouped(data: Iterable[_NumberT], interval: _NumberT = ...) -> _Numbe def mode(data: Iterable[_HashableT]) -> _HashableT: ... if sys.version_info >= (3, 8): - def multimode(data: Iterable[_HashableT]) -> List[_HashableT]: ... + def multimode(data: Iterable[_HashableT]) -> list[_HashableT]: ... -def pstdev(data: Iterable[_NumberT], mu: Optional[_NumberT] = ...) -> _NumberT: ... -def pvariance(data: Iterable[_NumberT], mu: Optional[_NumberT] = ...) -> _NumberT: ... +def pstdev(data: Iterable[_NumberT], mu: _NumberT | None = ...) -> _NumberT: ... +def pvariance(data: Iterable[_NumberT], mu: _NumberT | None = ...) -> _NumberT: ... if sys.version_info >= (3, 8): - def quantiles(data: Iterable[_NumberT], *, n: int = ..., method: str = ...) -> List[_NumberT]: ... + def quantiles(data: Iterable[_NumberT], *, n: int = ..., method: str = ...) -> list[_NumberT]: ... -def stdev(data: Iterable[_NumberT], xbar: Optional[_NumberT] = ...) -> _NumberT: ... -def variance(data: Iterable[_NumberT], xbar: Optional[_NumberT] = ...) -> _NumberT: ... +def stdev(data: Iterable[_NumberT], xbar: _NumberT | None = ...) -> _NumberT: ... +def variance(data: Iterable[_NumberT], xbar: _NumberT | None = ...) -> _NumberT: ... if sys.version_info >= (3, 8): class NormalDist: @@ -59,22 +59,22 @@ if sys.version_info >= (3, 8): def variance(self) -> float: ... @classmethod def from_samples(cls: Type[_T], data: Iterable[SupportsFloat]) -> _T: ... - def samples(self, n: int, *, seed: Optional[Any] = ...) -> List[float]: ... + def samples(self, n: int, *, seed: Any | None = ...) -> list[float]: ... def pdf(self, x: float) -> float: ... def cdf(self, x: float) -> float: ... def inv_cdf(self, p: float) -> float: ... def overlap(self, other: NormalDist) -> float: ... - def quantiles(self, n: int = ...) -> List[float]: ... + def quantiles(self, n: int = ...) -> list[float]: ... if sys.version_info >= (3, 9): def zscore(self, x: float) -> float: ... - def __add__(self, x2: Union[float, NormalDist]) -> NormalDist: ... - def __sub__(self, x2: Union[float, NormalDist]) -> NormalDist: ... + def __add__(self, x2: float | NormalDist) -> NormalDist: ... + def __sub__(self, x2: float | NormalDist) -> NormalDist: ... def __mul__(self, x2: float) -> NormalDist: ... def __truediv__(self, x2: float) -> NormalDist: ... def __pos__(self) -> NormalDist: ... def __neg__(self) -> NormalDist: ... __radd__ = __add__ - def __rsub__(self, x2: Union[float, NormalDist]) -> NormalDist: ... + def __rsub__(self, x2: float | NormalDist) -> NormalDist: ... __rmul__ = __mul__ def __hash__(self) -> int: ... @@ -82,6 +82,6 @@ if sys.version_info >= (3, 10): def correlation(__x: Sequence[_Number], __y: Sequence[_Number]) -> float: ... def covariance(__x: Sequence[_Number], __y: Sequence[_Number]) -> float: ... class LinearRegression(NamedTuple): - intercept: float slope: float + intercept: float def linear_regression(__regressor: Sequence[_Number], __dependent_variable: Sequence[_Number]) -> LinearRegression: ... diff --git a/mypy/typeshed/stdlib/string.pyi b/mypy/typeshed/stdlib/string.pyi index a39e64dd32ca..374d59959ac9 100644 --- a/mypy/typeshed/stdlib/string.pyi +++ b/mypy/typeshed/stdlib/string.pyi @@ -1,4 +1,11 @@ -from typing import Any, Iterable, Mapping, Optional, Sequence, Tuple, Union +import sys +from re import RegexFlag +from typing import Any, Iterable, Mapping, Sequence + +if sys.version_info >= (3, 8): + from re import Pattern +else: + from typing import Pattern ascii_letters: str ascii_lowercase: str @@ -10,10 +17,15 @@ punctuation: str printable: str whitespace: str -def capwords(s: str, sep: Optional[str] = ...) -> str: ... +def capwords(s: str, sep: str | None = ...) -> str: ... class Template: template: str + delimiter: str + idpattern: str + braceidpattern: str | None + flags: RegexFlag + pattern: Pattern[str] def __init__(self, template: str) -> None: ... def substitute(self, __mapping: Mapping[str, object] = ..., **kwds: object) -> str: ... def safe_substitute(self, __mapping: Mapping[str, object] = ..., **kwds: object) -> str: ... @@ -22,9 +34,9 @@ class Template: class Formatter: def format(self, __format_string: str, *args: Any, **kwargs: Any) -> str: ... def vformat(self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> str: ... - def parse(self, format_string: str) -> Iterable[Tuple[str, Optional[str], Optional[str], Optional[str]]]: ... + def parse(self, format_string: str) -> Iterable[tuple[str, str | None, str | None, str | None]]: ... def get_field(self, field_name: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... - def get_value(self, key: Union[int, str], args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... - def check_unused_args(self, used_args: Sequence[Union[int, str]], args: Sequence[Any], kwargs: Mapping[str, Any]) -> None: ... + def get_value(self, key: int | str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... + def check_unused_args(self, used_args: Sequence[int | str], args: Sequence[Any], kwargs: Mapping[str, Any]) -> None: ... def format_field(self, value: Any, format_spec: str) -> Any: ... def convert_field(self, value: Any, conversion: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/stringprep.pyi b/mypy/typeshed/stdlib/stringprep.pyi index 604fd2f2cae7..cbc562d460f6 100644 --- a/mypy/typeshed/stdlib/stringprep.pyi +++ b/mypy/typeshed/stdlib/stringprep.pyi @@ -1,21 +1,19 @@ -from typing import Text - -def in_table_a1(code: Text) -> bool: ... -def in_table_b1(code: Text) -> bool: ... -def map_table_b3(code: Text) -> Text: ... -def map_table_b2(a: Text) -> Text: ... -def in_table_c11(code: Text) -> bool: ... -def in_table_c12(code: Text) -> bool: ... -def in_table_c11_c12(code: Text) -> bool: ... -def in_table_c21(code: Text) -> bool: ... -def in_table_c22(code: Text) -> bool: ... -def in_table_c21_c22(code: Text) -> bool: ... -def in_table_c3(code: Text) -> bool: ... -def in_table_c4(code: Text) -> bool: ... -def in_table_c5(code: Text) -> bool: ... -def in_table_c6(code: Text) -> bool: ... -def in_table_c7(code: Text) -> bool: ... -def in_table_c8(code: Text) -> bool: ... -def in_table_c9(code: Text) -> bool: ... -def in_table_d1(code: Text) -> bool: ... -def in_table_d2(code: Text) -> bool: ... +def in_table_a1(code: str) -> bool: ... +def in_table_b1(code: str) -> bool: ... +def map_table_b3(code: str) -> str: ... +def map_table_b2(a: str) -> str: ... +def in_table_c11(code: str) -> bool: ... +def in_table_c12(code: str) -> bool: ... +def in_table_c11_c12(code: str) -> bool: ... +def in_table_c21(code: str) -> bool: ... +def in_table_c22(code: str) -> bool: ... +def in_table_c21_c22(code: str) -> bool: ... +def in_table_c3(code: str) -> bool: ... +def in_table_c4(code: str) -> bool: ... +def in_table_c5(code: str) -> bool: ... +def in_table_c6(code: str) -> bool: ... +def in_table_c7(code: str) -> bool: ... +def in_table_c8(code: str) -> bool: ... +def in_table_c9(code: str) -> bool: ... +def in_table_d1(code: str) -> bool: ... +def in_table_d2(code: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/struct.pyi b/mypy/typeshed/stdlib/struct.pyi index 096f8b7b85ca..d7c9cbef7dce 100644 --- a/mypy/typeshed/stdlib/struct.pyi +++ b/mypy/typeshed/stdlib/struct.pyi @@ -1,27 +1,15 @@ import sys -from array import array -from mmap import mmap -from typing import Any, Iterator, Text, Tuple, Union +from _typeshed import ReadableBuffer, WriteableBuffer +from typing import Any, Iterator, Tuple class error(Exception): ... -_FmtType = Union[bytes, Text] -if sys.version_info >= (3,): - _BufferType = Union[array[int], bytes, bytearray, memoryview, mmap] - _WriteBufferType = Union[array[Any], bytearray, memoryview, mmap] -else: - _BufferType = Union[array[int], bytes, bytearray, buffer, memoryview, mmap] - _WriteBufferType = Union[array[Any], bytearray, buffer, memoryview, mmap] - -def pack(fmt: _FmtType, *v: Any) -> bytes: ... -def pack_into(fmt: _FmtType, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... -def unpack(__format: _FmtType, __buffer: _BufferType) -> Tuple[Any, ...]: ... -def unpack_from(__format: _FmtType, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... - -if sys.version_info >= (3, 4): - def iter_unpack(__format: _FmtType, __buffer: _BufferType) -> Iterator[Tuple[Any, ...]]: ... - -def calcsize(__format: _FmtType) -> int: ... +def pack(fmt: str | bytes, *v: Any) -> bytes: ... +def pack_into(fmt: str | bytes, buffer: WriteableBuffer, offset: int, *v: Any) -> None: ... +def unpack(__format: str | bytes, __buffer: ReadableBuffer) -> Tuple[Any, ...]: ... +def unpack_from(__format: str | bytes, buffer: ReadableBuffer, offset: int = ...) -> Tuple[Any, ...]: ... +def iter_unpack(__format: str | bytes, __buffer: ReadableBuffer) -> Iterator[Tuple[Any, ...]]: ... +def calcsize(__format: str | bytes) -> int: ... class Struct: if sys.version_info >= (3, 7): @@ -29,10 +17,9 @@ class Struct: else: format: bytes size: int - def __init__(self, format: _FmtType) -> None: ... + def __init__(self, format: str | bytes) -> None: ... def pack(self, *v: Any) -> bytes: ... - def pack_into(self, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... - def unpack(self, __buffer: _BufferType) -> Tuple[Any, ...]: ... - def unpack_from(self, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... - if sys.version_info >= (3, 4): - def iter_unpack(self, __buffer: _BufferType) -> Iterator[Tuple[Any, ...]]: ... + def pack_into(self, buffer: WriteableBuffer, offset: int, *v: Any) -> None: ... + def unpack(self, __buffer: ReadableBuffer) -> Tuple[Any, ...]: ... + def unpack_from(self, buffer: ReadableBuffer, offset: int = ...) -> Tuple[Any, ...]: ... + def iter_unpack(self, __buffer: ReadableBuffer) -> Iterator[Tuple[Any, ...]]: ... diff --git a/mypy/typeshed/stdlib/subprocess.pyi b/mypy/typeshed/stdlib/subprocess.pyi index 3a0361ca0931..fce517745ee6 100644 --- a/mypy/typeshed/stdlib/subprocess.pyi +++ b/mypy/typeshed/stdlib/subprocess.pyi @@ -1,7 +1,7 @@ import sys -from _typeshed import AnyPath +from _typeshed import Self, StrOrBytesPath from types import TracebackType -from typing import IO, Any, AnyStr, Callable, Generic, Mapping, Optional, Sequence, Tuple, Type, TypeVar, Union, overload +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, Type, TypeVar, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 9): @@ -24,28 +24,27 @@ if sys.version_info >= (3, 9): _FILE = Union[None, int, IO[Any]] _TXT = Union[bytes, str] if sys.version_info >= (3, 8): - _CMD = Union[AnyPath, Sequence[AnyPath]] + _CMD = Union[StrOrBytesPath, Sequence[StrOrBytesPath]] else: # Python 3.6 doesn't support _CMD being a single PathLike. # See: https://bugs.python.org/issue31961 - _CMD = Union[_TXT, Sequence[AnyPath]] + _CMD = Union[_TXT, Sequence[StrOrBytesPath]] if sys.platform == "win32": _ENV = Mapping[str, str] else: - _ENV = Union[Mapping[bytes, AnyPath], Mapping[str, AnyPath]] + _ENV = Union[Mapping[bytes, StrOrBytesPath], Mapping[str, StrOrBytesPath]] -_S = TypeVar("_S") _T = TypeVar("_T") class CompletedProcess(Generic[_T]): # morally: _CMD args: Any returncode: int - # These are really both Optional, but requiring checks would be tedious + # These can both be None, but requiring checks for None would be tedious # and writing all the overloads would be horrific. stdout: _T stderr: _T - def __init__(self, args: _CMD, returncode: int, stdout: Optional[_T] = ..., stderr: Optional[_T] = ...) -> None: ... + def __init__(self, args: _CMD, returncode: int, stdout: _T | None = ..., stderr: _T | None = ...) -> None: ... def check_returncode(self) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -56,15 +55,15 @@ if sys.version_info >= (3, 7): def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -74,25 +73,25 @@ if sys.version_info >= (3, 7): *, capture_output: bool = ..., check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + input: str | None = ..., text: Literal[True], - timeout: Optional[float] = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -103,24 +102,24 @@ if sys.version_info >= (3, 7): capture_output: bool = ..., check: bool = ..., encoding: str, - errors: Optional[str] = ..., - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., + errors: str | None = ..., + input: str | None = ..., + text: bool | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -130,25 +129,25 @@ if sys.version_info >= (3, 7): *, capture_output: bool = ..., check: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., errors: str, - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., + input: str | None = ..., + text: bool | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., *, universal_newlines: Literal[True], startupinfo: Any = ..., @@ -159,25 +158,25 @@ if sys.version_info >= (3, 7): # where the *real* keyword only args start capture_output: bool = ..., check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., + encoding: str | None = ..., + errors: str | None = ..., + input: str | None = ..., + text: bool | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -189,23 +188,23 @@ if sys.version_info >= (3, 7): check: bool = ..., encoding: None = ..., errors: None = ..., - input: Optional[bytes] = ..., + input: bytes | None = ..., text: Literal[None, False] = ..., - timeout: Optional[float] = ..., + timeout: float | None = ..., ) -> CompletedProcess[bytes]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -215,11 +214,11 @@ if sys.version_info >= (3, 7): *, capture_output: bool = ..., check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[_TXT] = ..., - text: Optional[bool] = ..., - timeout: Optional[float] = ..., + encoding: str | None = ..., + errors: str | None = ..., + input: _TXT | None = ..., + text: bool | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[Any]: ... else: @@ -228,15 +227,15 @@ else: def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -246,23 +245,23 @@ else: *, check: bool = ..., encoding: str, - errors: Optional[str] = ..., - input: Optional[str] = ..., - timeout: Optional[float] = ..., + errors: str | None = ..., + input: str | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -271,24 +270,24 @@ else: pass_fds: Any = ..., *, check: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., errors: str, - input: Optional[str] = ..., - timeout: Optional[float] = ..., + input: str | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., *, universal_newlines: Literal[True], startupinfo: Any = ..., @@ -298,24 +297,24 @@ else: pass_fds: Any = ..., # where the *real* keyword only args start check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[str] = ..., - timeout: Optional[float] = ..., + encoding: str | None = ..., + errors: str | None = ..., + input: str | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[str]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -326,22 +325,22 @@ else: check: bool = ..., encoding: None = ..., errors: None = ..., - input: Optional[bytes] = ..., - timeout: Optional[float] = ..., + input: bytes | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[bytes]: ... @overload def run( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -350,25 +349,25 @@ else: pass_fds: Any = ..., *, check: bool = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - input: Optional[_TXT] = ..., - timeout: Optional[float] = ..., + encoding: str | None = ..., + errors: str | None = ..., + input: _TXT | None = ..., + timeout: float | None = ..., ) -> CompletedProcess[Any]: ... # Same args as Popen.__init__ def call( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -376,29 +375,29 @@ def call( start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., + timeout: float | None = ..., ) -> int: ... # Same args as Popen.__init__ def check_call( args: _CMD, bufsize: int = ..., - executable: AnyPath = ..., + executable: StrOrBytesPath = ..., stdin: _FILE = ..., stdout: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., - timeout: Optional[float] = ..., + timeout: float | None = ..., ) -> int: ... if sys.version_info >= (3, 7): @@ -407,14 +406,14 @@ if sys.version_info >= (3, 7): def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -422,24 +421,24 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., + errors: str | None = ..., text: Literal[True], ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -447,24 +446,24 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., encoding: str, - errors: Optional[str] = ..., - text: Optional[bool] = ..., + errors: str | None = ..., + text: bool | None = ..., ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -472,24 +471,24 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., errors: str, - text: Optional[bool] = ..., + text: bool | None = ..., ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., *, universal_newlines: Literal[True], startupinfo: Any = ..., @@ -498,24 +497,24 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., # where the real keyword only ones start - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - text: Optional[bool] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + text: bool | None = ..., ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -523,8 +522,8 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., encoding: None = ..., errors: None = ..., text: Literal[None, False] = ..., @@ -533,14 +532,14 @@ if sys.version_info >= (3, 7): def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -548,11 +547,11 @@ if sys.version_info >= (3, 7): start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - text: Optional[bool] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + text: bool | None = ..., ) -> Any: ... # morally: -> _TXT else: @@ -560,14 +559,14 @@ else: def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -575,23 +574,23 @@ else: start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., encoding: str, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -599,23 +598,23 @@ else: start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., errors: str, ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., startupinfo: Any = ..., creationflags: int = ..., restore_signals: bool = ..., @@ -623,23 +622,23 @@ else: pass_fds: Any = ..., *, universal_newlines: Literal[True], - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> str: ... @overload def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -647,8 +646,8 @@ else: start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., encoding: None = ..., errors: None = ..., ) -> bytes: ... @@ -656,14 +655,14 @@ else: def check_output( args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., + executable: StrOrBytesPath | None = ..., stdin: _FILE = ..., stderr: _FILE = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., startupinfo: Any = ..., creationflags: int = ..., @@ -671,10 +670,10 @@ else: start_new_session: bool = ..., pass_fds: Any = ..., *, - timeout: Optional[float] = ..., - input: Optional[_TXT] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + timeout: float | None = ..., + input: _TXT | None = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Any: ... # morally: -> _TXT PIPE: int @@ -684,11 +683,11 @@ DEVNULL: int class SubprocessError(Exception): ... class TimeoutExpired(SubprocessError): - def __init__(self, cmd: _CMD, timeout: float, output: Optional[_TXT] = ..., stderr: Optional[_TXT] = ...) -> None: ... + def __init__(self, cmd: _CMD, timeout: float, output: _TXT | None = ..., stderr: _TXT | None = ...) -> None: ... # morally: _CMD cmd: Any timeout: float - # morally: Optional[_TXT] + # morally: _TXT | None output: Any stdout: Any stderr: Any @@ -697,19 +696,19 @@ class CalledProcessError(SubprocessError): returncode: int # morally: _CMD cmd: Any - # morally: Optional[_TXT] + # morally: _TXT | None output: Any - # morally: Optional[_TXT] + # morally: _TXT | None stdout: Any stderr: Any - def __init__(self, returncode: int, cmd: _CMD, output: Optional[_TXT] = ..., stderr: Optional[_TXT] = ...) -> None: ... + def __init__(self, returncode: int, cmd: _CMD, output: _TXT | None = ..., stderr: _TXT | None = ...) -> None: ... class Popen(Generic[AnyStr]): args: _CMD - stdin: Optional[IO[AnyStr]] - stdout: Optional[IO[AnyStr]] - stderr: Optional[IO[AnyStr]] + stdin: IO[AnyStr] | None + stdout: IO[AnyStr] | None + stderr: IO[AnyStr] | None pid: int returncode: int universal_newlines: bool @@ -724,49 +723,49 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, - text: Optional[bool] = ..., + text: bool | None = ..., encoding: str, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> Popen[str]: ... @overload def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, - text: Optional[bool] = ..., - encoding: Optional[str] = ..., + text: bool | None = ..., + encoding: str | None = ..., errors: str, ) -> Popen[str]: ... @overload @@ -774,68 +773,68 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., *, universal_newlines: Literal[True], - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., # where the *real* keyword only args start - text: Optional[bool] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Popen[str]: ... @overload def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, text: Literal[True], - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Popen[str]: ... @overload def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., @@ -850,25 +849,25 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, - text: Optional[bool] = ..., - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Popen[Any]: ... else: @overload @@ -876,47 +875,47 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, encoding: str, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> Popen[str]: ... @overload def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, - encoding: Optional[str] = ..., + encoding: str | None = ..., errors: str, ) -> Popen[str]: ... @overload @@ -924,42 +923,42 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., *, universal_newlines: Literal[True], - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., # where the *real* keyword only args start - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Popen[str]: ... @overload def __new__( cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: Literal[False] = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., @@ -973,51 +972,56 @@ class Popen(Generic[AnyStr]): cls, args: _CMD, bufsize: int = ..., - executable: Optional[AnyPath] = ..., - stdin: Optional[_FILE] = ..., - stdout: Optional[_FILE] = ..., - stderr: Optional[_FILE] = ..., - preexec_fn: Optional[Callable[[], Any]] = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., close_fds: bool = ..., shell: bool = ..., - cwd: Optional[AnyPath] = ..., - env: Optional[_ENV] = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., universal_newlines: bool = ..., - startupinfo: Optional[Any] = ..., + startupinfo: Any | None = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Any = ..., *, - encoding: Optional[str] = ..., - errors: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., ) -> Popen[Any]: ... - def poll(self) -> Optional[int]: ... + def poll(self) -> int | None: ... if sys.version_info >= (3, 7): - def wait(self, timeout: Optional[float] = ...) -> int: ... + def wait(self, timeout: float | None = ...) -> int: ... else: - def wait(self, timeout: Optional[float] = ..., endtime: Optional[float] = ...) -> int: ... + def wait(self, timeout: float | None = ..., endtime: float | None = ...) -> int: ... # Return str/bytes def communicate( self, - input: Optional[AnyStr] = ..., - timeout: Optional[float] = ..., + input: AnyStr | None = ..., + timeout: float | None = ..., # morally this should be optional - ) -> Tuple[AnyStr, AnyStr]: ... + ) -> tuple[AnyStr, AnyStr]: ... def send_signal(self, sig: int) -> None: ... def terminate(self) -> None: ... def kill(self) -> None: ... - def __enter__(self: _S) -> _S: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, type: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType] + self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... # The result really is always a str. -def getstatusoutput(cmd: _TXT) -> Tuple[int, str]: ... +def getstatusoutput(cmd: _TXT) -> tuple[int, str]: ... def getoutput(cmd: _TXT) -> str: ... -def list2cmdline(seq: Sequence[str]) -> str: ... # undocumented + +if sys.version_info >= (3, 8): + def list2cmdline(seq: Iterable[StrOrBytesPath]) -> str: ... # undocumented + +else: + def list2cmdline(seq: Iterable[str]) -> str: ... # undocumented if sys.platform == "win32": class STARTUPINFO: @@ -1026,16 +1030,16 @@ if sys.platform == "win32": self, *, dwFlags: int = ..., - hStdInput: Optional[Any] = ..., - hStdOutput: Optional[Any] = ..., - hStdError: Optional[Any] = ..., + hStdInput: Any | None = ..., + hStdOutput: Any | None = ..., + hStdError: Any | None = ..., wShowWindow: int = ..., - lpAttributeList: Optional[Mapping[str, Any]] = ..., + lpAttributeList: Mapping[str, Any] | None = ..., ) -> None: ... dwFlags: int - hStdInput: Optional[Any] - hStdOutput: Optional[Any] - hStdError: Optional[Any] + hStdInput: Any | None + hStdOutput: Any | None + hStdError: Any | None wShowWindow: int if sys.version_info >= (3, 7): lpAttributeList: Mapping[str, Any] diff --git a/mypy/typeshed/stdlib/sunau.pyi b/mypy/typeshed/stdlib/sunau.pyi index 175068861ee9..8393136aa795 100644 --- a/mypy/typeshed/stdlib/sunau.pyi +++ b/mypy/typeshed/stdlib/sunau.pyi @@ -1,7 +1,8 @@ import sys -from typing import IO, Any, NamedTuple, NoReturn, Optional, Text, Tuple, Union +from _typeshed import Self +from typing import IO, Any, NamedTuple, NoReturn, Union -_File = Union[Text, IO[bytes]] +_File = Union[str, IO[bytes]] class Error(Exception): ... @@ -20,24 +21,19 @@ AUDIO_FILE_ENCODING_ADPCM_G723_5: int AUDIO_FILE_ENCODING_ALAW_8: int AUDIO_UNKNOWN_SIZE: int -if sys.version_info >= (3, 0): - class _sunau_params(NamedTuple): - nchannels: int - sampwidth: int - framerate: int - nframes: int - comptype: str - compname: str - -else: - _sunau_params = Tuple[int, int, int, int, str, str] +class _sunau_params(NamedTuple): + nchannels: int + sampwidth: int + framerate: int + nframes: int + comptype: str + compname: str class Au_read: def __init__(self, f: _File) -> None: ... - if sys.version_info >= (3, 3): - def __enter__(self) -> Au_read: ... - def __exit__(self, *args: Any) -> None: ... - def getfp(self) -> Optional[IO[bytes]]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: Any) -> None: ... + def getfp(self) -> IO[bytes] | None: ... def rewind(self) -> None: ... def close(self) -> None: ... def tell(self) -> int: ... @@ -51,13 +47,12 @@ class Au_read: def getmarkers(self) -> None: ... def getmark(self, id: Any) -> NoReturn: ... def setpos(self, pos: int) -> None: ... - def readframes(self, nframes: int) -> Optional[bytes]: ... + def readframes(self, nframes: int) -> bytes | None: ... class Au_write: def __init__(self, f: _File) -> None: ... - if sys.version_info >= (3, 3): - def __enter__(self) -> Au_write: ... - def __exit__(self, *args: Any) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: Any) -> None: ... def setnchannels(self, nchannels: int) -> None: ... def getnchannels(self) -> int: ... def setsampwidth(self, sampwidth: int) -> None: ... @@ -78,7 +73,7 @@ class Au_write: def close(self) -> None: ... # Returns a Au_read if mode is rb and Au_write if mode is wb -def open(f: _File, mode: Optional[str] = ...) -> Any: ... +def open(f: _File, mode: str | None = ...) -> Any: ... if sys.version_info < (3, 9): openfp = open diff --git a/mypy/typeshed/stdlib/symbol.pyi b/mypy/typeshed/stdlib/symbol.pyi index 6fbe306fabe9..2d3bd83087c7 100644 --- a/mypy/typeshed/stdlib/symbol.pyi +++ b/mypy/typeshed/stdlib/symbol.pyi @@ -1,5 +1,3 @@ -from typing import Dict - single_input: int file_input: int eval_input: int @@ -87,4 +85,4 @@ encoding_decl: int yield_expr: int yield_arg: int -sym_name: Dict[int, str] +sym_name: dict[int, str] diff --git a/mypy/typeshed/stdlib/symtable.pyi b/mypy/typeshed/stdlib/symtable.pyi index b528481bf510..613ac90ef7a9 100644 --- a/mypy/typeshed/stdlib/symtable.pyi +++ b/mypy/typeshed/stdlib/symtable.pyi @@ -1,7 +1,7 @@ import sys -from typing import Any, List, Optional, Sequence, Text, Tuple +from typing import Any, Sequence, Tuple -def symtable(code: Text, filename: Text, compile_type: Text) -> SymbolTable: ... +def symtable(code: str, filename: str, compile_type: str) -> SymbolTable: ... class SymbolTable(object): def __init__(self, raw_table: Any, filename: str) -> None: ... @@ -13,12 +13,10 @@ class SymbolTable(object): def is_nested(self) -> bool: ... def has_children(self) -> bool: ... def has_exec(self) -> bool: ... - if sys.version_info < (3, 0): - def has_import_star(self) -> bool: ... def get_identifiers(self) -> Sequence[str]: ... def lookup(self, name: str) -> Symbol: ... - def get_symbols(self) -> List[Symbol]: ... - def get_children(self) -> List[SymbolTable]: ... + def get_symbols(self) -> list[Symbol]: ... + def get_children(self) -> list[SymbolTable]: ... class Function(SymbolTable): def get_parameters(self) -> Tuple[str, ...]: ... @@ -32,21 +30,25 @@ class Class(SymbolTable): class Symbol(object): if sys.version_info >= (3, 8): def __init__( - self, name: str, flags: int, namespaces: Optional[Sequence[SymbolTable]] = ..., *, module_scope: bool = ... + self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ..., *, module_scope: bool = ... ) -> None: ... else: - def __init__(self, name: str, flags: int, namespaces: Optional[Sequence[SymbolTable]] = ...) -> None: ... + def __init__(self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ...) -> None: ... def get_name(self) -> str: ... def is_referenced(self) -> bool: ... def is_parameter(self) -> bool: ... def is_global(self) -> bool: ... def is_declared_global(self) -> bool: ... def is_local(self) -> bool: ... - if sys.version_info >= (3, 6): - def is_annotated(self) -> bool: ... + def is_annotated(self) -> bool: ... def is_free(self) -> bool: ... def is_imported(self) -> bool: ... def is_assigned(self) -> bool: ... def is_namespace(self) -> bool: ... def get_namespaces(self) -> Sequence[SymbolTable]: ... def get_namespace(self) -> SymbolTable: ... + +class SymbolTableFactory(object): + def __init__(self) -> None: ... + def new(self, table: Any, filename: str) -> SymbolTable: ... + def __call__(self, table: Any, filename: str) -> SymbolTable: ... diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index d431d2733b1c..274e4b90fd6e 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -1,14 +1,13 @@ import sys from builtins import object as _object -from importlib.abc import Loader, PathEntryFinder +from importlib.abc import PathEntryFinder from importlib.machinery import ModuleSpec +from io import TextIOWrapper from types import FrameType, ModuleType, TracebackType from typing import ( Any, AsyncGenerator, Callable, - Dict, - List, NoReturn, Optional, Protocol, @@ -20,63 +19,64 @@ from typing import ( Union, overload, ) +from typing_extensions import Literal _T = TypeVar("_T") # The following type alias are stub-only and do not exist during runtime _ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] _OptExcInfo = Union[_ExcInfo, Tuple[None, None, None]] -_PathSequence = Sequence[Union[bytes, str]] -# Unlike importlib.abc.MetaPathFinder, invalidate_caches() might not exist (see python docs) +# Intentionally omits one deprecated and one optional method of `importlib.abc.MetaPathFinder` class _MetaPathFinder(Protocol): - def find_module(self, fullname: str, path: Optional[_PathSequence]) -> Optional[Loader]: ... - def find_spec( - self, fullname: str, path: Optional[_PathSequence], target: Optional[ModuleType] = ... - ) -> Optional[ModuleSpec]: ... + def find_spec(self, fullname: str, path: Sequence[str] | None, target: ModuleType | None = ...) -> ModuleSpec | None: ... # ----- sys variables ----- if sys.platform != "win32": abiflags: str -argv: List[str] +argv: list[str] base_exec_prefix: str base_prefix: str -byteorder: str +byteorder: Literal["little", "big"] builtin_module_names: Sequence[str] # actually a tuple of strings copyright: str if sys.platform == "win32": dllhandle: int dont_write_bytecode: bool displayhook: Callable[[object], Any] -excepthook: Callable[[Type[BaseException], BaseException, TracebackType], Any] +excepthook: Callable[[Type[BaseException], BaseException, TracebackType | None], Any] exec_prefix: str executable: str float_repr_style: str hexversion: int -last_type: Optional[Type[BaseException]] -last_value: Optional[BaseException] -last_traceback: Optional[TracebackType] +last_type: Type[BaseException] | None +last_value: BaseException | None +last_traceback: TracebackType | None maxsize: int maxunicode: int -meta_path: List[_MetaPathFinder] -modules: Dict[str, ModuleType] -path: List[str] -path_hooks: List[Any] # TODO precise type; function, path to finder -path_importer_cache: Dict[str, Optional[PathEntryFinder]] +meta_path: list[_MetaPathFinder] +modules: dict[str, ModuleType] +if sys.version_info >= (3, 10): + orig_argv: list[str] +path: list[str] +path_hooks: list[Any] # TODO precise type; function, path to finder +path_importer_cache: dict[str, PathEntryFinder | None] platform: str if sys.version_info >= (3, 9): platlibdir: str prefix: str if sys.version_info >= (3, 8): - pycache_prefix: Optional[str] -ps1: str -ps2: str + pycache_prefix: str | None +ps1: object +ps2: object stdin: TextIO stdout: TextIO stderr: TextIO -__stdin__: TextIO -__stdout__: TextIO -__stderr__: TextIO +if sys.version_info >= (3, 10): + stdlib_module_names: frozenset[str] +__stdin__: TextIOWrapper +__stdout__: TextIOWrapper +__stderr__: TextIOWrapper tracebacklimit: int version: str api_version: int @@ -85,7 +85,7 @@ warnoptions: Any # lineno) if sys.platform == "win32": winver: str -_xoptions: Dict[Any, Any] +_xoptions: dict[Any, Any] flags: _flags @@ -138,6 +138,7 @@ class _implementation: version: _version_info hexversion: int cache_tag: str + _multiarch: str int_info: _int_info @@ -156,7 +157,7 @@ version_info: _version_info def call_tracing(__func: Callable[..., _T], __args: Any) -> _T: ... def _clear_type_cache() -> None: ... -def _current_frames() -> Dict[int, FrameType]: ... +def _current_frames() -> dict[int, FrameType]: ... def _getframe(__depth: int = ...) -> FrameType: ... def _debugmallocstats() -> None: ... def __displayhook__(value: object) -> None: ... @@ -165,6 +166,7 @@ def exc_info() -> _OptExcInfo: ... # sys.exit() accepts an optional argument of anything printable def exit(__status: object = ...) -> NoReturn: ... +def getallocatedblocks() -> int: ... def getdefaultencoding() -> str: ... if sys.platform != "win32": @@ -182,13 +184,13 @@ def getswitchinterval() -> float: ... _ProfileFunc = Callable[[FrameType, str, Any], Any] -def getprofile() -> Optional[_ProfileFunc]: ... -def setprofile(profilefunc: Optional[_ProfileFunc]) -> None: ... +def getprofile() -> _ProfileFunc | None: ... +def setprofile(profilefunc: _ProfileFunc | None) -> None: ... _TraceFunc = Callable[[FrameType, str, Any], Optional[Callable[[FrameType, str, Any], Any]]] -def gettrace() -> Optional[_TraceFunc]: ... -def settrace(tracefunc: Optional[_TraceFunc]) -> None: ... +def gettrace() -> _TraceFunc | None: ... +def settrace(tracefunc: _TraceFunc | None) -> None: ... class _WinVersion(Tuple[int, int, int, int, str, int, int, int, int, Tuple[int, int, int]]): major: int @@ -200,7 +202,7 @@ class _WinVersion(Tuple[int, int, int, int, str, int, int, int, int, Tuple[int, service_pack_major: int suite_mast: int product_type: int - platform_version: Tuple[int, int, int] + platform_version: tuple[int, int, int] if sys.platform == "win32": def getwindowsversion() -> _WinVersion: ... @@ -227,10 +229,10 @@ if sys.version_info >= (3, 8): # not exported by sys class UnraisableHookArgs: exc_type: Type[BaseException] - exc_value: Optional[BaseException] - exc_traceback: Optional[TracebackType] - err_msg: Optional[str] - object: Optional[_object] + exc_value: BaseException | None + exc_traceback: TracebackType | None + err_msg: str | None + object: _object | None unraisablehook: Callable[[UnraisableHookArgs], Any] def addaudithook(hook: Callable[[str, Tuple[Any, ...]], Any]) -> None: ... def audit(__event: str, *args: Any) -> None: ... @@ -243,3 +245,7 @@ class _asyncgen_hooks(Tuple[_AsyncgenHook, _AsyncgenHook]): def get_asyncgen_hooks() -> _asyncgen_hooks: ... def set_asyncgen_hooks(firstiter: _AsyncgenHook = ..., finalizer: _AsyncgenHook = ...) -> None: ... + +if sys.version_info >= (3, 7): + def get_coroutine_origin_tracking_depth() -> int: ... + def set_coroutine_origin_tracking_depth(depth: int) -> None: ... diff --git a/mypy/typeshed/stdlib/sysconfig.pyi b/mypy/typeshed/stdlib/sysconfig.pyi index b8044bcaa615..ff828d519912 100644 --- a/mypy/typeshed/stdlib/sysconfig.pyi +++ b/mypy/typeshed/stdlib/sysconfig.pyi @@ -1,17 +1,17 @@ -from typing import IO, Any, Dict, List, Optional, Tuple, overload +from typing import IO, Any, Tuple, overload -def get_config_var(name: str) -> Optional[str]: ... +def get_config_var(name: str) -> str | None: ... @overload -def get_config_vars() -> Dict[str, Any]: ... +def get_config_vars() -> dict[str, Any]: ... @overload -def get_config_vars(arg: str, *args: str) -> List[Any]: ... +def get_config_vars(arg: str, *args: str) -> list[Any]: ... def get_scheme_names() -> Tuple[str, ...]: ... def get_path_names() -> Tuple[str, ...]: ... -def get_path(name: str, scheme: str = ..., vars: Optional[Dict[str, Any]] = ..., expand: bool = ...) -> Optional[str]: ... -def get_paths(scheme: str = ..., vars: Optional[Dict[str, Any]] = ..., expand: bool = ...) -> Dict[str, str]: ... +def get_path(name: str, scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> str: ... +def get_paths(scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> dict[str, str]: ... def get_python_version() -> str: ... def get_platform() -> str: ... def is_python_build(check_home: bool = ...) -> bool: ... -def parse_config_h(fp: IO[Any], vars: Optional[Dict[str, Any]] = ...) -> Dict[str, Any]: ... +def parse_config_h(fp: IO[Any], vars: dict[str, Any] | None = ...) -> dict[str, Any]: ... def get_config_h_filename() -> str: ... def get_makefile_filename() -> str: ... diff --git a/mypy/typeshed/stdlib/tabnanny.pyi b/mypy/typeshed/stdlib/tabnanny.pyi index 7784c9fc8d1b..4c7be83b0511 100644 --- a/mypy/typeshed/stdlib/tabnanny.pyi +++ b/mypy/typeshed/stdlib/tabnanny.pyi @@ -1,5 +1,5 @@ -from _typeshed import AnyPath -from typing import Iterable, Tuple +from _typeshed import StrOrBytesPath +from typing import Iterable verbose: int filename_only: int @@ -10,5 +10,5 @@ class NannyNag(Exception): def get_msg(self) -> str: ... def get_line(self) -> str: ... -def check(file: AnyPath) -> None: ... -def process_tokens(tokens: Iterable[Tuple[int, str, Tuple[int, int], Tuple[int, int], str]]) -> None: ... +def check(file: StrOrBytesPath) -> None: ... +def process_tokens(tokens: Iterable[tuple[int, str, tuple[int, int], tuple[int, int], str]]) -> None: ... diff --git a/mypy/typeshed/stdlib/tarfile.pyi b/mypy/typeshed/stdlib/tarfile.pyi index afb88161d68b..0134316d8107 100644 --- a/mypy/typeshed/stdlib/tarfile.pyi +++ b/mypy/typeshed/stdlib/tarfile.pyi @@ -1,8 +1,30 @@ +import bz2 import io import sys -from _typeshed import AnyPath, StrPath +from _typeshed import Self, StrOrBytesPath, StrPath +from collections.abc import Callable, Iterable, Iterator, Mapping +from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType -from typing import IO, Callable, Dict, Iterable, Iterator, List, Mapping, Optional, Set, Tuple, Type, Union +from typing import IO, Protocol, Tuple, Type, TypeVar, overload +from typing_extensions import Literal + +_TF = TypeVar("_TF", bound=TarFile) + +class _Fileobj(Protocol): + def read(self, __size: int) -> bytes: ... + def write(self, __b: bytes) -> object: ... + def tell(self) -> int: ... + def seek(self, __pos: int) -> object: ... + def close(self) -> object: ... + # Optional fields: + # name: str | bytes + # mode: Literal["rb", "r+b", "wb", "xb"] + +class _Bz2ReadableFileobj(bz2._ReadableFileobj): + def close(self) -> object: ... + +class _Bz2WritableFileobj(bz2._WritableFileobj): + def close(self) -> object: ... # tar constants NUL: bytes @@ -44,243 +66,251 @@ SUPPORTED_TYPES: Tuple[bytes, ...] REGULAR_TYPES: Tuple[bytes, ...] GNU_TYPES: Tuple[bytes, ...] PAX_FIELDS: Tuple[str, ...] -PAX_NUMBER_FIELDS: Dict[str, type] - -if sys.version_info >= (3,): - PAX_NAME_FIELDS: Set[str] +PAX_NUMBER_FIELDS: dict[str, type] +PAX_NAME_FIELDS: set[str] ENCODING: str -if sys.version_info < (3,): - TAR_PLAIN: int - TAR_GZIPPED: int - def open( - name: Optional[AnyPath] = ..., + name: StrOrBytesPath | None = ..., mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., + fileobj: IO[bytes] | None = ..., # depends on mode bufsize: int = ..., *, - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., errors: str = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - compresslevel: Optional[int] = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + compresslevel: int | None = ..., ) -> TarFile: ... class ExFileObject(io.BufferedReader): def __init__(self, tarfile: TarFile, tarinfo: TarInfo) -> None: ... -class TarFile(Iterable[TarInfo]): +_list = list # conflicts with method name + +class TarFile: OPEN_METH: Mapping[str, str] - name: Optional[AnyPath] - mode: str - fileobj: Optional[IO[bytes]] - format: Optional[int] + name: StrOrBytesPath | None + mode: Literal["r", "a", "w", "x"] + fileobj: _Fileobj | None + format: int | None tarinfo: Type[TarInfo] - dereference: Optional[bool] - ignore_zeros: Optional[bool] - encoding: Optional[str] + dereference: bool | None + ignore_zeros: bool | None + encoding: str | None errors: str fileobject: Type[ExFileObject] - pax_headers: Optional[Mapping[str, str]] - debug: Optional[int] - errorlevel: Optional[int] + pax_headers: Mapping[str, str] | None + debug: int | None + errorlevel: int | None offset: int # undocumented - if sys.version_info < (3,): - posix: bool def __init__( self, - name: Optional[AnyPath] = ..., - mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., + name: StrOrBytesPath | None = ..., + mode: Literal["r", "a", "w", "x"] = ..., + fileobj: _Fileobj | None = ..., + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., errors: str = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - copybufsize: Optional[int] = ..., # undocumented + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + copybufsize: int | None = ..., # undocumented ) -> None: ... - def __enter__(self) -> TarFile: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __iter__(self) -> Iterator[TarInfo]: ... @classmethod def open( - cls, - name: Optional[AnyPath] = ..., + cls: Type[_TF], + name: StrOrBytesPath | None = ..., mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., + fileobj: IO[bytes] | None = ..., # depends on mode bufsize: int = ..., *, - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., errors: str = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - ) -> TarFile: ... + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... @classmethod def taropen( - cls, - name: Optional[AnyPath], - mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["r", "a", "w", "x"] = ..., + fileobj: _Fileobj | None = ..., *, compresslevel: int = ..., - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - ) -> TarFile: ... + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... + @overload @classmethod def gzopen( - cls, - name: Optional[AnyPath], - mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["r"] = ..., + fileobj: _GzipReadableFileobj | None = ..., compresslevel: int = ..., *, - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - ) -> TarFile: ... + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... + @overload + @classmethod + def gzopen( + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["w", "x"], + fileobj: _GzipWritableFileobj | None = ..., + compresslevel: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... + @overload @classmethod def bz2open( - cls, - name: Optional[AnyPath], - mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["w", "x"], + fileobj: _Bz2WritableFileobj | None = ..., + compresslevel: int = ..., + *, + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... + @overload + @classmethod + def bz2open( + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["r"] = ..., + fileobj: _Bz2ReadableFileobj | None = ..., compresslevel: int = ..., *, - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - ) -> TarFile: ... + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... @classmethod def xzopen( - cls, - name: Optional[AnyPath], - mode: str = ..., - fileobj: Optional[IO[bytes]] = ..., - preset: Optional[int] = ..., + cls: Type[_TF], + name: StrOrBytesPath | None, + mode: Literal["r", "w", "x"] = ..., + fileobj: IO[bytes] | None = ..., + preset: int | None = ..., *, - format: Optional[int] = ..., - tarinfo: Optional[Type[TarInfo]] = ..., - dereference: Optional[bool] = ..., - ignore_zeros: Optional[bool] = ..., - encoding: Optional[str] = ..., - pax_headers: Optional[Mapping[str, str]] = ..., - debug: Optional[int] = ..., - errorlevel: Optional[int] = ..., - ) -> TarFile: ... + format: int | None = ..., + tarinfo: Type[TarInfo] | None = ..., + dereference: bool | None = ..., + ignore_zeros: bool | None = ..., + encoding: str | None = ..., + pax_headers: Mapping[str, str] | None = ..., + debug: int | None = ..., + errorlevel: int | None = ..., + ) -> _TF: ... def getmember(self, name: str) -> TarInfo: ... - def getmembers(self) -> List[TarInfo]: ... - def getnames(self) -> List[str]: ... - if sys.version_info >= (3, 5): - def list(self, verbose: bool = ..., *, members: Optional[List[TarInfo]] = ...) -> None: ... - else: - def list(self, verbose: bool = ...) -> None: ... - def next(self) -> Optional[TarInfo]: ... - if sys.version_info >= (3, 5): - def extractall( - self, path: AnyPath = ..., members: Optional[Iterable[TarInfo]] = ..., *, numeric_owner: bool = ... - ) -> None: ... - else: - def extractall(self, path: AnyPath = ..., members: Optional[Iterable[TarInfo]] = ...) -> None: ... - if sys.version_info >= (3, 5): - def extract( - self, member: Union[str, TarInfo], path: AnyPath = ..., set_attrs: bool = ..., *, numeric_owner: bool = ... - ) -> None: ... - else: - def extract(self, member: Union[str, TarInfo], path: AnyPath = ...) -> None: ... - def extractfile(self, member: Union[str, TarInfo]) -> Optional[IO[bytes]]: ... - def makedir(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def makefile(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def makeunknown(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def makefifo(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def makedev(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def makelink(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - if sys.version_info >= (3, 5): - def chown(self, tarinfo: TarInfo, targetpath: AnyPath, numeric_owner: bool) -> None: ... # undocumented - else: - def chown(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def chmod(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented - def utime(self, tarinfo: TarInfo, targetpath: AnyPath) -> None: ... # undocumented + def getmembers(self) -> _list[TarInfo]: ... + def getnames(self) -> _list[str]: ... + def list(self, verbose: bool = ..., *, members: _list[TarInfo] | None = ...) -> None: ... + def next(self) -> TarInfo | None: ... + def extractall( + self, path: StrOrBytesPath = ..., members: Iterable[TarInfo] | None = ..., *, numeric_owner: bool = ... + ) -> None: ... + def extract( + self, member: str | TarInfo, path: StrOrBytesPath = ..., set_attrs: bool = ..., *, numeric_owner: bool = ... + ) -> None: ... + def _extract_member( + self, tarinfo: TarInfo, targetpath: str, set_attrs: bool = ..., numeric_owner: bool = ... + ) -> None: ... # undocumented + def extractfile(self, member: str | TarInfo) -> IO[bytes] | None: ... + def makedir(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def makefile(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def makeunknown(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def makefifo(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def makedev(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def makelink(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def chown(self, tarinfo: TarInfo, targetpath: StrOrBytesPath, numeric_owner: bool) -> None: ... # undocumented + def chmod(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented + def utime(self, tarinfo: TarInfo, targetpath: StrOrBytesPath) -> None: ... # undocumented if sys.version_info >= (3, 7): def add( self, name: StrPath, - arcname: Optional[StrPath] = ..., + arcname: StrPath | None = ..., recursive: bool = ..., *, - filter: Optional[Callable[[TarInfo], Optional[TarInfo]]] = ..., + filter: Callable[[TarInfo], TarInfo | None] | None = ..., ) -> None: ... - elif sys.version_info >= (3,): + else: def add( self, name: StrPath, - arcname: Optional[StrPath] = ..., + arcname: StrPath | None = ..., recursive: bool = ..., - exclude: Optional[Callable[[str], bool]] = ..., + exclude: Callable[[str], bool] | None = ..., *, - filter: Optional[Callable[[TarInfo], Optional[TarInfo]]] = ..., + filter: Callable[[TarInfo], TarInfo | None] | None = ..., ) -> None: ... - else: - def add( - self, - name: str, - arcname: Optional[str] = ..., - recursive: bool = ..., - exclude: Optional[Callable[[str], bool]] = ..., - filter: Optional[Callable[[TarInfo], Optional[TarInfo]]] = ..., - ) -> None: ... - def addfile(self, tarinfo: TarInfo, fileobj: Optional[IO[bytes]] = ...) -> None: ... - def gettarinfo( - self, name: Optional[str] = ..., arcname: Optional[str] = ..., fileobj: Optional[IO[bytes]] = ... - ) -> TarInfo: ... + def addfile(self, tarinfo: TarInfo, fileobj: IO[bytes] | None = ...) -> None: ... + def gettarinfo(self, name: str | None = ..., arcname: str | None = ..., fileobj: IO[bytes] | None = ...) -> TarInfo: ... def close(self) -> None: ... if sys.version_info >= (3, 9): - def is_tarfile(name: Union[AnyPath, IO[bytes]]) -> bool: ... + def is_tarfile(name: StrOrBytesPath | IO[bytes]) -> bool: ... else: - def is_tarfile(name: AnyPath) -> bool: ... + def is_tarfile(name: StrOrBytesPath) -> bool: ... if sys.version_info < (3, 8): def filemode(mode: int) -> str: ... # undocumented -if sys.version_info < (3,): - class TarFileCompat: - def __init__(self, filename: str, mode: str = ..., compression: int = ...) -> None: ... - class TarError(Exception): ... class ReadError(TarError): ... class CompressionError(TarError): ... @@ -298,8 +328,8 @@ class TarInfo: devminor: int offset: int offset_data: int - sparse: Optional[bytes] - tarfile: Optional[TarFile] + sparse: bytes | None + tarfile: TarFile | None mode: int type: bytes linkname: str @@ -309,27 +339,23 @@ class TarInfo: gname: str pax_headers: Mapping[str, str] def __init__(self, name: str = ...) -> None: ... - if sys.version_info >= (3,): - @classmethod - def frombuf(cls, buf: bytes, encoding: str, errors: str) -> TarInfo: ... - else: - @classmethod - def frombuf(cls, buf: bytes) -> TarInfo: ... + @classmethod + def frombuf(cls, buf: bytes, encoding: str, errors: str) -> TarInfo: ... @classmethod def fromtarfile(cls, tarfile: TarFile) -> TarInfo: ... @property def linkpath(self) -> str: ... @linkpath.setter def linkpath(self, linkname: str) -> None: ... - def get_info(self) -> Mapping[str, Union[str, int, bytes, Mapping[str, str]]]: ... - def tobuf(self, format: Optional[int] = ..., encoding: Optional[str] = ..., errors: str = ...) -> bytes: ... + def get_info(self) -> Mapping[str, str | int | bytes | Mapping[str, str]]: ... + def tobuf(self, format: int | None = ..., encoding: str | None = ..., errors: str = ...) -> bytes: ... def create_ustar_header( - self, info: Mapping[str, Union[str, int, bytes, Mapping[str, str]]], encoding: str, errors: str + self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str, errors: str ) -> bytes: ... def create_gnu_header( - self, info: Mapping[str, Union[str, int, bytes, Mapping[str, str]]], encoding: str, errors: str + self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str, errors: str ) -> bytes: ... - def create_pax_header(self, info: Mapping[str, Union[str, int, bytes, Mapping[str, str]]], encoding: str) -> bytes: ... + def create_pax_header(self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str) -> bytes: ... @classmethod def create_pax_global_header(cls, pax_headers: Mapping[str, str]) -> bytes: ... def isfile(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/telnetlib.pyi b/mypy/typeshed/stdlib/telnetlib.pyi index 31fd3eef81cd..cf00856d9332 100644 --- a/mypy/typeshed/stdlib/telnetlib.pyi +++ b/mypy/typeshed/stdlib/telnetlib.pyi @@ -1,6 +1,6 @@ import socket -import sys -from typing import Any, Callable, Match, Optional, Pattern, Sequence, Tuple, Union +from _typeshed import Self +from typing import Any, Callable, Match, Pattern, Sequence DEBUGLEVEL: int TELNET_PORT: int @@ -82,8 +82,8 @@ EXOPL: bytes NOOPT: bytes class Telnet: - host: Optional[str] # undocumented - def __init__(self, host: Optional[str] = ..., port: int = ..., timeout: float = ...) -> None: ... + host: str | None # undocumented + def __init__(self, host: str | None = ..., port: int = ..., timeout: float = ...) -> None: ... def open(self, host: str, port: int = ..., timeout: float = ...) -> None: ... def msg(self, msg: str, *args: Any) -> None: ... def set_debuglevel(self, debuglevel: int) -> None: ... @@ -91,7 +91,7 @@ class Telnet: def get_socket(self) -> socket.socket: ... def fileno(self) -> int: ... def write(self, buffer: bytes) -> None: ... - def read_until(self, match: bytes, timeout: Optional[float] = ...) -> bytes: ... + def read_until(self, match: bytes, timeout: float | None = ...) -> bytes: ... def read_all(self) -> bytes: ... def read_some(self) -> bytes: ... def read_very_eager(self) -> bytes: ... @@ -99,7 +99,7 @@ class Telnet: def read_lazy(self) -> bytes: ... def read_very_lazy(self) -> bytes: ... def read_sb_data(self) -> bytes: ... - def set_option_negotiation_callback(self, callback: Optional[Callable[[socket.socket, bytes, bytes], Any]]) -> None: ... + def set_option_negotiation_callback(self, callback: Callable[[socket.socket, bytes, bytes], Any] | None) -> None: ... def process_rawq(self) -> None: ... def rawq_getchar(self) -> bytes: ... def fill_rawq(self) -> None: ... @@ -108,8 +108,7 @@ class Telnet: def mt_interact(self) -> None: ... def listener(self) -> None: ... def expect( - self, list: Sequence[Union[Pattern[bytes], bytes]], timeout: Optional[float] = ... - ) -> Tuple[int, Optional[Match[bytes]], bytes]: ... - if sys.version_info >= (3, 6): - def __enter__(self) -> Telnet: ... - def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... + self, list: Sequence[Pattern[bytes] | bytes], timeout: float | None = ... + ) -> tuple[int, Match[bytes] | None, bytes]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/tempfile.pyi b/mypy/typeshed/stdlib/tempfile.pyi index ddf9f582809c..119c111bc4e1 100644 --- a/mypy/typeshed/stdlib/tempfile.pyi +++ b/mypy/typeshed/stdlib/tempfile.pyi @@ -1,7 +1,8 @@ import os import sys +from _typeshed import Self from types import TracebackType -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, List, Optional, Tuple, Type, TypeVar, Union, overload +from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, Tuple, Type, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 9): @@ -9,10 +10,9 @@ if sys.version_info >= (3, 9): # global variables TMP_MAX: int -tempdir: Optional[str] +tempdir: str | None template: str -_S = TypeVar("_S") _DirT = Union[AnyStr, os.PathLike[AnyStr]] if sys.version_info >= (3, 8): @@ -20,76 +20,76 @@ if sys.version_info >= (3, 8): def NamedTemporaryFile( mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., *, - errors: Optional[str] = ..., - ) -> IO[str]: ... + errors: str | None = ..., + ) -> _TemporaryFileWrapper[str]: ... @overload def NamedTemporaryFile( mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., *, - errors: Optional[str] = ..., - ) -> IO[bytes]: ... + errors: str | None = ..., + ) -> _TemporaryFileWrapper[bytes]: ... @overload def NamedTemporaryFile( mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., *, - errors: Optional[str] = ..., - ) -> IO[Any]: ... + errors: str | None = ..., + ) -> _TemporaryFileWrapper[Any]: ... else: @overload def NamedTemporaryFile( mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., - ) -> IO[str]: ... + ) -> _TemporaryFileWrapper[str]: ... @overload def NamedTemporaryFile( mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., - ) -> IO[bytes]: ... + ) -> _TemporaryFileWrapper[bytes]: ... @overload def NamedTemporaryFile( mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., delete: bool = ..., - ) -> IO[Any]: ... + ) -> _TemporaryFileWrapper[Any]: ... if sys.platform == "win32": TemporaryFile = NamedTemporaryFile @@ -99,106 +99,114 @@ else: def TemporaryFile( mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> IO[str]: ... @overload def TemporaryFile( mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> IO[bytes]: ... @overload def TemporaryFile( mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> IO[Any]: ... else: @overload def TemporaryFile( mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., ) -> IO[str]: ... @overload def TemporaryFile( mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., ) -> IO[bytes]: ... @overload def TemporaryFile( mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[AnyStr] = ..., - prefix: Optional[AnyStr] = ..., - dir: Optional[_DirT[AnyStr]] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., ) -> IO[Any]: ... -class _TemporaryFileWrapper(IO[str]): - file: IO[str] - name: Any +class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): + file: IO[AnyStr] # io.TextIOWrapper, io.BufferedReader or io.BufferedWriter + name: str delete: bool - def __init__(self, file: IO[str], name: Any, delete: bool = ...) -> None: ... - def __enter__(self) -> _TemporaryFileWrapper: ... - def __exit__( - self, exc: Optional[Type[BaseException]], value: Optional[BaseException], tb: Optional[TracebackType] - ) -> Optional[bool]: ... + def __init__(self, file: IO[AnyStr], name: str, delete: bool = ...) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, exc: Type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> bool | None: ... def __getattr__(self, name: str) -> Any: ... def close(self) -> None: ... - def unlink(self, path: str) -> None: ... # These methods don't exist directly on this object, but # are delegated to the underlying IO object through __getattr__. # We need to add them here so that this class is concrete. - def __iter__(self) -> Iterator[str]: ... - def __next__(self) -> str: ... + def __iter__(self) -> Iterator[AnyStr]: ... + # FIXME: __next__ doesn't actually exist on this class and should be removed: + # see also https://github.com/python/typeshed/pull/5456#discussion_r633068648 + # >>> import tempfile + # >>> ntf=tempfile.NamedTemporaryFile() + # >>> next(ntf) + # Traceback (most recent call last): + # File "", line 1, in + # TypeError: '_TemporaryFileWrapper' object is not an iterator + def __next__(self) -> AnyStr: ... def fileno(self) -> int: ... def flush(self) -> None: ... def isatty(self) -> bool: ... - def next(self) -> str: ... - def read(self, n: int = ...) -> str: ... + def read(self, n: int = ...) -> AnyStr: ... def readable(self) -> bool: ... - def readline(self, limit: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readline(self, limit: int = ...) -> AnyStr: ... + def readlines(self, hint: int = ...) -> list[AnyStr]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... - def write(self, s: str) -> int: ... - def writelines(self, lines: Iterable[str]) -> None: ... + def write(self, s: AnyStr) -> int: ... + def writelines(self, lines: Iterable[AnyStr]) -> None: ... # It does not actually derive from IO[AnyStr], but it does implement the # protocol. class SpooledTemporaryFile(IO[AnyStr]): + @property + def encoding(self) -> str: ... # undocumented + @property + def newlines(self) -> str | Tuple[str, ...] | None: ... # undocumented # bytes needs to go first, as default mode is to open as bytes if sys.version_info >= (3, 8): @overload @@ -207,13 +215,13 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> None: ... @overload def __init__( @@ -221,13 +229,13 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> None: ... @overload def __init__( @@ -235,16 +243,16 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., *, - errors: Optional[str] = ..., + errors: str | None = ..., ) -> None: ... @property - def errors(self) -> Optional[str]: ... + def errors(self) -> str | None: ... else: @overload def __init__( @@ -252,11 +260,11 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., ) -> None: ... @overload def __init__( @@ -264,11 +272,11 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., ) -> None: ... @overload def __init__( @@ -276,17 +284,17 @@ class SpooledTemporaryFile(IO[AnyStr]): max_size: int = ..., mode: str = ..., buffering: int = ..., - encoding: Optional[str] = ..., - newline: Optional[str] = ..., - suffix: Optional[str] = ..., - prefix: Optional[str] = ..., - dir: Optional[str] = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., ) -> None: ... def rollover(self) -> None: ... - def __enter__(self: _S) -> _S: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... # These methods are copied from the abstract methods of IO, because # SpooledTemporaryFile implements IO. # See also https://github.com/python/typeshed/pull/2452#issuecomment-420657918. @@ -296,10 +304,10 @@ class SpooledTemporaryFile(IO[AnyStr]): def isatty(self) -> bool: ... def read(self, n: int = ...) -> AnyStr: ... def readline(self, limit: int = ...) -> AnyStr: ... - def readlines(self, hint: int = ...) -> List[AnyStr]: ... + def readlines(self, hint: int = ...) -> list[AnyStr]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def write(self, s: AnyStr) -> int: ... def writelines(self, iterable: Iterable[AnyStr]) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... @@ -308,37 +316,55 @@ class SpooledTemporaryFile(IO[AnyStr]): def seekable(self) -> bool: ... def writable(self) -> bool: ... def __next__(self) -> AnyStr: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class TemporaryDirectory(Generic[AnyStr]): name: AnyStr - @overload - def __init__(self: TemporaryDirectory[str], suffix: None = ..., prefix: None = ..., dir: None = ...) -> None: ... - @overload - def __init__( - self, suffix: Optional[AnyStr] = ..., prefix: Optional[AnyStr] = ..., dir: Optional[_DirT[AnyStr]] = ... - ) -> None: ... + if sys.version_info >= (3, 10): + @overload + def __init__( + self: TemporaryDirectory[str], + suffix: None = ..., + prefix: None = ..., + dir: None = ..., + ignore_cleanup_errors: bool = ..., + ) -> None: ... + @overload + def __init__( + self, + suffix: AnyStr | None = ..., + prefix: AnyStr | None = ..., + dir: _DirT[AnyStr] | None = ..., + ignore_cleanup_errors: bool = ..., + ) -> None: ... + else: + @overload + def __init__(self: TemporaryDirectory[str], suffix: None = ..., prefix: None = ..., dir: None = ...) -> None: ... + @overload + def __init__(self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> None: ... def cleanup(self) -> None: ... def __enter__(self) -> AnyStr: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @overload -def mkstemp() -> Tuple[int, str]: ... +def mkstemp() -> tuple[int, str]: ... @overload def mkstemp( - suffix: Optional[AnyStr] = ..., prefix: Optional[AnyStr] = ..., dir: Optional[_DirT[AnyStr]] = ..., text: bool = ... -) -> Tuple[int, AnyStr]: ... + suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ..., text: bool = ... +) -> tuple[int, AnyStr]: ... @overload def mkdtemp() -> str: ... @overload -def mkdtemp(suffix: Optional[AnyStr] = ..., prefix: Optional[AnyStr] = ..., dir: Optional[_DirT[AnyStr]] = ...) -> AnyStr: ... +def mkdtemp(suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> AnyStr: ... @overload def mktemp() -> str: ... @overload -def mktemp(suffix: Optional[AnyStr] = ..., prefix: Optional[AnyStr] = ..., dir: Optional[_DirT[AnyStr]] = ...) -> AnyStr: ... +def mktemp(suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> AnyStr: ... def gettempdirb() -> bytes: ... def gettempprefixb() -> bytes: ... def gettempdir() -> str: ... diff --git a/mypy/typeshed/stdlib/termios.pyi b/mypy/typeshed/stdlib/termios.pyi index 0c627f4b72bd..ed8522dccc51 100644 --- a/mypy/typeshed/stdlib/termios.pyi +++ b/mypy/typeshed/stdlib/termios.pyi @@ -236,7 +236,7 @@ VWERASE: int XCASE: int XTABS: int -def tcgetattr(__fd: FileDescriptorLike) -> List[Any]: ... +def tcgetattr(__fd: FileDescriptorLike) -> list[Any]: ... def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... def tcdrain(__fd: FileDescriptorLike) -> None: ... diff --git a/mypy/typeshed/stdlib/textwrap.pyi b/mypy/typeshed/stdlib/textwrap.pyi index 0fd80bcb6cff..3b8fd5c0349a 100644 --- a/mypy/typeshed/stdlib/textwrap.pyi +++ b/mypy/typeshed/stdlib/textwrap.pyi @@ -1,27 +1,27 @@ -from typing import Callable, Dict, List, Optional, Pattern +from typing import Callable, Pattern class TextWrapper: - width: int = ... - initial_indent: str = ... - subsequent_indent: str = ... - expand_tabs: bool = ... - replace_whitespace: bool = ... - fix_sentence_endings: bool = ... - drop_whitespace: bool = ... - break_long_words: bool = ... - break_on_hyphens: bool = ... - tabsize: int = ... - max_lines: Optional[int] = ... - placeholder: str = ... + width: int + initial_indent: str + subsequent_indent: str + expand_tabs: bool + replace_whitespace: bool + fix_sentence_endings: bool + drop_whitespace: bool + break_long_words: bool + break_on_hyphens: bool + tabsize: int + max_lines: int | None + placeholder: str # Attributes not present in documentation - sentence_end_re: Pattern[str] = ... - wordsep_re: Pattern[str] = ... - wordsep_simple_re: Pattern[str] = ... - whitespace_trans: str = ... - unicode_whitespace_trans: Dict[int, int] = ... - uspace: int = ... - x: str = ... # leaked loop variable + sentence_end_re: Pattern[str] + wordsep_re: Pattern[str] + wordsep_simple_re: Pattern[str] + whitespace_trans: str + unicode_whitespace_trans: dict[int, int] + uspace: int + x: str # leaked loop variable def __init__( self, width: int = ..., @@ -35,17 +35,17 @@ class TextWrapper: break_on_hyphens: bool = ..., tabsize: int = ..., *, - max_lines: Optional[int] = ..., + max_lines: int | None = ..., placeholder: str = ..., ) -> None: ... # Private methods *are* part of the documented API for subclasses. def _munge_whitespace(self, text: str) -> str: ... - def _split(self, text: str) -> List[str]: ... - def _fix_sentence_endings(self, chunks: List[str]) -> None: ... - def _handle_long_word(self, reversed_chunks: List[str], cur_line: List[str], cur_len: int, width: int) -> None: ... - def _wrap_chunks(self, chunks: List[str]) -> List[str]: ... - def _split_chunks(self, text: str) -> List[str]: ... - def wrap(self, text: str) -> List[str]: ... + def _split(self, text: str) -> list[str]: ... + def _fix_sentence_endings(self, chunks: list[str]) -> None: ... + def _handle_long_word(self, reversed_chunks: list[str], cur_line: list[str], cur_len: int, width: int) -> None: ... + def _wrap_chunks(self, chunks: list[str]) -> list[str]: ... + def _split_chunks(self, text: str) -> list[str]: ... + def wrap(self, text: str) -> list[str]: ... def fill(self, text: str) -> str: ... def wrap( @@ -63,7 +63,7 @@ def wrap( drop_whitespace: bool = ..., max_lines: int = ..., placeholder: str = ..., -) -> List[str]: ... +) -> list[str]: ... def fill( text: str, width: int = ..., @@ -97,4 +97,4 @@ def shorten( placeholder: str = ..., ) -> str: ... def dedent(text: str) -> str: ... -def indent(text: str, prefix: str, predicate: Optional[Callable[[str], bool]] = ...) -> str: ... +def indent(text: str, prefix: str, predicate: Callable[[str], bool] | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/this.pyi b/mypy/typeshed/stdlib/this.pyi index 0687a6675cca..8de996b04aec 100644 --- a/mypy/typeshed/stdlib/this.pyi +++ b/mypy/typeshed/stdlib/this.pyi @@ -1,4 +1,2 @@ -from typing import Dict - s: str -d: Dict[str, str] +d: dict[str, str] diff --git a/mypy/typeshed/stdlib/threading.pyi b/mypy/typeshed/stdlib/threading.pyi index af0b0af89d9b..64998d86bf9f 100644 --- a/mypy/typeshed/stdlib/threading.pyi +++ b/mypy/typeshed/stdlib/threading.pyi @@ -1,6 +1,6 @@ import sys from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar, Union +from typing import Any, Callable, Iterable, Mapping, Optional, Type, TypeVar # TODO recursive type _TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] @@ -8,33 +8,23 @@ _TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] _PF = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") -__all__: List[str] +__all__: list[str] def active_count() -> int: ... - -if sys.version_info < (3,): - def activeCount() -> int: ... - def current_thread() -> Thread: ... def currentThread() -> Thread: ... - -if sys.version_info >= (3,): - def get_ident() -> int: ... - -def enumerate() -> List[Thread]: ... - -if sys.version_info >= (3, 4): - def main_thread() -> Thread: ... +def get_ident() -> int: ... +def enumerate() -> list[Thread]: ... +def main_thread() -> Thread: ... if sys.version_info >= (3, 8): from _thread import get_native_id as get_native_id def settrace(func: _TF) -> None: ... -def setprofile(func: Optional[_PF]) -> None: ... +def setprofile(func: _PF | None) -> None: ... def stack_size(size: int = ...) -> int: ... -if sys.version_info >= (3,): - TIMEOUT_MAX: float +TIMEOUT_MAX: float class ThreadError(Exception): ... @@ -45,36 +35,26 @@ class local(object): class Thread: name: str - ident: Optional[int] + ident: int | None daemon: bool - if sys.version_info >= (3,): - def __init__( - self, - group: None = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[str] = ..., - args: Iterable[Any] = ..., - kwargs: Optional[Mapping[str, Any]] = ..., - *, - daemon: Optional[bool] = ..., - ) -> None: ... - else: - def __init__( - self, - group: None = ..., - target: Optional[Callable[..., Any]] = ..., - name: Optional[Text] = ..., - args: Iterable[Any] = ..., - kwargs: Optional[Mapping[Text, Any]] = ..., - ) -> None: ... + def __init__( + self, + group: None = ..., + target: Callable[..., Any] | None = ..., + name: str | None = ..., + args: Iterable[Any] = ..., + kwargs: Mapping[str, Any] | None = ..., + *, + daemon: bool | None = ..., + ) -> None: ... def start(self) -> None: ... def run(self) -> None: ... - def join(self, timeout: Optional[float] = ...) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... def getName(self) -> str: ... - def setName(self, name: Text) -> None: ... + def setName(self, name: str) -> None: ... if sys.version_info >= (3, 8): @property - def native_id(self) -> Optional[int]: ... # only available on some platforms + def native_id(self) -> int | None: ... # only available on some platforms def is_alive(self) -> bool: ... if sys.version_info < (3, 9): def isAlive(self) -> bool: ... @@ -87,12 +67,9 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... def locked(self) -> bool: ... @@ -100,30 +77,23 @@ class _RLock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... RLock = _RLock class Condition: - def __init__(self, lock: Union[Lock, _RLock, None] = ...) -> None: ... + def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... - if sys.version_info >= (3,): - def wait_for(self, predicate: Callable[[], _T], timeout: Optional[float] = ...) -> _T: ... + def wait(self, timeout: float | None = ...) -> bool: ... + def wait_for(self, predicate: Callable[[], _T], timeout: float | None = ...) -> _T: ... def notify(self, n: int = ...) -> None: ... def notify_all(self) -> None: ... def notifyAll(self) -> None: ... @@ -131,14 +101,10 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... - if sys.version_info >= (3,): - def acquire(self, blocking: bool = ..., timeout: Optional[float] = ...) -> bool: ... - def __enter__(self, blocking: bool = ..., timeout: Optional[float] = ...) -> bool: ... - else: - def acquire(self, blocking: bool = ...) -> bool: ... - def __enter__(self, blocking: bool = ...) -> bool: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def acquire(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... + def __enter__(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... if sys.version_info >= (3, 9): def release(self, n: int = ...) -> None: ... else: @@ -149,11 +115,9 @@ class BoundedSemaphore(Semaphore): ... class Event: def __init__(self) -> None: ... def is_set(self) -> bool: ... - if sys.version_info < (3,): - def isSet(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> bool: ... + def wait(self, timeout: float | None = ...) -> bool: ... if sys.version_info >= (3, 8): from _thread import _excepthook, _ExceptHookArgs @@ -162,27 +126,22 @@ if sys.version_info >= (3, 8): ExceptHookArgs = _ExceptHookArgs class Timer(Thread): - if sys.version_info >= (3,): - def __init__( - self, - interval: float, - function: Callable[..., Any], - args: Optional[Iterable[Any]] = ..., - kwargs: Optional[Mapping[str, Any]] = ..., - ) -> None: ... - else: - def __init__( - self, interval: float, function: Callable[..., Any], args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ... - ) -> None: ... + def __init__( + self, + interval: float, + function: Callable[..., Any], + args: Iterable[Any] | None = ..., + kwargs: Mapping[str, Any] | None = ..., + ) -> None: ... def cancel(self) -> None: ... -if sys.version_info >= (3,): - class Barrier: - parties: int - n_waiting: int - broken: bool - def __init__(self, parties: int, action: Optional[Callable[[], None]] = ..., timeout: Optional[float] = ...) -> None: ... - def wait(self, timeout: Optional[float] = ...) -> int: ... - def reset(self) -> None: ... - def abort(self) -> None: ... - class BrokenBarrierError(RuntimeError): ... +class Barrier: + parties: int + n_waiting: int + broken: bool + def __init__(self, parties: int, action: Callable[[], None] | None = ..., timeout: float | None = ...) -> None: ... + def wait(self, timeout: float | None = ...) -> int: ... + def reset(self) -> None: ... + def abort(self) -> None: ... + +class BrokenBarrierError(RuntimeError): ... diff --git a/mypy/typeshed/stdlib/time.pyi b/mypy/typeshed/stdlib/time.pyi index 6e926c68dc39..bf370d68e83d 100644 --- a/mypy/typeshed/stdlib/time.pyi +++ b/mypy/typeshed/stdlib/time.pyi @@ -1,17 +1,14 @@ import sys -from typing import Any, NamedTuple, Optional, Tuple, Union - -if sys.version_info >= (3, 3): - from types import SimpleNamespace +from types import SimpleNamespace +from typing import Any, NamedTuple, Tuple +from typing_extensions import final _TimeTuple = Tuple[int, int, int, int, int, int, int, int, int] -if sys.version_info < (3, 3): - accept2dyear: bool altzone: int daylight: int timezone: int -tzname: Tuple[str, str] +tzname: tuple[str, str] if sys.version_info >= (3, 7): if sys.platform == "linux": @@ -20,7 +17,7 @@ if sys.version_info >= (3, 7): CLOCK_PROF: int # FreeBSD, NetBSD, OpenBSD CLOCK_UPTIME: int # FreeBSD, OpenBSD -if sys.version_info >= (3, 3) and sys.platform != "win32": +if sys.platform != "win32": CLOCK_MONOTONIC: int CLOCK_MONOTONIC_RAW: int CLOCK_PROCESS_CPUTIME_ID: int @@ -52,63 +49,53 @@ class _struct_time(NamedTuple): @property def n_unnamed_fields(self) -> int: ... -if sys.version_info >= (3, 3): - class struct_time(_struct_time): - def __init__( - self, - o: Union[ - Tuple[int, int, int, int, int, int, int, int, int], - Tuple[int, int, int, int, int, int, int, int, int, str], - Tuple[int, int, int, int, int, int, int, int, int, str, int], - ], - _arg: Any = ..., - ) -> None: ... - def __new__( - cls, - o: Union[ - Tuple[int, int, int, int, int, int, int, int, int], - Tuple[int, int, int, int, int, int, int, int, int, str], - Tuple[int, int, int, int, int, int, int, int, int, str, int], - ], - _arg: Any = ..., - ) -> struct_time: ... - if sys.version_info >= (3, 6) or sys.platform != "win32": - @property - def tm_zone(self) -> str: ... - @property - def tm_gmtoff(self) -> int: ... - -else: - class struct_time(_struct_time): - def __init__(self, o: _TimeTuple, _arg: Any = ...) -> None: ... - def __new__(cls, o: _TimeTuple, _arg: Any = ...) -> struct_time: ... +@final +class struct_time(_struct_time): + def __init__( + self, + o: tuple[int, int, int, int, int, int, int, int, int] + | tuple[int, int, int, int, int, int, int, int, int, str] + | tuple[int, int, int, int, int, int, int, int, int, str, int], + _arg: Any = ..., + ) -> None: ... + def __new__( + cls, + o: tuple[int, int, int, int, int, int, int, int, int] + | tuple[int, int, int, int, int, int, int, int, int, str] + | tuple[int, int, int, int, int, int, int, int, int, str, int], + _arg: Any = ..., + ) -> struct_time: ... + @property + def tm_zone(self) -> str: ... + @property + def tm_gmtoff(self) -> int: ... -def asctime(t: Union[_TimeTuple, struct_time] = ...) -> str: ... +def asctime(t: _TimeTuple | struct_time = ...) -> str: ... if sys.version_info < (3, 8): def clock() -> float: ... -def ctime(secs: Optional[float] = ...) -> str: ... -def gmtime(secs: Optional[float] = ...) -> struct_time: ... -def localtime(secs: Optional[float] = ...) -> struct_time: ... -def mktime(t: Union[_TimeTuple, struct_time]) -> float: ... +def ctime(secs: float | None = ...) -> str: ... +def gmtime(secs: float | None = ...) -> struct_time: ... +def localtime(secs: float | None = ...) -> struct_time: ... +def mktime(t: _TimeTuple | struct_time) -> float: ... def sleep(secs: float) -> None: ... -def strftime(format: str, t: Union[_TimeTuple, struct_time] = ...) -> str: ... +def strftime(format: str, t: _TimeTuple | struct_time = ...) -> str: ... def strptime(string: str, format: str = ...) -> struct_time: ... def time() -> float: ... if sys.platform != "win32": def tzset() -> None: ... # Unix only -if sys.version_info >= (3, 3): - def get_clock_info(name: str) -> SimpleNamespace: ... - def monotonic() -> float: ... - def perf_counter() -> float: ... - def process_time() -> float: ... - if sys.platform != "win32": - def clock_getres(clk_id: int) -> float: ... # Unix only - def clock_gettime(clk_id: int) -> float: ... # Unix only - def clock_settime(clk_id: int, time: float) -> None: ... # Unix only +def get_clock_info(name: str) -> SimpleNamespace: ... +def monotonic() -> float: ... +def perf_counter() -> float: ... +def process_time() -> float: ... + +if sys.platform != "win32": + def clock_getres(clk_id: int) -> float: ... # Unix only + def clock_gettime(clk_id: int) -> float: ... # Unix only + def clock_settime(clk_id: int, time: float) -> None: ... # Unix only if sys.version_info >= (3, 7): if sys.platform != "win32": diff --git a/mypy/typeshed/stdlib/timeit.pyi b/mypy/typeshed/stdlib/timeit.pyi index 8de9af28d7ad..d82dd80598dc 100644 --- a/mypy/typeshed/stdlib/timeit.pyi +++ b/mypy/typeshed/stdlib/timeit.pyi @@ -1,44 +1,31 @@ -import sys -from typing import IO, Any, Callable, Dict, List, Optional, Sequence, Text, Tuple, Union +from typing import IO, Any, Callable, Sequence, Union -_str = Union[str, Text] _Timer = Callable[[], float] -_stmt = Union[_str, Callable[[], Any]] +_Stmt = Union[str, Callable[[], Any]] default_timer: _Timer class Timer: - if sys.version_info >= (3, 5): - def __init__( - self, stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., globals: Optional[Dict[str, Any]] = ... - ) -> None: ... - else: - def __init__(self, stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ...) -> None: ... - def print_exc(self, file: Optional[IO[str]] = ...) -> None: ... + def __init__( + self, stmt: _Stmt = ..., setup: _Stmt = ..., timer: _Timer = ..., globals: dict[str, Any] | None = ... + ) -> None: ... + def print_exc(self, file: IO[str] | None = ...) -> None: ... def timeit(self, number: int = ...) -> float: ... - def repeat(self, repeat: int = ..., number: int = ...) -> List[float]: ... - if sys.version_info >= (3, 6): - def autorange(self, callback: Optional[Callable[[int, float], Any]] = ...) -> Tuple[int, float]: ... + def repeat(self, repeat: int = ..., number: int = ...) -> list[float]: ... + def autorange(self, callback: Callable[[int, float], Any] | None = ...) -> tuple[int, float]: ... -if sys.version_info >= (3, 5): - def timeit( - stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., number: int = ..., globals: Optional[Dict[str, Any]] = ... - ) -> float: ... - def repeat( - stmt: _stmt = ..., - setup: _stmt = ..., - timer: _Timer = ..., - repeat: int = ..., - number: int = ..., - globals: Optional[Dict[str, Any]] = ..., - ) -> List[float]: ... - -else: - def timeit(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., number: int = ...) -> float: ... - def repeat( - stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., repeat: int = ..., number: int = ... - ) -> List[float]: ... +def timeit( + stmt: _Stmt = ..., setup: _Stmt = ..., timer: _Timer = ..., number: int = ..., globals: dict[str, Any] | None = ... +) -> float: ... +def repeat( + stmt: _Stmt = ..., + setup: _Stmt = ..., + timer: _Timer = ..., + repeat: int = ..., + number: int = ..., + globals: dict[str, Any] | None = ..., +) -> list[float]: ... _timerFunc = Callable[[], float] -def main(args: Optional[Sequence[str]] = ..., *, _wrap_timer: Optional[Callable[[_timerFunc], _timerFunc]] = ...) -> None: ... +def main(args: Sequence[str] | None = ..., *, _wrap_timer: Callable[[_timerFunc], _timerFunc] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index db1dd1584ae8..bda37b406fc3 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -1,26 +1,11 @@ import _tkinter import sys -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from enum import Enum from tkinter.constants import * # comment this out to find undefined identifier names with flake8 from tkinter.font import _FontDescription from types import TracebackType -from typing import ( - Any, - Callable, - Dict, - Generic, - List, - Mapping, - Optional, - Protocol, - Sequence, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import Any, Callable, Generic, List, Mapping, Optional, Protocol, Sequence, Tuple, Type, TypeVar, Union, overload from typing_extensions import Literal, TypedDict # Using anything from tkinter.font in this file means that 'import tkinter' @@ -80,38 +65,36 @@ EXCEPTION = _tkinter.EXCEPTION # actually want _ScreenUnits instead. # # - If you think that Callable[something] is an appropriate type for -# something, then you may actually want Union[Callable[something], str], +# something, then you may actually want Callable[something] | str, # because it's often possible to specify a string of Tcl code. # +# - If you think the correct type is Iterable[Foo] or Sequence[Foo], it is +# probably list[Foo] | tuple[Foo, ...], disallowing other sequences such +# as deques: +# +# >>> tkinter.Label(font=('Helvetica', 12, collections.deque(['bold']))) +# Traceback (most recent call last): +# ... +# _tkinter.TclError: unknown font style "deque(['bold'])" +# # - Some options can be set only in __init__, but all options are available # when getting their values with configure's return value or cget. # # - Asks other tkinter users if you haven't worked much with tkinter. -# _TkinterSequence[T] represents a sequence that tkinter understands. It -# differs from typing.Sequence[T]. For example, collections.deque a valid -# Sequence but not a valid _TkinterSequence: -# -# >>> tkinter.Label(font=('Helvetica', 12, collections.deque(['bold']))) -# Traceback (most recent call last): -# ... -# _tkinter.TclError: unknown font style "deque(['bold'])" -_T = TypeVar("_T") -_TkinterSequence = Union[List[_T], Tuple[_T, ...]] -_TkinterSequence2D = Union[List[List[_T]], List[Tuple[_T, ...]], Tuple[List[_T], ...], Tuple[Tuple[_T, ...], ...]] - # Some widgets have an option named -compound that accepts different values # than the _Compound defined here. Many other options have similar things. _Anchor = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"] # manual page: Tk_GetAnchor _Bitmap = str # manual page: Tk_GetBitmap _ButtonCommand = Union[str, Callable[[], Any]] # return value is returned from Button.invoke() -_CanvasItemId = int # handles for items created on a canvas - can be passed to Canvas.delete() +_CanvasItemId = int _Color = str # typically '#rrggbb', '#rgb' or color names. _Compound = Literal["top", "left", "center", "right", "bottom", "none"] # -compound in manual page named 'options' _Cursor = Union[str, Tuple[str], Tuple[str, str], Tuple[str, str, str], Tuple[str, str, str, str]] # manual page: Tk_GetCursor _EntryValidateCommand = Union[ - Callable[[], bool], str, _TkinterSequence[str] + Callable[[], bool], str, List[str], Tuple[str, ...] ] # example when it's sequence: entry['invalidcommand'] = [entry.register(print), '%P'] +_GridIndex = Union[int, str, Literal["all"]] _ImageSpec = Union[_Image, str] # str can be from e.g. tkinter.image_names() _Padding = Union[ _ScreenUnits, @@ -126,55 +109,56 @@ _XYScrollCommand = Union[str, Callable[[float, float], Any]] # -xscrollcommand _TakeFocusValue = Union[int, Literal[""], Callable[[str], Optional[bool]]] # -takefocus in manual page named 'options' class EventType(str, Enum): - Activate: str = ... - ButtonPress: str = ... - ButtonRelease: str = ... - Circulate: str = ... - CirculateRequest: str = ... - ClientMessage: str = ... - Colormap: str = ... - Configure: str = ... - ConfigureRequest: str = ... - Create: str = ... - Deactivate: str = ... - Destroy: str = ... - Enter: str = ... - Expose: str = ... - FocusIn: str = ... - FocusOut: str = ... - GraphicsExpose: str = ... - Gravity: str = ... - KeyPress: str = ... - KeyRelease: str = ... - Keymap: str = ... - Leave: str = ... - Map: str = ... - MapRequest: str = ... - Mapping: str = ... - Motion: str = ... - MouseWheel: str = ... - NoExpose: str = ... - Property: str = ... - Reparent: str = ... - ResizeRequest: str = ... - Selection: str = ... - SelectionClear: str = ... - SelectionRequest: str = ... - Unmap: str = ... - VirtualEvent: str = ... - Visibility: str = ... + Activate: str + ButtonPress: str + ButtonRelease: str + Circulate: str + CirculateRequest: str + ClientMessage: str + Colormap: str + Configure: str + ConfigureRequest: str + Create: str + Deactivate: str + Destroy: str + Enter: str + Expose: str + FocusIn: str + FocusOut: str + GraphicsExpose: str + Gravity: str + KeyPress: str + KeyRelease: str + Keymap: str + Leave: str + Map: str + MapRequest: str + Mapping: str + Motion: str + MouseWheel: str + NoExpose: str + Property: str + Reparent: str + ResizeRequest: str + Selection: str + SelectionClear: str + SelectionRequest: str + Unmap: str + VirtualEvent: str + Visibility: str +_W = TypeVar("_W", bound="Misc") # Events considered covariant because you should never assign to event.widget. -_W = TypeVar("_W", covariant=True, bound="Misc") +_W_co = TypeVar("_W_co", covariant=True, bound="Misc") -class Event(Generic[_W]): +class Event(Generic[_W_co]): serial: int num: int focus: bool height: int width: int keycode: int - state: Union[int, str] + state: int | str time: int x: int y: int @@ -185,7 +169,7 @@ class Event(Generic[_W]): keysym: str keysym_num: int type: EventType - widget: _W + widget: _W_co delta: int def NoDefaultRoot(): ... @@ -193,38 +177,38 @@ def NoDefaultRoot(): ... _TraceMode = Literal["array", "read", "write", "unset"] class Variable: - def __init__(self, master: Optional[Misc] = ..., value: Optional[Any] = ..., name: Optional[str] = ...) -> None: ... + def __init__(self, master: Misc | None = ..., value: Any | None = ..., name: str | None = ...) -> None: ... def set(self, value: Any) -> None: ... initialize = set def get(self) -> Any: ... def trace_add(self, mode: _TraceMode, callback: Callable[[str, str, str], Any]) -> str: ... def trace_remove(self, mode: _TraceMode, cbname: str) -> None: ... - def trace_info(self) -> List[Tuple[Tuple[_TraceMode, ...], str]]: ... + def trace_info(self) -> list[tuple[Tuple[_TraceMode, ...], str]]: ... def trace_variable(self, mode, callback): ... # deprecated def trace_vdelete(self, mode, cbname): ... # deprecated def trace_vinfo(self): ... # deprecated trace = trace_variable # deprecated class StringVar(Variable): - def __init__(self, master: Optional[Misc] = ..., value: Optional[str] = ..., name: Optional[str] = ...) -> None: ... + def __init__(self, master: Misc | None = ..., value: str | None = ..., name: str | None = ...) -> None: ... def set(self, value: str) -> None: ... initialize = set def get(self) -> str: ... class IntVar(Variable): - def __init__(self, master: Optional[Misc] = ..., value: Optional[int] = ..., name: Optional[str] = ...) -> None: ... + def __init__(self, master: Misc | None = ..., value: int | None = ..., name: str | None = ...) -> None: ... def set(self, value: int) -> None: ... initialize = set def get(self) -> int: ... class DoubleVar(Variable): - def __init__(self, master: Optional[Misc] = ..., value: Optional[float] = ..., name: Optional[str] = ...) -> None: ... + def __init__(self, master: Misc | None = ..., value: float | None = ..., name: str | None = ...) -> None: ... def set(self, value: float) -> None: ... initialize = set def get(self) -> float: ... class BooleanVar(Variable): - def __init__(self, master: Optional[Misc] = ..., value: Optional[bool] = ..., name: Optional[str] = ...) -> None: ... + def __init__(self, master: Misc | None = ..., value: bool | None = ..., name: str | None = ...) -> None: ... def set(self, value: bool) -> None: ... initialize = set def get(self) -> bool: ... @@ -236,19 +220,25 @@ getdouble: Any def getboolean(s): ... +class _GridIndexInfo(TypedDict, total=False): + minsize: _ScreenUnits + pad: _ScreenUnits + uniform: str | None + weight: int + class Misc: - master: Optional[Misc] + master: Misc | None tk: _tkinter.TkappType - children: Dict[str, Widget] + children: dict[str, Widget] def destroy(self) -> None: ... def deletecommand(self, name: str) -> None: ... - def tk_strictMotif(self, boolean: Optional[Any] = ...): ... + def tk_strictMotif(self, boolean: Any | None = ...): ... def tk_bisque(self): ... def tk_setPalette(self, *args, **kw): ... - def wait_variable(self, name: Union[str, Variable] = ...) -> None: ... + def wait_variable(self, name: str | Variable = ...) -> None: ... waitvar = wait_variable - def wait_window(self, window: Optional[Misc] = ...) -> None: ... - def wait_visibility(self, window: Optional[Misc] = ...) -> None: ... + def wait_window(self, window: Misc | None = ...) -> None: ... + def wait_visibility(self, window: Misc | None = ...) -> None: ... def setvar(self, name: str = ..., value: str = ...): ... def getvar(self, name: str = ...): ... def getint(self, s): ... @@ -257,67 +247,67 @@ class Misc: def focus_set(self) -> None: ... focus = focus_set def focus_force(self) -> None: ... - def focus_get(self) -> Optional[Misc]: ... - def focus_displayof(self) -> Optional[Misc]: ... - def focus_lastfor(self) -> Optional[Misc]: ... + def focus_get(self) -> Misc | None: ... + def focus_displayof(self) -> Misc | None: ... + def focus_lastfor(self) -> Misc | None: ... def tk_focusFollowsMouse(self) -> None: ... - def tk_focusNext(self) -> Optional[Misc]: ... - def tk_focusPrev(self) -> Optional[Misc]: ... + def tk_focusNext(self) -> Misc | None: ... + def tk_focusPrev(self) -> Misc | None: ... @overload def after(self, ms: int, func: None = ...) -> None: ... @overload - def after(self, ms: Union[int, Literal["idle"]], func: Callable[..., Any], *args: Any) -> str: ... + def after(self, ms: int | Literal["idle"], func: Callable[..., Any], *args: Any) -> str: ... # after_idle is essentially partialmethod(after, "idle") def after_idle(self, func: Callable[..., Any], *args: Any) -> str: ... def after_cancel(self, id: str) -> None: ... - def bell(self, displayof: Union[Literal[0], Misc, None] = ...): ... + def bell(self, displayof: Literal[0] | Misc | None = ...): ... def clipboard_get(self, *, displayof: Misc = ..., type: str = ...) -> str: ... def clipboard_clear(self, *, displayof: Misc = ...) -> None: ... def clipboard_append(self, string: str, *, displayof: Misc = ..., format: str = ..., type: str = ...): ... def grab_current(self): ... def grab_release(self): ... - def grab_set(self): ... - def grab_set_global(self): ... + def grab_set(self) -> None: ... + def grab_set_global(self) -> None: ... def grab_status(self): ... - def option_add(self, pattern, value, priority: Optional[Any] = ...): ... + def option_add(self, pattern, value, priority: Any | None = ...): ... def option_clear(self): ... def option_get(self, name, className): ... - def option_readfile(self, fileName, priority: Optional[Any] = ...): ... + def option_readfile(self, fileName, priority: Any | None = ...): ... def selection_clear(self, **kw): ... def selection_get(self, **kw): ... def selection_handle(self, command, **kw): ... def selection_own(self, **kw): ... def selection_own_get(self, **kw): ... def send(self, interp, cmd, *args): ... - def lower(self, belowThis: Optional[Any] = ...): ... - def tkraise(self, aboveThis: Optional[Any] = ...): ... + def lower(self, belowThis: Any | None = ...): ... + def tkraise(self, aboveThis: Any | None = ...): ... lift = tkraise - def winfo_atom(self, name: str, displayof: Union[Literal[0], Misc, None] = ...): ... - def winfo_atomname(self, id: int, displayof: Union[Literal[0], Misc, None] = ...): ... + def winfo_atom(self, name: str, displayof: Literal[0] | Misc | None = ...): ... + def winfo_atomname(self, id: int, displayof: Literal[0] | Misc | None = ...): ... def winfo_cells(self) -> int: ... - def winfo_children(self) -> List[Widget]: ... # Widget because it can't be Toplevel or Tk + def winfo_children(self) -> list[Widget]: ... # Widget because it can't be Toplevel or Tk def winfo_class(self) -> str: ... def winfo_colormapfull(self) -> bool: ... - def winfo_containing(self, rootX: int, rootY: int, displayof: Union[Literal[0], Misc, None] = ...) -> Optional[Misc]: ... + def winfo_containing(self, rootX: int, rootY: int, displayof: Literal[0] | Misc | None = ...) -> Misc | None: ... def winfo_depth(self) -> int: ... def winfo_exists(self) -> bool: ... def winfo_fpixels(self, number: _ScreenUnits) -> float: ... def winfo_geometry(self) -> str: ... def winfo_height(self) -> int: ... def winfo_id(self) -> int: ... - def winfo_interps(self, displayof: Union[Literal[0], Misc, None] = ...) -> Tuple[str, ...]: ... + def winfo_interps(self, displayof: Literal[0] | Misc | None = ...) -> Tuple[str, ...]: ... def winfo_ismapped(self) -> bool: ... def winfo_manager(self) -> str: ... def winfo_name(self) -> str: ... def winfo_parent(self) -> str: ... # return value needs nametowidget() - def winfo_pathname(self, id: int, displayof: Union[Literal[0], Misc, None] = ...): ... + def winfo_pathname(self, id: int, displayof: Literal[0] | Misc | None = ...): ... def winfo_pixels(self, number: _ScreenUnits) -> int: ... def winfo_pointerx(self) -> int: ... - def winfo_pointerxy(self) -> Tuple[int, int]: ... + def winfo_pointerxy(self) -> tuple[int, int]: ... def winfo_pointery(self) -> int: ... def winfo_reqheight(self) -> int: ... def winfo_reqwidth(self) -> int: ... - def winfo_rgb(self, color: _Color) -> Tuple[int, int, int]: ... + def winfo_rgb(self, color: _Color) -> tuple[int, int, int]: ... def winfo_rootx(self) -> int: ... def winfo_rooty(self) -> int: ... def winfo_screen(self) -> str: ... @@ -329,11 +319,11 @@ class Misc: def winfo_screenvisual(self) -> str: ... def winfo_screenwidth(self) -> int: ... def winfo_server(self) -> str: ... - def winfo_toplevel(self) -> Union[Tk, Toplevel]: ... + def winfo_toplevel(self) -> Tk | Toplevel: ... def winfo_viewable(self) -> bool: ... def winfo_visual(self) -> str: ... def winfo_visualid(self) -> str: ... - def winfo_visualsavailable(self, includeids: int = ...) -> List[Tuple[str, int]]: ... + def winfo_visualsavailable(self, includeids: int = ...) -> list[tuple[str, int]]: ... def winfo_vrootheight(self) -> int: ... def winfo_vrootwidth(self) -> int: ... def winfo_vrootx(self) -> int: ... @@ -343,80 +333,104 @@ class Misc: def winfo_y(self) -> int: ... def update(self) -> None: ... def update_idletasks(self) -> None: ... - def bindtags(self, tagList: Optional[Any] = ...): ... + def bindtags(self, tagList: Any | None = ...): ... # bind with isinstance(func, str) doesn't return anything, but all other # binds do. The default value of func is not str. @overload def bind( - self, sequence: Optional[str] = ..., func: Optional[Callable[[Event[Misc]], Any]] = ..., add: Optional[bool] = ... + self, + sequence: str | None = ..., + func: Callable[[Event[Misc]], Any] | None = ..., + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def bind(self, sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... + def bind(self, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... @overload - def bind(self, *, func: str, add: Optional[bool] = ...) -> None: ... + def bind(self, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... # There's no way to know what type of widget bind_all and bind_class # callbacks will get, so those are Misc. @overload def bind_all( - self, sequence: Optional[str] = ..., func: Optional[Callable[[Event[Misc]], Any]] = ..., add: Optional[bool] = ... + self, + sequence: str | None = ..., + func: Callable[[Event[Misc]], Any] | None = ..., + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def bind_all(self, sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... + def bind_all(self, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... @overload - def bind_all(self, *, func: str, add: Optional[bool] = ...) -> None: ... + def bind_all(self, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... @overload def bind_class( self, className: str, - sequence: Optional[str] = ..., - func: Optional[Callable[[Event[Misc]], Any]] = ..., - add: Optional[bool] = ..., + sequence: str | None = ..., + func: Callable[[Event[Misc]], Any] | None = ..., + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def bind_class(self, className: str, sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... + def bind_class(self, className: str, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... @overload - def bind_class(self, className: str, *, func: str, add: Optional[bool] = ...) -> None: ... - def unbind(self, sequence: str, funcid: Optional[str] = ...) -> None: ... + def bind_class(self, className: str, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... + def unbind(self, sequence: str, funcid: str | None = ...) -> None: ... def unbind_all(self, sequence: str) -> None: ... def unbind_class(self, className: str, sequence: str) -> None: ... def mainloop(self, n: int = ...) -> None: ... def quit(self): ... - def nametowidget(self, name: Union[str, Misc, _tkinter.Tcl_Obj]) -> Any: ... + def nametowidget(self, name: str | Misc | _tkinter.Tcl_Obj) -> Any: ... def register( - self, func: Callable[..., Any], subst: Optional[Callable[..., Sequence[Any]]] = ..., needcleanup: int = ... + self, func: Callable[..., Any], subst: Callable[..., Sequence[Any]] | None = ..., needcleanup: int = ... ) -> str: ... - def keys(self) -> List[str]: ... + def keys(self) -> list[str]: ... @overload - def pack_propagate(self, flag: bool) -> Optional[bool]: ... + def pack_propagate(self, flag: bool) -> bool | None: ... @overload def pack_propagate(self) -> None: ... propagate = pack_propagate - def grid_anchor(self, anchor: Optional[_Anchor] = ...) -> None: ... + def grid_anchor(self, anchor: _Anchor | None = ...) -> None: ... anchor = grid_anchor @overload def grid_bbox( self, column: None = ..., row: None = ..., col2: None = ..., row2: None = ... - ) -> Optional[Tuple[int, int, int, int]]: ... + ) -> tuple[int, int, int, int] | None: ... @overload - def grid_bbox(self, column: int, row: int, col2: None = ..., row2: None = ...) -> Optional[Tuple[int, int, int, int]]: ... + def grid_bbox(self, column: int, row: int, col2: None = ..., row2: None = ...) -> tuple[int, int, int, int] | None: ... @overload - def grid_bbox(self, column: int, row: int, col2: int, row2: int) -> Optional[Tuple[int, int, int, int]]: ... + def grid_bbox(self, column: int, row: int, col2: int, row2: int) -> tuple[int, int, int, int] | None: ... bbox = grid_bbox - def grid_columnconfigure(self, index, cnf=..., **kw): ... # TODO - def grid_rowconfigure(self, index, cnf=..., **kw): ... # TODO + def grid_columnconfigure( + self, + index: _GridIndex, + cnf: _GridIndexInfo = ..., + *, + minsize: _ScreenUnits = ..., + pad: _ScreenUnits = ..., + uniform: str = ..., + weight: int = ..., + ) -> _GridIndexInfo | Any: ... # can be None but annoying to check + def grid_rowconfigure( + self, + index: _GridIndex, + cnf: _GridIndexInfo = ..., + *, + minsize: _ScreenUnits = ..., + pad: _ScreenUnits = ..., + uniform: str = ..., + weight: int = ..., + ) -> _GridIndexInfo | Any: ... # can be None but annoying to check columnconfigure = grid_columnconfigure rowconfigure = grid_rowconfigure - def grid_location(self, x: _ScreenUnits, y: _ScreenUnits) -> Tuple[int, int]: ... + def grid_location(self, x: _ScreenUnits, y: _ScreenUnits) -> tuple[int, int]: ... @overload def grid_propagate(self, flag: bool) -> None: ... @overload def grid_propagate(self) -> bool: ... - def grid_size(self) -> Tuple[int, int]: ... + def grid_size(self) -> tuple[int, int]: ... size = grid_size # Widget because Toplevel or Tk is never a slave - def pack_slaves(self) -> List[Widget]: ... - def grid_slaves(self, row: Optional[int] = ..., column: Optional[int] = ...) -> List[Widget]: ... - def place_slaves(self) -> List[Widget]: ... + def pack_slaves(self) -> list[Widget]: ... + def grid_slaves(self, row: int | None = ..., column: int | None = ...) -> list[Widget]: ... + def place_slaves(self) -> list[Widget]: ... slaves = pack_slaves def event_add(self, virtual: str, *sequences: str) -> None: ... def event_delete(self, virtual: str, *sequences: str) -> None: ... @@ -424,7 +438,7 @@ class Misc: self, sequence: str, *, - above: Union[Misc, int] = ..., + above: Misc | int = ..., borderwidth: _ScreenUnits = ..., button: int = ..., count: int = ..., @@ -438,13 +452,13 @@ class Misc: mode: str = ..., override: bool = ..., place: Literal["PlaceOnTop", "PlaceOnBottom"] = ..., - root: Union[Misc, int] = ..., + root: Misc | int = ..., rootx: _ScreenUnits = ..., rooty: _ScreenUnits = ..., sendevent: bool = ..., serial: int = ..., - state: Union[int, str] = ..., - subwindow: Union[Misc, int] = ..., + state: int | str = ..., + subwindow: Misc | int = ..., time: int = ..., warp: bool = ..., width: _ScreenUnits = ..., @@ -452,7 +466,7 @@ class Misc: x: _ScreenUnits = ..., y: _ScreenUnits = ..., ) -> None: ... - def event_info(self, virtual: Optional[str] = ...) -> Tuple[str, ...]: ... + def event_info(self, virtual: str | None = ...) -> Tuple[str, ...]: ... def image_names(self) -> Tuple[str, ...]: ... def image_types(self) -> Tuple[str, ...]: ... # See #4363 and #4891 @@ -470,14 +484,26 @@ class CallWrapper: def __call__(self, *args): ... class XView: - def xview(self, *args): ... - def xview_moveto(self, fraction): ... - def xview_scroll(self, number, what): ... + @overload + def xview(self) -> tuple[float, float]: ... + @overload + def xview(self, *args: Any) -> Any: ... + def xview_moveto(self, fraction: float) -> None: ... + @overload + def xview_scroll(self, number: int, what: Literal["units", "pages"]) -> None: ... + @overload + def xview_scroll(self, number: _ScreenUnits, what: Literal["pixels"]) -> None: ... class YView: - def yview(self, *args): ... - def yview_moveto(self, fraction): ... - def yview_scroll(self, number, what): ... + @overload + def yview(self) -> tuple[float, float]: ... + @overload + def yview(self, *args: Any) -> Any: ... + def yview_moveto(self, fraction: float) -> None: ... + @overload + def yview_scroll(self, number: int, what: Literal["units", "pages"]) -> None: ... + @overload + def yview_scroll(self, number: _ScreenUnits, what: Literal["pixels"]) -> None: ... class Wm: @overload @@ -485,7 +511,7 @@ class Wm: @overload def wm_aspect( self, minNumer: None = ..., minDenom: None = ..., maxNumer: None = ..., maxDenom: None = ... - ) -> Optional[Tuple[int, int, int, int]]: ... + ) -> tuple[int, int, int, int] | None: ... aspect = wm_aspect @overload def wm_attributes(self) -> Tuple[Any, ...]: ... @@ -494,21 +520,21 @@ class Wm: @overload def wm_attributes(self, __option: str, __value: Any, *__other_option_value_pairs: Any) -> None: ... attributes = wm_attributes - def wm_client(self, name: Optional[str] = ...) -> str: ... + def wm_client(self, name: str | None = ...) -> str: ... client = wm_client @overload - def wm_colormapwindows(self) -> List[Misc]: ... + def wm_colormapwindows(self) -> list[Misc]: ... @overload - def wm_colormapwindows(self, __wlist: _TkinterSequence[Misc]) -> None: ... + def wm_colormapwindows(self, __wlist: list[Misc] | Tuple[Misc, ...]) -> None: ... @overload def wm_colormapwindows(self, __first_wlist_item: Misc, *other_wlist_items: Misc) -> None: ... colormapwindows = wm_colormapwindows - def wm_command(self, value: Optional[str] = ...) -> str: ... + def wm_command(self, value: str | None = ...) -> str: ... command = wm_command # Some of these always return empty string, but return type is set to None to prevent accidentally using it def wm_deiconify(self) -> None: ... deiconify = wm_deiconify - def wm_focusmodel(self, model: Optional[Any] = ...): ... + def wm_focusmodel(self, model: Any | None = ...): ... focusmodel = wm_focusmodel def wm_forget(self, window: Wm) -> None: ... forget = wm_forget @@ -520,61 +546,57 @@ class Wm: def wm_geometry(self, newGeometry: str) -> None: ... geometry = wm_geometry def wm_grid( - self, - baseWidth: Optional[Any] = ..., - baseHeight: Optional[Any] = ..., - widthInc: Optional[Any] = ..., - heightInc: Optional[Any] = ..., + self, baseWidth: Any | None = ..., baseHeight: Any | None = ..., widthInc: Any | None = ..., heightInc: Any | None = ... ): ... grid = wm_grid - def wm_group(self, pathName: Optional[Any] = ...): ... + def wm_group(self, pathName: Any | None = ...): ... group = wm_group - def wm_iconbitmap(self, bitmap: Optional[Any] = ..., default: Optional[Any] = ...): ... + def wm_iconbitmap(self, bitmap: Any | None = ..., default: Any | None = ...): ... iconbitmap = wm_iconbitmap def wm_iconify(self) -> None: ... iconify = wm_iconify - def wm_iconmask(self, bitmap: Optional[Any] = ...): ... + def wm_iconmask(self, bitmap: Any | None = ...): ... iconmask = wm_iconmask - def wm_iconname(self, newName: Optional[Any] = ...): ... + def wm_iconname(self, newName: Any | None = ...): ... iconname = wm_iconname def wm_iconphoto(self, default: bool, __image1: Image, *args: Image) -> None: ... iconphoto = wm_iconphoto - def wm_iconposition(self, x: Optional[Any] = ..., y: Optional[Any] = ...): ... + def wm_iconposition(self, x: Any | None = ..., y: Any | None = ...): ... iconposition = wm_iconposition - def wm_iconwindow(self, pathName: Optional[Any] = ...): ... + def wm_iconwindow(self, pathName: Any | None = ...): ... iconwindow = wm_iconwindow def wm_manage(self, widget): ... manage = wm_manage @overload - def wm_maxsize(self, width: None = ..., height: None = ...) -> Tuple[int, int]: ... + def wm_maxsize(self, width: None = ..., height: None = ...) -> tuple[int, int]: ... @overload def wm_maxsize(self, width: int, height: int) -> None: ... maxsize = wm_maxsize @overload - def wm_minsize(self, width: None = ..., height: None = ...) -> Tuple[int, int]: ... + def wm_minsize(self, width: None = ..., height: None = ...) -> tuple[int, int]: ... @overload def wm_minsize(self, width: int, height: int) -> None: ... minsize = wm_minsize @overload - def wm_overrideredirect(self, boolean: None = ...) -> Optional[bool]: ... # returns True or None + def wm_overrideredirect(self, boolean: None = ...) -> bool | None: ... # returns True or None @overload def wm_overrideredirect(self, boolean: bool) -> None: ... overrideredirect = wm_overrideredirect - def wm_positionfrom(self, who: Optional[Any] = ...): ... + def wm_positionfrom(self, who: Any | None = ...): ... positionfrom = wm_positionfrom @overload - def wm_protocol(self, name: str, func: Union[Callable[[], Any], str]) -> None: ... + def wm_protocol(self, name: str, func: Callable[[], Any] | str) -> None: ... @overload def wm_protocol(self, name: str, func: None = ...) -> str: ... @overload def wm_protocol(self, name: None = ..., func: None = ...) -> Tuple[str, ...]: ... protocol = wm_protocol @overload - def wm_resizable(self, width: None = ..., height: None = ...) -> Tuple[bool, bool]: ... + def wm_resizable(self, width: None = ..., height: None = ...) -> tuple[bool, bool]: ... @overload def wm_resizable(self, width: bool, height: bool) -> None: ... resizable = wm_resizable - def wm_sizefrom(self, who: Optional[Any] = ...): ... + def wm_sizefrom(self, who: Any | None = ...): ... sizefrom = wm_sizefrom @overload def wm_state(self, newstate: None = ...) -> str: ... @@ -589,29 +611,30 @@ class Wm: @overload def wm_transient(self, master: None = ...) -> _tkinter.Tcl_Obj: ... @overload - def wm_transient(self, master: Union[Wm, _tkinter.Tcl_Obj]) -> None: ... + def wm_transient(self, master: Wm | _tkinter.Tcl_Obj) -> None: ... transient = wm_transient def wm_withdraw(self) -> None: ... withdraw = wm_withdraw class _ExceptionReportingCallback(Protocol): - def __call__(self, __exc: Type[BaseException], __val: BaseException, __tb: TracebackType) -> Any: ... + def __call__(self, __exc: Type[BaseException], __val: BaseException, __tb: TracebackType | None) -> Any: ... class Tk(Misc, Wm): master: None def __init__( + # please update ttkthemes stub if you change this self, - screenName: Optional[str] = ..., - baseName: Optional[str] = ..., + screenName: str | None = ..., + baseName: str | None = ..., className: str = ..., useTk: bool = ..., sync: bool = ..., - use: Optional[str] = ..., + use: str | None = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -629,9 +652,9 @@ class Tk(Misc, Wm): relief: _Relief = ..., takefocus: _TakeFocusValue = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def loadtk(self) -> None: ... # differs from _tkinter.TkappType.loadtk def destroy(self) -> None: ... @@ -671,7 +694,7 @@ class Tk(Misc, Wm): wantobjects: Any willdispatch: Any -def Tcl(screenName: Optional[Any] = ..., baseName: Optional[Any] = ..., className: str = ..., useTk: bool = ...): ... +def Tcl(screenName: Any | None = ..., baseName: Any | None = ..., className: str = ..., useTk: bool = ...): ... _InMiscTotal = TypedDict("_InMiscTotal", {"in": Misc}) _InMiscNonTotal = TypedDict("_InMiscNonTotal", {"in": Misc}, total=False) @@ -686,8 +709,8 @@ class _PackInfo(_InMiscTotal): # can be specified in pack(). ipadx: int ipady: int - padx: Union[int, Tuple[int, int]] - pady: Union[int, Tuple[int, int]] + padx: int | tuple[int, int] + pady: int | tuple[int, int] class Pack: # _PackInfo is not the valid type for cnf because pad stuff accepts any @@ -696,7 +719,7 @@ class Pack: # replaced by **kwargs. def pack_configure( self, - cnf: Optional[Mapping[str, Any]] = ..., + cnf: Mapping[str, Any] | None = ..., *, after: Misc = ..., anchor: _Anchor = ..., @@ -706,8 +729,8 @@ class Pack: side: Literal["left", "right", "top", "bottom"] = ..., ipadx: _ScreenUnits = ..., ipady: _ScreenUnits = ..., - padx: Union[_ScreenUnits, Tuple[_ScreenUnits, _ScreenUnits]] = ..., - pady: Union[_ScreenUnits, Tuple[_ScreenUnits, _ScreenUnits]] = ..., + padx: _ScreenUnits | tuple[_ScreenUnits, _ScreenUnits] = ..., + pady: _ScreenUnits | tuple[_ScreenUnits, _ScreenUnits] = ..., in_: Misc = ..., **kw: Any, # allow keyword argument named 'in', see #4836 ) -> None: ... @@ -717,7 +740,7 @@ class Pack: forget = pack_forget propagate = Misc.pack_propagate # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overrided with different things + # inheritance and how things get overridden with different things # info = pack_info # pack_propagate = Misc.pack_propagate # configure = pack_configure @@ -740,7 +763,7 @@ class _PlaceInfo(_InMiscNonTotal): # empty dict if widget hasn't been placed class Place: def place_configure( self, - cnf: Optional[Mapping[str, Any]] = ..., + cnf: Mapping[str, Any] | None = ..., *, anchor: _Anchor = ..., bordermode: Literal["inside", "outside", "ignore"] = ..., @@ -749,10 +772,10 @@ class Place: x: _ScreenUnits = ..., y: _ScreenUnits = ..., # str allowed for compatibility with place_info() - relheight: Union[str, float] = ..., - relwidth: Union[str, float] = ..., - relx: Union[str, float] = ..., - rely: Union[str, float] = ..., + relheight: str | float = ..., + relwidth: str | float = ..., + relx: str | float = ..., + rely: str | float = ..., in_: Misc = ..., **kw: Any, # allow keyword argument named 'in', see #4836 ) -> None: ... @@ -761,7 +784,7 @@ class Place: place = place_configure info = place_info # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overrided with different things + # inheritance and how things get overridden with different things # config = place_configure # configure = place_configure # forget = place_forget @@ -775,14 +798,14 @@ class _GridInfo(_InMiscNonTotal): # empty dict if widget hasn't been gridded rowspan: int ipadx: int ipady: int - padx: Union[int, Tuple[int, int]] - pady: Union[int, Tuple[int, int]] + padx: int | tuple[int, int] + pady: int | tuple[int, int] sticky: str # consists of letters 'n', 's', 'w', 'e', no repeats, may be empty class Grid: def grid_configure( self, - cnf: Optional[Mapping[str, Any]] = ..., + cnf: Mapping[str, Any] | None = ..., *, column: int = ..., columnspan: int = ..., @@ -790,8 +813,8 @@ class Grid: rowspan: int = ..., ipadx: _ScreenUnits = ..., ipady: _ScreenUnits = ..., - padx: Union[_ScreenUnits, Tuple[_ScreenUnits, _ScreenUnits]] = ..., - pady: Union[_ScreenUnits, Tuple[_ScreenUnits, _ScreenUnits]] = ..., + padx: _ScreenUnits | tuple[_ScreenUnits, _ScreenUnits] = ..., + pady: _ScreenUnits | tuple[_ScreenUnits, _ScreenUnits] = ..., sticky: str = ..., # consists of letters 'n', 's', 'w', 'e', may contain repeats, may be empty in_: Misc = ..., **kw: Any, # allow keyword argument named 'in', see #4836 @@ -803,7 +826,7 @@ class Grid: location = Misc.grid_location size = Misc.grid_size # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overrided with different things + # inheritance and how things get overridden with different things # bbox = Misc.grid_bbox # grid_bbox = Misc.grid_bbox # forget = grid_forget @@ -834,12 +857,15 @@ class Widget(BaseWidget, Pack, Place, Grid): # widgets don't. @overload def bind( - self: _W, sequence: Optional[str] = ..., func: Optional[Callable[[Event[_W]], Any]] = ..., add: Optional[bool] = ... + self: _W, + sequence: str | None = ..., + func: Callable[[Event[_W]], Any] | None = ..., + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def bind(self, sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... + def bind(self, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... @overload - def bind(self, *, func: str, add: Optional[bool] = ...) -> None: ... + def bind(self, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... class Toplevel(BaseWidget, Wm): # Toplevel and Tk have the same options because they correspond to the same @@ -847,8 +873,8 @@ class Toplevel(BaseWidget, Wm): # copy/pasted here instead of aliasing as 'config = Tk.config'. def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -856,7 +882,7 @@ class Toplevel(BaseWidget, Wm): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., class_: str = ..., - colormap: Union[Literal["new", ""], Misc] = ..., + colormap: Literal["new", ""] | Misc = ..., container: bool = ..., cursor: _Cursor = ..., height: _ScreenUnits = ..., @@ -871,13 +897,13 @@ class Toplevel(BaseWidget, Wm): screen: str = ..., # can't be changed after creating widget takefocus: _TakeFocusValue = ..., use: int = ..., - visual: Union[str, Tuple[str, int]] = ..., + visual: str | tuple[str, int] = ..., width: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -895,16 +921,16 @@ class Toplevel(BaseWidget, Wm): relief: _Relief = ..., takefocus: _TakeFocusValue = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Button(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -940,8 +966,8 @@ class Button(Widget): repeatinterval: int = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., - # We allow the textvariable to be any Variable, not necessarly + text: float | str = ..., + # We allow the textvariable to be any Variable, not necessarily # StringVar. This is useful for e.g. a button that displays the value # of an IntVar. textvariable: Variable = ..., @@ -952,7 +978,7 @@ class Button(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -985,23 +1011,23 @@ class Button(Widget): repeatinterval: int = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., underline: int = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def flash(self): ... - def invoke(self): ... + def invoke(self) -> Any: ... class Canvas(Widget, XView, YView): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1027,7 +1053,7 @@ class Canvas(Widget, XView, YView): relief: _Relief = ..., # Setting scrollregion to None doesn't reset it back to empty, # but setting it to () does. - scrollregion: Union[Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], Tuple[()]] = ..., + scrollregion: tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits] | tuple[()] = ..., selectbackground: _Color = ..., selectborderwidth: _ScreenUnits = ..., selectforeground: _Color = ..., @@ -1043,7 +1069,7 @@ class Canvas(Widget, XView, YView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1064,7 +1090,7 @@ class Canvas(Widget, XView, YView): insertwidth: _ScreenUnits = ..., offset: Any = ..., # undocumented relief: _Relief = ..., - scrollregion: Union[Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], Tuple[()]] = ..., + scrollregion: tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits] | tuple[()] = ..., selectbackground: _Color = ..., selectborderwidth: _ScreenUnits = ..., selectforeground: _Color = ..., @@ -1075,38 +1101,70 @@ class Canvas(Widget, XView, YView): xscrollincrement: _ScreenUnits = ..., yscrollcommand: _XYScrollCommand = ..., yscrollincrement: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def addtag(self, *args): ... - def addtag_above(self, newtag, tagOrId): ... - def addtag_all(self, newtag): ... - def addtag_below(self, newtag, tagOrId): ... - def addtag_closest(self, newtag, x, y, halo: Optional[Any] = ..., start: Optional[Any] = ...): ... - def addtag_enclosed(self, newtag, x1, y1, x2, y2): ... - def addtag_overlapping(self, newtag, x1, y1, x2, y2): ... - def addtag_withtag(self, newtag, tagOrId): ... - def bbox(self, *args): ... + def addtag(self, *args): ... # internal method + def addtag_above(self, newtag: str, tagOrId: str | _CanvasItemId) -> None: ... + def addtag_all(self, newtag: str) -> None: ... + def addtag_below(self, newtag: str, tagOrId: str | _CanvasItemId) -> None: ... + def addtag_closest( + self, + newtag: str, + x: _ScreenUnits, + y: _ScreenUnits, + halo: _ScreenUnits | None = ..., + start: str | _CanvasItemId | None = ..., + ) -> None: ... + def addtag_enclosed(self, newtag: str, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: _ScreenUnits) -> None: ... + def addtag_overlapping(self, newtag: str, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: _ScreenUnits) -> None: ... + def addtag_withtag(self, newtag: str, tagOrId: str | _CanvasItemId) -> None: ... + def find(self, *args): ... # internal method + def find_above(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... + def find_all(self) -> Tuple[_CanvasItemId, ...]: ... + def find_below(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... + def find_closest( + self, x: _ScreenUnits, y: _ScreenUnits, halo: _ScreenUnits | None = ..., start: str | _CanvasItemId | None = ... + ) -> Tuple[_CanvasItemId, ...]: ... + def find_enclosed( + self, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: _ScreenUnits + ) -> Tuple[_CanvasItemId, ...]: ... + def find_overlapping(self, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: float) -> Tuple[_CanvasItemId, ...]: ... + def find_withtag(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... + # Canvas.bbox() args are `str | _CanvasItemId`, but mypy rejects that + # description because it's incompatible with Misc.bbox(), an alias for + # Misc.grid_bbox(). Yes it is, but there's not much we can do about it. + def bbox(self, *args: str | _CanvasItemId) -> tuple[int, int, int, int]: ... # type: ignore @overload def tag_bind( self, - tagOrId: Union[str, int], - sequence: Optional[str] = ..., - func: Optional[Callable[[Event[Canvas]], Any]] = ..., - add: Optional[bool] = ..., + tagOrId: str | int, + sequence: str | None = ..., + func: Callable[[Event[Canvas]], Any] | None = ..., + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def tag_bind(self, tagOrId: Union[str, int], sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... + def tag_bind( + self, tagOrId: str | int, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ... + ) -> None: ... + @overload + def tag_bind(self, tagOrId: str | int, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... + def tag_unbind(self, tagOrId: str | int, sequence: str, funcid: str | None = ...) -> None: ... + def canvasx(self, screenx, gridspacing: Any | None = ...): ... + def canvasy(self, screeny, gridspacing: Any | None = ...): ... + @overload + def coords(self) -> list[float]: ... + @overload + def coords(self, __args: list[int] | list[float] | Tuple[float, ...]) -> None: ... @overload - def tag_bind(self, tagOrId: Union[str, int], *, func: str, add: Optional[bool] = ...) -> None: ... - def tag_unbind(self, tagOrId: Union[str, int], sequence: str, funcid: Optional[str] = ...) -> None: ... - def canvasx(self, screenx, gridspacing: Optional[Any] = ...): ... - def canvasy(self, screeny, gridspacing: Optional[Any] = ...): ... - def coords(self, *args): ... + def coords(self, __x1: float, __y1: float, *args: float) -> None: ... + # create_foo() methods accept coords as a list, a tuple, or as separate arguments. + # Keyword arguments should be the same in each pair of overloads. def create_arc(self, *args, **kw) -> _CanvasItemId: ... def create_bitmap(self, *args, **kw) -> _CanvasItemId: ... def create_image(self, *args, **kw) -> _CanvasItemId: ... + @overload def create_line( self, __x0: float, @@ -1114,16 +1172,16 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: _Color = ..., + activedash: str | list[int] | Tuple[int, ...] = ..., activefill: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., arrow: Literal["first", "last", "both"] = ..., - arrowshape: Tuple[float, float, float] = ..., + arrowshape: tuple[float, float, float] = ..., capstyle: Literal["round", "projecting", "butt"] = ..., - dash: Union[Tuple[float], Tuple[float, float], Tuple[float, float, float, float]] = ..., + dash: str | list[int] | Tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: _Color = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., disabledfill: _Color = ..., disabledstipple: _Bitmap = ..., disabledwidth: _ScreenUnits = ..., @@ -1134,9 +1192,38 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: Union[str, Tuple[str, ...]] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... + @overload + def create_line( + self, + __coords: tuple[float, float, float, float] | list[int] | list[float], + *, + activedash: str | list[int] | Tuple[int, ...] = ..., + activefill: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + arrow: Literal["first", "last", "both"] = ..., + arrowshape: tuple[float, float, float] = ..., + capstyle: Literal["round", "projecting", "butt"] = ..., + dash: str | list[int] | Tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + joinstyle: Literal["round", "bevel", "miter"] = ..., + offset: _ScreenUnits = ..., + smooth: bool = ..., + splinesteps: float = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload def create_oval( self, __x0: float, @@ -1144,15 +1231,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: _Color = ..., + activedash: str | list[int] | Tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: Union[Tuple[float], Tuple[float, float], Tuple[float, float, float, float]] = ..., + dash: str | list[int] | Tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: _Color = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1165,9 +1252,39 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: Union[str, Tuple[str, ...]] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... + @overload + def create_oval( + self, + __coords: tuple[float, float, float, float] | list[int] | list[float], + *, + activedash: str | list[int] | Tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | Tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload def create_polygon( self, __x0: float, @@ -1175,15 +1292,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *xy_pairs: float, - activedash: _Color = ..., + activedash: str | list[int] | Tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: Union[Tuple[float], Tuple[float, float], Tuple[float, float, float, float]] = ..., + dash: str | list[int] | Tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: _Color = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1199,9 +1316,42 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: Union[str, Tuple[str, ...]] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... + @overload + def create_polygon( + self, + __coords: Tuple[float, ...] | list[int] | list[float], + *, + activedash: str | list[int] | Tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | Tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + joinstyle: Literal["round", "bevel", "miter"] = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + smooth: bool = ..., + splinesteps: float = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload def create_rectangle( self, __x0: float, @@ -1209,15 +1359,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: _Color = ..., + activedash: str | list[int] | Tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: Union[Tuple[float], Tuple[float, float], Tuple[float, float, float, float]] = ..., + dash: str | list[int] | Tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: _Color = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1230,9 +1380,39 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: Union[str, Tuple[str, ...]] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... + @overload + def create_rectangle( + self, + __coords: tuple[float, float, float, float] | list[int] | list[float], + *, + activedash: str | list[int] | Tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | Tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | Tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload def create_text( self, __x: float, @@ -1249,10 +1429,31 @@ class Canvas(Widget, XView, YView): offset: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: Union[str, Tuple[str, ...]] = ..., - text: Union[float, str] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + text: float | str = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload + def create_text( + self, + __coords: tuple[float, float] | list[int] | list[float], + *, + activefill: _Color = ..., + activestipple: str = ..., + anchor: _Anchor = ..., + disabledfill: _Color = ..., + disabledstipple: _Bitmap = ..., + fill: _Color = ..., + font: _FontDescription = ..., + justify: Literal["left", "center", "right"] = ..., + offset: _ScreenUnits = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + text: float | str = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... + @overload def create_window( self, __x: float, @@ -1261,39 +1462,53 @@ class Canvas(Widget, XView, YView): anchor: _Anchor = ..., height: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., - tags: Union[str, Tuple[str, ...]] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + width: _ScreenUnits = ..., + window: Widget = ..., + ) -> _CanvasItemId: ... + @overload + def create_window( + self, + __coords: tuple[float, float] | list[int] | list[float], + *, + anchor: _Anchor = ..., + height: _ScreenUnits = ..., + state: Literal["normal", "active", "disabled"] = ..., + tags: str | list[str] | Tuple[str, ...] = ..., width: _ScreenUnits = ..., window: Widget = ..., ) -> _CanvasItemId: ... def dchars(self, *args): ... - def delete(self, *tagsOrCanvasIds: Union[str, _CanvasItemId]) -> None: ... - def dtag(self, *args): ... - def find(self, *args): ... - def find_above(self, tagOrId: Union[str, _CanvasItemId]): ... - def find_all(self): ... - def find_below(self, tagOrId: Union[str, _CanvasItemId]): ... - def find_closest(self, x, y, halo: Optional[Any] = ..., start: Optional[Any] = ...): ... - def find_enclosed(self, x1, y1, x2, y2): ... - def find_overlapping(self, x1, y1, x2, y2): ... - def find_withtag(self, tagOrId: Union[str, _CanvasItemId]): ... + def delete(self, *tagsOrCanvasIds: str | _CanvasItemId) -> None: ... + @overload + def dtag(self, __tag: str, __tag_to_delete: str | None = ...) -> None: ... + @overload + def dtag(self, __id: _CanvasItemId, __tag_to_delete: str) -> None: ... def focus(self, *args): ... - def gettags(self, *args): ... + def gettags(self, __tagOrId: str | _CanvasItemId) -> Tuple[str, ...]: ... def icursor(self, *args): ... def index(self, *args): ... def insert(self, *args): ... def itemcget(self, tagOrId, option): ... - def itemconfigure(self, tagOrId, cnf: Optional[Any] = ..., **kw): ... - itemconfig: Any - def tag_lower(self, *args): ... - lower: Any + # itemconfigure kwargs depend on item type, which is not known when type checking + def itemconfigure( + self, tagOrId: str | _CanvasItemId, cnf: dict[str, Any] | None = ..., **kw: Any + ) -> dict[str, tuple[str, str, str, str, str]] | None: ... + itemconfig = itemconfigure def move(self, *args): ... if sys.version_info >= (3, 8): - def moveto( - self, tagOrId: Union[str, _CanvasItemId], x: Union[Literal[""], float] = ..., y: Union[Literal[""], float] = ... - ) -> None: ... + def moveto(self, tagOrId: str | _CanvasItemId, x: Literal[""] | float = ..., y: Literal[""] | float = ...) -> None: ... def postscript(self, cnf=..., **kw): ... - def tag_raise(self, *args): ... - lift: Any + # tkinter does: + # lower = tag_lower + # lift = tkraise = tag_raise + # + # But mypy doesn't like aliasing here (maybe because Misc defines the same names) + def tag_lower(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... + def lower(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore + def tag_raise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... + def tkraise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore + def lift(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore def scale(self, *args): ... def scan_mark(self, x, y): ... def scan_dragto(self, x, y, gain: int = ...): ... @@ -1307,8 +1522,8 @@ class Canvas(Widget, XView, YView): class Checkbutton(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -1341,8 +1556,8 @@ class Checkbutton(Widget): # # I think Checkbutton shouldn't be generic, because then specifying # "any checkbutton regardless of what variable it uses" would be - # difficult, and we might run into issues just like how List[float] - # and List[int] are incompatible. Also, we would need a way to + # difficult, and we might run into issues just like how list[float] + # and list[int] are incompatible. Also, we would need a way to # specify "Checkbutton not associated with any variable", which is # done by setting variable to empty string (the default). offvalue: Any = ..., @@ -1355,19 +1570,19 @@ class Checkbutton(Widget): selectimage: _ImageSpec = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., tristateimage: _ImageSpec = ..., tristatevalue: Any = ..., underline: int = ..., - variable: Union[Variable, Literal[""]] = ..., + variable: Variable | Literal[""] = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -1403,29 +1618,31 @@ class Checkbutton(Widget): selectimage: _ImageSpec = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., tristateimage: _ImageSpec = ..., tristatevalue: Any = ..., underline: int = ..., - variable: Union[Variable, Literal[""]] = ..., + variable: Variable | Literal[""] = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def deselect(self): ... def flash(self): ... - def invoke(self): ... + def invoke(self) -> Any: ... def select(self): ... def toggle(self): ... +_EntryIndex = Union[str, int] # "INDICES" in manual page + class Entry(Widget, XView): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1469,7 +1686,7 @@ class Entry(Widget, XView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1508,35 +1725,35 @@ class Entry(Widget, XView): vcmd: _EntryValidateCommand = ..., width: int = ..., xscrollcommand: _XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def delete(self, first, last: Optional[Any] = ...): ... - def get(self): ... - def icursor(self, index): ... - def index(self, index): ... - def insert(self, index, string): ... + def delete(self, first: _EntryIndex, last: _EntryIndex | None = ...) -> None: ... + def get(self) -> str: ... + def icursor(self, index: _EntryIndex) -> None: ... + def index(self, index: _EntryIndex) -> int: ... + def insert(self, index: _EntryIndex, string: str) -> None: ... def scan_mark(self, x): ... def scan_dragto(self, x): ... - def selection_adjust(self, index): ... - select_adjust: Any - def selection_clear(self): ... - select_clear: Any - def selection_from(self, index): ... - select_from: Any - def selection_present(self): ... - select_present: Any - def selection_range(self, start, end): ... - select_range: Any - def selection_to(self, index): ... - select_to: Any + def selection_adjust(self, index: _EntryIndex) -> None: ... + def selection_clear(self) -> None: ... # type: ignore + def selection_from(self, index: _EntryIndex) -> None: ... + def selection_present(self) -> bool: ... + def selection_range(self, start: _EntryIndex, end: _EntryIndex) -> None: ... + def selection_to(self, index: _EntryIndex) -> None: ... + select_adjust = selection_adjust + select_clear = selection_clear + select_from = selection_from + select_present = selection_present + select_range = selection_range + select_to = selection_to class Frame(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1544,7 +1761,7 @@ class Frame(Widget): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., class_: str = ..., - colormap: Union[Literal["new", ""], Misc] = ..., + colormap: Literal["new", ""] | Misc = ..., container: bool = ..., cursor: _Cursor = ..., height: _ScreenUnits = ..., @@ -1556,13 +1773,13 @@ class Frame(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - visual: Union[str, Tuple[str, int]] = ..., + visual: str | tuple[str, int] = ..., width: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -1579,16 +1796,16 @@ class Frame(Widget): relief: _Relief = ..., takefocus: _TakeFocusValue = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Label(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -1617,7 +1834,7 @@ class Label(Widget): relief: _Relief = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., underline: int = ..., width: _ScreenUnits = ..., @@ -1626,7 +1843,7 @@ class Label(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -1654,21 +1871,21 @@ class Label(Widget): relief: _Relief = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., underline: int = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Listbox(Widget, XView, YView): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activestyle: Literal["dotbox", "none", "underline"] = ..., background: _Color = ..., @@ -1718,7 +1935,7 @@ class Listbox(Widget, XView, YView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activestyle: Literal["dotbox", "none", "underline"] = ..., background: _Color = ..., @@ -1749,15 +1966,15 @@ class Listbox(Widget, XView, YView): width: int = ..., xscrollcommand: _XYScrollCommand = ..., yscrollcommand: _XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def activate(self, index): ... def bbox(self, index): ... def curselection(self): ... - def delete(self, first, last: Optional[Any] = ...): ... - def get(self, first, last: Optional[Any] = ...): ... + def delete(self, first, last: Any | None = ...): ... + def get(self, first, last: Any | None = ...): ... def index(self, index): ... def insert(self, index, *elements): ... def nearest(self, y): ... @@ -1766,15 +1983,15 @@ class Listbox(Widget, XView, YView): def see(self, index): ... def selection_anchor(self, index): ... select_anchor: Any - def selection_clear(self, first, last: Optional[Any] = ...): ... # type: ignore + def selection_clear(self, first, last: Any | None = ...): ... # type: ignore select_clear: Any def selection_includes(self, index): ... select_includes: Any - def selection_set(self, first, last: Optional[Any] = ...): ... + def selection_set(self, first, last: Any | None = ...): ... select_set: Any def size(self): ... def itemcget(self, index, option): ... - def itemconfigure(self, index, cnf: Optional[Any] = ..., **kw): ... + def itemconfigure(self, index, cnf: Any | None = ..., **kw): ... itemconfig: Any _MenuIndex = Union[str, int] @@ -1782,8 +1999,8 @@ _MenuIndex = Union[str, int] class Menu(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeborderwidth: _ScreenUnits = ..., @@ -1799,7 +2016,7 @@ class Menu(Widget): font: _FontDescription = ..., foreground: _Color = ..., name: str = ..., - postcommand: Union[Callable[[], Any], str] = ..., + postcommand: Callable[[], Any] | str = ..., relief: _Relief = ..., selectcolor: _Color = ..., takefocus: _TakeFocusValue = ..., @@ -1807,14 +2024,14 @@ class Menu(Widget): # I guess tearoffcommand arguments are supposed to be widget objects, # but they are widget name strings. Use nametowidget() to handle the # arguments of tearoffcommand. - tearoffcommand: Union[Callable[[str, str], Any], str] = ..., + tearoffcommand: Callable[[str, str], Any] | str = ..., title: str = ..., type: Literal["menubar", "tearoff", "normal"] = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeborderwidth: _ScreenUnits = ..., @@ -1829,25 +2046,25 @@ class Menu(Widget): fg: _Color = ..., font: _FontDescription = ..., foreground: _Color = ..., - postcommand: Union[Callable[[], Any], str] = ..., + postcommand: Callable[[], Any] | str = ..., relief: _Relief = ..., selectcolor: _Color = ..., takefocus: _TakeFocusValue = ..., tearoff: bool = ..., - tearoffcommand: Union[Callable[[str, str], Any], str] = ..., + tearoffcommand: Callable[[str, str], Any] | str = ..., title: str = ..., type: Literal["menubar", "tearoff", "normal"] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def tk_popup(self, x: int, y: int, entry: _MenuIndex = ...): ... - def activate(self, index): ... - def add(self, itemType, cnf=..., **kw): ... - def insert(self, index, itemType, cnf=..., **kw): ... + def tk_popup(self, x: int, y: int, entry: _MenuIndex = ...) -> None: ... + def activate(self, index: _MenuIndex) -> None: ... + def add(self, itemType, cnf=..., **kw): ... # docstring says "Internal function." + def insert(self, index, itemType, cnf=..., **kw): ... # docstring says "Internal function." def add_cascade( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1855,7 +2072,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1868,7 +2085,7 @@ class Menu(Widget): ) -> None: ... def add_checkbutton( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1876,7 +2093,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1894,7 +2111,7 @@ class Menu(Widget): ) -> None: ... def add_command( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1902,7 +2119,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1914,7 +2131,7 @@ class Menu(Widget): ) -> None: ... def add_radiobutton( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1922,7 +2139,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1937,11 +2154,11 @@ class Menu(Widget): value: Any = ..., variable: Variable = ..., ) -> None: ... - def add_separator(self, cnf: Optional[Dict[str, Any]] = ..., *, background: _Color = ...) -> None: ... + def add_separator(self, cnf: dict[str, Any] | None = ..., *, background: _Color = ...) -> None: ... def insert_cascade( self, index: _MenuIndex, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1949,7 +2166,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1963,7 +2180,7 @@ class Menu(Widget): def insert_checkbutton( self, index: _MenuIndex, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1971,7 +2188,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -1990,7 +2207,7 @@ class Menu(Widget): def insert_command( self, index: _MenuIndex, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -1998,7 +2215,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -2011,7 +2228,7 @@ class Menu(Widget): def insert_radiobutton( self, index: _MenuIndex, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., activebackground: _Color = ..., @@ -2019,7 +2236,7 @@ class Menu(Widget): background: _Color = ..., bitmap: _Bitmap = ..., columnbreak: int = ..., - command: Union[Callable[[], Any], str] = ..., + command: Callable[[], Any] | str = ..., compound: _Compound = ..., font: _FontDescription = ..., foreground: _Color = ..., @@ -2034,24 +2251,26 @@ class Menu(Widget): value: Any = ..., variable: Variable = ..., ) -> None: ... - def insert_separator(self, index: _MenuIndex, cnf: Optional[Dict[str, Any]] = ..., *, background: _Color = ...) -> None: ... - def delete(self, index1, index2: Optional[Any] = ...): ... - def entrycget(self, index, option): ... - def entryconfigure(self, index, cnf: Optional[Any] = ..., **kw): ... - entryconfig: Any - def index(self, index): ... - def invoke(self, index): ... - def post(self, x, y): ... - def type(self, index): ... - def unpost(self): ... - def xposition(self, index): ... - def yposition(self, index): ... + def insert_separator(self, index: _MenuIndex, cnf: dict[str, Any] | None = ..., *, background: _Color = ...) -> None: ... + def delete(self, index1: _MenuIndex, index2: _MenuIndex | None = ...) -> None: ... + def entrycget(self, index: _MenuIndex, option: str) -> Any: ... + def entryconfigure( + self, index: _MenuIndex, cnf: dict[str, Any] | None = ..., **kw: Any + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... + entryconfig = entryconfigure + def index(self, index: _MenuIndex) -> int | None: ... + def invoke(self, index: _MenuIndex) -> Any: ... + def post(self, x: int, y: int) -> None: ... + def type(self, index: _MenuIndex) -> Literal["cascade", "checkbutton", "command", "radiobutton", "separator"]: ... + def unpost(self) -> None: ... + def xposition(self, index: _MenuIndex) -> int: ... + def yposition(self, index: _MenuIndex) -> int: ... class Menubutton(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -2083,7 +2302,7 @@ class Menubutton(Widget): relief: _Relief = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., underline: int = ..., width: _ScreenUnits = ..., @@ -2092,7 +2311,7 @@ class Menubutton(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -2123,21 +2342,21 @@ class Menubutton(Widget): relief: _Relief = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., underline: int = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Message(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, anchor: _Anchor = ..., aspect: int = ..., @@ -2159,7 +2378,7 @@ class Message(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., # there's width but no height width: _ScreenUnits = ..., @@ -2167,7 +2386,7 @@ class Message(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, anchor: _Anchor = ..., aspect: int = ..., @@ -2188,19 +2407,19 @@ class Message(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Radiobutton(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -2235,20 +2454,20 @@ class Radiobutton(Widget): selectimage: _ImageSpec = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., tristateimage: _ImageSpec = ..., tristatevalue: Any = ..., underline: int = ..., value: Any = ..., - variable: Union[Variable, Literal[""]] = ..., + variable: Variable | Literal[""] = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activeforeground: _Color = ..., @@ -2282,29 +2501,29 @@ class Radiobutton(Widget): selectimage: _ImageSpec = ..., state: Literal["normal", "active", "disabled"] = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: Variable = ..., tristateimage: _ImageSpec = ..., tristatevalue: Any = ..., underline: int = ..., value: Any = ..., - variable: Union[Variable, Literal[""]] = ..., + variable: Variable | Literal[""] = ..., width: _ScreenUnits = ..., wraplength: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def deselect(self): ... def flash(self): ... - def invoke(self): ... + def invoke(self) -> Any: ... def select(self): ... class Scale(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., background: _Color = ..., @@ -2314,7 +2533,7 @@ class Scale(Widget): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., # don't know why the callback gets string instead of float - command: Union[str, Callable[[str], Any]] = ..., + command: str | Callable[[str], Any] = ..., cursor: _Cursor = ..., digits: int = ..., fg: _Color = ..., @@ -2340,13 +2559,13 @@ class Scale(Widget): tickinterval: float = ..., to: float = ..., troughcolor: _Color = ..., - variable: Union[IntVar, DoubleVar] = ..., + variable: IntVar | DoubleVar = ..., width: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., background: _Color = ..., @@ -2355,7 +2574,7 @@ class Scale(Widget): bigincrement: float = ..., border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., - command: Union[str, Callable[[str], Any]] = ..., + command: str | Callable[[str], Any] = ..., cursor: _Cursor = ..., digits: int = ..., fg: _Color = ..., @@ -2380,22 +2599,22 @@ class Scale(Widget): tickinterval: float = ..., to: float = ..., troughcolor: _Color = ..., - variable: Union[IntVar, DoubleVar] = ..., + variable: IntVar | DoubleVar = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def get(self): ... def set(self, value): ... - def coords(self, value: Optional[Any] = ...): ... + def coords(self, value: Any | None = ...): ... def identify(self, x, y): ... class Scrollbar(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activerelief: _Relief = ..., @@ -2408,7 +2627,7 @@ class Scrollbar(Widget): # 'SCROLLING COMMANDS' in scrollbar man page. There doesn't seem to # be any way to specify an overloaded callback function, so we say # that it can take any args while it can't in reality. - command: Union[Callable[..., Optional[Tuple[float, float]]], str] = ..., + command: Callable[..., tuple[float, float] | None] | str = ..., cursor: _Cursor = ..., elementborderwidth: _ScreenUnits = ..., highlightbackground: _Color = ..., @@ -2427,7 +2646,7 @@ class Scrollbar(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., activerelief: _Relief = ..., @@ -2436,7 +2655,7 @@ class Scrollbar(Widget): bg: _Color = ..., border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., - command: Union[Callable[..., Optional[Tuple[float, float]]], str] = ..., + command: Callable[..., tuple[float, float] | None] | str = ..., cursor: _Cursor = ..., elementborderwidth: _ScreenUnits = ..., highlightbackground: _Color = ..., @@ -2450,11 +2669,11 @@ class Scrollbar(Widget): takefocus: _TakeFocusValue = ..., troughcolor: _Color = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def activate(self, index: Optional[Any] = ...): ... + def activate(self, index: Any | None = ...): ... def delta(self, deltax, deltay): ... def fraction(self, x, y): ... def identify(self, x, y): ... @@ -2466,8 +2685,8 @@ _TextIndex = Union[_tkinter.Tcl_Obj, str, float, Misc] class Text(Widget, XView, YView): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, autoseparators: bool = ..., background: _Color = ..., @@ -2477,7 +2696,7 @@ class Text(Widget, XView, YView): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., cursor: _Cursor = ..., - endline: Union[int, Literal[""]] = ..., + endline: int | Literal[""] = ..., exportselection: bool = ..., fg: _Color = ..., font: _FontDescription = ..., @@ -2508,10 +2727,10 @@ class Text(Widget, XView, YView): spacing1: _ScreenUnits = ..., spacing2: _ScreenUnits = ..., spacing3: _ScreenUnits = ..., - startline: Union[int, Literal[""]] = ..., + startline: int | Literal[""] = ..., state: Literal["normal", "disabled"] = ..., # Literal inside Tuple doesn't actually work - tabs: Union[_ScreenUnits, str, Tuple[Union[_ScreenUnits, str], ...]] = ..., + tabs: _ScreenUnits | str | Tuple[_ScreenUnits | str, ...] = ..., tabstyle: Literal["tabular", "wordprocessor"] = ..., takefocus: _TakeFocusValue = ..., undo: bool = ..., @@ -2523,7 +2742,7 @@ class Text(Widget, XView, YView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, autoseparators: bool = ..., background: _Color = ..., @@ -2533,7 +2752,7 @@ class Text(Widget, XView, YView): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., cursor: _Cursor = ..., - endline: Union[int, Literal[""]] = ..., + endline: int | Literal[""] = ..., exportselection: bool = ..., fg: _Color = ..., font: _FontDescription = ..., @@ -2560,9 +2779,9 @@ class Text(Widget, XView, YView): spacing1: _ScreenUnits = ..., spacing2: _ScreenUnits = ..., spacing3: _ScreenUnits = ..., - startline: Union[int, Literal[""]] = ..., + startline: int | Literal[""] = ..., state: Literal["normal", "disabled"] = ..., - tabs: Union[_ScreenUnits, str, Tuple[Union[_ScreenUnits, str], ...]] = ..., + tabs: _ScreenUnits | str | Tuple[_ScreenUnits | str, ...] = ..., tabstyle: Literal["tabular", "wordprocessor"] = ..., takefocus: _TakeFocusValue = ..., undo: bool = ..., @@ -2570,24 +2789,24 @@ class Text(Widget, XView, YView): wrap: Literal["none", "char", "word"] = ..., xscrollcommand: _XYScrollCommand = ..., yscrollcommand: _XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def bbox(self, index: _TextIndex) -> Optional[Tuple[int, int, int, int]]: ... # type: ignore + def bbox(self, index: _TextIndex) -> tuple[int, int, int, int] | None: ... # type: ignore def compare(self, index1: _TextIndex, op: Literal["<", "<=", "==", ">=", ">", "!="], index2: _TextIndex) -> bool: ... def count(self, index1, index2, *args): ... # TODO @overload def debug(self, boolean: None = ...) -> bool: ... @overload def debug(self, boolean: bool) -> None: ... - def delete(self, index1: _TextIndex, index2: Optional[_TextIndex] = ...) -> None: ... - def dlineinfo(self, index: _TextIndex) -> Optional[Tuple[int, int, int, int, int]]: ... + def delete(self, index1: _TextIndex, index2: _TextIndex | None = ...) -> None: ... + def dlineinfo(self, index: _TextIndex) -> tuple[int, int, int, int, int] | None: ... @overload def dump( self, index1: _TextIndex, - index2: Optional[_TextIndex] = ..., + index2: _TextIndex | None = ..., command: None = ..., *, all: bool = ..., @@ -2596,13 +2815,13 @@ class Text(Widget, XView, YView): tag: bool = ..., text: bool = ..., window: bool = ..., - ) -> List[Tuple[str, str, str]]: ... + ) -> list[tuple[str, str, str]]: ... @overload def dump( self, index1: _TextIndex, - index2: Optional[_TextIndex], - command: Union[Callable[[str, str, str], Any], str], + index2: _TextIndex | None, + command: Callable[[str, str, str], Any] | str, *, all: bool = ..., image: bool = ..., @@ -2615,9 +2834,9 @@ class Text(Widget, XView, YView): def dump( self, index1: _TextIndex, - index2: Optional[_TextIndex] = ..., + index2: _TextIndex | None = ..., *, - command: Union[Callable[[str, str, str], Any], str], + command: Callable[[str, str, str], Any] | str, all: bool = ..., image: bool = ..., mark: bool = ..., @@ -2634,14 +2853,14 @@ class Text(Widget, XView, YView): def edit_reset(self) -> None: ... # actually returns empty string def edit_separator(self) -> None: ... # actually returns empty string def edit_undo(self) -> None: ... # actually returns empty string - def get(self, index1: _TextIndex, index2: Optional[_TextIndex] = ...) -> str: ... + def get(self, index1: _TextIndex, index2: _TextIndex | None = ...) -> str: ... # TODO: image_* methods def image_cget(self, index, option): ... - def image_configure(self, index, cnf: Optional[Any] = ..., **kw): ... + def image_configure(self, index, cnf: Any | None = ..., **kw): ... def image_create(self, index, cnf=..., **kw): ... def image_names(self): ... def index(self, index: _TextIndex) -> str: ... - def insert(self, index: _TextIndex, chars: str, *args: Union[str, _TkinterSequence[str]]) -> None: ... + def insert(self, index: _TextIndex, chars: str, *args: str | list[str] | Tuple[str, ...]) -> None: ... @overload def mark_gravity(self, markName: str, direction: None = ...) -> Literal["left", "right"]: ... @overload @@ -2649,44 +2868,48 @@ class Text(Widget, XView, YView): def mark_names(self) -> Tuple[str, ...]: ... def mark_set(self, markName: str, index: _TextIndex) -> None: ... def mark_unset(self, *markNames: str) -> None: ... - def mark_next(self, index: _TextIndex) -> Optional[str]: ... - def mark_previous(self, index: _TextIndex) -> Optional[str]: ... + def mark_next(self, index: _TextIndex) -> str | None: ... + def mark_previous(self, index: _TextIndex) -> str | None: ... # **kw of peer_create is same as the kwargs of Text.__init__ - def peer_create(self, newPathName: Union[str, Text], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def peer_create(self, newPathName: str | Text, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def peer_names(self) -> Tuple[_tkinter.Tcl_Obj, ...]: ... - def replace(self, index1: _TextIndex, index2: _TextIndex, chars: str, *args: Union[str, _TkinterSequence[str]]) -> None: ... + def replace(self, index1: _TextIndex, index2: _TextIndex, chars: str, *args: str | list[str] | Tuple[str, ...]) -> None: ... def scan_mark(self, x: int, y: int) -> None: ... def scan_dragto(self, x: int, y: int) -> None: ... def search( self, pattern: str, index: _TextIndex, - stopindex: Optional[_TextIndex] = ..., - forwards: Optional[bool] = ..., - backwards: Optional[bool] = ..., - exact: Optional[bool] = ..., - regexp: Optional[bool] = ..., - nocase: Optional[bool] = ..., - count: Optional[Variable] = ..., - elide: Optional[bool] = ..., + stopindex: _TextIndex | None = ..., + forwards: bool | None = ..., + backwards: bool | None = ..., + exact: bool | None = ..., + regexp: bool | None = ..., + nocase: bool | None = ..., + count: Variable | None = ..., + elide: bool | None = ..., ) -> str: ... # returns empty string for not found def see(self, index: _TextIndex) -> None: ... def tag_add(self, tagName: str, index1: _TextIndex, *args: _TextIndex) -> None: ... # tag_bind stuff is very similar to Canvas @overload def tag_bind( - self, tagName: str, sequence: Optional[str], func: Optional[Callable[[Event[Text]], Any]], add: Optional[bool] = ... + self, + tagName: str, + sequence: str | None, + func: Callable[[Event[Text]], Any] | None, + add: Literal["", "+"] | bool | None = ..., ) -> str: ... @overload - def tag_bind(self, tagName: str, sequence: Optional[str], func: str, add: Optional[bool] = ...) -> None: ... - def tag_unbind(self, tagName: str, sequence: str, funcid: Optional[str] = ...) -> None: ... + def tag_bind(self, tagName: str, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... + def tag_unbind(self, tagName: str, sequence: str, funcid: str | None = ...) -> None: ... # allowing any string for cget instead of just Literals because there's no other way to look up tag options def tag_cget(self, tagName: str, option: str) -> Any: ... @overload def tag_configure( self, tagName: str, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bgstipple: _Bitmap = ..., @@ -2716,33 +2939,29 @@ class Text(Widget, XView, YView): underline: bool = ..., underlinefg: _Color = ..., wrap: Literal["none", "char", "word"] = ..., # be careful with "none" vs None - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def tag_configure(self, tagName: str, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def tag_configure(self, tagName: str, cnf: str) -> tuple[str, str, str, Any, Any]: ... tag_config = tag_configure def tag_delete(self, __first_tag_name: str, *tagNames: str) -> None: ... # error if no tag names given - def tag_lower(self, tagName: str, belowThis: Optional[str] = ...) -> None: ... - def tag_names(self, index: Optional[_TextIndex] = ...) -> Tuple[str, ...]: ... - def tag_nextrange( - self, tagName: str, index1: _TextIndex, index2: Optional[_TextIndex] = ... - ) -> Union[Tuple[str, str], Tuple[()]]: ... - def tag_prevrange( - self, tagName: str, index1: _TextIndex, index2: Optional[_TextIndex] = ... - ) -> Union[Tuple[str, str], Tuple[()]]: ... - def tag_raise(self, tagName: str, aboveThis: Optional[str] = ...) -> None: ... + def tag_lower(self, tagName: str, belowThis: str | None = ...) -> None: ... + def tag_names(self, index: _TextIndex | None = ...) -> Tuple[str, ...]: ... + def tag_nextrange(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> tuple[str, str] | tuple[()]: ... + def tag_prevrange(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> tuple[str, str] | tuple[()]: ... + def tag_raise(self, tagName: str, aboveThis: str | None = ...) -> None: ... def tag_ranges(self, tagName: str) -> Tuple[_tkinter.Tcl_Obj, ...]: ... # tag_remove and tag_delete are different - def tag_remove(self, tagName: str, index1: _TextIndex, index2: Optional[_TextIndex] = ...) -> None: ... + def tag_remove(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> None: ... # TODO: window_* methods def window_cget(self, index, option): ... - def window_configure(self, index, cnf: Optional[Any] = ..., **kw): ... + def window_configure(self, index, cnf: Any | None = ..., **kw): ... window_config = window_configure def window_create(self, index, cnf=..., **kw): ... def window_names(self): ... def yview_pickplace(self, *what): ... # deprecated class _setit: - def __init__(self, var, value, callback: Optional[Any] = ...): ... + def __init__(self, var, value, callback: Any | None = ...): ... def __call__(self, *args): ... # manual page: tk_optionMenu @@ -2752,15 +2971,15 @@ class OptionMenu(Menubutton): def __init__( # differs from other widgets self, - master: Optional[Misc], + master: Misc | None, variable: StringVar, value: str, *values: str, # kwarg only from now on - command: Optional[Callable[[StringVar], Any]] = ..., + command: Callable[[StringVar], Any] | None = ..., ) -> None: ... # configure, config, cget are inherited from Menubutton - # destroy and __getitem__ are overrided, signature does not change + # destroy and __getitem__ are overridden, signature does not change class _Image(Protocol): tk: _tkinter.TkappType @@ -2770,9 +2989,7 @@ class _Image(Protocol): class Image: name: Any tk: _tkinter.TkappType - def __init__( - self, imgtype, name: Optional[Any] = ..., cnf=..., master: Optional[Union[Misc, _tkinter.TkappType]] = ..., **kw - ): ... + def __init__(self, imgtype, name: Any | None = ..., cnf=..., master: Misc | _tkinter.TkappType | None = ..., **kw): ... def __del__(self): ... def __setitem__(self, key, value): ... def __getitem__(self, key): ... @@ -2785,27 +3002,27 @@ class Image: class PhotoImage(Image): def __init__( self, - name: Optional[str] = ..., - cnf: Dict[str, Any] = ..., - master: Optional[Union[Misc, _tkinter.TkappType]] = ..., + name: str | None = ..., + cnf: dict[str, Any] = ..., + master: Misc | _tkinter.TkappType | None = ..., *, - data: Union[str, bytes] = ..., # not same as data argument of put() + data: str | bytes = ..., # not same as data argument of put() format: str = ..., - file: AnyPath = ..., + file: StrOrBytesPath = ..., gamma: float = ..., height: int = ..., - palette: Union[int, str] = ..., + palette: int | str = ..., width: int = ..., ) -> None: ... def configure( self, *, - data: Union[str, bytes] = ..., + data: str | bytes = ..., format: str = ..., - file: AnyPath = ..., + file: StrOrBytesPath = ..., gamma: float = ..., height: int = ..., - palette: Union[int, str] = ..., + palette: int | str = ..., width: int = ..., ) -> None: ... config = configure @@ -2813,13 +3030,23 @@ class PhotoImage(Image): def cget(self, option: str) -> str: ... def __getitem__(self, key: str) -> str: ... # always string: image['height'] can be '0' def copy(self) -> PhotoImage: ... - def zoom(self, x: int, y: Union[int, Literal[""]] = ...) -> PhotoImage: ... - def subsample(self, x: int, y: Union[int, Literal[""]] = ...) -> PhotoImage: ... - def get(self, x: int, y: int) -> Tuple[int, int, int]: ... + def zoom(self, x: int, y: int | Literal[""] = ...) -> PhotoImage: ... + def subsample(self, x: int, y: int | Literal[""] = ...) -> PhotoImage: ... + def get(self, x: int, y: int) -> tuple[int, int, int]: ... def put( - self, data: Union[str, _TkinterSequence[str], _TkinterSequence2D[_Color]], to: Optional[Tuple[int, int]] = ... + self, + data: ( + str + | list[str] + | list[list[_Color]] + | list[Tuple[_Color, ...]] + | Tuple[str, ...] + | Tuple[list[_Color], ...] + | Tuple[Tuple[_Color, ...], ...] + ), + to: tuple[int, int] | None = ..., ) -> None: ... - def write(self, filename: AnyPath, format: Optional[str] = ..., from_coords: Optional[Tuple[int, int]] = ...) -> None: ... + def write(self, filename: StrOrBytesPath, format: str | None = ..., from_coords: tuple[int, int] | None = ...) -> None: ... if sys.version_info >= (3, 8): def transparency_get(self, x: int, y: int) -> bool: ... def transparency_set(self, x: int, y: int, boolean: bool) -> None: ... @@ -2827,16 +3054,16 @@ class PhotoImage(Image): class BitmapImage(Image): def __init__( self, - name: Optional[Any] = ..., - cnf: Dict[str, Any] = ..., - master: Optional[Union[Misc, _tkinter.TkappType]] = ..., + name: Any | None = ..., + cnf: dict[str, Any] = ..., + master: Misc | _tkinter.TkappType | None = ..., *, background: _Color = ..., - data: Union[str, bytes] = ..., - file: AnyPath = ..., + data: str | bytes = ..., + file: StrOrBytesPath = ..., foreground: _Color = ..., maskdata: str = ..., - maskfile: AnyPath = ..., + maskfile: StrOrBytesPath = ..., ) -> None: ... def image_names() -> Tuple[str, ...]: ... @@ -2845,8 +3072,8 @@ def image_types() -> Tuple[str, ...]: ... class Spinbox(Widget, XView): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., background: _Color = ..., @@ -2858,8 +3085,8 @@ class Spinbox(Widget, XView): buttoncursor: _Cursor = ..., buttondownrelief: _Relief = ..., buttonuprelief: _Relief = ..., - # percent substitutions don't seem to be supported, it's similar to Entry's validion stuff - command: Union[Callable[[], Any], str, _TkinterSequence[str]] = ..., + # percent substitutions don't seem to be supported, it's similar to Entry's validation stuff + command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., cursor: _Cursor = ..., disabledbackground: _Color = ..., disabledforeground: _Color = ..., @@ -2896,7 +3123,7 @@ class Spinbox(Widget, XView): validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: _EntryValidateCommand = ..., vcmd: _EntryValidateCommand = ..., - values: _TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: _XYScrollCommand = ..., @@ -2904,7 +3131,7 @@ class Spinbox(Widget, XView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, activebackground: _Color = ..., background: _Color = ..., @@ -2916,7 +3143,7 @@ class Spinbox(Widget, XView): buttoncursor: _Cursor = ..., buttondownrelief: _Relief = ..., buttonuprelief: _Relief = ..., - command: Union[Callable[[], Any], str, _TkinterSequence[str]] = ..., + command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., cursor: _Cursor = ..., disabledbackground: _Color = ..., disabledforeground: _Color = ..., @@ -2952,29 +3179,30 @@ class Spinbox(Widget, XView): validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: _EntryValidateCommand = ..., vcmd: _EntryValidateCommand = ..., - values: _TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: _XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def bbox(self, index): ... - def delete(self, first, last: Optional[Any] = ...): ... + def delete(self, first, last: Any | None = ...): ... def get(self): ... def icursor(self, index): ... def identify(self, x, y): ... def index(self, index): ... def insert(self, index, s): ... - def invoke(self, element): ... + # spinbox.invoke("asdf") gives error mentioning .invoke("none"), but it's not documented + def invoke(self, element: Literal["none", "buttonup", "buttondown"]) -> Literal[""]: ... def scan(self, *args): ... def scan_mark(self, x): ... def scan_dragto(self, x): ... def selection(self, *args: Any) -> Tuple[int, ...]: ... def selection_adjust(self, index): ... def selection_clear(self): ... - def selection_element(self, element: Optional[Any] = ...): ... + def selection_element(self, element: Any | None = ...): ... if sys.version_info >= (3, 8): def selection_from(self, index: int) -> None: ... def selection_present(self) -> None: ... @@ -2984,8 +3212,8 @@ class Spinbox(Widget, XView): class LabelFrame(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -2993,7 +3221,7 @@ class LabelFrame(Widget): border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., class_: str = ..., - colormap: Union[Literal["new", ""], Misc] = ..., + colormap: Literal["new", ""] | Misc = ..., container: bool = ..., # undocumented cursor: _Cursor = ..., fg: _Color = ..., @@ -3011,14 +3239,14 @@ class LabelFrame(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., - visual: Union[str, Tuple[str, int]] = ..., + text: float | str = ..., + visual: str | tuple[str, int] = ..., width: _ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -3039,18 +3267,18 @@ class LabelFrame(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class PanedWindow(Widget): def __init__( self, - master: Optional[Misc] = ..., - cnf: Optional[Dict[str, Any]] = ..., + master: Misc | None = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -3078,7 +3306,7 @@ class PanedWindow(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: _Color = ..., bd: _ScreenUnits = ..., @@ -3101,11 +3329,11 @@ class PanedWindow(Widget): sashwidth: _ScreenUnits = ..., showhandle: bool = ..., width: _ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def add(self, child, **kw): ... + def add(self, child: Widget, **kw): ... def remove(self, child): ... forget: Any def identify(self, x, y): ... @@ -3118,6 +3346,6 @@ class PanedWindow(Widget): def sash_mark(self, index): ... def sash_place(self, index, x, y): ... def panecget(self, child, option): ... - def paneconfigure(self, tagOrId, cnf: Optional[Any] = ..., **kw): ... + def paneconfigure(self, tagOrId, cnf: Any | None = ..., **kw): ... paneconfig: Any def panes(self): ... diff --git a/mypy/typeshed/stdlib/tkinter/colorchooser.pyi b/mypy/typeshed/stdlib/tkinter/colorchooser.pyi index c99c16f0e3bf..b5fdc7c54914 100644 --- a/mypy/typeshed/stdlib/tkinter/colorchooser.pyi +++ b/mypy/typeshed/stdlib/tkinter/colorchooser.pyi @@ -1,9 +1,7 @@ from tkinter.commondialog import Dialog -from typing import Any, ClassVar, Optional, Tuple, Union +from typing import Any, ClassVar class Chooser(Dialog): command: ClassVar[str] -def askcolor( - color: Optional[Union[str, bytes]] = ..., **options: Any -) -> Union[Tuple[None, None], Tuple[Tuple[float, float, float], str]]: ... +def askcolor(color: str | bytes | None = ..., **options: Any) -> tuple[None, None] | tuple[tuple[float, float, float], str]: ... diff --git a/mypy/typeshed/stdlib/tkinter/commondialog.pyi b/mypy/typeshed/stdlib/tkinter/commondialog.pyi index 8efefe468b04..aee58111c73f 100644 --- a/mypy/typeshed/stdlib/tkinter/commondialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/commondialog.pyi @@ -1,8 +1,8 @@ -from typing import Any, ClassVar, Mapping, Optional +from typing import Any, ClassVar, Mapping class Dialog: - command: ClassVar[Optional[str]] = ... - master: Optional[Any] = ... - options: Mapping[str, Any] = ... - def __init__(self, master: Optional[Any] = ..., **options) -> None: ... + command: ClassVar[str | None] + master: Any | None + options: Mapping[str, Any] + def __init__(self, master: Any | None = ..., **options) -> None: ... def show(self, **options) -> Any: ... diff --git a/mypy/typeshed/stdlib/tkinter/dialog.pyi b/mypy/typeshed/stdlib/tkinter/dialog.pyi index d02036a64f10..bc927e1f24ac 100644 --- a/mypy/typeshed/stdlib/tkinter/dialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/dialog.pyi @@ -1,10 +1,10 @@ from tkinter import Widget -from typing import Any, Mapping, Optional +from typing import Any, Mapping DIALOG_ICON: str class Dialog(Widget): - widgetName: str = ... - num: int = ... - def __init__(self, master: Optional[Any] = ..., cnf: Mapping[str, Any] = ..., **kw) -> None: ... + widgetName: str + num: int + def __init__(self, master: Any | None = ..., cnf: Mapping[str, Any] = ..., **kw) -> None: ... def destroy(self) -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/dnd.pyi b/mypy/typeshed/stdlib/tkinter/dnd.pyi index 7371f91b524e..339291a20d0f 100644 --- a/mypy/typeshed/stdlib/tkinter/dnd.pyi +++ b/mypy/typeshed/stdlib/tkinter/dnd.pyi @@ -1,13 +1,15 @@ -from _typeshed.tkinter import DndSource -from tkinter import Event, Misc, Tk -from typing import ClassVar, Optional +from tkinter import Event, Misc, Tk, Widget +from typing import ClassVar, Protocol + +class _DndSource(Protocol): + def dnd_end(self, target: Widget | None, event: Event[Misc] | None) -> None: ... class DndHandler: - root: ClassVar[Optional[Tk]] - def __init__(self, source: DndSource, event: Event[Misc]) -> None: ... - def cancel(self, event: Optional[Event[Misc]] = ...) -> None: ... - def finish(self, event: Optional[Event[Misc]], commit: int = ...) -> None: ... + root: ClassVar[Tk | None] + def __init__(self, source: _DndSource, event: Event[Misc]) -> None: ... + def cancel(self, event: Event[Misc] | None = ...) -> None: ... + def finish(self, event: Event[Misc] | None, commit: int = ...) -> None: ... def on_motion(self, event: Event[Misc]) -> None: ... def on_release(self, event: Event[Misc]) -> None: ... -def dnd_start(source, event) -> Optional[DndHandler]: ... +def dnd_start(source, event) -> DndHandler | None: ... diff --git a/mypy/typeshed/stdlib/tkinter/filedialog.pyi b/mypy/typeshed/stdlib/tkinter/filedialog.pyi index 86238f0be798..0fc7d6e8a3bc 100644 --- a/mypy/typeshed/stdlib/tkinter/filedialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/filedialog.pyi @@ -1,67 +1,133 @@ -from tkinter import Button, Entry, Frame, Listbox, Scrollbar, Toplevel, commondialog -from typing import Any, ClassVar, Dict, Optional, Tuple +from _typeshed import StrOrBytesPath +from tkinter import Button, Entry, Frame, Listbox, Misc, Scrollbar, StringVar, Toplevel, commondialog +from typing import IO, Any, ClassVar, Iterable, Tuple +from typing_extensions import Literal -dialogstates: Dict[Any, Tuple[Any, Any]] +dialogstates: dict[Any, tuple[Any, Any]] class FileDialog: - title: str = ... - master: Any = ... - directory: Optional[Any] = ... - top: Toplevel = ... - botframe: Frame = ... - selection: Entry = ... - filter: Entry = ... - midframe: Entry = ... - filesbar: Scrollbar = ... - files: Listbox = ... - dirsbar: Scrollbar = ... - dirs: Listbox = ... - ok_button: Button = ... - filter_button: Button = ... - cancel_button: Button = ... + title: str + master: Any + directory: Any | None + top: Toplevel + botframe: Frame + selection: Entry + filter: Entry + midframe: Entry + filesbar: Scrollbar + files: Listbox + dirsbar: Scrollbar + dirs: Listbox + ok_button: Button + filter_button: Button + cancel_button: Button def __init__( - self, master, title: Optional[Any] = ... + self, master, title: Any | None = ... ) -> None: ... # title is usually a str or None, but e.g. int doesn't raise en exception either - how: Optional[Any] = ... - def go(self, dir_or_file: Any = ..., pattern: str = ..., default: str = ..., key: Optional[Any] = ...): ... - def quit(self, how: Optional[Any] = ...) -> None: ... + how: Any | None + def go(self, dir_or_file: Any = ..., pattern: str = ..., default: str = ..., key: Any | None = ...): ... + def quit(self, how: Any | None = ...) -> None: ... def dirs_double_event(self, event) -> None: ... def dirs_select_event(self, event) -> None: ... def files_double_event(self, event) -> None: ... def files_select_event(self, event) -> None: ... def ok_event(self, event) -> None: ... def ok_command(self) -> None: ... - def filter_command(self, event: Optional[Any] = ...) -> None: ... + def filter_command(self, event: Any | None = ...) -> None: ... def get_filter(self): ... def get_selection(self): ... - def cancel_command(self, event: Optional[Any] = ...) -> None: ... + def cancel_command(self, event: Any | None = ...) -> None: ... def set_filter(self, dir, pat) -> None: ... def set_selection(self, file) -> None: ... class LoadFileDialog(FileDialog): - title: str = ... + title: str def ok_command(self) -> None: ... class SaveFileDialog(FileDialog): - title: str = ... + title: str def ok_command(self): ... class _Dialog(commondialog.Dialog): ... class Open(_Dialog): - command: ClassVar[str] = ... + command: ClassVar[str] class SaveAs(_Dialog): - command: ClassVar[str] = ... + command: ClassVar[str] class Directory(commondialog.Dialog): - command: ClassVar[str] = ... + command: ClassVar[str] -def askopenfilename(**options): ... -def asksaveasfilename(**options): ... -def askopenfilenames(**options): ... -def askopenfile(mode: str = ..., **options): ... -def askopenfiles(mode: str = ..., **options): ... -def asksaveasfile(mode: str = ..., **options): ... -def askdirectory(**options): ... +# TODO: command kwarg available on macos +def asksaveasfilename( + *, + confirmoverwrite: bool | None = ..., + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> str: ... # can be empty string +def askopenfilename( + *, + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> str: ... # can be empty string +def askopenfilenames( + *, + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> Literal[""] | Tuple[str, ...]: ... +def askdirectory( + *, initialdir: StrOrBytesPath | None = ..., mustexist: bool | None = ..., parent: Misc | None = ..., title: str | None = ... +) -> str: ... # can be empty string + +# TODO: If someone actually uses these, overload to have the actual return type of open(..., mode) +def asksaveasfile( + mode: str = ..., + *, + confirmoverwrite: bool | None = ..., + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> IO[Any] | None: ... +def askopenfile( + mode: str = ..., + *, + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> IO[Any] | None: ... +def askopenfiles( + mode: str = ..., + *, + defaultextension: str | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + initialdir: StrOrBytesPath | None = ..., + initialfile: StrOrBytesPath | None = ..., + parent: Misc | None = ..., + title: str | None = ..., + typevariable: StringVar | str | None = ..., +) -> Tuple[IO[Any], ...]: ... # can be empty tuple def test() -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/font.pyi b/mypy/typeshed/stdlib/tkinter/font.pyi index a19c2dd6dc67..fccc0fbf1f0a 100644 --- a/mypy/typeshed/stdlib/tkinter/font.pyi +++ b/mypy/typeshed/stdlib/tkinter/font.pyi @@ -1,6 +1,7 @@ +import _tkinter import sys import tkinter -from typing import Any, List, Optional, Tuple, TypeVar, Union, overload +from typing import Any, List, Tuple, Union, overload from typing_extensions import Literal, TypedDict NORMAL: Literal["normal"] @@ -8,8 +9,17 @@ ROMAN: Literal["roman"] BOLD: Literal["bold"] ITALIC: Literal["italic"] -# Can contain e.g. nested sequences ('FONT DESCRIPTIONS' in font man page) -_FontDescription = Union[str, Font, tkinter._TkinterSequence[Any]] +_FontDescription = Union[ + # "Helvetica 12" + str, + # A font object constructed in Python + Font, + # ("Helvetica", 12, BOLD) + List[Any], + Tuple[Any, ...], + # A font object constructed in Tcl + _tkinter.Tcl_Obj, +] class _FontDict(TypedDict): family: str @@ -32,9 +42,9 @@ class Font: self, # In tkinter, 'root' refers to tkinter.Tk by convention, but the code # actually works with any tkinter widget so we use tkinter.Misc. - root: Optional[tkinter.Misc] = ..., - font: Optional[_FontDescription] = ..., - name: Optional[str] = ..., + root: tkinter.Misc | None = ..., + font: _FontDescription | None = ..., + name: str | None = ..., exists: bool = ..., *, family: str = ..., @@ -59,19 +69,19 @@ class Font: def cget(self, option: str) -> Any: ... __getitem__ = cget @overload - def actual(self, option: Literal["family"], displayof: Optional[tkinter.Misc] = ...) -> str: ... + def actual(self, option: Literal["family"], displayof: tkinter.Misc | None = ...) -> str: ... @overload - def actual(self, option: Literal["size"], displayof: Optional[tkinter.Misc] = ...) -> int: ... + def actual(self, option: Literal["size"], displayof: tkinter.Misc | None = ...) -> int: ... @overload - def actual(self, option: Literal["weight"], displayof: Optional[tkinter.Misc] = ...) -> Literal["normal", "bold"]: ... + def actual(self, option: Literal["weight"], displayof: tkinter.Misc | None = ...) -> Literal["normal", "bold"]: ... @overload - def actual(self, option: Literal["slant"], displayof: Optional[tkinter.Misc] = ...) -> Literal["roman", "italic"]: ... + def actual(self, option: Literal["slant"], displayof: tkinter.Misc | None = ...) -> Literal["roman", "italic"]: ... @overload - def actual(self, option: Literal["underline", "overstrike"], displayof: Optional[tkinter.Misc] = ...) -> bool: ... + def actual(self, option: Literal["underline", "overstrike"], displayof: tkinter.Misc | None = ...) -> bool: ... @overload - def actual(self, option: None, displayof: Optional[tkinter.Misc] = ...) -> _FontDict: ... + def actual(self, option: None, displayof: tkinter.Misc | None = ...) -> _FontDict: ... @overload - def actual(self, *, displayof: Optional[tkinter.Misc] = ...) -> _FontDict: ... + def actual(self, *, displayof: tkinter.Misc | None = ...) -> _FontDict: ... def config( self, *, @@ -81,22 +91,22 @@ class Font: slant: Literal["roman", "italic"] = ..., underline: bool = ..., overstrike: bool = ..., - ) -> Optional[_FontDict]: ... + ) -> _FontDict | None: ... configure = config def copy(self) -> Font: ... @overload - def metrics(self, __option: Literal["ascent", "descent", "linespace"], *, displayof: Optional[tkinter.Misc] = ...) -> int: ... + def metrics(self, __option: Literal["ascent", "descent", "linespace"], *, displayof: tkinter.Misc | None = ...) -> int: ... @overload - def metrics(self, __option: Literal["fixed"], *, displayof: Optional[tkinter.Misc] = ...) -> bool: ... + def metrics(self, __option: Literal["fixed"], *, displayof: tkinter.Misc | None = ...) -> bool: ... @overload - def metrics(self, *, displayof: Optional[tkinter.Misc] = ...) -> _MetricsDict: ... - def measure(self, text: str, displayof: Optional[tkinter.Misc] = ...) -> int: ... + def metrics(self, *, displayof: tkinter.Misc | None = ...) -> _MetricsDict: ... + def measure(self, text: str, displayof: tkinter.Misc | None = ...) -> int: ... -def families(root: Optional[tkinter.Misc] = ..., displayof: Optional[tkinter.Misc] = ...) -> Tuple[str, ...]: ... -def names(root: Optional[tkinter.Misc] = ...) -> Tuple[str, ...]: ... +def families(root: tkinter.Misc | None = ..., displayof: tkinter.Misc | None = ...) -> Tuple[str, ...]: ... +def names(root: tkinter.Misc | None = ...) -> Tuple[str, ...]: ... if sys.version_info >= (3, 10): - def nametofont(name: str, root: Optional[tkinter.Misc] = ...) -> Font: ... + def nametofont(name: str, root: tkinter.Misc | None = ...) -> Font: ... else: def nametofont(name: str) -> Font: ... diff --git a/mypy/typeshed/stdlib/tkinter/messagebox.pyi b/mypy/typeshed/stdlib/tkinter/messagebox.pyi index b291a45e87c9..fc4afcef0cc2 100644 --- a/mypy/typeshed/stdlib/tkinter/messagebox.pyi +++ b/mypy/typeshed/stdlib/tkinter/messagebox.pyi @@ -1,5 +1,5 @@ from tkinter.commondialog import Dialog -from typing import Any, ClassVar, Optional +from typing import Any, ClassVar ERROR: str INFO: str @@ -19,13 +19,13 @@ YES: str NO: str class Message(Dialog): - command: ClassVar[str] = ... + command: ClassVar[str] -def showinfo(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> str: ... -def showwarning(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> str: ... -def showerror(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> str: ... -def askquestion(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> str: ... -def askokcancel(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> bool: ... -def askyesno(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> bool: ... -def askyesnocancel(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> Optional[bool]: ... -def askretrycancel(title: Optional[str] = ..., message: Optional[str] = ..., **options: Any) -> bool: ... +def showinfo(title: str | None = ..., message: str | None = ..., **options: Any) -> str: ... +def showwarning(title: str | None = ..., message: str | None = ..., **options: Any) -> str: ... +def showerror(title: str | None = ..., message: str | None = ..., **options: Any) -> str: ... +def askquestion(title: str | None = ..., message: str | None = ..., **options: Any) -> str: ... +def askokcancel(title: str | None = ..., message: str | None = ..., **options: Any) -> bool: ... +def askyesno(title: str | None = ..., message: str | None = ..., **options: Any) -> bool: ... +def askyesnocancel(title: str | None = ..., message: str | None = ..., **options: Any) -> bool | None: ... +def askretrycancel(title: str | None = ..., message: str | None = ..., **options: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi b/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi index 12c614072ba2..246979d5afd7 100644 --- a/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi +++ b/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi @@ -1,8 +1,8 @@ -from tkinter import Frame, Grid, Misc, Pack, Place, Scrollbar, Text -from typing import Any, Optional +from tkinter import Frame, Misc, Scrollbar, Text +from typing import Any # The methods from Pack, Place, and Grid are dynamically added over the parent's impls class ScrolledText(Text): frame: Frame vbar: Scrollbar - def __init__(self, master: Optional[Misc] = ..., **kwargs: Any) -> None: ... + def __init__(self, master: Misc | None = ..., **kwargs: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/simpledialog.pyi b/mypy/typeshed/stdlib/tkinter/simpledialog.pyi index b29bb7bfc153..ec801afaceee 100644 --- a/mypy/typeshed/stdlib/tkinter/simpledialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/simpledialog.pyi @@ -1,27 +1,27 @@ from tkinter import Event, Misc, Toplevel -from typing import Any, List, Optional +from typing import Any class Dialog(Toplevel): - def __init__(self, parent: Optional[Misc], title: Optional[str] = ...) -> None: ... + def __init__(self, parent: Misc | None, title: str | None = ...) -> None: ... def body(self, master) -> None: ... def buttonbox(self): ... class SimpleDialog: def __init__( self, - master: Optional[Misc], + master: Misc | None, text: str = ..., - buttons: List[str] = ..., - default: Optional[int] = ..., - cancel: Optional[int] = ..., - title: Optional[str] = ..., - class_: Optional[str] = ..., + buttons: list[str] = ..., + default: int | None = ..., + cancel: int | None = ..., + title: str | None = ..., + class_: str | None = ..., ) -> None: ... - def go(self) -> Optional[int]: ... + def go(self) -> int | None: ... def return_event(self, event: Event[Misc]) -> None: ... def wm_delete_window(self) -> None: ... def done(self, num: int) -> None: ... -def askfloat(title: Optional[str], prompt: str, **kwargs: Any) -> float: ... -def askinteger(title: Optional[str], prompt: str, **kwargs: Any) -> int: ... -def askstring(title: Optional[str], prompt: str, **kwargs: Any) -> str: ... +def askfloat(title: str | None, prompt: str, **kwargs: Any) -> float: ... +def askinteger(title: str | None, prompt: str, **kwargs: Any) -> int: ... +def askstring(title: str | None, prompt: str, **kwargs: Any) -> str: ... diff --git a/mypy/typeshed/stdlib/tkinter/tix.pyi b/mypy/typeshed/stdlib/tkinter/tix.pyi index 78493900f119..3037212c0ad1 100644 --- a/mypy/typeshed/stdlib/tkinter/tix.pyi +++ b/mypy/typeshed/stdlib/tkinter/tix.pyi @@ -1,5 +1,5 @@ import tkinter -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Tuple from typing_extensions import Literal WINDOW: Literal["window"] @@ -37,33 +37,31 @@ TCL_ALL_EVENTS: Literal[0] class tixCommand: def tix_addbitmapdir(self, directory: str) -> None: ... def tix_cget(self, option: str) -> Any: ... - def tix_configure(self, cnf: Optional[Dict[str, Any]] = ..., **kw: Any) -> Any: ... - def tix_filedialog(self, dlgclass: Optional[str] = ...) -> str: ... + def tix_configure(self, cnf: dict[str, Any] | None = ..., **kw: Any) -> Any: ... + def tix_filedialog(self, dlgclass: str | None = ...) -> str: ... def tix_getbitmap(self, name: str) -> str: ... def tix_getimage(self, name: str) -> str: ... def tix_option_get(self, name: str) -> Any: ... - def tix_resetoptions(self, newScheme: str, newFontSet: str, newScmPrio: Optional[str] = ...) -> None: ... + def tix_resetoptions(self, newScheme: str, newFontSet: str, newScmPrio: str | None = ...) -> None: ... class Tk(tkinter.Tk, tixCommand): - def __init__(self, screenName: Optional[str] = ..., baseName: Optional[str] = ..., className: str = ...): ... + def __init__(self, screenName: str | None = ..., baseName: str | None = ..., className: str = ...): ... class TixWidget(tkinter.Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., - widgetName: Optional[str] = ..., - static_options: Optional[List[str]] = ..., - cnf: Dict[str, Any] = ..., - kw: Dict[str, Any] = ..., + master: tkinter.Misc | None = ..., + widgetName: str | None = ..., + static_options: list[str] | None = ..., + cnf: dict[str, Any] = ..., + kw: dict[str, Any] = ..., ) -> None: ... def __getattr__(self, name: str) -> Any: ... def set_silent(self, value: str) -> None: ... def subwidget(self, name: str) -> tkinter.Widget: ... - def subwidgets_all(self) -> List[tkinter.Widget]: ... + def subwidgets_all(self) -> list[tkinter.Widget]: ... def config_all(self, option: Any, value: Any) -> None: ... - def image_create( - self, imgtype: str, cnf: Dict[str, Any] = ..., master: Optional[tkinter.Widget] = ..., **kw: Any - ) -> None: ... + def image_create(self, imgtype: str, cnf: dict[str, Any] = ..., master: tkinter.Widget | None = ..., **kw: Any) -> None: ... def image_delete(self, imgname: str) -> None: ... class TixSubWidget(TixWidget): @@ -72,108 +70,106 @@ class TixSubWidget(TixWidget): ) -> None: ... class DisplayStyle: - def __init__( - self, itemtype: str, cnf: Dict[str, Any] = ..., *, master: Optional[tkinter.Widget] = ..., **kw: Any - ) -> None: ... + def __init__(self, itemtype: str, cnf: dict[str, Any] = ..., *, master: tkinter.Widget | None = ..., **kw: Any) -> None: ... def __getitem__(self, key: str) -> Any: ... def __setitem__(self, key: str, value: Any) -> None: ... def delete(self) -> None: ... - def config(self, cnf: Dict[str, Any] = ..., **kw: Any) -> Any: ... + def config(self, cnf: dict[str, Any] = ..., **kw: Any) -> Any: ... class Balloon(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def bind_widget(self, widget: tkinter.Widget, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def bind_widget(self, widget: tkinter.Widget, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def unbind_widget(self, widget: tkinter.Widget) -> None: ... class ButtonBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... def invoke(self, name: str) -> None: ... class ComboBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def add_history(self, str: str) -> None: ... def append_history(self, str: str) -> None: ... def insert(self, index: int, str: str) -> None: ... def pick(self, index: int) -> None: ... class Control(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def decrement(self) -> None: ... def increment(self) -> None: ... def invoke(self) -> None: ... class LabelEntry(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... class LabelFrame(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... class Meter(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... class OptionMenu(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add_command(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add_separator(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add_command(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add_separator(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def delete(self, name: str) -> None: ... def disable(self, name: str) -> None: ... def enable(self, name: str) -> None: ... class PopupMenu(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def bind_widget(self, widget: tkinter.Widget) -> None: ... def unbind_widget(self, widget: tkinter.Widget) -> None: ... def post_widget(self, widget: tkinter.Widget, x: int, y: int) -> None: ... class Select(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... def invoke(self, name: str) -> None: ... class StdButtonBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def invoke(self, name: str) -> None: ... class DirList(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def chdir(self, dir: str) -> None: ... class DirTree(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def chdir(self, dir: str) -> None: ... class DirSelectDialog(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def popup(self) -> None: ... def popdown(self) -> None: ... class DirSelectBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... class ExFileSelectBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def filter(self) -> None: ... def invoke(self) -> None: ... class FileSelectBox(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def apply_filter(self) -> None: ... def invoke(self) -> None: ... class FileEntry(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def invoke(self) -> None: ... def file_dialog(self) -> None: ... class HList(TixWidget, tkinter.XView, tkinter.YView): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, entry: str, cnf: Dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... - def add_child(self, parent: Optional[str] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... + def add_child(self, parent: str | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> tkinter.Widget: ... def anchor_set(self, entry: str) -> None: ... def anchor_clear(self) -> None: ... # FIXME: Overload, certain combos return, others don't - def column_width(self, col: int = ..., width: Optional[int] = ..., chars: Optional[int] = ...) -> Optional[int]: ... + def column_width(self, col: int = ..., width: int | None = ..., chars: int | None = ...) -> int | None: ... def delete_all(self) -> None: ... def delete_entry(self, entry: str) -> None: ... def delete_offsprings(self, entry: str) -> None: ... @@ -182,23 +178,23 @@ class HList(TixWidget, tkinter.XView, tkinter.YView): def dragsite_clear(self) -> None: ... def dropsite_set(self, index: int) -> None: ... def dropsite_clear(self) -> None: ... - def header_create(self, col: int, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def header_configure(self, col: int, cnf: Dict[str, Any] = ..., **kw: Any) -> Optional[Any]: ... + def header_create(self, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def header_configure(self, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... def header_cget(self, col: int, opt: Any) -> Any: ... def header_exists(self, col: int) -> bool: ... def header_exist(self, col: int) -> bool: ... def header_delete(self, col: int) -> None: ... def header_size(self, col: int) -> int: ... def hide_entry(self, entry: str) -> None: ... - def indicator_create(self, entry: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def indicator_configure(self, entry: str, cnf: Dict[str, Any] = ..., **kw: Any) -> Optional[Any]: ... + def indicator_create(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def indicator_configure(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... def indicator_cget(self, entry: str, opt: Any) -> Any: ... def indicator_exists(self, entry: str) -> bool: ... def indicator_delete(self, entry: str) -> None: ... def indicator_size(self, entry: str) -> int: ... def info_anchor(self) -> str: ... - def info_bbox(self, entry: str) -> Tuple[int, int, int, int]: ... - def info_children(self, entry: Optional[str] = ...) -> Tuple[str, ...]: ... + def info_bbox(self, entry: str) -> tuple[int, int, int, int]: ... + def info_children(self, entry: str | None = ...) -> Tuple[str, ...]: ... def info_data(self, entry: str) -> Any: ... def info_dragsite(self) -> str: ... def info_dropsite(self) -> str: ... @@ -209,21 +205,21 @@ class HList(TixWidget, tkinter.XView, tkinter.YView): def info_prev(self, entry: str) -> str: ... def info_selection(self) -> Tuple[str, ...]: ... def item_cget(self, entry: str, col: int, opt: Any) -> Any: ... - def item_configure(self, entry: str, col: int, cnf: Dict[str, Any] = ..., **kw: Any) -> Optional[Any]: ... - def item_create(self, entry: str, col: int, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def item_configure(self, entry: str, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... + def item_create(self, entry: str, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def item_exists(self, entry: str, col: int) -> bool: ... def item_delete(self, entry: str, col: int) -> None: ... def entrycget(self, entry: str, opt: Any) -> Any: ... - def entryconfigure(self, entry: str, cnf: Dict[str, Any] = ..., **kw: Any) -> Optional[Any]: ... + def entryconfigure(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... def nearest(self, y: int) -> str: ... def see(self, entry: str) -> None: ... - def selection_clear(self, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def selection_clear(self, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def selection_includes(self, entry: str) -> bool: ... - def selection_set(self, first: str, last: Optional[str] = ...) -> None: ... + def selection_set(self, first: str, last: str | None = ...) -> None: ... def show_entry(self, entry: str) -> None: ... class CheckList(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def autosetmode(self) -> None: ... def close(self, entrypath: str) -> None: ... def getmode(self, entrypath: str) -> str: ... @@ -233,7 +229,7 @@ class CheckList(TixWidget): def setstatus(self, entrypath: str, mode: str = ...) -> None: ... class Tree(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def autosetmode(self) -> None: ... def close(self, entrypath: str) -> None: ... def getmode(self, entrypath: str) -> str: ... @@ -241,17 +237,17 @@ class Tree(TixWidget): def setmode(self, entrypath: str, mode: str = ...) -> None: ... class TList(TixWidget, tkinter.XView, tkinter.YView): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def active_set(self, index: int) -> None: ... def active_clear(self) -> None: ... def anchor_set(self, index: int) -> None: ... def anchor_clear(self) -> None: ... - def delete(self, from_: int, to: Optional[int] = ...) -> None: ... + def delete(self, from_: int, to: int | None = ...) -> None: ... def dragsite_set(self, index: int) -> None: ... def dragsite_clear(self) -> None: ... def dropsite_set(self, index: int) -> None: ... def dropsite_clear(self) -> None: ... - def insert(self, index: int, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def insert(self, index: int, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def info_active(self) -> int: ... def info_anchor(self) -> int: ... def info_down(self, index: int) -> int: ... @@ -262,44 +258,44 @@ class TList(TixWidget, tkinter.XView, tkinter.YView): def info_up(self, index: int) -> int: ... def nearest(self, x: int, y: int) -> int: ... def see(self, index: int) -> None: ... - def selection_clear(self, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def selection_clear(self, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def selection_includes(self, index: int) -> bool: ... - def selection_set(self, first: int, last: Optional[int] = ...) -> None: ... + def selection_set(self, first: int, last: int | None = ...) -> None: ... class PanedWindow(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def delete(self, name: str) -> None: ... def forget(self, name: str) -> None: ... # type: ignore def panecget(self, entry: str, opt: Any) -> Any: ... - def paneconfigure(self, entry: str, cnf: Dict[str, Any] = ..., **kw: Any) -> Optional[Any]: ... - def panes(self) -> List[tkinter.Widget]: ... + def paneconfigure(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... + def panes(self) -> list[tkinter.Widget]: ... class ListNoteBook(TixWidget): - def __init__(self, master: Optional[tkinter.Widget], cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def page(self, name: str) -> tkinter.Widget: ... - def pages(self) -> List[tkinter.Widget]: ... + def pages(self) -> list[tkinter.Widget]: ... def raise_page(self, name: str) -> None: ... class NoteBook(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def add(self, name: str, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def delete(self, name: str) -> None: ... def page(self, name: str) -> tkinter.Widget: ... - def pages(self) -> List[tkinter.Widget]: ... + def pages(self) -> list[tkinter.Widget]: ... def raise_page(self, name: str) -> None: ... def raised(self) -> bool: ... class InputOnly(TixWidget): - def __init__(self, master: Optional[tkinter.Widget] = ..., cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def __init__(self, master: tkinter.Widget | None = ..., cnf: dict[str, Any] = ..., **kw: Any) -> None: ... class Form: def __setitem__(self, key: str, value: Any) -> None: ... - def config(self, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... - def form(self, cnf: Dict[str, Any] = ..., **kw: Any) -> None: ... + def config(self, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... + def form(self, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def check(self) -> bool: ... def forget(self) -> None: ... - def grid(self, xsize: int = ..., ysize: int = ...) -> Optional[Tuple[int, int]]: ... - def info(self, option: Optional[str] = ...) -> Any: ... - def slaves(self) -> List[tkinter.Widget]: ... + def grid(self, xsize: int = ..., ysize: int = ...) -> tuple[int, int] | None: ... + def info(self, option: str | None = ...) -> Any: ... + def slaves(self) -> list[tkinter.Widget]: ... diff --git a/mypy/typeshed/stdlib/tkinter/ttk.pyi b/mypy/typeshed/stdlib/tkinter/ttk.pyi index af3c75142598..be0713ec2e4b 100644 --- a/mypy/typeshed/stdlib/tkinter/ttk.pyi +++ b/mypy/typeshed/stdlib/tkinter/ttk.pyi @@ -2,11 +2,11 @@ import _tkinter import sys import tkinter from tkinter.font import _FontDescription -from typing import Any, Callable, Dict, List, Optional, Tuple, Union, overload -from typing_extensions import Literal +from typing import Any, Callable, Tuple, Union, overload +from typing_extensions import Literal, TypedDict def tclobjs_to_py(adict): ... -def setup_master(master: Optional[Any] = ...): ... +def setup_master(master: Any | None = ...): ... # from ttk_widget (aka ttk::widget) manual page, differs from tkinter._Compound _TtkCompound = Literal["text", "image", tkinter._Compound] @@ -14,29 +14,32 @@ _TtkCompound = Literal["text", "image", tkinter._Compound] class Style: master: Any tk: _tkinter.TkappType - def __init__(self, master: Optional[Any] = ...): ... - def configure(self, style, query_opt: Optional[Any] = ..., **kw): ... - def map(self, style, query_opt: Optional[Any] = ..., **kw): ... - def lookup(self, style, option, state: Optional[Any] = ..., default: Optional[Any] = ...): ... - def layout(self, style, layoutspec: Optional[Any] = ...): ... + def __init__(self, master: tkinter.Misc | None = ...): ... + def configure(self, style, query_opt: Any | None = ..., **kw): ... + def map(self, style, query_opt: Any | None = ..., **kw): ... + def lookup(self, style, option, state: Any | None = ..., default: Any | None = ...): ... + def layout(self, style, layoutspec: Any | None = ...): ... def element_create(self, elementname, etype, *args, **kw): ... def element_names(self): ... def element_options(self, elementname): ... - def theme_create(self, themename, parent: Optional[Any] = ..., settings: Optional[Any] = ...): ... + def theme_create(self, themename, parent: Any | None = ..., settings: Any | None = ...): ... def theme_settings(self, themename, settings): ... - def theme_names(self): ... - def theme_use(self, themename: Optional[Any] = ...): ... + def theme_names(self) -> Tuple[str, ...]: ... + @overload + def theme_use(self, themename: str) -> None: ... + @overload + def theme_use(self, themename: None = ...) -> str: ... class Widget(tkinter.Widget): - def __init__(self, master: Optional[tkinter.Misc], widgetname, kw: Optional[Any] = ...): ... + def __init__(self, master: tkinter.Misc | None, widgetname, kw: Any | None = ...): ... def identify(self, x, y): ... - def instate(self, statespec, callback: Optional[Any] = ..., *args, **kw): ... - def state(self, statespec: Optional[Any] = ...): ... + def instate(self, statespec, callback: Any | None = ..., *args, **kw): ... + def state(self, statespec: Any | None = ...): ... class Button(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., command: tkinter._ButtonCommand = ..., @@ -49,15 +52,15 @@ class Button(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., + width: int | Literal[""] = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, command: tkinter._ButtonCommand = ..., compound: _TtkCompound = ..., @@ -68,20 +71,20 @@ class Button(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + width: int | Literal[""] = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def invoke(self): ... + def invoke(self) -> Any: ... class Checkbutton(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., command: tkinter._ButtonCommand = ..., @@ -95,19 +98,19 @@ class Checkbutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., # Seems like variable can be empty string, but actually setting it to # empty string segfaults before Tcl 8.6.9. Search for ttk::checkbutton # here: https://sourceforge.net/projects/tcl/files/Tcl/8.6.9/tcltk-release-notes-8.6.9.txt/view variable: tkinter.Variable = ..., - width: Union[int, Literal[""]] = ..., + width: int | Literal[""] = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, command: tkinter._ButtonCommand = ..., compound: _TtkCompound = ..., @@ -119,22 +122,22 @@ class Checkbutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., variable: tkinter.Variable = ..., - width: Union[int, Literal[""]] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + width: int | Literal[""] = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def invoke(self): ... + def invoke(self) -> Any: ... class Entry(Widget, tkinter.Entry): def __init__( self, - master: Optional[tkinter.Misc] = ..., - widget: Optional[str] = ..., + master: tkinter.Misc | None = ..., + widget: str | None = ..., *, background: tkinter._Color = ..., # undocumented class_: str = ..., @@ -158,7 +161,7 @@ class Entry(Widget, tkinter.Entry): @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., cursor: tkinter._Cursor = ..., @@ -176,14 +179,14 @@ class Entry(Widget, tkinter.Entry): validatecommand: tkinter._EntryValidateCommand = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Entry().config is mypy error (don't know why) @overload # type: ignore def config( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., cursor: tkinter._Cursor = ..., @@ -201,9 +204,9 @@ class Entry(Widget, tkinter.Entry): validatecommand: tkinter._EntryValidateCommand = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def config(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... def bbox(self, index): ... def identify(self, x, y): ... def validate(self): ... @@ -211,7 +214,7 @@ class Entry(Widget, tkinter.Entry): class Combobox(Entry): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, background: tkinter._Color = ..., # undocumented class_: str = ..., @@ -223,7 +226,7 @@ class Combobox(Entry): invalidcommand: tkinter._EntryValidateCommand = ..., # undocumented justify: Literal["left", "center", "right"] = ..., name: str = ..., - postcommand: Union[Callable[[], Any], str] = ..., + postcommand: Callable[[], Any] | str = ..., show: Any = ..., # undocumented state: str = ..., style: str = ..., @@ -231,14 +234,14 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., # undocumented validatecommand: tkinter._EntryValidateCommand = ..., # undocumented - values: tkinter._TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., # undocumented ) -> None: ... @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., cursor: tkinter._Cursor = ..., @@ -248,7 +251,7 @@ class Combobox(Entry): height: int = ..., invalidcommand: tkinter._EntryValidateCommand = ..., justify: Literal["left", "center", "right"] = ..., - postcommand: Union[Callable[[], Any], str] = ..., + postcommand: Callable[[], Any] | str = ..., show: Any = ..., state: str = ..., style: str = ..., @@ -256,17 +259,17 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: tkinter._TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Combobox().config is mypy error (don't know why) @overload # type: ignore def config( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., cursor: tkinter._Cursor = ..., @@ -276,7 +279,7 @@ class Combobox(Entry): height: int = ..., invalidcommand: tkinter._EntryValidateCommand = ..., justify: Literal["left", "center", "right"] = ..., - postcommand: Union[Callable[[], Any], str] = ..., + postcommand: Callable[[], Any] | str = ..., show: Any = ..., state: str = ..., style: str = ..., @@ -284,19 +287,19 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: tkinter._TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def config(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... - def current(self, newindex: Optional[Any] = ...): ... + def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... + def current(self, newindex: Any | None = ...): ... def set(self, value): ... class Frame(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, border: tkinter._ScreenUnits = ..., borderwidth: tkinter._ScreenUnits = ..., @@ -313,7 +316,7 @@ class Frame(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, border: tkinter._ScreenUnits = ..., borderwidth: tkinter._ScreenUnits = ..., @@ -324,15 +327,15 @@ class Frame(Widget): style: str = ..., takefocus: tkinter._TakeFocusValue = ..., width: tkinter._ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Label(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, anchor: tkinter._Anchor = ..., background: tkinter._Color = ..., @@ -351,16 +354,16 @@ class Label(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., + width: int | Literal[""] = ..., wraplength: tkinter._ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, anchor: tkinter._Anchor = ..., background: tkinter._Color = ..., @@ -377,20 +380,20 @@ class Label(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., + width: int | Literal[""] = ..., wraplength: tkinter._ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Labelframe(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, border: tkinter._ScreenUnits = ..., borderwidth: tkinter._ScreenUnits = ..., # undocumented @@ -404,14 +407,14 @@ class Labelframe(Widget): relief: tkinter._Relief = ..., # undocumented style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., underline: int = ..., width: tkinter._ScreenUnits = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, border: tkinter._ScreenUnits = ..., borderwidth: tkinter._ScreenUnits = ..., @@ -423,12 +426,12 @@ class Labelframe(Widget): relief: tkinter._Relief = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., underline: int = ..., width: tkinter._ScreenUnits = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure LabelFrame = Labelframe @@ -436,7 +439,7 @@ LabelFrame = Labelframe class Menubutton(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., compound: _TtkCompound = ..., @@ -449,15 +452,15 @@ class Menubutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., + width: int | Literal[""] = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, compound: _TtkCompound = ..., cursor: tkinter._Cursor = ..., @@ -468,19 +471,19 @@ class Menubutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., - width: Union[int, Literal[""]] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + width: int | Literal[""] = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Notebook(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., cursor: tkinter._Cursor = ..., @@ -494,7 +497,7 @@ class Notebook(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., height: int = ..., @@ -502,25 +505,36 @@ class Notebook(Widget): style: str = ..., takefocus: tkinter._TakeFocusValue = ..., width: int = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def add(self, child, **kw): ... + def add( + self, + child: tkinter.Widget, + *, + state: Literal["normal", "disabled", "hidden"] = ..., + sticky: str = ..., # consists of letters 'n', 's', 'w', 'e', no repeats, may be empty + padding: tkinter._Padding = ..., + text: str = ..., + image: Any = ..., # Sequence of an image name, followed by zero or more (sequences of one or more state names followed by an image name) + compound: tkinter._Compound = ..., + underline: int = ..., + ) -> None: ... def forget(self, tab_id): ... def hide(self, tab_id): ... def identify(self, x, y): ... def index(self, tab_id): ... def insert(self, pos, child, **kw): ... - def select(self, tab_id: Optional[Any] = ...): ... - def tab(self, tab_id, option: Optional[Any] = ..., **kw): ... + def select(self, tab_id: Any | None = ...): ... + def tab(self, tab_id, option: Any | None = ..., **kw): ... def tabs(self): ... - def enable_traversal(self): ... + def enable_traversal(self) -> None: ... class Panedwindow(Widget, tkinter.PanedWindow): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., cursor: tkinter._Cursor = ..., @@ -532,44 +546,45 @@ class Panedwindow(Widget, tkinter.PanedWindow): takefocus: tkinter._TakeFocusValue = ..., width: int = ..., ) -> None: ... + def add(self, child: tkinter.Widget, *, weight: int = ..., **kw) -> None: ... @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., height: int = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., width: int = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Panedwindow().config is mypy error (don't know why) @overload # type: ignore def config( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., height: int = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., width: int = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def config(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... forget: Any def insert(self, pos, child, **kw): ... - def pane(self, pane, option: Optional[Any] = ..., **kw): ... - def sashpos(self, index, newpos: Optional[Any] = ...): ... + def pane(self, pane, option: Any | None = ..., **kw): ... + def sashpos(self, index, newpos: Any | None = ...): ... PanedWindow = Panedwindow class Progressbar(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., cursor: tkinter._Cursor = ..., @@ -582,12 +597,12 @@ class Progressbar(Widget): style: str = ..., takefocus: tkinter._TakeFocusValue = ..., value: float = ..., - variable: Union[tkinter.IntVar, tkinter.DoubleVar] = ..., + variable: tkinter.IntVar | tkinter.DoubleVar = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., length: tkinter._ScreenUnits = ..., @@ -598,19 +613,19 @@ class Progressbar(Widget): style: str = ..., takefocus: tkinter._TakeFocusValue = ..., value: float = ..., - variable: Union[tkinter.IntVar, tkinter.DoubleVar] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + variable: tkinter.IntVar | tkinter.DoubleVar = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def start(self, interval: Optional[Any] = ...): ... - def step(self, amount: Optional[Any] = ...): ... + def start(self, interval: Any | None = ...): ... + def step(self, amount: Any | None = ...): ... def stop(self): ... class Radiobutton(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., command: tkinter._ButtonCommand = ..., @@ -622,17 +637,17 @@ class Radiobutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., value: Any = ..., - variable: Union[tkinter.Variable, Literal[""]] = ..., - width: Union[int, Literal[""]] = ..., + variable: tkinter.Variable | Literal[""] = ..., + width: int | Literal[""] = ..., ) -> None: ... @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, command: tkinter._ButtonCommand = ..., compound: _TtkCompound = ..., @@ -642,25 +657,25 @@ class Radiobutton(Widget): state: str = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - text: Union[float, str] = ..., + text: float | str = ..., textvariable: tkinter.Variable = ..., underline: int = ..., value: Any = ..., - variable: Union[tkinter.Variable, Literal[""]] = ..., - width: Union[int, Literal[""]] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + variable: tkinter.Variable | Literal[""] = ..., + width: int | Literal[""] = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def invoke(self): ... + def invoke(self) -> Any: ... class Scale(Widget, tkinter.Scale): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., - command: Union[str, Callable[[str], Any]] = ..., + command: str | Callable[[str], Any] = ..., cursor: tkinter._Cursor = ..., from_: float = ..., length: tkinter._ScreenUnits = ..., @@ -671,14 +686,14 @@ class Scale(Widget, tkinter.Scale): takefocus: tkinter._TakeFocusValue = ..., to: float = ..., value: float = ..., - variable: Union[tkinter.IntVar, tkinter.DoubleVar] = ..., + variable: tkinter.IntVar | tkinter.DoubleVar = ..., ) -> None: ... @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, - command: Union[str, Callable[[str], Any]] = ..., + command: str | Callable[[str], Any] = ..., cursor: tkinter._Cursor = ..., from_: float = ..., length: tkinter._ScreenUnits = ..., @@ -688,17 +703,17 @@ class Scale(Widget, tkinter.Scale): takefocus: tkinter._TakeFocusValue = ..., to: float = ..., value: float = ..., - variable: Union[tkinter.IntVar, tkinter.DoubleVar] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + variable: tkinter.IntVar | tkinter.DoubleVar = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Scale().config is mypy error (don't know why) @overload # type: ignore def config( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, - command: Union[str, Callable[[str], Any]] = ..., + command: str | Callable[[str], Any] = ..., cursor: tkinter._Cursor = ..., from_: float = ..., length: tkinter._ScreenUnits = ..., @@ -708,19 +723,19 @@ class Scale(Widget, tkinter.Scale): takefocus: tkinter._TakeFocusValue = ..., to: float = ..., value: float = ..., - variable: Union[tkinter.IntVar, tkinter.DoubleVar] = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + variable: tkinter.IntVar | tkinter.DoubleVar = ..., + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def config(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... - def get(self, x: Optional[Any] = ..., y: Optional[Any] = ...): ... + def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... + def get(self, x: Any | None = ..., y: Any | None = ...): ... class Scrollbar(Widget, tkinter.Scrollbar): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., - command: Union[Callable[..., Optional[Tuple[float, float]]], str] = ..., + command: Callable[..., tuple[float, float] | None] | str = ..., cursor: tkinter._Cursor = ..., name: str = ..., orient: Literal["horizontal", "vertical"] = ..., @@ -730,35 +745,35 @@ class Scrollbar(Widget, tkinter.Scrollbar): @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, - command: Union[Callable[..., Optional[Tuple[float, float]]], str] = ..., + command: Callable[..., tuple[float, float] | None] | str = ..., cursor: tkinter._Cursor = ..., orient: Literal["horizontal", "vertical"] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Scrollbar().config is mypy error (don't know why) @overload # type: ignore def config( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, - command: Union[Callable[..., Optional[Tuple[float, float]]], str] = ..., + command: Callable[..., tuple[float, float] | None] | str = ..., cursor: tkinter._Cursor = ..., orient: Literal["horizontal", "vertical"] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def config(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... class Separator(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., cursor: tkinter._Cursor = ..., @@ -770,21 +785,21 @@ class Separator(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., orient: Literal["horizontal", "vertical"] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure class Sizegrip(Widget): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., cursor: tkinter._Cursor = ..., @@ -795,25 +810,25 @@ class Sizegrip(Widget): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, cursor: tkinter._Cursor = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure if sys.version_info >= (3, 7): class Spinbox(Entry): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, background: tkinter._Color = ..., # undocumented class_: str = ..., - command: Union[Callable[[], Any], str, tkinter._TkinterSequence[str]] = ..., + command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., exportselection: bool = ..., # undocumented font: _FontDescription = ..., # undocumented @@ -832,7 +847,7 @@ if sys.version_info >= (3, 7): to: float = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: tkinter._TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., # undocumented wrap: bool = ..., xscrollcommand: tkinter._XYScrollCommand = ..., @@ -840,10 +855,10 @@ if sys.version_info >= (3, 7): @overload # type: ignore def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., - command: Union[Callable[[], Any], str, tkinter._TkinterSequence[str]] = ..., + command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., exportselection: bool = ..., font: _FontDescription = ..., @@ -861,34 +876,64 @@ if sys.version_info >= (3, 7): to: float = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: tkinter._TkinterSequence[str] = ..., + values: list[str] | Tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure # type: ignore def set(self, value: Any) -> None: ... +class _TreeviewItemDict(TypedDict): + text: str + image: list[str] | Literal[""] # no idea why it's wrapped in list + values: list[Any] | Literal[""] + open: bool # actually 0 or 1 + tags: list[str] | Literal[""] + +class _TreeviewTagDict(TypedDict): + # There is also 'text' and 'anchor', but they don't seem to do anything, using them is likely a bug + foreground: tkinter._Color + background: tkinter._Color + font: _FontDescription + image: Literal[""] | str # not wrapped in list :D + +class _TreeviewHeaderDict(TypedDict): + text: str + image: list[str] + anchor: tkinter._Anchor + command: str + state: str # Doesn't seem to appear anywhere else than in these dicts + +class _TreeviewColumnDict(TypedDict): + width: int + minwidth: int + stretch: bool # actually 0 or 1 + anchor: tkinter._Anchor + id: str + +_TreeviewColumnId = Union[int, str] # manual page: "COLUMN IDENTIFIERS" + class Treeview(Widget, tkinter.XView, tkinter.YView): def __init__( self, - master: Optional[tkinter.Misc] = ..., + master: tkinter.Misc | None = ..., *, class_: str = ..., - columns: Union[str, tkinter._TkinterSequence[str]] = ..., + columns: str | list[str] | Tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., - displaycolumns: Union[str, tkinter._TkinterSequence[str], tkinter._TkinterSequence[int], Literal["#all"]] = ..., + displaycolumns: str | list[str] | Tuple[str, ...] | list[int] | Tuple[int, ...] | Literal["#all"] = ..., height: int = ..., name: str = ..., padding: tkinter._Padding = ..., selectmode: Literal["extended", "browse", "none"] = ..., - # _TkinterSequences of Literal don't actually work, using str instead. + # list/tuple of Literal don't actually work in mypy # # 'tree headings' is same as ['tree', 'headings'], and I wouldn't be - # surprised if someone was using it. - show: Union[Literal["tree", "headings", "tree headings"], tkinter._TkinterSequence[str]] = ..., + # surprised if someone is using it. + show: Literal["tree", "headings", "tree headings", ""] | list[str] | Tuple[str, ...] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., xscrollcommand: tkinter._XYScrollCommand = ..., @@ -897,67 +942,171 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): @overload def configure( self, - cnf: Optional[Dict[str, Any]] = ..., + cnf: dict[str, Any] | None = ..., *, - columns: Union[str, tkinter._TkinterSequence[str]] = ..., + columns: str | list[str] | Tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., - displaycolumns: Union[str, tkinter._TkinterSequence[str], tkinter._TkinterSequence[int], Literal["#all"]] = ..., + displaycolumns: str | list[str] | Tuple[str, ...] | list[int] | Tuple[int, ...] | Literal["#all"] = ..., height: int = ..., padding: tkinter._Padding = ..., selectmode: Literal["extended", "browse", "none"] = ..., - show: Union[Literal["tree", "headings", "tree headings"], tkinter._TkinterSequence[str]] = ..., + show: Literal["tree", "headings", "tree headings", ""] | list[str] | Tuple[str, ...] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., xscrollcommand: tkinter._XYScrollCommand = ..., yscrollcommand: tkinter._XYScrollCommand = ..., - ) -> Optional[Dict[str, Tuple[str, str, str, Any, Any]]]: ... + ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload - def configure(self, cnf: str) -> Tuple[str, str, str, Any, Any]: ... + def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def bbox(self, item, column: Optional[Any] = ...): ... # type: ignore - def get_children(self, item: Optional[Any] = ...): ... - def set_children(self, item, *newchildren): ... - def column(self, column, option: Optional[Any] = ..., **kw): ... - def delete(self, *items): ... - def detach(self, *items): ... - def exists(self, item): ... - def focus(self, item: Optional[Any] = ...): ... - def heading(self, column, option: Optional[Any] = ..., **kw): ... + def bbox(self, item, column: _TreeviewColumnId | None = ...) -> tuple[int, int, int, int] | Literal[""]: ... # type: ignore + def get_children(self, item: str | None = ...) -> Tuple[str, ...]: ... + def set_children(self, item: str, *newchildren: str) -> None: ... + @overload + def column(self, column: _TreeviewColumnId, option: Literal["width", "minwidth"]) -> int: ... + @overload + def column(self, column: _TreeviewColumnId, option: Literal["stretch"]) -> bool: ... # actually 0 or 1 + @overload + def column(self, column: _TreeviewColumnId, option: Literal["anchor"]) -> _tkinter.Tcl_Obj: ... + @overload + def column(self, column: _TreeviewColumnId, option: Literal["id"]) -> str: ... + @overload + def column(self, column: _TreeviewColumnId, option: str) -> Any: ... + @overload + def column( + self, + column: _TreeviewColumnId, + option: None = ..., + *, + width: int = ..., + minwidth: int = ..., + stretch: bool = ..., + anchor: tkinter._Anchor = ..., + # id is read-only + ) -> _TreeviewColumnDict | None: ... + def delete(self, *items: str) -> None: ... + def detach(self, *items: str) -> None: ... + def exists(self, item: str) -> bool: ... + @overload # type: ignore + def focus(self, item: None = ...) -> str: ... # can return empty string + @overload + def focus(self, item: str) -> Literal[""]: ... + @overload + def heading(self, column: _TreeviewColumnId, option: Literal["text"]) -> str: ... + @overload + def heading(self, column: _TreeviewColumnId, option: Literal["image"]) -> tuple[str]: ... + @overload + def heading(self, column: _TreeviewColumnId, option: Literal["anchor"]) -> _tkinter.Tcl_Obj: ... + @overload + def heading(self, column: _TreeviewColumnId, option: Literal["command"]) -> str: ... + @overload + def heading(self, column: _TreeviewColumnId, option: str) -> Any: ... + @overload + def heading( + self, + column: _TreeviewColumnId, + option: None = ..., + *, + text: str = ..., + image: tkinter._ImageSpec = ..., + anchor: tkinter._Anchor = ..., + command: str | Callable[[], Any] = ..., + ) -> _TreeviewHeaderDict | None: ... def identify(self, component, x, y): ... - def identify_row(self, y): ... - def identify_column(self, x): ... - def identify_region(self, x, y): ... - def identify_element(self, x, y): ... - def index(self, item): ... - def insert(self, parent, index, iid: Optional[Any] = ..., **kw): ... - def item(self, item, option: Optional[Any] = ..., **kw): ... - def move(self, item, parent, index): ... - reattach: Any - def next(self, item): ... - def parent(self, item): ... - def prev(self, item): ... - def see(self, item): ... + def identify_row(self, y: int) -> str: ... + def identify_column(self, x: int) -> str: ... + def identify_region(self, x: int, y: int) -> Literal["heading", "separator", "tree", "cell", "nothing"]: ... + def identify_element(self, x: int, y: int) -> str: ... # don't know what possible return values are + def index(self, item: str) -> int: ... + def insert( + self, + parent: str, + index: int | Literal["end"], + iid: str | None = ..., + *, + id: str = ..., # same as iid + text: str = ..., + image: tkinter._ImageSpec = ..., + values: list[Any] | Tuple[Any, ...] = ..., + open: bool = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + ) -> str: ... + @overload + def item(self, item: str, option: Literal["text"]) -> str: ... + @overload + def item(self, item: str, option: Literal["image"]) -> tuple[str] | Literal[""]: ... + @overload + def item(self, item: str, option: Literal["values"]) -> Tuple[Any, ...] | Literal[""]: ... + @overload + def item(self, item: str, option: Literal["open"]) -> bool: ... # actually 0 or 1 + @overload + def item(self, item: str, option: Literal["tags"]) -> Tuple[str, ...] | Literal[""]: ... + @overload + def item(self, item: str, option: str) -> Any: ... + @overload + def item( + self, + item: str, + option: None = ..., + *, + text: str = ..., + image: tkinter._ImageSpec = ..., + values: list[Any] | Tuple[Any, ...] | Literal[""] = ..., + open: bool = ..., + tags: str | list[str] | Tuple[str, ...] = ..., + ) -> _TreeviewItemDict | None: ... + def move(self, item: str, parent: str, index: int) -> None: ... + reattach = move + def next(self, item: str) -> str: ... # returning empty string means last item + def parent(self, item: str) -> str: ... + def prev(self, item: str) -> str: ... # returning empty string means first item + def see(self, item: str) -> None: ... if sys.version_info >= (3, 8): def selection(self) -> Tuple[str, ...]: ... else: - def selection(self, selop: Optional[Any] = ..., items: Optional[Any] = ...) -> Tuple[str, ...]: ... - def selection_set(self, items): ... - def selection_add(self, items): ... - def selection_remove(self, items): ... - def selection_toggle(self, items): ... - def set(self, item, column: Optional[Any] = ..., value: Optional[Any] = ...): ... + def selection(self, selop: Any | None = ..., items: Any | None = ...) -> Tuple[str, ...]: ... + def selection_set(self, items: str | list[str] | Tuple[str, ...]) -> None: ... + def selection_add(self, items: str | list[str] | Tuple[str, ...]) -> None: ... + def selection_remove(self, items: str | list[str] | Tuple[str, ...]) -> None: ... + def selection_toggle(self, items: str | list[str] | Tuple[str, ...]) -> None: ... + @overload + def set(self, item: str, column: None = ..., value: None = ...) -> dict[str, Any]: ... + @overload + def set(self, item: str, column: _TreeviewColumnId, value: None = ...) -> Any: ... + @overload + def set(self, item: str, column: _TreeviewColumnId, value: Any) -> Literal[""]: ... # There's no tag_unbind() or 'add' argument for whatever reason. # Also, it's 'callback' instead of 'func' here. @overload def tag_bind( - self, tagname: str, sequence: Optional[str] = ..., callback: Optional[Callable[[tkinter.Event[Treeview]], Any]] = ... + self, tagname: str, sequence: str | None = ..., callback: Callable[[tkinter.Event[Treeview]], Any] | None = ... ) -> str: ... @overload - def tag_bind(self, tagname: str, sequence: Optional[str], callback: str) -> None: ... + def tag_bind(self, tagname: str, sequence: str | None, callback: str) -> None: ... @overload def tag_bind(self, tagname: str, *, callback: str) -> None: ... - def tag_configure(self, tagname, option: Optional[Any] = ..., **kw): ... - def tag_has(self, tagname, item: Optional[Any] = ...): ... + @overload + def tag_configure(self, tagname: str, option: Literal["foreground", "background"]) -> tkinter._Color: ... + @overload + def tag_configure(self, tagname: str, option: Literal["font"]) -> _FontDescription: ... + @overload + def tag_configure(self, tagname: str, option: Literal["image"]) -> str: ... + @overload + def tag_configure( + self, + tagname: str, + option: None = ..., + *, + # There is also 'text' and 'anchor', but they don't seem to do anything, using them is likely a bug + foreground: tkinter._Color = ..., + background: tkinter._Color = ..., + font: _FontDescription = ..., + image: tkinter._ImageSpec = ..., + ) -> _TreeviewTagDict | Any: ... # can be None but annoying to check + @overload + def tag_has(self, tagname: str, item: None = ...) -> Tuple[str, ...]: ... + @overload + def tag_has(self, tagname: str, item: str) -> bool: ... class LabeledScale(Frame): label: Any @@ -965,15 +1114,15 @@ class LabeledScale(Frame): # TODO: don't any-type **kw. That goes to Frame.__init__. def __init__( self, - master: Optional[tkinter.Misc] = ..., - variable: Optional[Union[tkinter.IntVar, tkinter.DoubleVar]] = ..., + master: tkinter.Misc | None = ..., + variable: tkinter.IntVar | tkinter.DoubleVar | None = ..., from_: float = ..., to: float = ..., *, - compound: Union[Literal["top"], Literal["bottom"]] = ..., + compound: Literal["top"] | Literal["bottom"] = ..., **kw: Any, ) -> None: ... - # destroy is overrided, signature does not change + # destroy is overridden, signature does not change value: Any class OptionMenu(Menubutton): @@ -981,13 +1130,13 @@ class OptionMenu(Menubutton): self, master, variable, - default: Optional[str] = ..., + default: str | None = ..., *values: str, # rest of these are keyword-only because *args syntax used above style: str = ..., - direction: Union[Literal["above"], Literal["below"], Literal["left"], Literal["right"], Literal["flush"]] = ..., - command: Optional[Callable[[tkinter.StringVar], Any]] = ..., + direction: Literal["above"] | Literal["below"] | Literal["left"] | Literal["right"] | Literal["flush"] = ..., + command: Callable[[tkinter.StringVar], Any] | None = ..., ) -> None: ... # configure, config, cget, destroy are inherited from Menubutton - # destroy and __setitem__ are overrided, signature does not change - def set_menu(self, default: Optional[Any] = ..., *values): ... + # destroy and __setitem__ are overridden, signature does not change + def set_menu(self, default: Any | None = ..., *values): ... diff --git a/mypy/typeshed/stdlib/token.pyi b/mypy/typeshed/stdlib/token.pyi index a806a466b8ea..90381833511b 100644 --- a/mypy/typeshed/stdlib/token.pyi +++ b/mypy/typeshed/stdlib/token.pyi @@ -1,5 +1,4 @@ import sys -from typing import Dict ENDMARKER: int NAME: int @@ -26,8 +25,6 @@ GREATER: int EQUAL: int DOT: int PERCENT: int -if sys.version_info < (3,): - BACKQUOTE: int LBRACE: int RBRACE: int EQEQUAL: int @@ -53,23 +50,18 @@ DOUBLESTAREQUAL: int DOUBLESLASH: int DOUBLESLASHEQUAL: int AT: int -if sys.version_info >= (3,): - RARROW: int - ELLIPSIS: int -if sys.version_info >= (3, 5): - ATEQUAL: int - if sys.version_info < (3, 7): - # These were removed in Python 3.7 but added back in Python 3.8 - AWAIT: int - ASYNC: int -if sys.version_info >= (3, 8): +RARROW: int +ELLIPSIS: int +ATEQUAL: int +if sys.version_info < (3, 7) or sys.version_info >= (3, 8): + # These were removed in Python 3.7 but added back in Python 3.8 AWAIT: int ASYNC: int OP: int ERRORTOKEN: int N_TOKENS: int NT_OFFSET: int -tok_name: Dict[int, str] +tok_name: dict[int, str] if sys.version_info >= (3, 7): COMMENT: int NL: int @@ -78,7 +70,7 @@ if sys.version_info >= (3, 8): TYPE_COMMENT: int TYPE_IGNORE: int COLONEQUAL: int - EXACT_TOKEN_TYPES: Dict[str, int] + EXACT_TOKEN_TYPES: dict[str, int] def ISTERMINAL(x: int) -> bool: ... def ISNONTERMINAL(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/tokenize.pyi b/mypy/typeshed/stdlib/tokenize.pyi index 23babea287e3..a8294adb653f 100644 --- a/mypy/typeshed/stdlib/tokenize.pyi +++ b/mypy/typeshed/stdlib/tokenize.pyi @@ -1,23 +1,8 @@ import sys +from _typeshed import StrOrBytesPath from builtins import open as _builtin_open -from os import PathLike from token import * # noqa: F403 -from typing import ( - Any, - Callable, - Dict, - Generator, - Iterable, - List, - NamedTuple, - Optional, - Pattern, - Sequence, - Set, - TextIO, - Tuple, - Union, -) +from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO, Tuple, Union if sys.version_info < (3, 7): COMMENT: int @@ -47,22 +32,22 @@ class TokenError(Exception): ... class StopTokenizing(Exception): ... # undocumented class Untokenizer: - tokens: List[str] + tokens: list[str] prev_row: int prev_col: int - encoding: Optional[str] + encoding: str | None def __init__(self) -> None: ... def add_whitespace(self, start: _Position) -> None: ... def untokenize(self, iterable: Iterable[_Token]) -> str: ... - def compat(self, token: Sequence[Union[int, str]], iterable: Iterable[_Token]) -> None: ... + def compat(self, token: Sequence[int | str], iterable: Iterable[_Token]) -> None: ... # the docstring says "returns bytes" but is incorrect -- # if the ENCODING token is missing, it skips the encode def untokenize(iterable: Iterable[_Token]) -> Any: ... -def detect_encoding(readline: Callable[[], bytes]) -> Tuple[str, Sequence[bytes]]: ... +def detect_encoding(readline: Callable[[], bytes]) -> tuple[str, Sequence[bytes]]: ... def tokenize(readline: Callable[[], bytes]) -> Generator[TokenInfo, None, None]: ... def generate_tokens(readline: Callable[[], str]) -> Generator[TokenInfo, None, None]: ... # undocumented -def open(filename: Union[str, bytes, int, PathLike[Any]]) -> TextIO: ... +def open(filename: StrOrBytesPath | int) -> TextIO: ... def group(*choices: str) -> str: ... # undocumented def any(*choices: str) -> str: ... # undocumented def maybe(*choices: str) -> str: ... # undocumented @@ -84,7 +69,7 @@ Floatnumber: str # undocumented Imagnumber: str # undocumented Number: str # undocumented -def _all_string_prefixes() -> Set[str]: ... # undocumented +def _all_string_prefixes() -> set[str]: ... # undocumented StringPrefix: str # undocumented @@ -109,8 +94,8 @@ ContStr: str # undocumented PseudoExtras: str # undocumented PseudoToken: str # undocumented -endpats: Dict[str, str] # undocumented -single_quoted: Set[str] # undocumented -triple_quoted: Set[str] # undocumented +endpats: dict[str, str] # undocumented +single_quoted: set[str] # undocumented +triple_quoted: set[str] # undocumented tabsize: int # undocumented diff --git a/mypy/typeshed/stdlib/trace.pyi b/mypy/typeshed/stdlib/trace.pyi index 810639869e20..bab75c9ada8d 100644 --- a/mypy/typeshed/stdlib/trace.pyi +++ b/mypy/typeshed/stdlib/trace.pyi @@ -1,25 +1,29 @@ +import sys import types from _typeshed import StrPath -from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, TypeVar, Union +from typing import Any, Callable, Mapping, Optional, Sequence, Tuple, TypeVar +from typing_extensions import ParamSpec _T = TypeVar("_T") +_P = ParamSpec("_P") _localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] _fileModuleFunction = Tuple[str, Optional[str], str] class CoverageResults: def __init__( self, - counts: Optional[Dict[Tuple[str, int], int]] = ..., - calledfuncs: Optional[Dict[_fileModuleFunction, int]] = ..., - infile: Optional[StrPath] = ..., - callers: Optional[Dict[Tuple[_fileModuleFunction, _fileModuleFunction], int]] = ..., - outfile: Optional[StrPath] = ..., + counts: dict[tuple[str, int], int] | None = ..., + calledfuncs: dict[_fileModuleFunction, int] | None = ..., + infile: StrPath | None = ..., + callers: dict[tuple[_fileModuleFunction, _fileModuleFunction], int] | None = ..., + outfile: StrPath | None = ..., ) -> None: ... # undocumented def update(self, other: CoverageResults) -> None: ... - def write_results(self, show_missing: bool = ..., summary: bool = ..., coverdir: Optional[StrPath] = ...) -> None: ... + def write_results(self, show_missing: bool = ..., summary: bool = ..., coverdir: StrPath | None = ...) -> None: ... def write_results_file( - self, path: StrPath, lines: Sequence[str], lnotab: Any, lines_hit: Mapping[int, int], encoding: Optional[str] = ... - ) -> Tuple[int, int]: ... + self, path: StrPath, lines: Sequence[str], lnotab: Any, lines_hit: Mapping[int, int], encoding: str | None = ... + ) -> tuple[int, int]: ... + def is_ignored_filename(self, filename: str) -> bool: ... # undocumented class Trace: def __init__( @@ -30,18 +34,18 @@ class Trace: countcallers: int = ..., ignoremods: Sequence[str] = ..., ignoredirs: Sequence[str] = ..., - infile: Optional[StrPath] = ..., - outfile: Optional[StrPath] = ..., + infile: StrPath | None = ..., + outfile: StrPath | None = ..., timing: bool = ..., ) -> None: ... - def run(self, cmd: Union[str, types.CodeType]) -> None: ... + def run(self, cmd: str | types.CodeType) -> None: ... def runctx( - self, - cmd: Union[str, types.CodeType], - globals: Optional[Mapping[str, Any]] = ..., - locals: Optional[Mapping[str, Any]] = ..., + self, cmd: str | types.CodeType, globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ... ) -> None: ... - def runfunc(self, func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + if sys.version_info >= (3, 9): + def runfunc(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... # type: ignore + else: + def runfunc(self, func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... # type: ignore def file_module_function_of(self, frame: types.FrameType) -> _fileModuleFunction: ... def globaltrace_trackcallers(self, frame: types.FrameType, why: str, arg: Any) -> None: ... def globaltrace_countfuncs(self, frame: types.FrameType, why: str, arg: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/traceback.pyi b/mypy/typeshed/stdlib/traceback.pyi index 3c24ee21bee4..e685b09a6ae4 100644 --- a/mypy/typeshed/stdlib/traceback.pyi +++ b/mypy/typeshed/stdlib/traceback.pyi @@ -1,197 +1,157 @@ import sys from _typeshed import SupportsWrite from types import FrameType, TracebackType -from typing import IO, Any, Dict, Generator, Iterable, Iterator, List, Mapping, Optional, Set, Tuple, Type +from typing import IO, Any, Generator, Iterable, Iterator, List, Mapping, Optional, Tuple, Type _PT = Tuple[str, int, str, Optional[str]] -def print_tb(tb: Optional[TracebackType], limit: Optional[int] = ..., file: Optional[IO[str]] = ...) -> None: ... +def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... if sys.version_info >= (3, 10): def print_exception( - __exc: Optional[Type[BaseException]], - value: Optional[BaseException] = ..., - tb: Optional[TracebackType] = ..., - limit: Optional[int] = ..., - file: Optional[IO[str]] = ..., - chain: bool = ..., - ) -> None: ... - -elif sys.version_info >= (3,): - def print_exception( - etype: Optional[Type[BaseException]], - value: Optional[BaseException], - tb: Optional[TracebackType], - limit: Optional[int] = ..., - file: Optional[IO[str]] = ..., + __exc: Type[BaseException] | None, + value: BaseException | None = ..., + tb: TracebackType | None = ..., + limit: int | None = ..., + file: IO[str] | None = ..., chain: bool = ..., ) -> None: ... else: def print_exception( - etype: Optional[Type[BaseException]], - value: Optional[BaseException], - tb: Optional[TracebackType], - limit: Optional[int] = ..., - file: Optional[IO[str]] = ..., + etype: Type[BaseException] | None, + value: BaseException | None, + tb: TracebackType | None, + limit: int | None = ..., + file: IO[str] | None = ..., + chain: bool = ..., ) -> None: ... -if sys.version_info >= (3,): - def print_exc(limit: Optional[int] = ..., file: Optional[IO[str]] = ..., chain: bool = ...) -> None: ... - def print_last(limit: Optional[int] = ..., file: Optional[IO[str]] = ..., chain: bool = ...) -> None: ... - -else: - def print_exc(limit: Optional[int] = ..., file: Optional[IO[str]] = ...) -> None: ... - def print_last(limit: Optional[int] = ..., file: Optional[IO[str]] = ...) -> None: ... - -def print_stack(f: Optional[FrameType] = ..., limit: Optional[int] = ..., file: Optional[IO[str]] = ...) -> None: ... +def print_exc(limit: int | None = ..., file: IO[str] | None = ..., chain: bool = ...) -> None: ... +def print_last(limit: int | None = ..., file: IO[str] | None = ..., chain: bool = ...) -> None: ... +def print_stack(f: FrameType | None = ..., limit: int | None = ..., file: IO[str] | None = ...) -> None: ... +def extract_tb(tb: TracebackType | None, limit: int | None = ...) -> StackSummary: ... +def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> StackSummary: ... +def format_list(extracted_list: list[FrameSummary]) -> list[str]: ... -if sys.version_info >= (3, 5): - def extract_tb(tb: Optional[TracebackType], limit: Optional[int] = ...) -> StackSummary: ... - def extract_stack(f: Optional[FrameType] = ..., limit: Optional[int] = ...) -> StackSummary: ... - def format_list(extracted_list: List[FrameSummary]) -> List[str]: ... - # undocumented - def print_list(extracted_list: List[FrameSummary], file: Optional[SupportsWrite[str]] = ...) -> None: ... - -else: - def extract_tb(tb: Optional[TracebackType], limit: Optional[int] = ...) -> List[_PT]: ... - def extract_stack(f: Optional[FrameType] = ..., limit: Optional[int] = ...) -> List[_PT]: ... - def format_list(extracted_list: List[_PT]) -> List[str]: ... +# undocumented +def print_list(extracted_list: list[FrameSummary], file: SupportsWrite[str] | None = ...) -> None: ... if sys.version_info >= (3, 10): - def format_exception_only(__exc: Optional[Type[BaseException]], value: Optional[BaseException] = ...) -> List[str]: ... + def format_exception_only(__exc: Type[BaseException] | None, value: BaseException | None = ...) -> list[str]: ... else: - def format_exception_only(etype: Optional[Type[BaseException]], value: Optional[BaseException]) -> List[str]: ... + def format_exception_only(etype: Type[BaseException] | None, value: BaseException | None) -> list[str]: ... if sys.version_info >= (3, 10): def format_exception( - __exc: Optional[Type[BaseException]], - value: Optional[BaseException] = ..., - tb: Optional[TracebackType] = ..., - limit: Optional[int] = ..., - chain: bool = ..., - ) -> List[str]: ... - -elif sys.version_info >= (3,): - def format_exception( - etype: Optional[Type[BaseException]], - value: Optional[BaseException], - tb: Optional[TracebackType], - limit: Optional[int] = ..., + __exc: Type[BaseException] | None, + value: BaseException | None = ..., + tb: TracebackType | None = ..., + limit: int | None = ..., chain: bool = ..., - ) -> List[str]: ... + ) -> list[str]: ... else: def format_exception( - etype: Optional[Type[BaseException]], - value: Optional[BaseException], - tb: Optional[TracebackType], - limit: Optional[int] = ..., - ) -> List[str]: ... - -if sys.version_info >= (3,): - def format_exc(limit: Optional[int] = ..., chain: bool = ...) -> str: ... - -else: - def format_exc(limit: Optional[int] = ...) -> str: ... - -def format_tb(tb: Optional[TracebackType], limit: Optional[int] = ...) -> List[str]: ... -def format_stack(f: Optional[FrameType] = ..., limit: Optional[int] = ...) -> List[str]: ... - -if sys.version_info >= (3, 4): - def clear_frames(tb: TracebackType) -> None: ... - -if sys.version_info >= (3, 5): - def walk_stack(f: Optional[FrameType]) -> Iterator[Tuple[FrameType, int]]: ... - def walk_tb(tb: Optional[TracebackType]) -> Iterator[Tuple[FrameType, int]]: ... - -if sys.version_info < (3,): - def tb_lineno(tb: TracebackType) -> int: ... - -if sys.version_info >= (3, 5): - class TracebackException: - __cause__: TracebackException - __context__: TracebackException - __suppress_context__: bool - stack: StackSummary - exc_type: Type[BaseException] - filename: str - lineno: int - text: str - offset: int - msg: str - if sys.version_info >= (3, 10): - def __init__( - self, - exc_type: Type[BaseException], - exc_value: BaseException, - exc_traceback: TracebackType, - *, - limit: Optional[int] = ..., - lookup_lines: bool = ..., - capture_locals: bool = ..., - compact: bool = ..., - _seen: Optional[Set[int]] = ..., - ) -> None: ... - @classmethod - def from_exception( - cls, - exc: BaseException, - *, - limit: Optional[int] = ..., - lookup_lines: bool = ..., - capture_locals: bool = ..., - compact: bool = ..., - ) -> TracebackException: ... - else: - def __init__( - self, - exc_type: Type[BaseException], - exc_value: BaseException, - exc_traceback: TracebackType, - *, - limit: Optional[int] = ..., - lookup_lines: bool = ..., - capture_locals: bool = ..., - _seen: Optional[Set[int]] = ..., - ) -> None: ... - @classmethod - def from_exception( - cls, exc: BaseException, *, limit: Optional[int] = ..., lookup_lines: bool = ..., capture_locals: bool = ... - ) -> TracebackException: ... - def format(self, *, chain: bool = ...) -> Generator[str, None, None]: ... - def format_exception_only(self) -> Generator[str, None, None]: ... - class FrameSummary(Iterable[Any]): - filename: str - lineno: int - name: str - line: str - locals: Optional[Dict[str, str]] + etype: Type[BaseException] | None, + value: BaseException | None, + tb: TracebackType | None, + limit: int | None = ..., + chain: bool = ..., + ) -> list[str]: ... + +def format_exc(limit: int | None = ..., chain: bool = ...) -> str: ... +def format_tb(tb: TracebackType | None, limit: int | None = ...) -> list[str]: ... +def format_stack(f: FrameType | None = ..., limit: int | None = ...) -> list[str]: ... +def clear_frames(tb: TracebackType) -> None: ... +def walk_stack(f: FrameType | None) -> Iterator[tuple[FrameType, int]]: ... +def walk_tb(tb: TracebackType | None) -> Iterator[tuple[FrameType, int]]: ... + +class TracebackException: + __cause__: TracebackException + __context__: TracebackException + __suppress_context__: bool + stack: StackSummary + exc_type: Type[BaseException] + filename: str + lineno: int + text: str + offset: int + msg: str + if sys.version_info >= (3, 10): def __init__( self, - filename: str, - lineno: int, - name: str, + exc_type: Type[BaseException], + exc_value: BaseException, + exc_traceback: TracebackType, *, - lookup_line: bool = ..., - locals: Optional[Mapping[str, str]] = ..., - line: Optional[str] = ..., + limit: int | None = ..., + lookup_lines: bool = ..., + capture_locals: bool = ..., + compact: bool = ..., + _seen: set[int] | None = ..., ) -> None: ... - # TODO: more precise typing for __getitem__ and __iter__, - # for a namedtuple-like view on (filename, lineno, name, str). - def __getitem__(self, i: int) -> Any: ... - def __iter__(self) -> Iterator[Any]: ... - class StackSummary(List[FrameSummary]): @classmethod - def extract( + def from_exception( cls, - frame_gen: Generator[Tuple[FrameType, int], None, None], + exc: BaseException, *, - limit: Optional[int] = ..., + limit: int | None = ..., lookup_lines: bool = ..., capture_locals: bool = ..., - ) -> StackSummary: ... + compact: bool = ..., + ) -> TracebackException: ... + else: + def __init__( + self, + exc_type: Type[BaseException], + exc_value: BaseException, + exc_traceback: TracebackType, + *, + limit: int | None = ..., + lookup_lines: bool = ..., + capture_locals: bool = ..., + _seen: set[int] | None = ..., + ) -> None: ... @classmethod - def from_list(cls, a_list: List[_PT]) -> StackSummary: ... - def format(self) -> List[str]: ... + def from_exception( + cls, exc: BaseException, *, limit: int | None = ..., lookup_lines: bool = ..., capture_locals: bool = ... + ) -> TracebackException: ... + def format(self, *, chain: bool = ...) -> Generator[str, None, None]: ... + def format_exception_only(self) -> Generator[str, None, None]: ... + +class FrameSummary(Iterable[Any]): + filename: str + lineno: int + name: str + line: str + locals: dict[str, str] | None + def __init__( + self, + filename: str, + lineno: int, + name: str, + *, + lookup_line: bool = ..., + locals: Mapping[str, str] | None = ..., + line: str | None = ..., + ) -> None: ... + # TODO: more precise typing for __getitem__ and __iter__, + # for a namedtuple-like view on (filename, lineno, name, str). + def __getitem__(self, i: int) -> Any: ... + def __iter__(self) -> Iterator[Any]: ... + +class StackSummary(List[FrameSummary]): + @classmethod + def extract( + cls, + frame_gen: Iterable[tuple[FrameType, int]], + *, + limit: int | None = ..., + lookup_lines: bool = ..., + capture_locals: bool = ..., + ) -> StackSummary: ... + @classmethod + def from_list(cls, a_list: list[_PT]) -> StackSummary: ... + def format(self) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/tracemalloc.pyi b/mypy/typeshed/stdlib/tracemalloc.pyi index 593c4edaec65..ca4d5901b870 100644 --- a/mypy/typeshed/stdlib/tracemalloc.pyi +++ b/mypy/typeshed/stdlib/tracemalloc.pyi @@ -1,9 +1,8 @@ import sys -from typing import List, Optional, Sequence, Tuple, Union, overload - from _tracemalloc import * +from typing import Optional, Sequence, Tuple, Union, overload -def get_object_traceback(obj: object) -> Optional[Traceback]: ... +def get_object_traceback(obj: object) -> Traceback | None: ... def take_snapshot() -> Snapshot: ... class DomainFilter: @@ -12,18 +11,13 @@ class DomainFilter: def __init__(self, inclusive: bool, domain: int) -> None: ... class Filter: - domain: Optional[int] + domain: int | None inclusive: bool - lineno: Optional[int] + lineno: int | None filename_pattern: str all_frames: bool def __init__( - self, - inclusive: bool, - filename_pattern: str, - lineno: Optional[int] = ..., - all_frames: bool = ..., - domain: Optional[int] = ..., + self, inclusive: bool, filename_pattern: str, lineno: int | None = ..., all_frames: bool = ..., domain: int | None = ... ) -> None: ... class Statistic: @@ -60,14 +54,14 @@ class Trace: class Traceback(Sequence[Frame]): if sys.version_info >= (3, 9): - total_nframe: Optional[int] - def __init__(self, frames: Sequence[_FrameTupleT], total_nframe: Optional[int] = ...) -> None: ... + total_nframe: int | None + def __init__(self, frames: Sequence[_FrameTupleT], total_nframe: int | None = ...) -> None: ... else: def __init__(self, frames: Sequence[_FrameTupleT]) -> None: ... if sys.version_info >= (3, 7): - def format(self, limit: Optional[int] = ..., most_recent_first: bool = ...) -> List[str]: ... + def format(self, limit: int | None = ..., most_recent_first: bool = ...) -> list[str]: ... else: - def format(self, limit: Optional[int] = ...) -> List[str]: ... + def format(self, limit: int | None = ...) -> list[str]: ... @overload def __getitem__(self, i: int) -> Frame: ... @overload @@ -76,11 +70,11 @@ class Traceback(Sequence[Frame]): class Snapshot: def __init__(self, traces: Sequence[_TraceTupleT], traceback_limit: int) -> None: ... - def compare_to(self, old_snapshot: Snapshot, key_type: str, cumulative: bool = ...) -> List[StatisticDiff]: ... + def compare_to(self, old_snapshot: Snapshot, key_type: str, cumulative: bool = ...) -> list[StatisticDiff]: ... def dump(self, filename: str) -> None: ... - def filter_traces(self, filters: Sequence[Union[DomainFilter, Filter]]) -> Snapshot: ... + def filter_traces(self, filters: Sequence[DomainFilter | Filter]) -> Snapshot: ... @staticmethod def load(filename: str) -> Snapshot: ... - def statistics(self, key_type: str, cumulative: bool = ...) -> List[Statistic]: ... + def statistics(self, key_type: str, cumulative: bool = ...) -> list[Statistic]: ... traceback_limit: int traces: Sequence[Trace] diff --git a/mypy/typeshed/stdlib/turtle.pyi b/mypy/typeshed/stdlib/turtle.pyi index a44b25926968..9371f2a7a547 100644 --- a/mypy/typeshed/stdlib/turtle.pyi +++ b/mypy/typeshed/stdlib/turtle.pyi @@ -1,18 +1,11 @@ -import sys -from typing import Any, Callable, Dict, List, Optional, Sequence, Text, Tuple, TypeVar, Union, overload - -if sys.version_info >= (3,): - from tkinter import Canvas, PhotoImage -else: - # TODO: Replace these aliases once we have Python 2 stubs for the Tkinter module. - Canvas = Any - PhotoImage = Any +from tkinter import Canvas, PhotoImage +from typing import Any, Callable, Dict, Sequence, Tuple, TypeVar, Union, overload # Note: '_Color' is the alias we use for arguments and _AnyColor is the # alias we use for return types. Really, these two aliases should be the # same, but as per the "no union returns" typeshed policy, we'll return # Any instead. -_Color = Union[Text, Tuple[float, float, float]] +_Color = Union[str, Tuple[float, float, float]] _AnyColor = Any # TODO: Replace this with a TypedDict once it becomes standardized. @@ -26,30 +19,24 @@ _PolygonCoords = Sequence[Tuple[float, float]] Vec2D = Tuple[float, float] class TurtleScreenBase(object): - cv: Canvas = ... - canvwidth: int = ... - canvheight: int = ... - xscale: float = ... - yscale: float = ... + cv: Canvas + canvwidth: int + canvheight: int + xscale: float + yscale: float def __init__(self, cv: Canvas) -> None: ... - if sys.version_info >= (3,): - def mainloop(self) -> None: ... - def textinput(self, title: str, prompt: str) -> Optional[str]: ... - def numinput( - self, - title: str, - prompt: str, - default: Optional[float] = ..., - minval: Optional[float] = ..., - maxval: Optional[float] = ..., - ) -> Optional[float]: ... + def mainloop(self) -> None: ... + def textinput(self, title: str, prompt: str) -> str | None: ... + def numinput( + self, title: str, prompt: str, default: float | None = ..., minval: float | None = ..., maxval: float | None = ... + ) -> float | None: ... class Terminator(Exception): ... class TurtleGraphicsError(Exception): ... class Shape(object): - def __init__(self, type_: str, data: Union[_PolygonCoords, PhotoImage, None] = ...) -> None: ... - def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: Optional[_Color] = ...) -> None: ... + def __init__(self, type_: str, data: _PolygonCoords | PhotoImage | None = ...) -> None: ... + def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: _Color | None = ...) -> None: ... class TurtleScreen(TurtleScreenBase): def __init__(self, cv: Canvas, mode: str = ..., colormode: float = ..., delay: int = ...) -> None: ... @@ -59,13 +46,13 @@ class TurtleScreen(TurtleScreenBase): @overload def mode(self, mode: str) -> None: ... def setworldcoordinates(self, llx: float, lly: float, urx: float, ury: float) -> None: ... - def register_shape(self, name: str, shape: Union[_PolygonCoords, Shape, None] = ...) -> None: ... + def register_shape(self, name: str, shape: _PolygonCoords | Shape | None = ...) -> None: ... @overload def colormode(self, cmode: None = ...) -> float: ... @overload def colormode(self, cmode: float) -> None: ... def reset(self) -> None: ... - def turtles(self) -> List[Turtle]: ... + def turtles(self) -> list[Turtle]: ... @overload def bgcolor(self) -> _AnyColor: ... @overload @@ -75,7 +62,7 @@ class TurtleScreen(TurtleScreenBase): @overload def tracer(self, n: None = ...) -> int: ... @overload - def tracer(self, n: int, delay: Optional[int] = ...) -> None: ... + def tracer(self, n: int, delay: int | None = ...) -> None: ... @overload def delay(self, delay: None = ...) -> int: ... @overload @@ -84,33 +71,32 @@ class TurtleScreen(TurtleScreenBase): def window_width(self) -> int: ... def window_height(self) -> int: ... def getcanvas(self) -> Canvas: ... - def getshapes(self) -> List[str]: ... - def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ... + def getshapes(self) -> list[str]: ... + def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... def onkey(self, fun: Callable[[], Any], key: str) -> None: ... - def listen(self, xdummy: Optional[float] = ..., ydummy: Optional[float] = ...) -> None: ... + def listen(self, xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... def ontimer(self, fun: Callable[[], Any], t: int = ...) -> None: ... @overload def bgpic(self, picname: None = ...) -> str: ... @overload def bgpic(self, picname: str) -> None: ... @overload - def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... + def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> tuple[int, int]: ... # Looks like if self.cv is not a ScrolledCanvas, this could return a tuple as well @overload - def screensize(self, canvwidth: int, canvheight: int, bg: Optional[_Color] = ...) -> None: ... + def screensize(self, canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... onscreenclick = onclick resetscreen = reset clearscreen = clear addshape = register_shape - if sys.version_info >= (3,): - def onkeypress(self, fun: Callable[[], Any], key: Optional[str] = ...) -> None: ... - onkeyrelease = onkey + def onkeypress(self, fun: Callable[[], Any], key: str | None = ...) -> None: ... + onkeyrelease = onkey class TNavigator(object): - START_ORIENTATION: Dict[str, Vec2D] = ... - DEFAULT_MODE: str = ... - DEFAULT_ANGLEOFFSET: int = ... - DEFAULT_ANGLEORIENT: int = ... + START_ORIENTATION: dict[str, Vec2D] + DEFAULT_MODE: str + DEFAULT_ANGLEOFFSET: int + DEFAULT_ANGLEORIENT: int def __init__(self, mode: str = ...) -> None: ... def reset(self) -> None: ... def degrees(self, fullcircle: float = ...) -> None: ... @@ -123,23 +109,23 @@ class TNavigator(object): def xcor(self) -> float: ... def ycor(self) -> float: ... @overload - def goto(self, x: Tuple[float, float], y: None = ...) -> None: ... + def goto(self, x: tuple[float, float], y: None = ...) -> None: ... @overload def goto(self, x: float, y: float) -> None: ... def home(self) -> None: ... def setx(self, x: float) -> None: ... def sety(self, y: float) -> None: ... @overload - def distance(self, x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ... + def distance(self, x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def distance(self, x: float, y: float) -> float: ... @overload - def towards(self, x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ... + def towards(self, x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def towards(self, x: float, y: float) -> float: ... def heading(self) -> float: ... def setheading(self, to_angle: float) -> None: ... - def circle(self, radius: float, extent: Optional[float] = ..., steps: Optional[int] = ...) -> None: ... + def circle(self, radius: float, extent: float | None = ..., steps: int | None = ...) -> None: ... fd = forward bk = back backward = back @@ -180,7 +166,7 @@ class TPen(object): @overload def fillcolor(self, r: float, g: float, b: float) -> None: ... @overload - def color(self) -> Tuple[_AnyColor, _AnyColor]: ... + def color(self) -> tuple[_AnyColor, _AnyColor]: ... @overload def color(self, color: _Color) -> None: ... @overload @@ -196,7 +182,7 @@ class TPen(object): @overload def pen( self, - pen: Optional[_PenState] = ..., + pen: _PenState | None = ..., *, shown: bool = ..., pendown: bool = ..., @@ -205,7 +191,7 @@ class TPen(object): pensize: int = ..., speed: int = ..., resizemode: str = ..., - stretchfactor: Tuple[float, float] = ..., + stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... @@ -221,10 +207,10 @@ _T = TypeVar("_T") class RawTurtle(TPen, TNavigator): def __init__( - self, canvas: Union[Canvas, TurtleScreen, None] = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ... + self, canvas: Canvas | TurtleScreen | None = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ... ) -> None: ... def reset(self) -> None: ... - def setundobuffer(self, size: Optional[int]) -> None: ... + def setundobuffer(self, size: int | None) -> None: ... def undobufferentries(self) -> int: ... def clear(self) -> None: ... def clone(self: _T) -> _T: ... @@ -234,24 +220,23 @@ class RawTurtle(TPen, TNavigator): def shape(self, name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload - def shapesize(self) -> Tuple[float, float, float]: ... # type: ignore + def shapesize(self) -> tuple[float, float, float]: ... # type: ignore @overload def shapesize( - self, stretch_wid: Optional[float] = ..., stretch_len: Optional[float] = ..., outline: Optional[float] = ... + self, stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ... ) -> None: ... - if sys.version_info >= (3,): - @overload - def shearfactor(self, shear: None = ...) -> float: ... - @overload - def shearfactor(self, shear: float) -> None: ... - # Unsafely overlaps when no arguments are provided - @overload - def shapetransform(self) -> Tuple[float, float, float, float]: ... # type: ignore - @overload - def shapetransform( - self, t11: Optional[float] = ..., t12: Optional[float] = ..., t21: Optional[float] = ..., t22: Optional[float] = ... - ) -> None: ... - def get_shapepoly(self) -> Optional[_PolygonCoords]: ... + @overload + def shearfactor(self, shear: None = ...) -> float: ... + @overload + def shearfactor(self, shear: float) -> None: ... + # Unsafely overlaps when no arguments are provided + @overload + def shapetransform(self) -> tuple[float, float, float, float]: ... # type: ignore + @overload + def shapetransform( + self, t11: float | None = ..., t12: float | None = ..., t21: float | None = ..., t22: float | None = ... + ) -> None: ... + def get_shapepoly(self) -> _PolygonCoords | None: ... def settiltangle(self, angle: float) -> None: ... @overload def tiltangle(self, angle: None = ...) -> float: ... @@ -262,22 +247,22 @@ class RawTurtle(TPen, TNavigator): # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp(self) -> Any: ... - def clearstamp(self, stampid: Union[int, Tuple[int, ...]]) -> None: ... - def clearstamps(self, n: Optional[int] = ...) -> None: ... + def clearstamp(self, stampid: int | Tuple[int, ...]) -> None: ... + def clearstamps(self, n: int | None = ...) -> None: ... def filling(self) -> bool: ... def begin_fill(self) -> None: ... def end_fill(self) -> None: ... - def dot(self, size: Optional[int] = ..., *color: _Color) -> None: ... - def write(self, arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... + def dot(self, size: int | None = ..., *color: _Color) -> None: ... + def write(self, arg: object, move: bool = ..., align: str = ..., font: tuple[str, int, str] = ...) -> None: ... def begin_poly(self) -> None: ... def end_poly(self) -> None: ... - def get_poly(self) -> Optional[_PolygonCoords]: ... + def get_poly(self) -> _PolygonCoords | None: ... def getscreen(self) -> TurtleScreen: ... def getturtle(self: _T) -> _T: ... getpen = getturtle - def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ... - def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ... - def ondrag(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ... + def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... + def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... + def ondrag(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... def undo(self) -> None: ... turtlesize = shapesize @@ -285,11 +270,7 @@ class _Screen(TurtleScreen): def __init__(self) -> None: ... # Note int and float are interpreted differently, hence the Union instead of just float def setup( - self, - width: Union[int, float] = ..., - height: Union[int, float] = ..., - startx: Optional[int] = ..., - starty: Optional[int] = ..., + self, width: int | float = ..., height: int | float = ..., startx: int | None = ..., starty: int | None = ... ) -> None: ... def title(self, titlestring: str) -> None: ... def bye(self) -> None: ... @@ -317,12 +298,10 @@ def write_docstringdict(filename: str = ...) -> None: ... # Note: mainloop() was always present in the global scope, but was added to # TurtleScreenBase in Python 3.0 def mainloop() -> None: ... - -if sys.version_info >= (3,): - def textinput(title: str, prompt: str) -> Optional[str]: ... - def numinput( - title: str, prompt: str, default: Optional[float] = ..., minval: Optional[float] = ..., maxval: Optional[float] = ... - ) -> Optional[float]: ... +def textinput(title: str, prompt: str) -> str | None: ... +def numinput( + title: str, prompt: str, default: float | None = ..., minval: float | None = ..., maxval: float | None = ... +) -> float | None: ... # Functions copied from TurtleScreen: @@ -332,13 +311,13 @@ def mode(mode: None = ...) -> str: ... @overload def mode(mode: str) -> None: ... def setworldcoordinates(llx: float, lly: float, urx: float, ury: float) -> None: ... -def register_shape(name: str, shape: Union[_PolygonCoords, Shape, None] = ...) -> None: ... +def register_shape(name: str, shape: _PolygonCoords | Shape | None = ...) -> None: ... @overload def colormode(cmode: None = ...) -> float: ... @overload def colormode(cmode: float) -> None: ... def reset() -> None: ... -def turtles() -> List[Turtle]: ... +def turtles() -> list[Turtle]: ... @overload def bgcolor() -> _AnyColor: ... @overload @@ -348,7 +327,7 @@ def bgcolor(r: float, g: float, b: float) -> None: ... @overload def tracer(n: None = ...) -> int: ... @overload -def tracer(n: int, delay: Optional[int] = ...) -> None: ... +def tracer(n: int, delay: int | None = ...) -> None: ... @overload def delay(delay: None = ...) -> int: ... @overload @@ -357,31 +336,32 @@ def update() -> None: ... def window_width() -> int: ... def window_height() -> int: ... def getcanvas() -> Canvas: ... -def getshapes() -> List[str]: ... -def onclick(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ... +def getshapes() -> list[str]: ... +def onclick(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... def onkey(fun: Callable[[], Any], key: str) -> None: ... -def listen(xdummy: Optional[float] = ..., ydummy: Optional[float] = ...) -> None: ... +def listen(xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... def ontimer(fun: Callable[[], Any], t: int = ...) -> None: ... @overload def bgpic(picname: None = ...) -> str: ... @overload def bgpic(picname: str) -> None: ... @overload -def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... +def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> tuple[int, int]: ... @overload -def screensize(canvwidth: int, canvheight: int, bg: Optional[_Color] = ...) -> None: ... +def screensize(canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... onscreenclick = onclick resetscreen = reset clearscreen = clear addshape = register_shape -if sys.version_info >= (3,): - def onkeypress(fun: Callable[[], Any], key: Optional[str] = ...) -> None: ... - onkeyrelease = onkey + +def onkeypress(fun: Callable[[], Any], key: str | None = ...) -> None: ... + +onkeyrelease = onkey # Functions copied from _Screen: -def setup(width: float = ..., height: float = ..., startx: Optional[int] = ..., starty: Optional[int] = ...) -> None: ... +def setup(width: float = ..., height: float = ..., startx: int | None = ..., starty: int | None = ...) -> None: ... def title(titlestring: str) -> None: ... def bye() -> None: ... def exitonclick() -> None: ... @@ -399,23 +379,23 @@ def pos() -> Vec2D: ... def xcor() -> float: ... def ycor() -> float: ... @overload -def goto(x: Tuple[float, float], y: None = ...) -> None: ... +def goto(x: tuple[float, float], y: None = ...) -> None: ... @overload def goto(x: float, y: float) -> None: ... def home() -> None: ... def setx(x: float) -> None: ... def sety(y: float) -> None: ... @overload -def distance(x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ... +def distance(x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def distance(x: float, y: float) -> float: ... @overload -def towards(x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ... +def towards(x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def towards(x: float, y: float) -> float: ... def heading() -> float: ... def setheading(to_angle: float) -> None: ... -def circle(radius: float, extent: Optional[float] = ..., steps: Optional[int] = ...) -> None: ... +def circle(radius: float, extent: float | None = ..., steps: int | None = ...) -> None: ... fd = forward bk = back @@ -456,7 +436,7 @@ def fillcolor(color: _Color) -> None: ... @overload def fillcolor(r: float, g: float, b: float) -> None: ... @overload -def color() -> Tuple[_AnyColor, _AnyColor]: ... +def color() -> tuple[_AnyColor, _AnyColor]: ... @overload def color(color: _Color) -> None: ... @overload @@ -472,7 +452,7 @@ def isvisible() -> bool: ... def pen() -> _PenState: ... # type: ignore @overload def pen( - pen: Optional[_PenState] = ..., + pen: _PenState | None = ..., *, shown: bool = ..., pendown: bool = ..., @@ -481,7 +461,7 @@ def pen( pensize: int = ..., speed: int = ..., resizemode: str = ..., - stretchfactor: Tuple[float, float] = ..., + stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... @@ -496,7 +476,7 @@ ht = hideturtle # Functions copied from RawTurtle: -def setundobuffer(size: Optional[int]) -> None: ... +def setundobuffer(size: int | None) -> None: ... def undobufferentries() -> int: ... @overload def shape(name: None = ...) -> str: ... @@ -505,24 +485,22 @@ def shape(name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload -def shapesize() -> Tuple[float, float, float]: ... # type: ignore +def shapesize() -> tuple[float, float, float]: ... # type: ignore @overload -def shapesize(stretch_wid: Optional[float] = ..., stretch_len: Optional[float] = ..., outline: Optional[float] = ...) -> None: ... - -if sys.version_info >= (3,): - @overload - def shearfactor(shear: None = ...) -> float: ... - @overload - def shearfactor(shear: float) -> None: ... - # Unsafely overlaps when no arguments are provided - @overload - def shapetransform() -> Tuple[float, float, float, float]: ... # type: ignore - @overload - def shapetransform( - t11: Optional[float] = ..., t12: Optional[float] = ..., t21: Optional[float] = ..., t22: Optional[float] = ... - ) -> None: ... - def get_shapepoly() -> Optional[_PolygonCoords]: ... +def shapesize(stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ...) -> None: ... +@overload +def shearfactor(shear: None = ...) -> float: ... +@overload +def shearfactor(shear: float) -> None: ... +# Unsafely overlaps when no arguments are provided +@overload +def shapetransform() -> tuple[float, float, float, float]: ... # type: ignore +@overload +def shapetransform( + t11: float | None = ..., t12: float | None = ..., t21: float | None = ..., t22: float | None = ... +) -> None: ... +def get_shapepoly() -> _PolygonCoords | None: ... def settiltangle(angle: float) -> None: ... @overload def tiltangle(angle: None = ...) -> float: ... @@ -534,23 +512,23 @@ def tilt(angle: float) -> None: ... # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp() -> Any: ... -def clearstamp(stampid: Union[int, Tuple[int, ...]]) -> None: ... -def clearstamps(n: Optional[int] = ...) -> None: ... +def clearstamp(stampid: int | Tuple[int, ...]) -> None: ... +def clearstamps(n: int | None = ...) -> None: ... def filling() -> bool: ... def begin_fill() -> None: ... def end_fill() -> None: ... -def dot(size: Optional[int] = ..., *color: _Color) -> None: ... -def write(arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... +def dot(size: int | None = ..., *color: _Color) -> None: ... +def write(arg: object, move: bool = ..., align: str = ..., font: tuple[str, int, str] = ...) -> None: ... def begin_poly() -> None: ... def end_poly() -> None: ... -def get_poly() -> Optional[_PolygonCoords]: ... +def get_poly() -> _PolygonCoords | None: ... def getscreen() -> TurtleScreen: ... def getturtle() -> Turtle: ... getpen = getturtle -def onrelease(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ... -def ondrag(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ... +def onrelease(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... +def ondrag(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... def undo() -> None: ... turtlesize = shapesize diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index 2b4d32392a45..899024f2dd4d 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -1,44 +1,69 @@ import sys -import typing from importlib.abc import _LoaderProtocol from importlib.machinery import ModuleSpec -from typing import Any, Awaitable, Callable, Dict, Generic, Iterable, Iterator, Mapping, Optional, Tuple, Type, TypeVar, overload -from typing_extensions import Literal, final +from typing import ( + Any, + AsyncGenerator, + Awaitable, + Callable, + Coroutine, + Generator, + Generic, + ItemsView, + Iterable, + Iterator, + KeysView, + Mapping, + MutableSequence, + Tuple, + Type, + TypeVar, + ValuesView, + overload, +) +from typing_extensions import Literal, ParamSpec, final # Note, all classes "defined" here require special handling. _T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) _KT = TypeVar("_KT") -_VT = TypeVar("_VT") +_VT_co = TypeVar("_VT_co", covariant=True) +_V_co = TypeVar("_V_co", covariant=True) +@final class _Cell: + __hash__: None # type: ignore cell_contents: Any +@final class FunctionType: - __closure__: Optional[Tuple[_Cell, ...]] + __closure__: Tuple[_Cell, ...] | None __code__: CodeType - __defaults__: Optional[Tuple[Any, ...]] - __dict__: Dict[str, Any] - __globals__: Dict[str, Any] + __defaults__: Tuple[Any, ...] | None + __dict__: dict[str, Any] + __globals__: dict[str, Any] __name__: str __qualname__: str - __annotations__: Dict[str, Any] - __kwdefaults__: Dict[str, Any] + __annotations__: dict[str, Any] + __kwdefaults__: dict[str, Any] def __init__( self, code: CodeType, - globals: Dict[str, Any], - name: Optional[str] = ..., - argdefs: Optional[Tuple[object, ...]] = ..., - closure: Optional[Tuple[_Cell, ...]] = ..., + globals: dict[str, Any], + name: str | None = ..., + argdefs: Tuple[object, ...] | None = ..., + closure: Tuple[_Cell, ...] | None = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __get__(self, obj: Optional[object], type: Optional[type]) -> MethodType: ... + def __get__(self, obj: object | None, type: type | None) -> MethodType: ... LambdaType = FunctionType +@final class CodeType: """Create a code object. Not for the faint of heart.""" @@ -119,15 +144,28 @@ class CodeType: co_name: str = ..., co_lnotab: bytes = ..., ) -> CodeType: ... - -class MappingProxyType(Mapping[_KT, _VT], Generic[_KT, _VT]): - def __init__(self, mapping: Mapping[_KT, _VT]) -> None: ... - def __getitem__(self, k: _KT) -> _VT: ... + if sys.version_info >= (3, 11): + def co_positions(self) -> Iterable[tuple[int | None, int | None, int | None, int | None]]: ... + +@final +class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): + __hash__: None # type: ignore + def __init__(self, mapping: Mapping[_KT, _VT_co]) -> None: ... + def __getitem__(self, k: _KT) -> _VT_co: ... def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... - def copy(self) -> Dict[_KT, _VT]: ... + def copy(self) -> dict[_KT, _VT_co]: ... + def keys(self) -> KeysView[_KT]: ... + def values(self) -> ValuesView[_VT_co]: ... + def items(self) -> ItemsView[_KT, _VT_co]: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... + def __reversed__(self) -> Iterator[_KT]: ... + def __or__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT_co | _T2]: ... + def __ror__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT_co | _T2]: ... class SimpleNamespace: + __hash__: None # type: ignore def __init__(self, **kwargs: Any) -> None: ... def __getattribute__(self, name: str) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... @@ -135,58 +173,69 @@ class SimpleNamespace: class ModuleType: __name__: str - __file__: str - __dict__: Dict[str, Any] - __loader__: Optional[_LoaderProtocol] - __package__: Optional[str] - __spec__: Optional[ModuleSpec] - def __init__(self, name: str, doc: Optional[str] = ...) -> None: ... - -class GeneratorType: + __file__: str | None + __dict__: dict[str, Any] + __loader__: _LoaderProtocol | None + __package__: str | None + __path__: MutableSequence[str] + __spec__: ModuleSpec | None + def __init__(self, name: str, doc: str | None = ...) -> None: ... + # __getattr__ doesn't exist at runtime, + # but having it here in typeshed makes dynamic imports + # using `builtins.__import__` or `importlib.import_module` less painful + def __getattr__(self, name: str) -> Any: ... + +@final +class GeneratorType(Generator[_T_co, _T_contra, _V_co]): gi_code: CodeType gi_frame: FrameType gi_running: bool - gi_yieldfrom: Optional[GeneratorType] - def __iter__(self) -> GeneratorType: ... - def __next__(self) -> Any: ... + gi_yieldfrom: GeneratorType[_T_co, _T_contra, Any] | None + def __iter__(self) -> GeneratorType[_T_co, _T_contra, _V_co]: ... + def __next__(self) -> _T_co: ... def close(self) -> None: ... - def send(self, __arg: Any) -> Any: ... + def send(self, __arg: _T_contra) -> _T_co: ... @overload def throw( - self, __typ: Type[BaseException], __val: typing.Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... - ) -> Any: ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + ) -> _T_co: ... @overload - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> Any: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... -class AsyncGeneratorType(Generic[_T_co, _T_contra]): - ag_await: Optional[Awaitable[Any]] +@final +class AsyncGeneratorType(AsyncGenerator[_T_co, _T_contra]): + ag_await: Awaitable[Any] | None ag_frame: FrameType ag_running: bool ag_code: CodeType - def __aiter__(self) -> Awaitable[AsyncGeneratorType[_T_co, _T_contra]]: ... + def __aiter__(self) -> AsyncGeneratorType[_T_co, _T_contra]: ... def __anext__(self) -> Awaitable[_T_co]: ... def asend(self, __val: _T_contra) -> Awaitable[_T_co]: ... @overload def athrow( - self, __typ: Type[BaseException], __val: typing.Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> Awaitable[_T_co]: ... @overload - def athrow(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> Awaitable[_T_co]: ... + def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Awaitable[_T_co]: ... def aclose(self) -> Awaitable[None]: ... -class CoroutineType: - cr_await: Optional[Any] +@final +class CoroutineType(Coroutine[_T_co, _T_contra, _V_co]): + __name__: str + __qualname__: str + cr_await: Any | None cr_code: CodeType cr_frame: FrameType cr_running: bool def close(self) -> None: ... - def send(self, __arg: Any) -> Any: ... + def __await__(self) -> Generator[Any, None, _V_co]: ... + def send(self, __arg: _T_contra) -> _T_co: ... @overload def throw( - self, __typ: Type[BaseException], __val: typing.Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... - ) -> Any: ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + ) -> _T_co: ... @overload - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> Any: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... class _StaticFunctionType: """Fictional type to correct the type of MethodType.__func__. @@ -202,18 +251,22 @@ class _StaticFunctionType: being bound as a method. """ - def __get__(self, obj: Optional[object], type: Optional[type]) -> FunctionType: ... + def __get__(self, obj: object | None, type: type | None) -> FunctionType: ... +@final class MethodType: + __closure__: Tuple[_Cell, ...] | None # inherited from the added function + __defaults__: Tuple[Any, ...] | None # inherited from the added function __func__: _StaticFunctionType __self__: object - __name__: str - __qualname__: str + __name__: str # inherited from the added function + __qualname__: str # inherited from the added function def __init__(self, func: Callable[..., Any], obj: object) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... +@final class BuiltinFunctionType: - __self__: typing.Union[object, ModuleType] + __self__: object | ModuleType __name__: str __qualname__: str def __call__(self, *args: Any, **kwargs: Any) -> Any: ... @@ -221,12 +274,14 @@ class BuiltinFunctionType: BuiltinMethodType = BuiltinFunctionType if sys.version_info >= (3, 7): + @final class WrapperDescriptorType: __name__: str __qualname__: str __objclass__: type def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: Any, type: type = ...) -> Any: ... + @final class MethodWrapperType: __self__: object __name__: str @@ -235,12 +290,14 @@ if sys.version_info >= (3, 7): def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __eq__(self, other: Any) -> bool: ... def __ne__(self, other: Any) -> bool: ... + @final class MethodDescriptorType: __name__: str __qualname__: str __objclass__: type def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: Any, type: type = ...) -> Any: ... + @final class ClassMethodDescriptorType: __name__: str __qualname__: str @@ -248,13 +305,14 @@ if sys.version_info >= (3, 7): def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: Any, type: type = ...) -> Any: ... +@final class TracebackType: if sys.version_info >= (3, 7): - def __init__(self, tb_next: Optional[TracebackType], tb_frame: FrameType, tb_lasti: int, tb_lineno: int) -> None: ... - tb_next: Optional[TracebackType] + def __init__(self, tb_next: TracebackType | None, tb_frame: FrameType, tb_lasti: int, tb_lineno: int) -> None: ... + tb_next: TracebackType | None else: @property - def tb_next(self) -> Optional[TracebackType]: ... + def tb_next(self) -> TracebackType | None: ... # the rest are read-only even in 3.7 @property def tb_frame(self) -> FrameType: ... @@ -263,20 +321,22 @@ class TracebackType: @property def tb_lineno(self) -> int: ... +@final class FrameType: - f_back: Optional[FrameType] - f_builtins: Dict[str, Any] + f_back: FrameType | None + f_builtins: dict[str, Any] f_code: CodeType - f_globals: Dict[str, Any] + f_globals: dict[str, Any] f_lasti: int f_lineno: int - f_locals: Dict[str, Any] - f_trace: Optional[Callable[[FrameType, str, Any], Any]] + f_locals: dict[str, Any] + f_trace: Callable[[FrameType, str, Any], Any] | None if sys.version_info >= (3, 7): f_trace_lines: bool f_trace_opcodes: bool def clear(self) -> None: ... +@final class GetSetDescriptorType: __name__: str __objclass__: type @@ -284,6 +344,7 @@ class GetSetDescriptorType: def __set__(self, __instance: Any, __value: Any) -> None: ... def __delete__(self, obj: Any) -> None: ... +@final class MemberDescriptorType: __name__: str __objclass__: type @@ -295,8 +356,8 @@ if sys.version_info >= (3, 7): def new_class( name: str, bases: Iterable[object] = ..., - kwds: Optional[Dict[str, Any]] = ..., - exec_body: Optional[Callable[[Dict[str, Any]], None]] = ..., + kwds: dict[str, Any] | None = ..., + exec_body: Callable[[dict[str, Any]], None] | None = ..., ) -> type: ... def resolve_bases(bases: Iterable[object]) -> Tuple[Any, ...]: ... @@ -304,18 +365,29 @@ else: def new_class( name: str, bases: Tuple[type, ...] = ..., - kwds: Optional[Dict[str, Any]] = ..., - exec_body: Optional[Callable[[Dict[str, Any]], None]] = ..., + kwds: dict[str, Any] | None = ..., + exec_body: Callable[[dict[str, Any]], None] | None = ..., ) -> type: ... def prepare_class( - name: str, bases: Tuple[type, ...] = ..., kwds: Optional[Dict[str, Any]] = ... -) -> Tuple[type, Dict[str, Any], Dict[str, Any]]: ... + name: str, bases: Tuple[type, ...] = ..., kwds: dict[str, Any] | None = ... +) -> tuple[type, dict[str, Any], dict[str, Any]]: ... # Actually a different type, but `property` is special and we want that too. DynamicClassAttribute = property -def coroutine(func: Callable[..., Any]) -> CoroutineType: ... +_Fn = TypeVar("_Fn", bound=Callable[..., object]) +_R = TypeVar("_R") +_P = ParamSpec("_P") + +# it's not really an Awaitable, but can be used in an await expression. Real type: Generator & Awaitable +@overload +def coroutine(func: Callable[_P, Generator[_R, Any, Any]]) -> Callable[_P, Awaitable[_R]]: ... # type: ignore +@overload +def coroutine(func: _Fn) -> _Fn: ... # type: ignore + +if sys.version_info >= (3, 8): + CellType = _Cell if sys.version_info >= (3, 9): class GenericAlias: @@ -333,5 +405,8 @@ if sys.version_info >= (3, 10): from builtins import _NotImplementedType NotImplementedType = _NotImplementedType # noqa F811 from builtins - class Union: + @final + class UnionType: __args__: Tuple[Any, ...] + def __or__(self, obj: Any) -> UnionType: ... + def __ror__(self, obj: Any) -> UnionType: ... diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index aafb1fbdf1b3..4656add7ec21 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -2,6 +2,7 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType +from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final if sys.version_info >= (3, 7): from types import MethodDescriptorType, MethodWrapperType, WrapperDescriptorType @@ -16,7 +17,7 @@ Any = object() class TypeVar: __name__: str - __bound__: Optional[Type[Any]] + __bound__: Type[Any] | None __constraints__: Tuple[Type[Any], ...] __covariant__: bool __contravariant__: bool @@ -24,7 +25,7 @@ class TypeVar: self, name: str, *constraints: Type[Any], - bound: Union[None, Type[Any], str] = ..., + bound: None | Type[Any] | str = ..., covariant: bool = ..., contravariant: bool = ..., ) -> None: ... @@ -35,6 +36,8 @@ class _SpecialForm: def __getitem__(self, typeargs: Any) -> object: ... _F = TypeVar("_F", bound=Callable[..., Any]) +_P = _ParamSpec("_P") +_T = TypeVar("_T") def overload(func: _F) -> _F: ... @@ -47,9 +50,10 @@ Protocol: _SpecialForm = ... Callable: _SpecialForm = ... Type: _SpecialForm = ... ClassVar: _SpecialForm = ... +NoReturn: _SpecialForm = ... if sys.version_info >= (3, 8): Final: _SpecialForm = ... - def final(f: _F) -> _F: ... + def final(f: _T) -> _T: ... Literal: _SpecialForm = ... # TypedDict is a (non-subscriptable) special form. TypedDict: object @@ -66,11 +70,11 @@ if sys.version_info >= (3, 10): def __init__(self, origin: ParamSpec) -> None: ... class ParamSpec: __name__: str - __bound__: Optional[Type[Any]] + __bound__: Type[Any] | None __covariant__: bool __contravariant__: bool def __init__( - self, name: str, *, bound: Union[None, Type[Any], str] = ..., contravariant: bool = ..., covariant: bool = ... + self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... ) -> None: ... @property def args(self) -> ParamSpecArgs: ... @@ -80,13 +84,7 @@ if sys.version_info >= (3, 10): TypeAlias: _SpecialForm = ... TypeGuard: _SpecialForm = ... -# Return type that indicates a function does not return. -# This type is equivalent to the None type, but the no-op Union is necessary to -# distinguish the None type from the None value. -NoReturn = Union[None] - # These type variables are used by the container types. -_T = TypeVar("_T") _S = TypeVar("_S") _KT = TypeVar("_KT") # Key type. _VT = TypeVar("_VT") # Value type. @@ -98,7 +96,7 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # Ditto contravariant. _TC = TypeVar("_TC", bound=Type[object]) def no_type_check(arg: _F) -> _F: ... -def no_type_check_decorator(decorator: _F) -> _F: ... +def no_type_check_decorator(decorator: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore # Type aliases and type constructors @@ -165,7 +163,7 @@ class SupportsRound(Protocol[_T_co]): def __round__(self) -> int: ... @overload @abstractmethod - def __round__(self, ndigits: int) -> _T_co: ... + def __round__(self, __ndigits: int) -> _T_co: ... @runtime_checkable class Sized(Protocol, metaclass=ABCMeta): @@ -203,11 +201,11 @@ class Generator(Iterator[_T_co], Generic[_T_co, _T_contra, _V_co]): @overload @abstractmethod def throw( - self, __typ: Type[BaseException], __val: Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload @abstractmethod - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> _T_co: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... def close(self) -> None: ... def __iter__(self) -> Generator[_T_co, _T_contra, _V_co]: ... @property @@ -217,7 +215,7 @@ class Generator(Iterator[_T_co], Generic[_T_co, _T_contra, _V_co]): @property def gi_running(self) -> bool: ... @property - def gi_yieldfrom(self) -> Optional[Generator[Any, Any, Any]]: ... + def gi_yieldfrom(self) -> Generator[Any, Any, Any] | None: ... @runtime_checkable class Awaitable(Protocol[_T_co]): @@ -228,7 +226,7 @@ class Coroutine(Awaitable[_V_co], Generic[_T_co, _T_contra, _V_co]): __name__: str __qualname__: str @property - def cr_await(self) -> Optional[Any]: ... + def cr_await(self) -> Any | None: ... @property def cr_code(self) -> CodeType: ... @property @@ -240,11 +238,11 @@ class Coroutine(Awaitable[_V_co], Generic[_T_co, _T_contra, _V_co]): @overload @abstractmethod def throw( - self, __typ: Type[BaseException], __val: Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload @abstractmethod - def throw(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> _T_co: ... + def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... @abstractmethod def close(self) -> None: ... @@ -273,11 +271,11 @@ class AsyncGenerator(AsyncIterator[_T_co], Generic[_T_co, _T_contra]): @overload @abstractmethod def athrow( - self, __typ: Type[BaseException], __val: Union[BaseException, object] = ..., __tb: Optional[TracebackType] = ... + self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> Awaitable[_T_co]: ... @overload @abstractmethod - def athrow(self, __typ: BaseException, __val: None = ..., __tb: Optional[TracebackType] = ...) -> Awaitable[_T_co]: ... + def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Awaitable[_T_co]: ... @abstractmethod def aclose(self) -> Awaitable[None]: ... @abstractmethod @@ -302,9 +300,7 @@ class Collection(Iterable[_T_co], Container[_T_co], Protocol[_T_co]): @abstractmethod def __len__(self) -> int: ... -_Collection = Collection[_T_co] - -class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]): +class Sequence(Collection[_T_co], Reversible[_T_co], Generic[_T_co]): @overload @abstractmethod def __getitem__(self, i: int) -> _T_co: ... @@ -348,7 +344,7 @@ class MutableSequence(Sequence[_T], Generic[_T]): def remove(self, value: _T) -> None: ... def __iadd__(self, x: Iterable[_T]) -> MutableSequence[_T]: ... -class AbstractSet(_Collection[_T_co], Generic[_T_co]): +class AbstractSet(Collection[_T_co], Generic[_T_co]): @abstractmethod def __contains__(self, x: object) -> bool: ... # Mixin methods @@ -357,9 +353,9 @@ class AbstractSet(_Collection[_T_co], Generic[_T_co]): def __gt__(self, s: AbstractSet[Any]) -> bool: ... def __ge__(self, s: AbstractSet[Any]) -> bool: ... def __and__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __or__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... + def __or__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... def __sub__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... + def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... def isdisjoint(self, other: Iterable[Any]) -> bool: ... class MutableSet(AbstractSet[_T], Generic[_T]): @@ -371,9 +367,9 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def clear(self) -> None: ... def pop(self) -> _T: ... def remove(self, value: _T) -> None: ... - def __ior__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... + def __ior__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... def __iand__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... - def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... + def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... class MappingView(Sized): @@ -382,33 +378,33 @@ class MappingView(Sized): class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): def __init__(self, mapping: Mapping[_KT_co, _VT_co]) -> None: ... # undocumented - def __and__(self, o: Iterable[Any]) -> Set[Tuple[_KT_co, _VT_co]]: ... - def __rand__(self, o: Iterable[_T]) -> Set[_T]: ... + def __and__(self, o: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... + def __rand__(self, o: Iterable[_T]) -> set[_T]: ... def __contains__(self, o: object) -> bool: ... - def __iter__(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... + def __iter__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... if sys.version_info >= (3, 8): - def __reversed__(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... - def __or__(self, o: Iterable[_T]) -> Set[Union[Tuple[_KT_co, _VT_co], _T]]: ... - def __ror__(self, o: Iterable[_T]) -> Set[Union[Tuple[_KT_co, _VT_co], _T]]: ... - def __sub__(self, o: Iterable[Any]) -> Set[Tuple[_KT_co, _VT_co]]: ... - def __rsub__(self, o: Iterable[_T]) -> Set[_T]: ... - def __xor__(self, o: Iterable[_T]) -> Set[Union[Tuple[_KT_co, _VT_co], _T]]: ... - def __rxor__(self, o: Iterable[_T]) -> Set[Union[Tuple[_KT_co, _VT_co], _T]]: ... + def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... + def __or__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __ror__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __sub__(self, o: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... + def __rsub__(self, o: Iterable[_T]) -> set[_T]: ... + def __xor__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __rxor__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]): def __init__(self, mapping: Mapping[_KT_co, Any]) -> None: ... # undocumented - def __and__(self, o: Iterable[Any]) -> Set[_KT_co]: ... - def __rand__(self, o: Iterable[_T]) -> Set[_T]: ... + def __and__(self, o: Iterable[Any]) -> set[_KT_co]: ... + def __rand__(self, o: Iterable[_T]) -> set[_T]: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT_co]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[_KT_co]: ... - def __or__(self, o: Iterable[_T]) -> Set[Union[_KT_co, _T]]: ... - def __ror__(self, o: Iterable[_T]) -> Set[Union[_KT_co, _T]]: ... - def __sub__(self, o: Iterable[Any]) -> Set[_KT_co]: ... - def __rsub__(self, o: Iterable[_T]) -> Set[_T]: ... - def __xor__(self, o: Iterable[_T]) -> Set[Union[_KT_co, _T]]: ... - def __rxor__(self, o: Iterable[_T]) -> Set[Union[_KT_co, _T]]: ... + def __or__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... + def __ror__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... + def __sub__(self, o: Iterable[Any]) -> set[_KT_co]: ... + def __rsub__(self, o: Iterable[_T]) -> set[_T]: ... + def __xor__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... + def __rxor__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): def __init__(self, mapping: Mapping[Any, _VT_co]) -> None: ... # undocumented @@ -421,46 +417,43 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): class ContextManager(Protocol[_T_co]): def __enter__(self) -> _T_co: ... def __exit__( - self, - __exc_type: Optional[Type[BaseException]], - __exc_value: Optional[BaseException], - __traceback: Optional[TracebackType], - ) -> Optional[bool]: ... + self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> bool | None: ... @runtime_checkable class AsyncContextManager(Protocol[_T_co]): def __aenter__(self) -> Awaitable[_T_co]: ... def __aexit__( - self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> Awaitable[Optional[bool]]: ... + self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> Awaitable[bool | None]: ... -class Mapping(_Collection[_KT], Generic[_KT, _VT_co]): +class Mapping(Collection[_KT], Generic[_KT, _VT_co]): # TODO: We wish the key type could also be covariant, but that doesn't work, - # see discussion in https: //github.com/python/typing/pull/273. + # see discussion in https://github.com/python/typing/pull/273. @abstractmethod - def __getitem__(self, k: _KT) -> _VT_co: ... + def __getitem__(self, __k: _KT) -> _VT_co: ... # Mixin methods @overload - def get(self, key: _KT) -> Optional[_VT_co]: ... + def get(self, key: _KT) -> _VT_co | None: ... @overload - def get(self, key: _KT, default: Union[_VT_co, _T]) -> Union[_VT_co, _T]: ... - def items(self) -> AbstractSet[Tuple[_KT, _VT_co]]: ... - def keys(self) -> AbstractSet[_KT]: ... + def get(self, __key: _KT, __default: _VT_co | _T) -> _VT_co | _T: ... + def items(self) -> ItemsView[_KT, _VT_co]: ... + def keys(self) -> KeysView[_KT]: ... def values(self) -> ValuesView[_VT_co]: ... - def __contains__(self, o: object) -> bool: ... + def __contains__(self, __o: object) -> bool: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @abstractmethod - def __setitem__(self, k: _KT, v: _VT) -> None: ... + def __setitem__(self, __k: _KT, __v: _VT) -> None: ... @abstractmethod - def __delitem__(self, v: _KT) -> None: ... + def __delitem__(self, __v: _KT) -> None: ... def clear(self) -> None: ... @overload - def pop(self, key: _KT) -> _VT: ... + def pop(self, __key: _KT) -> _VT: ... @overload - def pop(self, key: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ... - def popitem(self) -> Tuple[_KT, _VT]: ... - def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + def pop(self, __key: _KT, __default: _VT | _T = ...) -> _VT | _T: ... + def popitem(self) -> tuple[_KT, _VT]: ... + def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... # 'update' used to take a Union, but using overloading is better. # The second overloaded type here is a bit too general, because # Mapping[Tuple[_KT, _VT], W] is a subclass of Iterable[Tuple[_KT, _VT]], @@ -474,7 +467,7 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @overload def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload def update(self, **kwargs: _VT) -> None: ... @@ -513,7 +506,7 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): @abstractmethod def tell(self) -> int: ... @abstractmethod - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... @abstractmethod def writable(self) -> bool: ... @abstractmethod @@ -528,8 +521,8 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): def __enter__(self) -> IO[AnyStr]: ... @abstractmethod def __exit__( - self, t: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> Optional[bool]: ... + self, t: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... class BinaryIO(IO[bytes]): @abstractmethod @@ -542,7 +535,7 @@ class TextIO(IO[str]): @property def encoding(self) -> str: ... @property - def errors(self) -> Optional[str]: ... + def errors(self) -> str | None: ... @property def line_buffering(self) -> int: ... # int on PyPy, bool on CPython @property @@ -552,42 +545,59 @@ class TextIO(IO[str]): class ByteString(Sequence[int], metaclass=ABCMeta): ... +@_final class Match(Generic[AnyStr]): pos: int endpos: int - lastindex: Optional[int] - lastgroup: Optional[AnyStr] + lastindex: int | None + lastgroup: AnyStr | None string: AnyStr # The regular expression object whose match() or search() method produced # this match instance. re: Pattern[AnyStr] def expand(self, template: AnyStr) -> AnyStr: ... - # TODO: The return for a group may be None, except if __group is 0 or not given. + # group() returns "AnyStr" or "AnyStr | None", depending on the pattern. + @overload + def group(self, __group: _Literal[0] = ...) -> AnyStr: ... + @overload + def group(self, __group: str | int) -> AnyStr | Any: ... @overload - def group(self, __group: Union[str, int] = ...) -> AnyStr: ... + def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[AnyStr | Any, ...]: ... + # Each item of groups()'s return tuple is either "AnyStr" or + # "AnyStr | None", depending on the pattern. @overload - def group(self, __group1: Union[str, int], __group2: Union[str, int], *groups: Union[str, int]) -> Tuple[AnyStr, ...]: ... - def groups(self, default: AnyStr = ...) -> Sequence[AnyStr]: ... - def groupdict(self, default: AnyStr = ...) -> dict[str, AnyStr]: ... - def start(self, __group: Union[int, str] = ...) -> int: ... - def end(self, __group: Union[int, str] = ...) -> int: ... - def span(self, __group: Union[int, str] = ...) -> Tuple[int, int]: ... + def groups(self) -> Tuple[AnyStr | Any, ...]: ... + @overload + def groups(self, default: _T) -> Tuple[AnyStr | _T, ...]: ... + # Each value in groupdict()'s return dict is either "AnyStr" or + # "AnyStr | None", depending on the pattern. + @overload + def groupdict(self) -> dict[str, AnyStr | Any]: ... + @overload + def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ... + def start(self, __group: int | str = ...) -> int: ... + def end(self, __group: int | str = ...) -> int: ... + def span(self, __group: int | str = ...) -> tuple[int, int]: ... @property - def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented - def __getitem__(self, g: Union[int, str]) -> AnyStr: ... + def regs(self) -> Tuple[tuple[int, int], ...]: ... # undocumented + # __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern. + @overload + def __getitem__(self, __key: _Literal[0]) -> AnyStr: ... + @overload + def __getitem__(self, __key: int | str) -> AnyStr | Any: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... +@_final class Pattern(Generic[AnyStr]): flags: int groupindex: Mapping[str, int] groups: int pattern: AnyStr - def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... - def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... - # New in Python 3.4 - def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... + def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... + def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... + def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... def split(self, string: AnyStr, maxsplit: int = ...) -> list[AnyStr]: ... def findall(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> list[Any]: ... def finditer(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Iterator[Match[AnyStr]]: ... @@ -596,9 +606,9 @@ class Pattern(Generic[AnyStr]): @overload def sub(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> AnyStr: ... @overload - def subn(self, repl: AnyStr, string: AnyStr, count: int = ...) -> Tuple[AnyStr, int]: ... + def subn(self, repl: AnyStr, string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... @overload - def subn(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> Tuple[AnyStr, int]: ... + def subn(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -624,18 +634,18 @@ else: if sys.version_info >= (3, 9): def get_type_hints( obj: _get_type_hints_obj_allowed_types, - globalns: Optional[Dict[str, Any]] = ..., - localns: Optional[Dict[str, Any]] = ..., + globalns: dict[str, Any] | None = ..., + localns: dict[str, Any] | None = ..., include_extras: bool = ..., - ) -> Dict[str, Any]: ... + ) -> dict[str, Any]: ... else: def get_type_hints( - obj: _get_type_hints_obj_allowed_types, globalns: Optional[Dict[str, Any]] = ..., localns: Optional[Dict[str, Any]] = ... - ) -> Dict[str, Any]: ... + obj: _get_type_hints_obj_allowed_types, globalns: dict[str, Any] | None = ..., localns: dict[str, Any] | None = ... + ) -> dict[str, Any]: ... if sys.version_info >= (3, 8): - def get_origin(tp: Any) -> Optional[Any]: ... + def get_origin(tp: Any) -> Any | None: ... def get_args(tp: Any) -> Tuple[Any, ...]: ... @overload @@ -650,14 +660,17 @@ def cast(typ: object, val: Any) -> Any: ... # NamedTuple is special-cased in the type checker class NamedTuple(Tuple[Any, ...]): _field_types: collections.OrderedDict[str, Type[Any]] - _field_defaults: Dict[str, Any] = ... + _field_defaults: dict[str, Any] _fields: Tuple[str, ...] _source: str - def __init__(self, typename: str, fields: Iterable[Tuple[str, Any]] = ..., **kwargs: Any) -> None: ... + @overload + def __init__(self, typename: str, fields: Iterable[tuple[str, Any]] = ...) -> None: ... + @overload + def __init__(self, typename: str, fields: None = ..., **kwargs: Any) -> None: ... @classmethod def _make(cls: Type[_T], iterable: Iterable[Any]) -> _T: ... if sys.version_info >= (3, 8): - def _asdict(self) -> Dict[str, Any]: ... + def _asdict(self) -> dict[str, Any]: ... else: def _asdict(self) -> collections.OrderedDict[str, Any]: ... def _replace(self: _T, **kwargs: Any) -> _T: ... @@ -684,15 +697,18 @@ def NewType(name: str, tp: Type[_T]) -> Type[_T]: ... def type_check_only(func_or_cls: _F) -> _F: ... if sys.version_info >= (3, 7): - from types import CodeType class ForwardRef: __forward_arg__: str __forward_code__: CodeType __forward_evaluated__: bool - __forward_value__: Optional[Any] + __forward_value__: Any | None __forward_is_argument__: bool - def __init__(self, arg: str, is_argument: bool = ...) -> None: ... - def _evaluate(self, globalns: Optional[Dict[str, Any]], localns: Optional[Dict[str, Any]]) -> Optional[Any]: ... + if sys.version_info >= (3, 9): + # The module argument was added in Python 3.9.7. + def __init__(self, arg: str, is_argument: bool = ..., module: Any | None = ...) -> None: ... + else: + def __init__(self, arg: str, is_argument: bool = ...) -> None: ... + def _evaluate(self, globalns: dict[str, Any] | None, localns: dict[str, Any] | None) -> Any | None: ... def __eq__(self, other: Any) -> bool: ... def __hash__(self) -> int: ... def __repr__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index 0250866f3eb8..ce407f996022 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -3,24 +3,28 @@ import sys from typing import ( TYPE_CHECKING as TYPE_CHECKING, Any, + AsyncContextManager as AsyncContextManager, + AsyncGenerator as AsyncGenerator, + AsyncIterable as AsyncIterable, + AsyncIterator as AsyncIterator, + Awaitable as Awaitable, Callable, + ChainMap as ChainMap, ClassVar as ClassVar, ContextManager as ContextManager, + Coroutine as Coroutine, Counter as Counter, DefaultDict as DefaultDict, Deque as Deque, - Dict, ItemsView, KeysView, Mapping, NewType as NewType, NoReturn as NoReturn, - Optional, Text as Text, Tuple, Type as Type, TypeVar, - Union, ValuesView, _Alias, overload as overload, @@ -39,6 +43,9 @@ def runtime_checkable(cls: _TC) -> _TC: ... runtime = runtime_checkable Protocol: _SpecialForm = ... Final: _SpecialForm = ... +Self: _SpecialForm = ... +Required: _SpecialForm = ... +NotRequired: _SpecialForm = ... def final(f: _F) -> _F: ... @@ -48,6 +55,9 @@ def IntVar(name: str) -> Any: ... # returns a new TypeVar # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): + __required_keys__: frozenset[str] + __optional_keys__: frozenset[str] + __total__: bool def copy(self: _T) -> _T: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. @@ -55,15 +65,9 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): # Mypy plugin hook for 'pop' expects that 'default' has a type variable type. def pop(self, k: NoReturn, default: _T = ...) -> object: ... # type: ignore def update(self: _T, __m: _T) -> None: ... - if sys.version_info >= (3, 0): - def items(self) -> ItemsView[str, object]: ... - def keys(self) -> KeysView[str]: ... - def values(self) -> ValuesView[object]: ... - else: - def has_key(self, k: str) -> bool: ... - def viewitems(self) -> ItemsView[str, object]: ... - def viewkeys(self) -> KeysView[str]: ... - def viewvalues(self) -> ValuesView[object]: ... + def items(self) -> ItemsView[str, object]: ... + def keys(self) -> KeysView[str]: ... + def values(self) -> ValuesView[object]: ... def __delitem__(self, k: NoReturn) -> None: ... # TypedDict is a (non-subscriptable) special form. @@ -71,31 +75,15 @@ TypedDict: object = ... OrderedDict = _Alias() -if sys.version_info >= (3, 3): - from typing import ChainMap as ChainMap - -if sys.version_info >= (3, 5): - from typing import ( - AsyncContextManager as AsyncContextManager, - AsyncIterable as AsyncIterable, - AsyncIterator as AsyncIterator, - Awaitable as Awaitable, - Coroutine as Coroutine, - ) - -if sys.version_info >= (3, 6): - from typing import AsyncGenerator as AsyncGenerator - -def get_type_hints( - obj: Callable[..., Any], - globalns: Optional[Dict[str, Any]] = ..., - localns: Optional[Dict[str, Any]] = ..., - include_extras: bool = ..., -) -> Dict[str, Any]: ... - if sys.version_info >= (3, 7): + def get_type_hints( + obj: Callable[..., Any], + globalns: dict[str, Any] | None = ..., + localns: dict[str, Any] | None = ..., + include_extras: bool = ..., + ) -> dict[str, Any]: ... def get_args(tp: Any) -> Tuple[Any, ...]: ... - def get_origin(tp: Any) -> Optional[Any]: ... + def get_origin(tp: Any) -> Any | None: ... Annotated: _SpecialForm = ... _AnnotatedAlias: Any = ... # undocumented @@ -117,11 +105,11 @@ else: def __init__(self, origin: ParamSpec) -> None: ... class ParamSpec: __name__: str - __bound__: Optional[Type[Any]] + __bound__: Type[Any] | None __covariant__: bool __contravariant__: bool def __init__( - self, name: str, *, bound: Union[None, Type[Any], str] = ..., contravariant: bool = ..., covariant: bool = ... + self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... ) -> None: ... @property def args(self) -> ParamSpecArgs: ... diff --git a/mypy/typeshed/stdlib/unicodedata.pyi b/mypy/typeshed/stdlib/unicodedata.pyi index a83d79ff2ed0..66c93f7439f7 100644 --- a/mypy/typeshed/stdlib/unicodedata.pyi +++ b/mypy/typeshed/stdlib/unicodedata.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Text, TypeVar, Union +from typing import Any, TypeVar ucd_3_2_0: UCD ucnhash_CAPI: Any @@ -7,36 +7,36 @@ unidata_version: str _T = TypeVar("_T") -def bidirectional(__chr: Text) -> Text: ... -def category(__chr: Text) -> Text: ... -def combining(__chr: Text) -> int: ... -def decimal(__chr: Text, __default: _T = ...) -> Union[int, _T]: ... -def decomposition(__chr: Text) -> Text: ... -def digit(__chr: Text, __default: _T = ...) -> Union[int, _T]: ... -def east_asian_width(__chr: Text) -> Text: ... +def bidirectional(__chr: str) -> str: ... +def category(__chr: str) -> str: ... +def combining(__chr: str) -> int: ... +def decimal(__chr: str, __default: _T = ...) -> int | _T: ... +def decomposition(__chr: str) -> str: ... +def digit(__chr: str, __default: _T = ...) -> int | _T: ... +def east_asian_width(__chr: str) -> str: ... if sys.version_info >= (3, 8): def is_normalized(__form: str, __unistr: str) -> bool: ... -def lookup(__name: Union[Text, bytes]) -> Text: ... -def mirrored(__chr: Text) -> int: ... -def name(__chr: Text, __default: _T = ...) -> Union[Text, _T]: ... -def normalize(__form: Text, __unistr: Text) -> Text: ... -def numeric(__chr: Text, __default: _T = ...) -> Union[float, _T]: ... +def lookup(__name: str | bytes) -> str: ... +def mirrored(__chr: str) -> int: ... +def name(__chr: str, __default: _T = ...) -> str | _T: ... +def normalize(__form: str, __unistr: str) -> str: ... +def numeric(__chr: str, __default: _T = ...) -> float | _T: ... class UCD(object): # The methods below are constructed from the same array in C # (unicodedata_functions) and hence identical to the methods above. unidata_version: str - def bidirectional(self, __chr: Text) -> str: ... - def category(self, __chr: Text) -> str: ... - def combining(self, __chr: Text) -> int: ... - def decimal(self, __chr: Text, __default: _T = ...) -> Union[int, _T]: ... - def decomposition(self, __chr: Text) -> str: ... - def digit(self, __chr: Text, __default: _T = ...) -> Union[int, _T]: ... - def east_asian_width(self, __chr: Text) -> str: ... - def lookup(self, __name: Union[Text, bytes]) -> Text: ... - def mirrored(self, __chr: Text) -> int: ... - def name(self, __chr: Text, __default: _T = ...) -> Union[Text, _T]: ... - def normalize(self, __form: Text, __unistr: Text) -> Text: ... - def numeric(self, __chr: Text, __default: _T = ...) -> Union[float, _T]: ... + def bidirectional(self, __chr: str) -> str: ... + def category(self, __chr: str) -> str: ... + def combining(self, __chr: str) -> int: ... + def decimal(self, __chr: str, __default: _T = ...) -> int | _T: ... + def decomposition(self, __chr: str) -> str: ... + def digit(self, __chr: str, __default: _T = ...) -> int | _T: ... + def east_asian_width(self, __chr: str) -> str: ... + def lookup(self, __name: str | bytes) -> str: ... + def mirrored(self, __chr: str) -> int: ... + def name(self, __chr: str, __default: _T = ...) -> str | _T: ... + def normalize(self, __form: str, __unistr: str) -> str: ... + def numeric(self, __chr: str, __default: _T = ...) -> float | _T: ... diff --git a/mypy/typeshed/stdlib/unittest/__init__.pyi b/mypy/typeshed/stdlib/unittest/__init__.pyi index b94cc8d9c1cd..8f0ef896fa0c 100644 --- a/mypy/typeshed/stdlib/unittest/__init__.pyi +++ b/mypy/typeshed/stdlib/unittest/__init__.pyi @@ -1,5 +1,4 @@ import sys -from typing import Optional from unittest.async_case import * from .case import ( @@ -22,4 +21,4 @@ from unittest.runner import * from unittest.signals import * from unittest.suite import * -def load_tests(loader: TestLoader, tests: TestSuite, pattern: Optional[str]) -> TestSuite: ... +def load_tests(loader: TestLoader, tests: TestSuite, pattern: str | None) -> TestSuite: ... diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 16036264af11..2ae07144373c 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -2,26 +2,25 @@ import datetime import logging import sys import unittest.result -from collections.abc import Set +from _typeshed import Self +from collections.abc import Set # equivalent to typing.AbstractSet, not builtins.set +from contextlib import AbstractContextManager from types import TracebackType from typing import ( Any, AnyStr, Callable, Container, - ContextManager, Generic, Iterable, - List, Mapping, + NamedTuple, NoReturn, - Optional, Pattern, Sequence, Tuple, Type, TypeVar, - Union, overload, ) from warnings import WarningMessage @@ -47,7 +46,7 @@ class SkipTest(Exception): class TestCase: failureException: Type[BaseException] longMessage: bool - maxDiff: Optional[int] + maxDiff: int | None # undocumented _testMethodName: str # undocumented @@ -59,10 +58,10 @@ class TestCase: def setUpClass(cls) -> None: ... @classmethod def tearDownClass(cls) -> None: ... - def run(self, result: Optional[unittest.result.TestResult] = ...) -> Optional[unittest.result.TestResult]: ... - def __call__(self, result: Optional[unittest.result.TestResult] = ...) -> Optional[unittest.result.TestResult]: ... + def run(self, result: unittest.result.TestResult | None = ...) -> unittest.result.TestResult | None: ... + def __call__(self, result: unittest.result.TestResult | None = ...) -> unittest.result.TestResult | None: ... def skipTest(self, reason: Any) -> None: ... - def subTest(self, msg: Any = ..., **params: Any) -> ContextManager[None]: ... + def subTest(self, msg: Any = ..., **params: Any) -> AbstractContextManager[None]: ... def debug(self) -> None: ... def _addSkip(self, result: unittest.result.TestResult, test_case: TestCase, reason: str) -> None: ... def assertEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... @@ -73,10 +72,10 @@ class TestCase: def assertIsNot(self, expr1: Any, expr2: Any, msg: Any = ...) -> None: ... def assertIsNone(self, obj: Any, msg: Any = ...) -> None: ... def assertIsNotNone(self, obj: Any, msg: Any = ...) -> None: ... - def assertIn(self, member: Any, container: Union[Iterable[Any], Container[Any]], msg: Any = ...) -> None: ... - def assertNotIn(self, member: Any, container: Union[Iterable[Any], Container[Any]], msg: Any = ...) -> None: ... - def assertIsInstance(self, obj: Any, cls: Union[type, Tuple[type, ...]], msg: Any = ...) -> None: ... - def assertNotIsInstance(self, obj: Any, cls: Union[type, Tuple[type, ...]], msg: Any = ...) -> None: ... + def assertIn(self, member: Any, container: Iterable[Any] | Container[Any], msg: Any = ...) -> None: ... + def assertNotIn(self, member: Any, container: Iterable[Any] | Container[Any], msg: Any = ...) -> None: ... + def assertIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: Any = ...) -> None: ... + def assertNotIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: Any = ...) -> None: ... def assertGreater(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertGreaterEqual(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertLess(self, a: Any, b: Any, msg: Any = ...) -> None: ... @@ -84,20 +83,18 @@ class TestCase: @overload def assertRaises( # type: ignore self, - expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + expected_exception: Type[BaseException] | Tuple[Type[BaseException], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any, ) -> None: ... @overload - def assertRaises( - self, expected_exception: Union[Type[_E], Tuple[Type[_E], ...]], msg: Any = ... - ) -> _AssertRaisesContext[_E]: ... + def assertRaises(self, expected_exception: Type[_E] | Tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... @overload def assertRaisesRegex( # type: ignore self, - expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + expected_exception: Type[BaseException] | Tuple[Type[BaseException], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], callable: Callable[..., Any], *args: Any, **kwargs: Any, @@ -105,27 +102,21 @@ class TestCase: @overload def assertRaisesRegex( self, - expected_exception: Union[Type[_E], Tuple[Type[_E], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + expected_exception: Type[_E] | Tuple[Type[_E], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertRaisesContext[_E]: ... @overload def assertWarns( # type: ignore - self, - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], - callable: Callable[..., Any], - *args: Any, - **kwargs: Any, + self, expected_warning: Type[Warning] | Tuple[Type[Warning], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any ) -> None: ... @overload - def assertWarns( - self, expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], msg: Any = ... - ) -> _AssertWarnsContext: ... + def assertWarns(self, expected_warning: Type[Warning] | Tuple[Type[Warning], ...], msg: Any = ...) -> _AssertWarnsContext: ... @overload def assertWarnsRegex( # type: ignore self, - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + expected_warning: Type[Warning] | Tuple[Type[Warning], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], callable: Callable[..., Any], *args: Any, **kwargs: Any, @@ -133,50 +124,48 @@ class TestCase: @overload def assertWarnsRegex( self, - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + expected_warning: Type[Warning] | Tuple[Type[Warning], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertWarnsContext: ... - def assertLogs( - self, logger: Optional[Union[str, logging.Logger]] = ..., level: Union[int, str, None] = ... - ) -> _AssertLogsContext: ... + def assertLogs(self, logger: str | logging.Logger | None = ..., level: int | str | None = ...) -> _AssertLogsContext: ... @overload def assertAlmostEqual( - self, first: float, second: float, places: Optional[int] = ..., msg: Any = ..., delta: Optional[float] = ... + self, first: float, second: float, places: int | None = ..., msg: Any = ..., delta: float | None = ... ) -> None: ... @overload def assertAlmostEqual( self, first: datetime.datetime, second: datetime.datetime, - places: Optional[int] = ..., + places: int | None = ..., msg: Any = ..., - delta: Optional[datetime.timedelta] = ..., + delta: datetime.timedelta | None = ..., ) -> None: ... @overload def assertNotAlmostEqual(self, first: float, second: float, *, msg: Any = ...) -> None: ... @overload - def assertNotAlmostEqual(self, first: float, second: float, places: Optional[int] = ..., msg: Any = ...) -> None: ... + def assertNotAlmostEqual(self, first: float, second: float, places: int | None = ..., msg: Any = ...) -> None: ... @overload - def assertNotAlmostEqual(self, first: float, second: float, *, msg: Any = ..., delta: Optional[float] = ...) -> None: ... + def assertNotAlmostEqual(self, first: float, second: float, *, msg: Any = ..., delta: float | None = ...) -> None: ... @overload def assertNotAlmostEqual( self, first: datetime.datetime, second: datetime.datetime, - places: Optional[int] = ..., + places: int | None = ..., msg: Any = ..., - delta: Optional[datetime.timedelta] = ..., + delta: datetime.timedelta | None = ..., ) -> None: ... - def assertRegex(self, text: AnyStr, expected_regex: Union[AnyStr, Pattern[AnyStr]], msg: Any = ...) -> None: ... - def assertNotRegex(self, text: AnyStr, unexpected_regex: Union[AnyStr, Pattern[AnyStr]], msg: Any = ...) -> None: ... + def assertRegex(self, text: AnyStr, expected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... + def assertNotRegex(self, text: AnyStr, unexpected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertCountEqual(self, first: Iterable[Any], second: Iterable[Any], msg: Any = ...) -> None: ... def addTypeEqualityFunc(self, typeobj: Type[Any], function: Callable[..., None]) -> None: ... def assertMultiLineEqual(self, first: str, second: str, msg: Any = ...) -> None: ... def assertSequenceEqual( - self, seq1: Sequence[Any], seq2: Sequence[Any], msg: Any = ..., seq_type: Optional[Type[Sequence[Any]]] = ... + self, seq1: Sequence[Any], seq2: Sequence[Any], msg: Any = ..., seq_type: Type[Sequence[Any]] | None = ... ) -> None: ... - def assertListEqual(self, list1: List[Any], list2: List[Any], msg: Any = ...) -> None: ... + def assertListEqual(self, list1: list[Any], list2: list[Any], msg: Any = ...) -> None: ... def assertTupleEqual(self, tuple1: Tuple[Any, ...], tuple2: Tuple[Any, ...], msg: Any = ...) -> None: ... def assertSetEqual(self, set1: Set[object], set2: Set[object], msg: Any = ...) -> None: ... def assertDictEqual(self, d1: Mapping[Any, object], d2: Mapping[Any, object], msg: Any = ...) -> None: ... @@ -184,7 +173,7 @@ class TestCase: def countTestCases(self) -> int: ... def defaultTestResult(self) -> unittest.result.TestResult: ... def id(self) -> str: ... - def shortDescription(self) -> Optional[str]: ... + def shortDescription(self) -> str | None: ... if sys.version_info >= (3, 8): def addCleanup(self, __function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... else: @@ -195,7 +184,7 @@ class TestCase: def addClassCleanup(cls, __function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... @classmethod def doClassCleanups(cls) -> None: ... - def _formatMessage(self, msg: Optional[str], standardMsg: str) -> str: ... # undocumented + def _formatMessage(self, msg: str | None, standardMsg: str) -> str: ... # undocumented def _getAssertEqualityFunc(self, first: Any, second: Any) -> Callable[..., None]: ... # undocumented # below is deprecated def failUnlessEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... @@ -208,26 +197,26 @@ class TestCase: @overload def failUnlessRaises( # type: ignore self, - exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + exception: Type[BaseException] | Tuple[Type[BaseException], ...], callable: Callable[..., Any] = ..., *args: Any, **kwargs: Any, ) -> None: ... @overload - def failUnlessRaises(self, exception: Union[Type[_E], Tuple[Type[_E], ...]], msg: Any = ...) -> _AssertRaisesContext[_E]: ... + def failUnlessRaises(self, exception: Type[_E] | Tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... def failUnlessAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... def assertAlmostEquals(self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ...) -> None: ... def failIfAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... def assertNotAlmostEquals( self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... ) -> None: ... - def assertRegexpMatches(self, text: AnyStr, regex: Union[AnyStr, Pattern[AnyStr]], msg: Any = ...) -> None: ... - def assertNotRegexpMatches(self, text: AnyStr, regex: Union[AnyStr, Pattern[AnyStr]], msg: Any = ...) -> None: ... + def assertRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... + def assertNotRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... @overload def assertRaisesRegexp( # type: ignore self, - exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + exception: Type[BaseException] | Tuple[Type[BaseException], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], callable: Callable[..., Any], *args: Any, **kwargs: Any, @@ -235,8 +224,8 @@ class TestCase: @overload def assertRaisesRegexp( self, - exception: Union[Type[_E], Tuple[Type[_E], ...]], - expected_regex: Union[str, bytes, Pattern[str], Pattern[bytes]], + exception: Type[_E] | Tuple[Type[_E], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertRaisesContext[_E]: ... def assertDictContainsSubset(self, subset: Mapping[Any, Any], dictionary: Mapping[Any, Any], msg: object = ...) -> None: ... @@ -245,17 +234,21 @@ class FunctionTestCase(TestCase): def __init__( self, testFunc: Callable[[], None], - setUp: Optional[Callable[[], None]] = ..., - tearDown: Optional[Callable[[], None]] = ..., - description: Optional[str] = ..., + setUp: Callable[[], None] | None = ..., + tearDown: Callable[[], None] | None = ..., + description: str | None = ..., ) -> None: ... def runTest(self) -> None: ... +class _LoggingWatcher(NamedTuple): + records: list[logging.LogRecord] + output: list[str] + class _AssertRaisesContext(Generic[_E]): exception: _E - def __enter__(self) -> _AssertRaisesContext[_E]: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -264,18 +257,21 @@ class _AssertWarnsContext: warning: WarningMessage filename: str lineno: int - warnings: List[WarningMessage] - def __enter__(self) -> _AssertWarnsContext: ... + warnings: list[WarningMessage] + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _AssertLogsContext: LOGGING_FORMAT: str - records: List[logging.LogRecord] - output: List[str] + records: list[logging.LogRecord] + output: list[str] def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... - def __enter__(self) -> _AssertLogsContext: ... + if sys.version_info >= (3, 10): + def __enter__(self) -> _LoggingWatcher | None: ... + else: + def __enter__(self) -> _LoggingWatcher: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... diff --git a/mypy/typeshed/stdlib/unittest/loader.pyi b/mypy/typeshed/stdlib/unittest/loader.pyi index 48c9f1c5f100..d3cb4cef733b 100644 --- a/mypy/typeshed/stdlib/unittest/loader.pyi +++ b/mypy/typeshed/stdlib/unittest/loader.pyi @@ -3,26 +3,26 @@ import unittest.case import unittest.result import unittest.suite from types import ModuleType -from typing import Any, Callable, List, Optional, Sequence, Type +from typing import Any, Callable, List, Sequence, Type _SortComparisonMethod = Callable[[str, str], int] _SuiteClass = Callable[[List[unittest.case.TestCase]], unittest.suite.TestSuite] class TestLoader: - errors: List[Type[BaseException]] + errors: list[Type[BaseException]] testMethodPrefix: str sortTestMethodsUsing: _SortComparisonMethod if sys.version_info >= (3, 7): - testNamePatterns: Optional[List[str]] + testNamePatterns: list[str] | None suiteClass: _SuiteClass def loadTestsFromTestCase(self, testCaseClass: Type[unittest.case.TestCase]) -> unittest.suite.TestSuite: ... def loadTestsFromModule(self, module: ModuleType, *args: Any, pattern: Any = ...) -> unittest.suite.TestSuite: ... - def loadTestsFromName(self, name: str, module: Optional[ModuleType] = ...) -> unittest.suite.TestSuite: ... - def loadTestsFromNames(self, names: Sequence[str], module: Optional[ModuleType] = ...) -> unittest.suite.TestSuite: ... + def loadTestsFromName(self, name: str, module: ModuleType | None = ...) -> unittest.suite.TestSuite: ... + def loadTestsFromNames(self, names: Sequence[str], module: ModuleType | None = ...) -> unittest.suite.TestSuite: ... def getTestCaseNames(self, testCaseClass: Type[unittest.case.TestCase]) -> Sequence[str]: ... - def discover(self, start_dir: str, pattern: str = ..., top_level_dir: Optional[str] = ...) -> unittest.suite.TestSuite: ... + def discover(self, start_dir: str, pattern: str = ..., top_level_dir: str | None = ...) -> unittest.suite.TestSuite: ... defaultTestLoader: TestLoader @@ -31,7 +31,7 @@ if sys.version_info >= (3, 7): testCaseClass: Type[unittest.case.TestCase], prefix: str, sortUsing: _SortComparisonMethod = ..., - testNamePatterns: Optional[List[str]] = ..., + testNamePatterns: list[str] | None = ..., ) -> Sequence[str]: ... else: diff --git a/mypy/typeshed/stdlib/unittest/main.pyi b/mypy/typeshed/stdlib/unittest/main.pyi index 5e6151eda3dd..cd887cec27d0 100644 --- a/mypy/typeshed/stdlib/unittest/main.pyi +++ b/mypy/typeshed/stdlib/unittest/main.pyi @@ -4,44 +4,44 @@ import unittest.loader import unittest.result import unittest.suite from types import ModuleType -from typing import Any, Iterable, List, Optional, Protocol, Type, Union +from typing import Any, Iterable, Protocol, Type class _TestRunner(Protocol): - def run(self, test: Union[unittest.suite.TestSuite, unittest.case.TestCase]) -> unittest.result.TestResult: ... + def run(self, test: unittest.suite.TestSuite | unittest.case.TestCase) -> unittest.result.TestResult: ... # not really documented class TestProgram: result: unittest.result.TestResult - module: Union[None, str, ModuleType] + module: None | str | ModuleType verbosity: int - failfast: Optional[bool] - catchbreak: Optional[bool] - buffer: Optional[bool] - progName: Optional[str] - warnings: Optional[str] + failfast: bool | None + catchbreak: bool | None + buffer: bool | None + progName: str | None + warnings: str | None if sys.version_info >= (3, 7): - testNamePatterns: Optional[List[str]] + testNamePatterns: list[str] | None def __init__( self, - module: Union[None, str, ModuleType] = ..., - defaultTest: Union[str, Iterable[str], None] = ..., - argv: Optional[List[str]] = ..., - testRunner: Union[Type[_TestRunner], _TestRunner, None] = ..., + module: None | str | ModuleType = ..., + defaultTest: str | Iterable[str] | None = ..., + argv: list[str] | None = ..., + testRunner: Type[_TestRunner] | _TestRunner | None = ..., testLoader: unittest.loader.TestLoader = ..., exit: bool = ..., verbosity: int = ..., - failfast: Optional[bool] = ..., - catchbreak: Optional[bool] = ..., - buffer: Optional[bool] = ..., - warnings: Optional[str] = ..., + failfast: bool | None = ..., + catchbreak: bool | None = ..., + buffer: bool | None = ..., + warnings: str | None = ..., *, tb_locals: bool = ..., ) -> None: ... def usageExit(self, msg: Any = ...) -> None: ... - def parseArgs(self, argv: List[str]) -> None: ... + def parseArgs(self, argv: list[str]) -> None: ... if sys.version_info >= (3, 7): - def createTests(self, from_discovery: bool = ..., Loader: Optional[unittest.loader.TestLoader] = ...) -> None: ... + def createTests(self, from_discovery: bool = ..., Loader: unittest.loader.TestLoader | None = ...) -> None: ... else: def createTests(self) -> None: ... def runTests(self) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/unittest/mock.pyi b/mypy/typeshed/stdlib/unittest/mock.pyi index fd767272e66a..567ce346f464 100644 --- a/mypy/typeshed/stdlib/unittest/mock.pyi +++ b/mypy/typeshed/stdlib/unittest/mock.pyi @@ -1,7 +1,6 @@ import sys -from typing import Any, Callable, Generic, Iterable, List, Mapping, Optional, Sequence, Tuple, Type, TypeVar, Union, overload +from typing import Any, Callable, Generic, Iterable, List, Mapping, Sequence, Tuple, Type, TypeVar, overload -_F = TypeVar("_F", bound=Callable[..., Any]) _T = TypeVar("_T") _TT = TypeVar("_TT", bound=Type[Any]) _R = TypeVar("_R") @@ -42,13 +41,13 @@ DEFAULT: Any class _Call(Tuple[Any, ...]): def __new__( - cls, value: Any = ..., name: Optional[Any] = ..., parent: Optional[Any] = ..., two: bool = ..., from_kall: bool = ... + cls, value: Any = ..., name: Any | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... ) -> Any: ... name: Any parent: Any from_kall: Any def __init__( - self, value: Any = ..., name: Optional[Any] = ..., parent: Optional[Any] = ..., two: bool = ..., from_kall: bool = ... + self, value: Any = ..., name: Any | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... ) -> None: ... def __eq__(self, other: Any) -> bool: ... __ne__: Any @@ -76,16 +75,16 @@ class NonCallableMock(Base, Any): # type: ignore def __new__(__cls, *args: Any, **kw: Any) -> NonCallableMock: ... def __init__( self, - spec: Union[List[str], object, Type[object], None] = ..., - wraps: Optional[Any] = ..., - name: Optional[str] = ..., - spec_set: Union[List[str], object, Type[object], None] = ..., - parent: Optional[NonCallableMock] = ..., - _spec_state: Optional[Any] = ..., + spec: list[str] | object | Type[object] | None = ..., + wraps: Any | None = ..., + name: str | None = ..., + spec_set: list[str] | object | Type[object] | None = ..., + parent: NonCallableMock | None = ..., + _spec_state: Any | None = ..., _new_name: str = ..., - _new_parent: Optional[NonCallableMock] = ..., + _new_parent: NonCallableMock | None = ..., _spec_as_instance: bool = ..., - _eat_self: Optional[bool] = ..., + _eat_self: bool | None = ..., unsafe: bool = ..., **kwargs: Any, ) -> None: ... @@ -96,7 +95,7 @@ class NonCallableMock(Base, Any): # type: ignore def assert_not_called(self) -> None: ... def assert_called_once_with(self, *args: Any, **kwargs: Any) -> None: ... def _format_mock_failure_message(self, args: Any, kwargs: Any, action: str = ...) -> str: ... - elif sys.version_info >= (3, 5): + else: def assert_called_with(_mock_self, *args: Any, **kwargs: Any) -> None: ... def assert_not_called(_mock_self) -> None: ... def assert_called_once_with(_mock_self, *args: Any, **kwargs: Any) -> None: ... @@ -104,7 +103,7 @@ class NonCallableMock(Base, Any): # type: ignore if sys.version_info >= (3, 8): def assert_called(self) -> None: ... def assert_called_once(self) -> None: ... - elif sys.version_info >= (3, 6): + else: def assert_called(_mock_self) -> None: ... def assert_called_once(_mock_self) -> None: ... def reset_mock(self, visited: Any = ..., *, return_value: bool = ..., side_effect: bool = ...) -> None: ... @@ -132,16 +131,16 @@ class CallableMixin(Base): side_effect: Any def __init__( self, - spec: Optional[Any] = ..., - side_effect: Optional[Any] = ..., + spec: Any | None = ..., + side_effect: Any | None = ..., return_value: Any = ..., - wraps: Optional[Any] = ..., - name: Optional[Any] = ..., - spec_set: Optional[Any] = ..., - parent: Optional[Any] = ..., - _spec_state: Optional[Any] = ..., + wraps: Any | None = ..., + name: Any | None = ..., + spec_set: Any | None = ..., + parent: Any | None = ..., + _spec_state: Any | None = ..., _new_name: Any = ..., - _new_parent: Optional[Any] = ..., + _new_parent: Any | None = ..., **kwargs: Any, ) -> None: ... def __call__(_mock_self, *args: Any, **kwargs: Any) -> Any: ... @@ -168,18 +167,21 @@ class _patch(Generic[_T]): getter: Callable[[], Any], attribute: str, new: _T, - spec: Optional[Any], + spec: Any | None, create: bool, - spec_set: Optional[Any], - autospec: Optional[Any], - new_callable: Optional[Any], + spec_set: Any | None, + autospec: Any | None, + new_callable: Any | None, kwargs: Mapping[str, Any], ) -> None: ... def copy(self) -> _patch[_T]: ... + @overload + def __call__(self, func: _TT) -> _TT: ... + @overload def __call__(self, func: Callable[..., _R]) -> Callable[..., _R]: ... def decorate_class(self, klass: _TT) -> _TT: ... - def decorate_callable(self, func: _F) -> _F: ... - def get_original(self) -> Tuple[Any, bool]: ... + def decorate_callable(self, func: Callable[..., _R]) -> Callable[..., _R]: ... + def get_original(self) -> tuple[Any, bool]: ... target: Any temp_original: Any is_local: bool @@ -204,122 +206,122 @@ class _patcher: TEST_PREFIX: str dict: Type[_patch_dict] if sys.version_info >= (3, 8): + # This overload also covers the case, where new==DEFAULT. In this case, the return type is _patch[Any]. + # Ideally we'd be able to add an overload for it so that the return type is _patch[MagicMock], + # but that's impossible with the current type system. + @overload + def __call__( # type: ignore + self, + target: Any, + new: _T, + spec: Any | None = ..., + create: bool = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[_T]: ... @overload def __call__( # type: ignore self, target: Any, *, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, - ) -> _patch[Union[MagicMock, AsyncMock]]: ... - # This overload also covers the case, where new==DEFAULT. In this case, the return type is _patch[Any]. - # Ideally we'd be able to add an overload for it so that the return type is _patch[MagicMock], - # but that's impossible with the current type system. + ) -> _patch[MagicMock | AsyncMock]: ... + else: @overload - def __call__( + def __call__( # type: ignore self, target: Any, new: _T, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, ) -> _patch[_T]: ... - else: @overload def __call__( # type: ignore self, target: Any, *, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, ) -> _patch[MagicMock]: ... + if sys.version_info >= (3, 8): @overload - def __call__( + def object( # type: ignore self, target: Any, + attribute: str, new: _T, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, ) -> _patch[_T]: ... - if sys.version_info >= (3, 8): @overload def object( # type: ignore self, target: Any, attribute: str, *, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, - ) -> _patch[Union[MagicMock, AsyncMock]]: ... + ) -> _patch[MagicMock | AsyncMock]: ... + else: @overload - def object( + def object( # type: ignore self, target: Any, attribute: str, - new: _T = ..., - spec: Optional[Any] = ..., + new: _T, + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, ) -> _patch[_T]: ... - else: @overload def object( # type: ignore self, target: Any, attribute: str, *, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., **kwargs: Any, ) -> _patch[MagicMock]: ... - @overload - def object( - self, - target: Any, - attribute: str, - new: _T = ..., - spec: Optional[Any] = ..., - create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., - **kwargs: Any, - ) -> _patch[_T]: ... def multiple( self, target: Any, - spec: Optional[Any] = ..., + spec: Any | None = ..., create: bool = ..., - spec_set: Optional[Any] = ..., - autospec: Optional[Any] = ..., - new_callable: Optional[Any] = ..., - **kwargs: _T, - ) -> _patch[_T]: ... + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[Any]: ... def stopall(self) -> None: ... patch: _patcher @@ -346,7 +348,7 @@ if sys.version_info >= (3, 8): def assert_not_awaited(self) -> None: ... def reset_mock(self, *args: Any, **kwargs: Any) -> None: ... await_count: int - await_args: Optional[_Call] + await_args: _Call | None await_args_list: _CallList class AsyncMagicMixin(MagicMixin): def __init__(self, *args: Any, **kw: Any) -> None: ... @@ -358,7 +360,7 @@ class MagicProxy: def __init__(self, name: Any, parent: Any) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def create_mock(self) -> Any: ... - def __get__(self, obj: Any, _type: Optional[Any] = ...) -> Any: ... + def __get__(self, obj: Any, _type: Any | None = ...) -> Any: ... class _ANY: def __eq__(self, other: Any) -> bool: ... @@ -367,7 +369,7 @@ class _ANY: ANY: Any def create_autospec( - spec: Any, spec_set: Any = ..., instance: Any = ..., _parent: Optional[Any] = ..., _name: Optional[Any] = ..., **kwargs: Any + spec: Any, spec_set: Any = ..., instance: Any = ..., _parent: Any | None = ..., _name: Any | None = ..., **kwargs: Any ) -> Any: ... class _SpecState: @@ -381,13 +383,13 @@ class _SpecState: self, spec: Any, spec_set: Any = ..., - parent: Optional[Any] = ..., - name: Optional[Any] = ..., - ids: Optional[Any] = ..., + parent: Any | None = ..., + name: Any | None = ..., + ids: Any | None = ..., instance: Any = ..., ) -> None: ... -def mock_open(mock: Optional[Any] = ..., read_data: Any = ...) -> Any: ... +def mock_open(mock: Any | None = ..., read_data: Any = ...) -> Any: ... PropertyMock = Any diff --git a/mypy/typeshed/stdlib/unittest/result.pyi b/mypy/typeshed/stdlib/unittest/result.pyi index 8c7ff78d6cdf..20c43cf38aa4 100644 --- a/mypy/typeshed/stdlib/unittest/result.pyi +++ b/mypy/typeshed/stdlib/unittest/result.pyi @@ -1,6 +1,6 @@ import unittest.case from types import TracebackType -from typing import Any, Callable, List, Optional, TextIO, Tuple, Type, TypeVar, Union +from typing import Any, Callable, TextIO, Tuple, Type, TypeVar, Union _SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, TracebackType], Tuple[None, None, None]] @@ -10,19 +10,17 @@ _F = TypeVar("_F", bound=Callable[..., Any]) def failfast(method: _F) -> _F: ... class TestResult: - errors: List[Tuple[unittest.case.TestCase, str]] - failures: List[Tuple[unittest.case.TestCase, str]] - skipped: List[Tuple[unittest.case.TestCase, str]] - expectedFailures: List[Tuple[unittest.case.TestCase, str]] - unexpectedSuccesses: List[unittest.case.TestCase] + errors: list[tuple[unittest.case.TestCase, str]] + failures: list[tuple[unittest.case.TestCase, str]] + skipped: list[tuple[unittest.case.TestCase, str]] + expectedFailures: list[tuple[unittest.case.TestCase, str]] + unexpectedSuccesses: list[unittest.case.TestCase] shouldStop: bool testsRun: int buffer: bool failfast: bool tb_locals: bool - def __init__( - self, stream: Optional[TextIO] = ..., descriptions: Optional[bool] = ..., verbosity: Optional[int] = ... - ) -> None: ... + def __init__(self, stream: TextIO | None = ..., descriptions: bool | None = ..., verbosity: int | None = ...) -> None: ... def printErrors(self) -> None: ... def wasSuccessful(self) -> bool: ... def stop(self) -> None: ... @@ -36,6 +34,4 @@ class TestResult: def addSkip(self, test: unittest.case.TestCase, reason: str) -> None: ... def addExpectedFailure(self, test: unittest.case.TestCase, err: _SysExcInfoType) -> None: ... def addUnexpectedSuccess(self, test: unittest.case.TestCase) -> None: ... - def addSubTest( - self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: Optional[_SysExcInfoType] - ) -> None: ... + def addSubTest(self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: _SysExcInfoType | None) -> None: ... diff --git a/mypy/typeshed/stdlib/unittest/runner.pyi b/mypy/typeshed/stdlib/unittest/runner.pyi index adb5fc50442a..bf8f3c05c1cd 100644 --- a/mypy/typeshed/stdlib/unittest/runner.pyi +++ b/mypy/typeshed/stdlib/unittest/runner.pyi @@ -1,7 +1,7 @@ import unittest.case import unittest.result import unittest.suite -from typing import Callable, Optional, TextIO, Tuple, Type, Union +from typing import Callable, TextIO, Type _ResultClassType = Callable[[TextIO, bool, int], unittest.result.TestResult] @@ -15,21 +15,21 @@ class TextTestResult(unittest.result.TestResult): def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... def getDescription(self, test: unittest.case.TestCase) -> str: ... def printErrors(self) -> None: ... - def printErrorList(self, flavour: str, errors: Tuple[unittest.case.TestCase, str]) -> None: ... + def printErrorList(self, flavour: str, errors: tuple[unittest.case.TestCase, str]) -> None: ... class TextTestRunner(object): resultclass: _ResultClassType def __init__( self, - stream: Optional[TextIO] = ..., + stream: TextIO | None = ..., descriptions: bool = ..., verbosity: int = ..., failfast: bool = ..., buffer: bool = ..., - resultclass: Optional[_ResultClassType] = ..., - warnings: Optional[Type[Warning]] = ..., + resultclass: _ResultClassType | None = ..., + warnings: Type[Warning] | None = ..., *, tb_locals: bool = ..., ) -> None: ... def _makeResult(self) -> unittest.result.TestResult: ... - def run(self, test: Union[unittest.suite.TestSuite, unittest.case.TestCase]) -> unittest.result.TestResult: ... + def run(self, test: unittest.suite.TestSuite | unittest.case.TestCase) -> unittest.result.TestResult: ... diff --git a/mypy/typeshed/stdlib/unittest/signals.pyi b/mypy/typeshed/stdlib/unittest/signals.pyi index 5a0a1d6220fb..375b7d736a35 100644 --- a/mypy/typeshed/stdlib/unittest/signals.pyi +++ b/mypy/typeshed/stdlib/unittest/signals.pyi @@ -1,7 +1,9 @@ import unittest.result -from typing import Any, Callable, TypeVar, overload +from typing import Callable, TypeVar, overload +from typing_extensions import ParamSpec -_F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") +_T = TypeVar("_T") def installHandler() -> None: ... def registerResult(result: unittest.result.TestResult) -> None: ... @@ -9,4 +11,4 @@ def removeResult(result: unittest.result.TestResult) -> bool: ... @overload def removeHandler(method: None = ...) -> None: ... @overload -def removeHandler(method: _F) -> _F: ... +def removeHandler(method: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore diff --git a/mypy/typeshed/stdlib/unittest/suite.pyi b/mypy/typeshed/stdlib/unittest/suite.pyi index 62869d2305d6..396b46eadf5a 100644 --- a/mypy/typeshed/stdlib/unittest/suite.pyi +++ b/mypy/typeshed/stdlib/unittest/suite.pyi @@ -1,11 +1,11 @@ import unittest.case import unittest.result -from typing import Iterable, Iterator, List, Union +from typing import Iterable, Iterator, Union _TestType = Union[unittest.case.TestCase, TestSuite] class BaseTestSuite(Iterable[_TestType]): - _tests: List[unittest.case.TestCase] + _tests: list[unittest.case.TestCase] _removed_tests: int def __init__(self, tests: Iterable[_TestType] = ...) -> None: ... def __call__(self, result: unittest.result.TestResult) -> unittest.result.TestResult: ... diff --git a/mypy/typeshed/stdlib/unittest/util.pyi b/mypy/typeshed/stdlib/unittest/util.pyi index 8b0e8ad28adc..ab6ed053a6ff 100644 --- a/mypy/typeshed/stdlib/unittest/util.pyi +++ b/mypy/typeshed/stdlib/unittest/util.pyi @@ -1,4 +1,4 @@ -from typing import Any, List, Sequence, Tuple, TypeVar +from typing import Any, Sequence, Tuple, TypeVar _T = TypeVar("_T") _Mismatch = Tuple[_T, _T, int] @@ -11,11 +11,11 @@ _MIN_COMMON_LEN: int _MIN_DIFF_LEN: int def _shorten(s: str, prefixlen: int, suffixlen: int) -> str: ... -def _common_shorten_repr(*args: str) -> Tuple[str]: ... +def _common_shorten_repr(*args: str) -> tuple[str]: ... def safe_repr(obj: object, short: bool = ...) -> str: ... def strclass(cls: type) -> str: ... -def sorted_list_difference(expected: Sequence[_T], actual: Sequence[_T]) -> Tuple[List[_T], List[_T]]: ... -def unorderable_list_difference(expected: Sequence[_T], actual: Sequence[_T]) -> Tuple[List[_T], List[_T]]: ... +def sorted_list_difference(expected: Sequence[_T], actual: Sequence[_T]) -> tuple[list[_T], list[_T]]: ... +def unorderable_list_difference(expected: Sequence[_T], actual: Sequence[_T]) -> tuple[list[_T], list[_T]]: ... def three_way_cmp(x: Any, y: Any) -> int: ... -def _count_diff_all_purpose(actual: Sequence[_T], expected: Sequence[_T]) -> List[_Mismatch[_T]]: ... -def _count_diff_hashable(actual: Sequence[_T], expected: Sequence[_T]) -> List[_Mismatch[_T]]: ... +def _count_diff_all_purpose(actual: Sequence[_T], expected: Sequence[_T]) -> list[_Mismatch[_T]]: ... +def _count_diff_hashable(actual: Sequence[_T], expected: Sequence[_T]) -> list[_Mismatch[_T]]: ... diff --git a/mypy/typeshed/stdlib/urllib/error.pyi b/mypy/typeshed/stdlib/urllib/error.pyi index d6ef9ff5f94f..1d91fedceeca 100644 --- a/mypy/typeshed/stdlib/urllib/error.pyi +++ b/mypy/typeshed/stdlib/urllib/error.pyi @@ -1,17 +1,17 @@ from email.message import Message -from typing import IO, Mapping, Optional, Tuple, Union +from typing import IO from urllib.response import addinfourl # Stubs for urllib.error class URLError(IOError): - reason: Union[str, BaseException] - def __init__(self, reason: Union[str, BaseException], filename: Optional[str] = ...) -> None: ... + reason: str | BaseException + def __init__(self, reason: str | BaseException, filename: str | None = ...) -> None: ... class HTTPError(URLError, addinfourl): code: int - def __init__(self, url: str, code: int, msg: str, hdrs: Mapping[str, str], fp: Optional[IO[bytes]]) -> None: ... + def __init__(self, url: str, code: int, msg: str, hdrs: Message, fp: IO[bytes] | None) -> None: ... class ContentTooShortError(URLError): - content: Tuple[str, Message] - def __init__(self, message: str, content: Tuple[str, Message]) -> None: ... + content: tuple[str, Message] + def __init__(self, message: str, content: tuple[str, Message]) -> None: ... diff --git a/mypy/typeshed/stdlib/urllib/parse.pyi b/mypy/typeshed/stdlib/urllib/parse.pyi index 00bdb5109044..a2467e96c43c 100644 --- a/mypy/typeshed/stdlib/urllib/parse.pyi +++ b/mypy/typeshed/stdlib/urllib/parse.pyi @@ -1,17 +1,17 @@ import sys -from typing import Any, AnyStr, Callable, Dict, Generic, List, Mapping, NamedTuple, Optional, Sequence, Tuple, Union, overload +from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, Tuple, Union, overload if sys.version_info >= (3, 9): from types import GenericAlias _Str = Union[bytes, str] -uses_relative: List[str] -uses_netloc: List[str] -uses_params: List[str] -non_hierarchical: List[str] -uses_query: List[str] -uses_fragment: List[str] +uses_relative: list[str] +uses_netloc: list[str] +uses_params: list[str] +non_hierarchical: list[str] +uses_query: list[str] +uses_fragment: list[str] scheme_chars: str MAX_CACHE_SIZE: int @@ -25,10 +25,10 @@ class _ResultMixinBytes(_ResultMixinBase[str]): def decode(self, encoding: str = ..., errors: str = ...) -> _ResultMixinStr: ... class _NetlocResultMixinBase(Generic[AnyStr]): - username: Optional[AnyStr] - password: Optional[AnyStr] - hostname: Optional[AnyStr] - port: Optional[int] + username: AnyStr | None + password: AnyStr | None + hostname: AnyStr | None + port: int | None if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -80,30 +80,30 @@ class SplitResultBytes(_SplitResultBytesBase, _NetlocResultMixinBytes): ... class ParseResultBytes(_ParseResultBytesBase, _NetlocResultMixinBytes): ... def parse_qs( - qs: Optional[AnyStr], + qs: AnyStr | None, keep_blank_values: bool = ..., strict_parsing: bool = ..., encoding: str = ..., errors: str = ..., - max_num_fields: Optional[int] = ..., + max_num_fields: int | None = ..., separator: str = ..., -) -> Dict[AnyStr, List[AnyStr]]: ... +) -> dict[AnyStr, list[AnyStr]]: ... def parse_qsl( - qs: Optional[AnyStr], + qs: AnyStr | None, keep_blank_values: bool = ..., strict_parsing: bool = ..., encoding: str = ..., errors: str = ..., - max_num_fields: Optional[int] = ..., + max_num_fields: int | None = ..., separator: str = ..., -) -> List[Tuple[AnyStr, AnyStr]]: ... +) -> list[tuple[AnyStr, AnyStr]]: ... @overload -def quote(string: str, safe: _Str = ..., encoding: Optional[str] = ..., errors: Optional[str] = ...) -> str: ... +def quote(string: str, safe: _Str = ..., encoding: str | None = ..., errors: str | None = ...) -> str: ... @overload def quote(string: bytes, safe: _Str = ...) -> str: ... def quote_from_bytes(bs: bytes, safe: _Str = ...) -> str: ... @overload -def quote_plus(string: str, safe: _Str = ..., encoding: Optional[str] = ..., errors: Optional[str] = ...) -> str: ... +def quote_plus(string: str, safe: _Str = ..., encoding: str | None = ..., errors: str | None = ...) -> str: ... @overload def quote_plus(string: bytes, safe: _Str = ...) -> str: ... def unquote(string: str, encoding: str = ..., errors: str = ...) -> str: ... @@ -112,33 +112,31 @@ def unquote_plus(string: str, encoding: str = ..., errors: str = ...) -> str: .. @overload def urldefrag(url: str) -> DefragResult: ... @overload -def urldefrag(url: Optional[bytes]) -> DefragResultBytes: ... +def urldefrag(url: bytes | None) -> DefragResultBytes: ... def urlencode( - query: Union[Mapping[Any, Any], Mapping[Any, Sequence[Any]], Sequence[Tuple[Any, Any]], Sequence[Tuple[Any, Sequence[Any]]]], + query: Mapping[Any, Any] | Mapping[Any, Sequence[Any]] | Sequence[tuple[Any, Any]] | Sequence[tuple[Any, Sequence[Any]]], doseq: bool = ..., safe: AnyStr = ..., encoding: str = ..., errors: str = ..., quote_via: Callable[[str, AnyStr, str, str], str] = ..., ) -> str: ... -def urljoin(base: AnyStr, url: Optional[AnyStr], allow_fragments: bool = ...) -> AnyStr: ... +def urljoin(base: AnyStr, url: AnyStr | None, allow_fragments: bool = ...) -> AnyStr: ... @overload -def urlparse(url: str, scheme: Optional[str] = ..., allow_fragments: bool = ...) -> ParseResult: ... +def urlparse(url: str, scheme: str | None = ..., allow_fragments: bool = ...) -> ParseResult: ... @overload -def urlparse(url: Optional[bytes], scheme: Optional[bytes] = ..., allow_fragments: bool = ...) -> ParseResultBytes: ... +def urlparse(url: bytes | None, scheme: bytes | None = ..., allow_fragments: bool = ...) -> ParseResultBytes: ... @overload -def urlsplit(url: str, scheme: Optional[str] = ..., allow_fragments: bool = ...) -> SplitResult: ... +def urlsplit(url: str, scheme: str | None = ..., allow_fragments: bool = ...) -> SplitResult: ... @overload -def urlsplit(url: Optional[bytes], scheme: Optional[bytes] = ..., allow_fragments: bool = ...) -> SplitResultBytes: ... +def urlsplit(url: bytes | None, scheme: bytes | None = ..., allow_fragments: bool = ...) -> SplitResultBytes: ... @overload def urlunparse( - components: Tuple[Optional[AnyStr], Optional[AnyStr], Optional[AnyStr], Optional[AnyStr], Optional[AnyStr], Optional[AnyStr]] + components: tuple[AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None] ) -> AnyStr: ... @overload -def urlunparse(components: Sequence[Optional[AnyStr]]) -> AnyStr: ... +def urlunparse(components: Sequence[AnyStr | None]) -> AnyStr: ... @overload -def urlunsplit( - components: Tuple[Optional[AnyStr], Optional[AnyStr], Optional[AnyStr], Optional[AnyStr], Optional[AnyStr]] -) -> AnyStr: ... +def urlunsplit(components: tuple[AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None]) -> AnyStr: ... @overload -def urlunsplit(components: Sequence[Optional[AnyStr]]) -> AnyStr: ... +def urlunsplit(components: Sequence[AnyStr | None]) -> AnyStr: ... diff --git a/mypy/typeshed/stdlib/urllib/request.pyi b/mypy/typeshed/stdlib/urllib/request.pyi index 3f09496a6dcf..3c8a6facde6f 100644 --- a/mypy/typeshed/stdlib/urllib/request.pyi +++ b/mypy/typeshed/stdlib/urllib/request.pyi @@ -1,26 +1,10 @@ -import os import ssl import sys +from _typeshed import StrOrBytesPath from email.message import Message from http.client import HTTPMessage, HTTPResponse, _HTTPConnectionProtocol from http.cookiejar import CookieJar -from typing import ( - IO, - Any, - Callable, - ClassVar, - Dict, - List, - Mapping, - NoReturn, - Optional, - Pattern, - Sequence, - Tuple, - TypeVar, - Union, - overload, -) +from typing import IO, Any, Callable, ClassVar, Mapping, NoReturn, Pattern, Sequence, Tuple, TypeVar, overload from urllib.error import HTTPError from urllib.response import addclosehook, addinfourl @@ -28,17 +12,17 @@ _T = TypeVar("_T") _UrlopenRet = Any def urlopen( - url: Union[str, Request], - data: Optional[bytes] = ..., - timeout: Optional[float] = ..., + url: str | Request, + data: bytes | None = ..., + timeout: float | None = ..., *, - cafile: Optional[str] = ..., - capath: Optional[str] = ..., + cafile: str | None = ..., + capath: str | None = ..., cadefault: bool = ..., - context: Optional[ssl.SSLContext] = ..., + context: ssl.SSLContext | None = ..., ) -> _UrlopenRet: ... def install_opener(opener: OpenerDirector) -> None: ... -def build_opener(*handlers: Union[BaseHandler, Callable[[], BaseHandler]]) -> OpenerDirector: ... +def build_opener(*handlers: BaseHandler | Callable[[], BaseHandler]) -> OpenerDirector: ... if sys.platform == "win32": from nturl2path import pathname2url as pathname2url, url2pathname as url2pathname @@ -46,15 +30,15 @@ else: def url2pathname(pathname: str) -> str: ... def pathname2url(pathname: str) -> str: ... -def getproxies() -> Dict[str, str]: ... -def parse_http_list(s: str) -> List[str]: ... -def parse_keqv_list(l: List[str]) -> Dict[str, str]: ... +def getproxies() -> dict[str, str]: ... +def parse_http_list(s: str) -> list[str]: ... +def parse_keqv_list(l: list[str]) -> dict[str, str]: ... if sys.platform == "win32" or sys.platform == "darwin": - def proxy_bypass(host: str) -> Any: ... # Undocumented + def proxy_bypass(host: str) -> Any: ... # undocumented else: - def proxy_bypass(host: str, proxies: Optional[Mapping[str, str]] = ...) -> Any: ... # Undocumented + def proxy_bypass(host: str, proxies: Mapping[str, str] | None = ...) -> Any: ... # undocumented class Request: @property @@ -67,20 +51,20 @@ class Request: host: str origin_req_host: str selector: str - data: Optional[bytes] - headers: Dict[str, str] - unredirected_hdrs: Dict[str, str] + data: bytes | None + headers: dict[str, str] + unredirected_hdrs: dict[str, str] unverifiable: bool - method: Optional[str] - timeout: Optional[float] # Undocumented, only set after __init__() by OpenerDirector.open() + method: str | None + timeout: float | None # Undocumented, only set after __init__() by OpenerDirector.open() def __init__( self, url: str, - data: Optional[bytes] = ..., - headers: Dict[str, str] = ..., - origin_req_host: Optional[str] = ..., + data: bytes | None = ..., + headers: dict[str, str] = ..., + origin_req_host: str | None = ..., unverifiable: bool = ..., - method: Optional[str] = ..., + method: str | None = ..., ) -> None: ... def get_method(self) -> str: ... def add_header(self, key: str, val: str) -> None: ... @@ -90,16 +74,16 @@ class Request: def get_full_url(self) -> str: ... def set_proxy(self, host: str, type: str) -> None: ... @overload - def get_header(self, header_name: str) -> Optional[str]: ... + def get_header(self, header_name: str) -> str | None: ... @overload - def get_header(self, header_name: str, default: _T) -> Union[str, _T]: ... - def header_items(self) -> List[Tuple[str, str]]: ... + def get_header(self, header_name: str, default: _T) -> str | _T: ... + def header_items(self) -> list[tuple[str, str]]: ... def has_proxy(self) -> bool: ... class OpenerDirector: - addheaders: List[Tuple[str, str]] + addheaders: list[tuple[str, str]] def add_handler(self, handler: BaseHandler) -> None: ... - def open(self, fullurl: Union[str, Request], data: Optional[bytes] = ..., timeout: Optional[float] = ...) -> _UrlopenRet: ... + def open(self, fullurl: str | Request, data: bytes | None = ..., timeout: float | None = ...) -> _UrlopenRet: ... def error(self, proto: str, *args: Any) -> _UrlopenRet: ... def close(self) -> None: ... @@ -111,7 +95,7 @@ class BaseHandler: class HTTPDefaultErrorHandler(BaseHandler): def http_error_default( - self, req: Request, fp: IO[bytes], code: int, msg: str, hdrs: Mapping[str, str] + self, req: Request, fp: IO[bytes], code: int, msg: str, hdrs: HTTPMessage ) -> HTTPError: ... # undocumented class HTTPRedirectHandler(BaseHandler): @@ -119,96 +103,80 @@ class HTTPRedirectHandler(BaseHandler): max_repeats: ClassVar[int] # undocumented inf_msg: ClassVar[str] # undocumented def redirect_request( - self, req: Request, fp: IO[str], code: int, msg: str, headers: Mapping[str, str], newurl: str - ) -> Optional[Request]: ... - def http_error_301( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... - def http_error_302( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... - def http_error_303( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... - def http_error_307( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... + self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage, newurl: str + ) -> Request | None: ... + def http_error_301(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... + def http_error_302(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... + def http_error_303(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... + def http_error_307(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... class HTTPCookieProcessor(BaseHandler): cookiejar: CookieJar - def __init__(self, cookiejar: Optional[CookieJar] = ...) -> None: ... + def __init__(self, cookiejar: CookieJar | None = ...) -> None: ... def http_request(self, request: Request) -> Request: ... # undocumented def http_response(self, request: Request, response: HTTPResponse) -> HTTPResponse: ... # undocumented def https_request(self, request: Request) -> Request: ... # undocumented def https_response(self, request: Request, response: HTTPResponse) -> HTTPResponse: ... # undocumented class ProxyHandler(BaseHandler): - def __init__(self, proxies: Optional[Dict[str, str]] = ...) -> None: ... - def proxy_open(self, req: Request, proxy: str, type: str) -> Optional[_UrlopenRet]: ... # undocumented + def __init__(self, proxies: dict[str, str] | None = ...) -> None: ... + def proxy_open(self, req: Request, proxy: str, type: str) -> _UrlopenRet | None: ... # undocumented # TODO add a method for every (common) proxy protocol class HTTPPasswordMgr: - def add_password(self, realm: str, uri: Union[str, Sequence[str]], user: str, passwd: str) -> None: ... - def find_user_password(self, realm: str, authuri: str) -> Tuple[Optional[str], Optional[str]]: ... + def add_password(self, realm: str, uri: str | Sequence[str], user: str, passwd: str) -> None: ... + def find_user_password(self, realm: str, authuri: str) -> tuple[str | None, str | None]: ... def is_suburi(self, base: str, test: str) -> bool: ... # undocumented def reduce_uri(self, uri: str, default_port: bool = ...) -> str: ... # undocumented class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): - def add_password(self, realm: Optional[str], uri: Union[str, Sequence[str]], user: str, passwd: str) -> None: ... - def find_user_password(self, realm: Optional[str], authuri: str) -> Tuple[Optional[str], Optional[str]]: ... + def add_password(self, realm: str | None, uri: str | Sequence[str], user: str, passwd: str) -> None: ... + def find_user_password(self, realm: str | None, authuri: str) -> tuple[str | None, str | None]: ... class HTTPPasswordMgrWithPriorAuth(HTTPPasswordMgrWithDefaultRealm): def add_password( - self, realm: Optional[str], uri: Union[str, Sequence[str]], user: str, passwd: str, is_authenticated: bool = ... + self, realm: str | None, uri: str | Sequence[str], user: str, passwd: str, is_authenticated: bool = ... ) -> None: ... - def update_authenticated(self, uri: Union[str, Sequence[str]], is_authenticated: bool = ...) -> None: ... + def update_authenticated(self, uri: str | Sequence[str], is_authenticated: bool = ...) -> None: ... def is_authenticated(self, authuri: str) -> bool: ... class AbstractBasicAuthHandler: rx: ClassVar[Pattern[str]] # undocumented passwd: HTTPPasswordMgr - add_password: Callable[[str, Union[str, Sequence[str]], str, str], None] - def __init__(self, password_mgr: Optional[HTTPPasswordMgr] = ...) -> None: ... - def http_error_auth_reqed(self, authreq: str, host: str, req: Request, headers: Mapping[str, str]) -> None: ... + add_password: Callable[[str, str | Sequence[str], str, str], None] + def __init__(self, password_mgr: HTTPPasswordMgr | None = ...) -> None: ... + def http_error_auth_reqed(self, authreq: str, host: str, req: Request, headers: HTTPMessage) -> None: ... def http_request(self, req: Request) -> Request: ... # undocumented def http_response(self, req: Request, response: HTTPResponse) -> HTTPResponse: ... # undocumented def https_request(self, req: Request) -> Request: ... # undocumented def https_response(self, req: Request, response: HTTPResponse) -> HTTPResponse: ... # undocumented - def retry_http_basic_auth(self, host: str, req: Request, realm: str) -> Optional[_UrlopenRet]: ... # undocumented + def retry_http_basic_auth(self, host: str, req: Request, realm: str) -> _UrlopenRet | None: ... # undocumented class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): auth_header: ClassVar[str] # undocumented - def http_error_401( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... + def http_error_401(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): auth_header: ClassVar[str] - def http_error_407( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... + def http_error_407(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... class AbstractDigestAuthHandler: - def __init__(self, passwd: Optional[HTTPPasswordMgr] = ...) -> None: ... + def __init__(self, passwd: HTTPPasswordMgr | None = ...) -> None: ... def reset_retry_count(self) -> None: ... - def http_error_auth_reqed(self, auth_header: str, host: str, req: Request, headers: Mapping[str, str]) -> None: ... - def retry_http_digest_auth(self, req: Request, auth: str) -> Optional[_UrlopenRet]: ... + def http_error_auth_reqed(self, auth_header: str, host: str, req: Request, headers: HTTPMessage) -> None: ... + def retry_http_digest_auth(self, req: Request, auth: str) -> _UrlopenRet | None: ... def get_cnonce(self, nonce: str) -> str: ... def get_authorization(self, req: Request, chal: Mapping[str, str]) -> str: ... - def get_algorithm_impls(self, algorithm: str) -> Tuple[Callable[[str], str], Callable[[str, str], str]]: ... - def get_entity_digest(self, data: Optional[bytes], chal: Mapping[str, str]) -> Optional[str]: ... + def get_algorithm_impls(self, algorithm: str) -> tuple[Callable[[str], str], Callable[[str, str], str]]: ... + def get_entity_digest(self, data: bytes | None, chal: Mapping[str, str]) -> str | None: ... class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): auth_header: ClassVar[str] # undocumented - def http_error_401( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... + def http_error_401(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): auth_header: ClassVar[str] # undocumented - def http_error_407( - self, req: Request, fp: IO[str], code: int, msg: int, headers: Mapping[str, str] - ) -> Optional[_UrlopenRet]: ... + def http_error_407(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... class AbstractHTTPHandler(BaseHandler): # undocumented def __init__(self, debuglevel: int = ...) -> None: ... @@ -222,13 +190,13 @@ class HTTPHandler(AbstractHTTPHandler): class HTTPSHandler(AbstractHTTPHandler): def __init__( - self, debuglevel: int = ..., context: Optional[ssl.SSLContext] = ..., check_hostname: Optional[bool] = ... + self, debuglevel: int = ..., context: ssl.SSLContext | None = ..., check_hostname: bool | None = ... ) -> None: ... def https_open(self, req: Request) -> HTTPResponse: ... def https_request(self, request: Request) -> Request: ... # undocumented class FileHandler(BaseHandler): - names: ClassVar[Optional[Tuple[str, ...]]] # undocumented + names: ClassVar[Tuple[str, ...] | None] # undocumented def file_open(self, req: Request) -> addinfourl: ... def get_names(self) -> Tuple[str, ...]: ... # undocumented def open_local_file(self, req: Request) -> addinfourl: ... # undocumented @@ -238,14 +206,14 @@ class DataHandler(BaseHandler): class ftpwrapper: # undocumented def __init__( - self, user: str, passwd: str, host: str, port: int, dirs: str, timeout: Optional[float] = ..., persistent: bool = ... + self, user: str, passwd: str, host: str, port: int, dirs: str, timeout: float | None = ..., persistent: bool = ... ) -> None: ... def close(self) -> None: ... def endtransfer(self) -> None: ... def file_close(self) -> None: ... def init(self) -> None: ... def real_close(self) -> None: ... - def retrfile(self, file: str, type: str) -> Tuple[addclosehook, int]: ... + def retrfile(self, file: str, type: str) -> tuple[addclosehook, int]: ... class FTPHandler(BaseHandler): def ftp_open(self, req: Request) -> addinfourl: ... @@ -271,91 +239,87 @@ class HTTPErrorProcessor(BaseHandler): def urlretrieve( url: str, - filename: Optional[Union[str, os.PathLike[Any]]] = ..., - reporthook: Optional[Callable[[int, int, int], None]] = ..., - data: Optional[bytes] = ..., -) -> Tuple[str, HTTPMessage]: ... + filename: StrOrBytesPath | None = ..., + reporthook: Callable[[int, int, int], None] | None = ..., + data: bytes | None = ..., +) -> tuple[str, HTTPMessage]: ... def urlcleanup() -> None: ... class URLopener: version: ClassVar[str] - def __init__(self, proxies: Optional[Dict[str, str]] = ..., **x509: str) -> None: ... - def open(self, fullurl: str, data: Optional[bytes] = ...) -> _UrlopenRet: ... - def open_unknown(self, fullurl: str, data: Optional[bytes] = ...) -> _UrlopenRet: ... + def __init__(self, proxies: dict[str, str] | None = ..., **x509: str) -> None: ... + def open(self, fullurl: str, data: bytes | None = ...) -> _UrlopenRet: ... + def open_unknown(self, fullurl: str, data: bytes | None = ...) -> _UrlopenRet: ... def retrieve( self, url: str, - filename: Optional[str] = ..., - reporthook: Optional[Callable[[int, int, int], None]] = ..., - data: Optional[bytes] = ..., - ) -> Tuple[str, Optional[Message]]: ... - def addheader(self, *args: Tuple[str, str]) -> None: ... # undocumented + filename: str | None = ..., + reporthook: Callable[[int, int, int], None] | None = ..., + data: bytes | None = ..., + ) -> tuple[str, Message | None]: ... + def addheader(self, *args: tuple[str, str]) -> None: ... # undocumented def cleanup(self) -> None: ... # undocumented def close(self) -> None: ... # undocumented def http_error( - self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ... + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... ) -> _UrlopenRet: ... # undocumented def http_error_default( - self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str] + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage ) -> _UrlopenRet: ... # undocumented - def open_data(self, url: str, data: Optional[bytes] = ...) -> addinfourl: ... # undocumented + def open_data(self, url: str, data: bytes | None = ...) -> addinfourl: ... # undocumented def open_file(self, url: str) -> addinfourl: ... # undocumented def open_ftp(self, url: str) -> addinfourl: ... # undocumented - def open_http(self, url: str, data: Optional[bytes] = ...) -> _UrlopenRet: ... # undocumented - def open_https(self, url: str, data: Optional[bytes] = ...) -> _UrlopenRet: ... # undocumented + def open_http(self, url: str, data: bytes | None = ...) -> _UrlopenRet: ... # undocumented + def open_https(self, url: str, data: bytes | None = ...) -> _UrlopenRet: ... # undocumented def open_local_file(self, url: str) -> addinfourl: ... # undocumented - def open_unknown_proxy(self, proxy: str, fullurl: str, data: Optional[bytes] = ...) -> None: ... # undocumented + def open_unknown_proxy(self, proxy: str, fullurl: str, data: bytes | None = ...) -> None: ... # undocumented class FancyURLopener(URLopener): - def prompt_user_passwd(self, host: str, realm: str) -> Tuple[str, str]: ... - def get_user_passwd(self, host: str, realm: str, clear_cache: int = ...) -> Tuple[str, str]: ... # undocumented + def prompt_user_passwd(self, host: str, realm: str) -> tuple[str, str]: ... + def get_user_passwd(self, host: str, realm: str, clear_cache: int = ...) -> tuple[str, str]: ... # undocumented def http_error_301( - self, url: str, fp: IO[str], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ... - ) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... + ) -> _UrlopenRet | addinfourl | None: ... # undocumented def http_error_302( - self, url: str, fp: IO[str], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ... - ) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... + ) -> _UrlopenRet | addinfourl | None: ... # undocumented def http_error_303( - self, url: str, fp: IO[str], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ... - ) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... + ) -> _UrlopenRet | addinfourl | None: ... # undocumented def http_error_307( - self, url: str, fp: IO[str], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] = ... - ) -> Optional[Union[_UrlopenRet, addinfourl]]: ... # undocumented + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... + ) -> _UrlopenRet | addinfourl | None: ... # undocumented def http_error_401( self, url: str, - fp: IO[str], + fp: IO[bytes], errcode: int, errmsg: str, - headers: Mapping[str, str], - data: Optional[bytes] = ..., + headers: HTTPMessage, + data: bytes | None = ..., retry: bool = ..., - ) -> Optional[_UrlopenRet]: ... # undocumented + ) -> _UrlopenRet | None: ... # undocumented def http_error_407( self, url: str, - fp: IO[str], + fp: IO[bytes], errcode: int, errmsg: str, - headers: Mapping[str, str], - data: Optional[bytes] = ..., + headers: HTTPMessage, + data: bytes | None = ..., retry: bool = ..., - ) -> Optional[_UrlopenRet]: ... # undocumented + ) -> _UrlopenRet | None: ... # undocumented def http_error_default( - self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: Mapping[str, str] + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage ) -> addinfourl: ... # undocumented def redirect_internal( - self, url: str, fp: IO[str], errcode: int, errmsg: str, headers: Mapping[str, str], data: Optional[bytes] - ) -> Optional[_UrlopenRet]: ... # undocumented - def retry_http_basic_auth( - self, url: str, realm: str, data: Optional[bytes] = ... - ) -> Optional[_UrlopenRet]: ... # undocumented - def retry_https_basic_auth( - self, url: str, realm: str, data: Optional[bytes] = ... - ) -> Optional[_UrlopenRet]: ... # undocumented + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None + ) -> _UrlopenRet | None: ... # undocumented + def retry_http_basic_auth(self, url: str, realm: str, data: bytes | None = ...) -> _UrlopenRet | None: ... # undocumented + def retry_https_basic_auth(self, url: str, realm: str, data: bytes | None = ...) -> _UrlopenRet | None: ... # undocumented def retry_proxy_http_basic_auth( - self, url: str, realm: str, data: Optional[bytes] = ... - ) -> Optional[_UrlopenRet]: ... # undocumented + self, url: str, realm: str, data: bytes | None = ... + ) -> _UrlopenRet | None: ... # undocumented def retry_proxy_https_basic_auth( - self, url: str, realm: str, data: Optional[bytes] = ... - ) -> Optional[_UrlopenRet]: ... # undocumented + self, url: str, realm: str, data: bytes | None = ... + ) -> _UrlopenRet | None: ... # undocumented diff --git a/mypy/typeshed/stdlib/urllib/response.pyi b/mypy/typeshed/stdlib/urllib/response.pyi index c8f9d75d2f14..647ebf874432 100644 --- a/mypy/typeshed/stdlib/urllib/response.pyi +++ b/mypy/typeshed/stdlib/urllib/response.pyi @@ -1,15 +1,17 @@ +import sys +from _typeshed import Self from email.message import Message from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, List, Optional, Tuple, Type, TypeVar +from typing import IO, Any, BinaryIO, Callable, Iterable, Tuple, Type, TypeVar _AIUT = TypeVar("_AIUT", bound=addbase) class addbase(BinaryIO): fp: IO[bytes] def __init__(self, fp: IO[bytes]) -> None: ... - def __enter__(self: _AIUT) -> _AIUT: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, type: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType] + self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... def __iter__(self: _AIUT) -> _AIUT: ... def __next__(self) -> bytes: ... @@ -24,11 +26,11 @@ class addbase(BinaryIO): def read(self, n: int = ...) -> bytes: ... def readable(self) -> bool: ... def readline(self, limit: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> List[bytes]: ... + def readlines(self, hint: int = ...) -> list[bytes]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... - def truncate(self, size: Optional[int] = ...) -> int: ... + def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... def write(self, s: bytes) -> int: ... def writelines(self, lines: Iterable[bytes]) -> None: ... @@ -45,7 +47,10 @@ class addinfo(addbase): class addinfourl(addinfo): url: str - code: int - def __init__(self, fp: IO[bytes], headers: Message, url: str, code: Optional[int] = ...) -> None: ... + code: int | None + if sys.version_info >= (3, 9): + @property + def status(self) -> int | None: ... + def __init__(self, fp: IO[bytes], headers: Message, url: str, code: int | None = ...) -> None: ... def geturl(self) -> str: ... - def getcode(self) -> int: ... + def getcode(self) -> int | None: ... diff --git a/mypy/typeshed/stdlib/urllib/robotparser.pyi b/mypy/typeshed/stdlib/urllib/robotparser.pyi index 382dcee0e859..361126327993 100644 --- a/mypy/typeshed/stdlib/urllib/robotparser.pyi +++ b/mypy/typeshed/stdlib/urllib/robotparser.pyi @@ -1,5 +1,5 @@ import sys -from typing import Iterable, List, NamedTuple, Optional +from typing import Iterable, NamedTuple class _RequestRate(NamedTuple): requests: int @@ -13,7 +13,7 @@ class RobotFileParser: def can_fetch(self, useragent: str, url: str) -> bool: ... def mtime(self) -> int: ... def modified(self) -> None: ... - def crawl_delay(self, useragent: str) -> Optional[str]: ... - def request_rate(self, useragent: str) -> Optional[_RequestRate]: ... + def crawl_delay(self, useragent: str) -> str | None: ... + def request_rate(self, useragent: str) -> _RequestRate | None: ... if sys.version_info >= (3, 8): - def site_maps(self) -> Optional[List[str]]: ... + def site_maps(self) -> list[str] | None: ... diff --git a/mypy/typeshed/stdlib/uu.pyi b/mypy/typeshed/stdlib/uu.pyi index 2bb2c2a1c90e..aacd458c02c7 100644 --- a/mypy/typeshed/stdlib/uu.pyi +++ b/mypy/typeshed/stdlib/uu.pyi @@ -1,16 +1,16 @@ import sys -from typing import BinaryIO, Optional, Text, Union +from typing import BinaryIO, Union -_File = Union[Text, BinaryIO] +_File = Union[str, BinaryIO] class Error(Exception): ... if sys.version_info >= (3, 7): def encode( - in_file: _File, out_file: _File, name: Optional[str] = ..., mode: Optional[int] = ..., *, backtick: bool = ... + in_file: _File, out_file: _File, name: str | None = ..., mode: int | None = ..., *, backtick: bool = ... ) -> None: ... else: - def encode(in_file: _File, out_file: _File, name: Optional[str] = ..., mode: Optional[int] = ...) -> None: ... + def encode(in_file: _File, out_file: _File, name: str | None = ..., mode: int | None = ...) -> None: ... -def decode(in_file: _File, out_file: Optional[_File] = ..., mode: Optional[int] = ..., quiet: int = ...) -> None: ... +def decode(in_file: _File, out_file: _File | None = ..., mode: int | None = ..., quiet: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/uuid.pyi b/mypy/typeshed/stdlib/uuid.pyi index 68b235162210..da13d819fbdf 100644 --- a/mypy/typeshed/stdlib/uuid.pyi +++ b/mypy/typeshed/stdlib/uuid.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Optional, Text, Tuple +from typing import Any, Tuple # Because UUID has properties called int and bytes we need to rename these temporarily. _Int = int @@ -17,12 +17,12 @@ class UUID: if sys.version_info >= (3, 7): def __init__( self, - hex: Optional[Text] = ..., - bytes: Optional[_Bytes] = ..., - bytes_le: Optional[_Bytes] = ..., - fields: Optional[_FieldsType] = ..., - int: Optional[_Int] = ..., - version: Optional[_Int] = ..., + hex: str | None = ..., + bytes: _Bytes | None = ..., + bytes_le: _Bytes | None = ..., + fields: _FieldsType | None = ..., + int: _Int | None = ..., + version: _Int | None = ..., *, is_safe: SafeUUID = ..., ) -> None: ... @@ -31,12 +31,12 @@ class UUID: else: def __init__( self, - hex: Optional[Text] = ..., - bytes: Optional[_Bytes] = ..., - bytes_le: Optional[_Bytes] = ..., - fields: Optional[_FieldsType] = ..., - int: Optional[_Int] = ..., - version: Optional[_Int] = ..., + hex: str | None = ..., + bytes: _Bytes | None = ..., + bytes_le: _Bytes | None = ..., + fields: _FieldsType | None = ..., + int: _Int | None = ..., + version: _Int | None = ..., ) -> None: ... @property def bytes(self) -> _Bytes: ... @@ -69,34 +69,16 @@ class UUID: @property def variant(self) -> str: ... @property - def version(self) -> Optional[_Int]: ... + def version(self) -> _Int | None: ... def __int__(self) -> _Int: ... - if sys.version_info >= (3,): - def __eq__(self, other: Any) -> bool: ... - def __lt__(self, other: Any) -> bool: ... - def __le__(self, other: Any) -> bool: ... - def __gt__(self, other: Any) -> bool: ... - def __ge__(self, other: Any) -> bool: ... - else: - def get_bytes(self) -> _Bytes: ... - def get_bytes_le(self) -> _Bytes: ... - def get_clock_seq(self) -> _Int: ... - def get_clock_seq_hi_variant(self) -> _Int: ... - def get_clock_seq_low(self) -> _Int: ... - def get_fields(self) -> _FieldsType: ... - def get_hex(self) -> str: ... - def get_node(self) -> _Int: ... - def get_time(self) -> _Int: ... - def get_time_hi_version(self) -> _Int: ... - def get_time_low(self) -> _Int: ... - def get_time_mid(self) -> _Int: ... - def get_urn(self) -> str: ... - def get_variant(self) -> str: ... - def get_version(self) -> Optional[_Int]: ... - def __cmp__(self, other: Any) -> _Int: ... + def __eq__(self, other: Any) -> bool: ... + def __lt__(self, other: Any) -> bool: ... + def __le__(self, other: Any) -> bool: ... + def __gt__(self, other: Any) -> bool: ... + def __ge__(self, other: Any) -> bool: ... def getnode() -> int: ... -def uuid1(node: Optional[_Int] = ..., clock_seq: Optional[_Int] = ...) -> UUID: ... +def uuid1(node: _Int | None = ..., clock_seq: _Int | None = ...) -> UUID: ... def uuid3(namespace: UUID, name: str) -> UUID: ... def uuid4() -> UUID: ... def uuid5(namespace: UUID, name: str) -> UUID: ... diff --git a/mypy/typeshed/stdlib/venv/__init__.pyi b/mypy/typeshed/stdlib/venv/__init__.pyi index d44d17ea9785..25cf615a3243 100644 --- a/mypy/typeshed/stdlib/venv/__init__.pyi +++ b/mypy/typeshed/stdlib/venv/__init__.pyi @@ -1,7 +1,7 @@ import sys -from _typeshed import AnyPath +from _typeshed import StrOrBytesPath from types import SimpleNamespace -from typing import Optional, Sequence +from typing import Sequence class EnvBuilder: system_site_packages: bool @@ -9,7 +9,7 @@ class EnvBuilder: symlinks: bool upgrade: bool with_pip: bool - prompt: Optional[str] + prompt: str | None if sys.version_info >= (3, 9): def __init__( @@ -19,7 +19,7 @@ class EnvBuilder: symlinks: bool = ..., upgrade: bool = ..., with_pip: bool = ..., - prompt: Optional[str] = ..., + prompt: str | None = ..., upgrade_deps: bool = ..., ) -> None: ... else: @@ -30,13 +30,15 @@ class EnvBuilder: symlinks: bool = ..., upgrade: bool = ..., with_pip: bool = ..., - prompt: Optional[str] = ..., + prompt: str | None = ..., ) -> None: ... - def create(self, env_dir: AnyPath) -> None: ... - def clear_directory(self, path: AnyPath) -> None: ... # undocumented - def ensure_directories(self, env_dir: AnyPath) -> SimpleNamespace: ... + def create(self, env_dir: StrOrBytesPath) -> None: ... + def clear_directory(self, path: StrOrBytesPath) -> None: ... # undocumented + def ensure_directories(self, env_dir: StrOrBytesPath) -> SimpleNamespace: ... def create_configuration(self, context: SimpleNamespace) -> None: ... - def symlink_or_copy(self, src: AnyPath, dst: AnyPath, relative_symlinks_ok: bool = ...) -> None: ... # undocumented + def symlink_or_copy( + self, src: StrOrBytesPath, dst: StrOrBytesPath, relative_symlinks_ok: bool = ... + ) -> None: ... # undocumented def setup_python(self, context: SimpleNamespace) -> None: ... def _setup_pip(self, context: SimpleNamespace) -> None: ... # undocumented def setup_scripts(self, context: SimpleNamespace) -> None: ... @@ -48,23 +50,23 @@ class EnvBuilder: if sys.version_info >= (3, 9): def create( - env_dir: AnyPath, + env_dir: StrOrBytesPath, system_site_packages: bool = ..., clear: bool = ..., symlinks: bool = ..., with_pip: bool = ..., - prompt: Optional[str] = ..., + prompt: str | None = ..., upgrade_deps: bool = ..., ) -> None: ... else: def create( - env_dir: AnyPath, + env_dir: StrOrBytesPath, system_site_packages: bool = ..., clear: bool = ..., symlinks: bool = ..., with_pip: bool = ..., - prompt: Optional[str] = ..., + prompt: str | None = ..., ) -> None: ... -def main(args: Optional[Sequence[str]] = ...) -> None: ... +def main(args: Sequence[str] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/warnings.pyi b/mypy/typeshed/stdlib/warnings.pyi index 0e64ec574775..b1c9f4dda8ed 100644 --- a/mypy/typeshed/stdlib/warnings.pyi +++ b/mypy/typeshed/stdlib/warnings.pyi @@ -1,73 +1,62 @@ -import sys +from _warnings import warn as warn, warn_explicit as warn_explicit from types import ModuleType, TracebackType -from typing import Any, List, Optional, TextIO, Type, Union, overload +from typing import Any, Sequence, TextIO, Type, overload from typing_extensions import Literal -from _warnings import warn as warn, warn_explicit as warn_explicit +_ActionKind = Literal["default", "error", "ignore", "always", "module", "once"] + +filters: Sequence[tuple[str, str | None, Type[Warning], str | None, int]] # undocumented, do not mutate def showwarning( - message: Union[Warning, str], - category: Type[Warning], - filename: str, - lineno: int, - file: Optional[TextIO] = ..., - line: Optional[str] = ..., + message: Warning | str, category: Type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... ) -> None: ... -def formatwarning( - message: Union[Warning, str], category: Type[Warning], filename: str, lineno: int, line: Optional[str] = ... -) -> str: ... +def formatwarning(message: Warning | str, category: Type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... def filterwarnings( - action: str, message: str = ..., category: Type[Warning] = ..., module: str = ..., lineno: int = ..., append: bool = ... + action: _ActionKind, + message: str = ..., + category: Type[Warning] = ..., + module: str = ..., + lineno: int = ..., + append: bool = ..., ) -> None: ... -def simplefilter(action: str, category: Type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... +def simplefilter(action: _ActionKind, category: Type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... def resetwarnings() -> None: ... class _OptionError(Exception): ... class WarningMessage: - message: Union[Warning, str] + message: Warning | str category: Type[Warning] filename: str lineno: int - file: Optional[TextIO] - line: Optional[str] - if sys.version_info >= (3, 6): - source: Optional[Any] - def __init__( - self, - message: Union[Warning, str], - category: Type[Warning], - filename: str, - lineno: int, - file: Optional[TextIO] = ..., - line: Optional[str] = ..., - source: Optional[Any] = ..., - ) -> None: ... - else: - def __init__( - self, - message: Union[Warning, str], - category: Type[Warning], - filename: str, - lineno: int, - file: Optional[TextIO] = ..., - line: Optional[str] = ..., - ) -> None: ... + file: TextIO | None + line: str | None + source: Any | None + def __init__( + self, + message: Warning | str, + category: Type[Warning], + filename: str, + lineno: int, + file: TextIO | None = ..., + line: str | None = ..., + source: Any | None = ..., + ) -> None: ... class catch_warnings: @overload - def __new__(cls, *, record: Literal[False] = ..., module: Optional[ModuleType] = ...) -> _catch_warnings_without_records: ... + def __new__(cls, *, record: Literal[False] = ..., module: ModuleType | None = ...) -> _catch_warnings_without_records: ... @overload - def __new__(cls, *, record: Literal[True], module: Optional[ModuleType] = ...) -> _catch_warnings_with_records: ... + def __new__(cls, *, record: Literal[True], module: ModuleType | None = ...) -> _catch_warnings_with_records: ... @overload - def __new__(cls, *, record: bool, module: Optional[ModuleType] = ...) -> catch_warnings: ... - def __enter__(self) -> Optional[List[WarningMessage]]: ... + def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... + def __enter__(self) -> list[WarningMessage] | None: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _catch_warnings_without_records(catch_warnings): def __enter__(self) -> None: ... class _catch_warnings_with_records(catch_warnings): - def __enter__(self) -> List[WarningMessage]: ... + def __enter__(self) -> list[WarningMessage]: ... diff --git a/mypy/typeshed/stdlib/wave.pyi b/mypy/typeshed/stdlib/wave.pyi index d415630427da..3ce1b88a6835 100644 --- a/mypy/typeshed/stdlib/wave.pyi +++ b/mypy/typeshed/stdlib/wave.pyi @@ -1,30 +1,26 @@ import sys -from typing import IO, Any, BinaryIO, NamedTuple, NoReturn, Optional, Text, Tuple, Union +from _typeshed import Self +from typing import IO, Any, BinaryIO, NamedTuple, NoReturn, Union -_File = Union[Text, IO[bytes]] +_File = Union[str, IO[bytes]] class Error(Exception): ... WAVE_FORMAT_PCM: int -if sys.version_info >= (3, 0): - class _wave_params(NamedTuple): - nchannels: int - sampwidth: int - framerate: int - nframes: int - comptype: str - compname: str - -else: - _wave_params = Tuple[int, int, int, int, str, str] +class _wave_params(NamedTuple): + nchannels: int + sampwidth: int + framerate: int + nframes: int + comptype: str + compname: str class Wave_read: def __init__(self, f: _File) -> None: ... - if sys.version_info >= (3, 0): - def __enter__(self) -> Wave_read: ... - def __exit__(self, *args: Any) -> None: ... - def getfp(self) -> Optional[BinaryIO]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: Any) -> None: ... + def getfp(self) -> BinaryIO | None: ... def rewind(self) -> None: ... def close(self) -> None: ... def tell(self) -> int: ... @@ -42,9 +38,8 @@ class Wave_read: class Wave_write: def __init__(self, f: _File) -> None: ... - if sys.version_info >= (3, 0): - def __enter__(self) -> Wave_write: ... - def __exit__(self, *args: Any) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: Any) -> None: ... def setnchannels(self, nchannels: int) -> None: ... def getnchannels(self) -> int: ... def setsampwidth(self, sampwidth: int) -> None: ... @@ -68,7 +63,7 @@ class Wave_write: def close(self) -> None: ... # Returns a Wave_read if mode is rb and Wave_write if mode is wb -def open(f: _File, mode: Optional[str] = ...) -> Any: ... +def open(f: _File, mode: str | None = ...) -> Any: ... if sys.version_info < (3, 9): openfp = open diff --git a/mypy/typeshed/stdlib/weakref.pyi b/mypy/typeshed/stdlib/weakref.pyi index b43b634d6216..dbb6b49f2f2e 100644 --- a/mypy/typeshed/stdlib/weakref.pyi +++ b/mypy/typeshed/stdlib/weakref.pyi @@ -1,23 +1,5 @@ -import sys -import types from _weakrefset import WeakSet as WeakSet -from typing import ( - Any, - Callable, - Dict, - Generic, - Iterable, - Iterator, - List, - Mapping, - MutableMapping, - Optional, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, Tuple, Type, TypeVar, overload from _weakref import ( CallableProxyType as CallableProxyType, @@ -29,50 +11,42 @@ from _weakref import ( ref as ref, ) -if sys.version_info < (3, 0): - from exceptions import ReferenceError as ReferenceError - _S = TypeVar("_S") _T = TypeVar("_T") _KT = TypeVar("_KT") _VT = TypeVar("_VT") +_CallableT = TypeVar("_CallableT", bound=Callable[..., Any]) ProxyTypes: Tuple[Type[Any], ...] -if sys.version_info >= (3, 4): - class WeakMethod(ref[types.MethodType]): - def __new__(cls, meth: types.MethodType, callback: Optional[Callable[[types.MethodType], Any]] = ...) -> WeakMethod: ... - def __call__(self) -> Optional[types.MethodType]: ... +class WeakMethod(ref[_CallableT], Generic[_CallableT]): + def __new__(cls, meth: _CallableT, callback: Callable[[_CallableT], object] | None = ...) -> WeakMethod[_CallableT]: ... + def __call__(self) -> _CallableT | None: ... class WeakValueDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self) -> None: ... @overload - def __init__(self, __other: Union[Mapping[_KT, _VT], Iterable[Tuple[_KT, _VT]]], **kwargs: _VT) -> None: ... + def __init__(self, __other: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... def __delitem__(self, v: _KT) -> None: ... - if sys.version_info < (3, 0): - def has_key(self, key: object) -> bool: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... def __str__(self) -> str: ... def copy(self) -> WeakValueDictionary[_KT, _VT]: ... - if sys.version_info >= (3, 0): - # These are incompatible with Mapping - def keys(self) -> Iterator[_KT]: ... # type: ignore - def values(self) -> Iterator[_VT]: ... # type: ignore - def items(self) -> Iterator[Tuple[_KT, _VT]]: ... # type: ignore - else: - def keys(self) -> List[_KT]: ... - def values(self) -> List[_VT]: ... - def items(self) -> List[Tuple[_KT, _VT]]: ... - def iterkeys(self) -> Iterator[_KT]: ... - def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + # These are incompatible with Mapping + def keys(self) -> Iterator[_KT]: ... # type: ignore + def values(self) -> Iterator[_VT]: ... # type: ignore + def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ... - def valuerefs(self) -> List[KeyedRef[_KT, _VT]]: ... + def valuerefs(self) -> list[KeyedRef[_KT, _VT]]: ... + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... class KeyedRef(ref[_T], Generic[_KT, _T]): key: _KT @@ -84,37 +58,30 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self, dict: None = ...) -> None: ... @overload - def __init__(self, dict: Union[Mapping[_KT, _VT], Iterable[Tuple[_KT, _VT]]]) -> None: ... + def __init__(self, dict: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]]) -> None: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... def __delitem__(self, v: _KT) -> None: ... - if sys.version_info < (3, 0): - def has_key(self, key: object) -> bool: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... def __str__(self) -> str: ... def copy(self) -> WeakKeyDictionary[_KT, _VT]: ... - if sys.version_info >= (3, 0): - # These are incompatible with Mapping - def keys(self) -> Iterator[_KT]: ... # type: ignore - def values(self) -> Iterator[_VT]: ... # type: ignore - def items(self) -> Iterator[Tuple[_KT, _VT]]: ... # type: ignore - else: - def keys(self) -> List[_KT]: ... - def values(self) -> List[_VT]: ... - def items(self) -> List[Tuple[_KT, _VT]]: ... - def iterkeys(self) -> Iterator[_KT]: ... - def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... - def iterkeyrefs(self) -> Iterator[ref[_KT]]: ... - def keyrefs(self) -> List[ref[_KT]]: ... + # These are incompatible with Mapping + def keys(self) -> Iterator[_KT]: ... # type: ignore + def values(self) -> Iterator[_VT]: ... # type: ignore + def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore + def keyrefs(self) -> list[ref[_KT]]: ... + def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... + @overload + def pop(self, key: _KT) -> _VT: ... + @overload + def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... -if sys.version_info >= (3, 4): - class finalize: - def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... - def __call__(self, _: Any = ...) -> Optional[Any]: ... - def detach(self) -> Optional[Tuple[Any, Any, Tuple[Any, ...], Dict[str, Any]]]: ... - def peek(self) -> Optional[Tuple[Any, Any, Tuple[Any, ...], Dict[str, Any]]]: ... - alive: bool - atexit: bool +class finalize: + def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def __call__(self, _: Any = ...) -> Any | None: ... + def detach(self) -> tuple[Any, Any, Tuple[Any, ...], dict[str, Any]] | None: ... + def peek(self) -> tuple[Any, Any, Tuple[Any, ...], dict[str, Any]] | None: ... + alive: bool + atexit: bool diff --git a/mypy/typeshed/stdlib/webbrowser.pyi b/mypy/typeshed/stdlib/webbrowser.pyi index 322ec2764e39..c85288cc562f 100644 --- a/mypy/typeshed/stdlib/webbrowser.pyi +++ b/mypy/typeshed/stdlib/webbrowser.pyi @@ -1,82 +1,82 @@ import sys -from typing import Callable, List, Optional, Sequence, Text, Union +from typing import Callable, Sequence class Error(Exception): ... if sys.version_info >= (3, 7): def register( - name: Text, klass: Optional[Callable[[], BaseBrowser]], instance: Optional[BaseBrowser] = ..., *, preferred: bool = ... + name: str, klass: Callable[[], BaseBrowser] | None, instance: BaseBrowser | None = ..., *, preferred: bool = ... ) -> None: ... else: def register( - name: Text, klass: Optional[Callable[[], BaseBrowser]], instance: Optional[BaseBrowser] = ..., update_tryorder: int = ... + name: str, klass: Callable[[], BaseBrowser] | None, instance: BaseBrowser | None = ..., update_tryorder: int = ... ) -> None: ... -def get(using: Optional[Text] = ...) -> BaseBrowser: ... -def open(url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... -def open_new(url: Text) -> bool: ... -def open_new_tab(url: Text) -> bool: ... +def get(using: str | None = ...) -> BaseBrowser: ... +def open(url: str, new: int = ..., autoraise: bool = ...) -> bool: ... +def open_new(url: str) -> bool: ... +def open_new_tab(url: str) -> bool: ... class BaseBrowser: - args: List[str] + args: list[str] name: str basename: str - def __init__(self, name: Text = ...) -> None: ... - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... - def open_new(self, url: Text) -> bool: ... - def open_new_tab(self, url: Text) -> bool: ... + def __init__(self, name: str = ...) -> None: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... + def open_new(self, url: str) -> bool: ... + def open_new_tab(self, url: str) -> bool: ... class GenericBrowser(BaseBrowser): - args: List[str] + args: list[str] name: str basename: str - def __init__(self, name: Union[Text, Sequence[Text]]) -> None: ... - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def __init__(self, name: str | Sequence[str]) -> None: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class BackgroundBrowser(GenericBrowser): - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class UnixBrowser(BaseBrowser): - raise_opts: Optional[List[str]] + raise_opts: list[str] | None background: bool redirect_stdout: bool - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class Mozilla(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Galeon(UnixBrowser): - raise_opts: List[str] - remote_args: List[str] + raise_opts: list[str] + remote_args: list[str] remote_action: str remote_action_newwin: str background: bool class Chrome(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Opera(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Elinks(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str @@ -84,20 +84,20 @@ class Elinks(UnixBrowser): redirect_stdout: bool class Konqueror(BaseBrowser): - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class Grail(BaseBrowser): - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... if sys.platform == "win32": class WindowsDefault(BaseBrowser): - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... if sys.platform == "darwin": class MacOSX(BaseBrowser): name: str - def __init__(self, name: Text) -> None: ... - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def __init__(self, name: str) -> None: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class MacOSXOSAScript(BaseBrowser): - def __init__(self, name: Text) -> None: ... - def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + def __init__(self, name: str) -> None: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/winreg.pyi b/mypy/typeshed/stdlib/winreg.pyi index 8f25dd61a092..5fff1104e246 100644 --- a/mypy/typeshed/stdlib/winreg.pyi +++ b/mypy/typeshed/stdlib/winreg.pyi @@ -1,29 +1,31 @@ +from _typeshed import Self from types import TracebackType -from typing import Any, Optional, Tuple, Type, Union +from typing import Any, Type, Union +from typing_extensions import final _KeyType = Union[HKEYType, int] def CloseKey(__hkey: _KeyType) -> None: ... -def ConnectRegistry(__computer_name: Optional[str], __key: _KeyType) -> HKEYType: ... -def CreateKey(__key: _KeyType, __sub_key: Optional[str]) -> HKEYType: ... -def CreateKeyEx(key: _KeyType, sub_key: Optional[str], reserved: int = ..., access: int = ...) -> HKEYType: ... +def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... +def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... +def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... def DeleteValue(__key: _KeyType, __value: str) -> None: ... def EnumKey(__key: _KeyType, __index: int) -> str: ... -def EnumValue(__key: _KeyType, __index: int) -> Tuple[str, Any, int]: ... +def EnumValue(__key: _KeyType, __index: int) -> tuple[str, Any, int]: ... def ExpandEnvironmentStrings(__str: str) -> str: ... def FlushKey(__key: _KeyType) -> None: ... def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... -def QueryInfoKey(__key: _KeyType) -> Tuple[int, int, int]: ... -def QueryValue(__key: _KeyType, __sub_key: Optional[str]) -> str: ... -def QueryValueEx(__key: _KeyType, __name: str) -> Tuple[Any, int]: ... +def QueryInfoKey(__key: _KeyType) -> tuple[int, int, int]: ... +def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... +def QueryValueEx(__key: _KeyType, __name: str) -> tuple[Any, int]: ... def SaveKey(__key: _KeyType, __file_name: str) -> None: ... def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... def SetValueEx( - __key: _KeyType, __value_name: Optional[str], __reserved: Any, __type: int, __value: Union[str, int] + __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int ) -> None: ... # reserved is ignored def DisableReflectionKey(__key: _KeyType) -> None: ... def EnableReflectionKey(__key: _KeyType) -> None: ... @@ -87,12 +89,13 @@ REG_WHOLE_HIVE_VOLATILE: int # undocumented error = OSError # Though this class has a __name__ of PyHKEY, it's exposed as HKEYType for some reason +@final class HKEYType: def __bool__(self) -> bool: ... def __int__(self) -> int: ... - def __enter__(self) -> HKEYType: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] - ) -> Optional[bool]: ... + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... def Close(self) -> None: ... def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/winsound.pyi b/mypy/typeshed/stdlib/winsound.pyi index be9a8c660781..3d79f3b043f2 100644 --- a/mypy/typeshed/stdlib/winsound.pyi +++ b/mypy/typeshed/stdlib/winsound.pyi @@ -1,5 +1,5 @@ import sys -from typing import Optional, Union, overload +from typing import overload from typing_extensions import Literal if sys.platform == "win32": @@ -21,7 +21,7 @@ if sys.platform == "win32": def Beep(frequency: int, duration: int) -> None: ... # Can actually accept anything ORed with 4, and if not it's definitely str, but that's inexpressible @overload - def PlaySound(sound: Optional[bytes], flags: Literal[4]) -> None: ... + def PlaySound(sound: bytes | None, flags: Literal[4]) -> None: ... @overload - def PlaySound(sound: Optional[Union[str, bytes]], flags: int) -> None: ... + def PlaySound(sound: str | bytes | None, flags: int) -> None: ... def MessageBeep(type: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/wsgiref/handlers.pyi index ff764e434169..ac1e56b7664e 100644 --- a/mypy/typeshed/stdlib/wsgiref/handlers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/handlers.pyi @@ -1,7 +1,6 @@ -import sys from abc import abstractmethod from types import TracebackType -from typing import IO, Callable, Dict, List, MutableMapping, Optional, Text, Tuple, Type +from typing import IO, Callable, MutableMapping, Optional, Tuple, Type from .headers import Headers from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment @@ -9,29 +8,27 @@ from .util import FileWrapper _exc_info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] -def format_date_time(timestamp: Optional[float]) -> str: ... # undocumented - -if sys.version_info >= (3, 2): - def read_environ() -> Dict[str, str]: ... +def format_date_time(timestamp: float | None) -> str: ... # undocumented +def read_environ() -> dict[str, str]: ... class BaseHandler: - wsgi_version: Tuple[int, int] # undocumented + wsgi_version: tuple[int, int] # undocumented wsgi_multithread: bool wsgi_multiprocess: bool wsgi_run_once: bool origin_server: bool http_version: str - server_software: Optional[str] + server_software: str | None os_environ: MutableMapping[str, str] - wsgi_file_wrapper: Optional[Type[FileWrapper]] + wsgi_file_wrapper: Type[FileWrapper] | None headers_class: Type[Headers] # undocumented - traceback_limit: Optional[int] + traceback_limit: int | None error_status: str - error_headers: List[Tuple[Text, Text]] + error_headers: list[tuple[str, str]] error_body: bytes def run(self, application: WSGIApplication) -> None: ... def setup_environ(self) -> None: ... @@ -40,7 +37,7 @@ class BaseHandler: def set_content_length(self) -> None: ... def cleanup_headers(self) -> None: ... def start_response( - self, status: Text, headers: List[Tuple[Text, Text]], exc_info: Optional[_exc_info] = ... + self, status: str, headers: list[tuple[str, str]], exc_info: _exc_info | None = ... ) -> Callable[[bytes], None]: ... def send_preamble(self) -> None: ... def write(self, data: bytes) -> None: ... @@ -52,7 +49,7 @@ class BaseHandler: def client_is_modern(self) -> bool: ... def log_exception(self, exc_info: _exc_info) -> None: ... def handle_error(self) -> None: ... - def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... + def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> list[bytes]: ... @abstractmethod def _write(self, data: bytes) -> None: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/wsgiref/headers.pyi b/mypy/typeshed/stdlib/wsgiref/headers.pyi index c3e943200e40..531a521d3824 100644 --- a/mypy/typeshed/stdlib/wsgiref/headers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/headers.pyi @@ -1,31 +1,24 @@ -import sys -from typing import List, Optional, Pattern, Tuple, overload +from typing import List, Pattern, Tuple, overload _HeaderList = List[Tuple[str, str]] tspecials: Pattern[str] # undocumented class Headers: - if sys.version_info < (3, 5): - def __init__(self, headers: _HeaderList) -> None: ... - else: - def __init__(self, headers: Optional[_HeaderList] = ...) -> None: ... + def __init__(self, headers: _HeaderList | None = ...) -> None: ... def __len__(self) -> int: ... def __setitem__(self, name: str, val: str) -> None: ... def __delitem__(self, name: str) -> None: ... - def __getitem__(self, name: str) -> Optional[str]: ... - if sys.version_info < (3,): - def has_key(self, name: str) -> bool: ... + def __getitem__(self, name: str) -> str | None: ... def __contains__(self, name: str) -> bool: ... - def get_all(self, name: str) -> List[str]: ... + def get_all(self, name: str) -> list[str]: ... @overload def get(self, name: str, default: str) -> str: ... @overload - def get(self, name: str, default: Optional[str] = ...) -> Optional[str]: ... - def keys(self) -> List[str]: ... - def values(self) -> List[str]: ... + def get(self, name: str, default: str | None = ...) -> str | None: ... + def keys(self) -> list[str]: ... + def values(self) -> list[str]: ... def items(self) -> _HeaderList: ... - if sys.version_info >= (3,): - def __bytes__(self) -> bytes: ... + def __bytes__(self) -> bytes: ... def setdefault(self, name: str, value: str) -> str: ... - def add_header(self, _name: str, _value: Optional[str], **_params: Optional[str]) -> None: ... + def add_header(self, _name: str, _value: str | None, **_params: str | None) -> None: ... diff --git a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi index 4e0abd7e8e9d..76d0b269793d 100644 --- a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi +++ b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi @@ -1,14 +1,9 @@ -import sys -from typing import List, Optional, Type, TypeVar, overload +from http.server import BaseHTTPRequestHandler, HTTPServer +from typing import Type, TypeVar, overload from .handlers import SimpleHandler from .types import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment -if sys.version_info >= (3, 0): - from http.server import BaseHTTPRequestHandler, HTTPServer -else: - from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer - server_version: str # undocumented sys_version: str # undocumented software_version: str # undocumented @@ -18,11 +13,11 @@ class ServerHandler(SimpleHandler): # undocumented def close(self) -> None: ... class WSGIServer(HTTPServer): - application: Optional[WSGIApplication] + application: WSGIApplication | None base_environ: WSGIEnvironment # only available after call to setup_environ() def setup_environ(self) -> None: ... - def get_app(self) -> Optional[WSGIApplication]: ... - def set_app(self, application: Optional[WSGIApplication]) -> None: ... + def get_app(self) -> WSGIApplication | None: ... + def set_app(self, application: WSGIApplication | None) -> None: ... class WSGIRequestHandler(BaseHTTPRequestHandler): server_version: str @@ -30,7 +25,7 @@ class WSGIRequestHandler(BaseHTTPRequestHandler): def get_stderr(self) -> ErrorStream: ... def handle(self) -> None: ... -def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... +def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> list[bytes]: ... _S = TypeVar("_S", bound=WSGIServer) diff --git a/mypy/typeshed/stdlib/wsgiref/util.pyi b/mypy/typeshed/stdlib/wsgiref/util.pyi index 1c66bc1fabdf..a7f710e8012c 100644 --- a/mypy/typeshed/stdlib/wsgiref/util.pyi +++ b/mypy/typeshed/stdlib/wsgiref/util.pyi @@ -1,5 +1,4 @@ -import sys -from typing import IO, Any, Callable, Optional +from typing import IO, Any, Callable from .types import WSGIEnvironment @@ -10,14 +9,11 @@ class FileWrapper: def __init__(self, filelike: IO[bytes], blksize: int = ...) -> None: ... def __getitem__(self, key: Any) -> bytes: ... def __iter__(self) -> FileWrapper: ... - if sys.version_info >= (3, 0): - def __next__(self) -> bytes: ... - else: - def next(self) -> bytes: ... + def __next__(self) -> bytes: ... def guess_scheme(environ: WSGIEnvironment) -> str: ... def application_uri(environ: WSGIEnvironment) -> str: ... def request_uri(environ: WSGIEnvironment, include_query: bool = ...) -> str: ... -def shift_path_info(environ: WSGIEnvironment) -> Optional[str]: ... +def shift_path_info(environ: WSGIEnvironment) -> str | None: ... def setup_testing_defaults(environ: WSGIEnvironment) -> None: ... def is_hop_by_hop(header_name: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/wsgiref/validate.pyi b/mypy/typeshed/stdlib/wsgiref/validate.pyi index bc9f0b8c680f..68e22727bc73 100644 --- a/mypy/typeshed/stdlib/wsgiref/validate.pyi +++ b/mypy/typeshed/stdlib/wsgiref/validate.pyi @@ -1,6 +1,5 @@ -import sys from _typeshed.wsgi import ErrorStream, InputStream, WSGIApplication -from typing import Any, Callable, Iterable, Iterator, NoReturn, Optional +from typing import Any, Callable, Iterable, Iterator, NoReturn class WSGIWarning(Warning): ... @@ -9,12 +8,8 @@ def validator(application: WSGIApplication) -> WSGIApplication: ... class InputWrapper: input: InputStream def __init__(self, wsgi_input: InputStream) -> None: ... - if sys.version_info >= (3, 0): - def read(self, size: int) -> bytes: ... - def readline(self, size: int = ...) -> bytes: ... - else: - def read(self, size: int = ...) -> bytes: ... - def readline(self) -> bytes: ... + def read(self, size: int) -> bytes: ... + def readline(self, size: int = ...) -> bytes: ... def readlines(self, hint: int = ...) -> bytes: ... def __iter__(self) -> Iterable[bytes]: ... def close(self) -> NoReturn: ... @@ -41,12 +36,9 @@ class IteratorWrapper: original_iterator: Iterator[bytes] iterator: Iterator[bytes] closed: bool - check_start_response: Optional[bool] - def __init__(self, wsgi_iterator: Iterator[bytes], check_start_response: Optional[bool]) -> None: ... + check_start_response: bool | None + def __init__(self, wsgi_iterator: Iterator[bytes], check_start_response: bool | None) -> None: ... def __iter__(self) -> IteratorWrapper: ... - if sys.version_info >= (3, 0): - def __next__(self) -> bytes: ... - else: - def next(self) -> bytes: ... + def __next__(self) -> bytes: ... def close(self) -> None: ... def __del__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/xdrlib.pyi b/mypy/typeshed/stdlib/xdrlib.pyi index 378504c37227..f59843f8ee9d 100644 --- a/mypy/typeshed/stdlib/xdrlib.pyi +++ b/mypy/typeshed/stdlib/xdrlib.pyi @@ -1,4 +1,4 @@ -from typing import Callable, List, Sequence, TypeVar +from typing import Callable, Sequence, TypeVar _T = TypeVar("_T") @@ -50,6 +50,6 @@ class Unpacker: def unpack_string(self) -> bytes: ... def unpack_opaque(self) -> bytes: ... def unpack_bytes(self) -> bytes: ... - def unpack_list(self, unpack_item: Callable[[], _T]) -> List[_T]: ... - def unpack_farray(self, n: int, unpack_item: Callable[[], _T]) -> List[_T]: ... - def unpack_array(self, unpack_item: Callable[[], _T]) -> List[_T]: ... + def unpack_list(self, unpack_item: Callable[[], _T]) -> list[_T]: ... + def unpack_farray(self, n: int, unpack_item: Callable[[], _T]) -> list[_T]: ... + def unpack_array(self, unpack_item: Callable[[], _T]) -> list[_T]: ... diff --git a/mypy/typeshed/stdlib/xml/dom/domreg.pyi b/mypy/typeshed/stdlib/xml/dom/domreg.pyi index bf63ff09e106..b9e2dd9eb263 100644 --- a/mypy/typeshed/stdlib/xml/dom/domreg.pyi +++ b/mypy/typeshed/stdlib/xml/dom/domreg.pyi @@ -1,10 +1,8 @@ from _typeshed.xml import DOMImplementation -from typing import Callable, Dict, Iterable, Optional, Tuple, Union +from typing import Callable, Iterable -well_known_implementations: Dict[str, str] -registered: Dict[str, Callable[[], DOMImplementation]] +well_known_implementations: dict[str, str] +registered: dict[str, Callable[[], DOMImplementation]] def registerDOMImplementation(name: str, factory: Callable[[], DOMImplementation]) -> None: ... -def getDOMImplementation( - name: Optional[str] = ..., features: Union[str, Iterable[Tuple[str, Optional[str]]]] = ... -) -> DOMImplementation: ... +def getDOMImplementation(name: str | None = ..., features: str | Iterable[tuple[str, str | None]] = ...) -> DOMImplementation: ... diff --git a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi index aa8efd03b19f..4bc60f7ab965 100644 --- a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi @@ -1,12 +1,12 @@ -from typing import Any, Iterable, List, Optional, Tuple, Type, TypeVar +from typing import Any, Iterable, List, Tuple, Type, TypeVar _T = TypeVar("_T") -StringTypes: Tuple[Type[str]] +StringTypes: tuple[Type[str]] class NodeList(List[_T]): length: int - def item(self, index: int) -> Optional[_T]: ... + def item(self, index: int) -> _T | None: ... class EmptyNodeList(Tuple[Any, ...]): length: int diff --git a/mypy/typeshed/stdlib/xml/dom/minidom.pyi b/mypy/typeshed/stdlib/xml/dom/minidom.pyi index 67e9b1189528..4d1d7a9d0faf 100644 --- a/mypy/typeshed/stdlib/xml/dom/minidom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minidom.pyi @@ -1,30 +1,33 @@ import sys import xml.dom -from typing import IO, Any, Optional, Text as _Text, TypeVar, Union +from _typeshed import Self +from typing import IO, Any from xml.dom.xmlbuilder import DocumentLS, DOMImplementationLS from xml.sax.xmlreader import XMLReader -_T = TypeVar("_T") - -def parse(file: Union[str, IO[Any]], parser: Optional[XMLReader] = ..., bufsize: Optional[int] = ...): ... -def parseString(string: Union[bytes, _Text], parser: Optional[XMLReader] = ...): ... -def getDOMImplementation(features=...): ... +def parse(file: str | IO[Any], parser: XMLReader | None = ..., bufsize: int | None = ...): ... +def parseString(string: str | bytes, parser: XMLReader | None = ...): ... +def getDOMImplementation(features=...) -> DOMImplementation | None: ... class Node(xml.dom.Node): - namespaceURI: Optional[str] + namespaceURI: str | None parentNode: Any ownerDocument: Any nextSibling: Any previousSibling: Any prefix: Any + @property + def firstChild(self) -> Node | None: ... + @property + def lastChild(self) -> Node | None: ... + @property + def localName(self) -> str | None: ... if sys.version_info >= (3, 9): - def toxml(self, encoding: Optional[Any] = ..., standalone: Optional[Any] = ...): ... - def toprettyxml( - self, indent: str = ..., newl: str = ..., encoding: Optional[Any] = ..., standalone: Optional[Any] = ... - ): ... + def toxml(self, encoding: Any | None = ..., standalone: Any | None = ...): ... + def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Any | None = ..., standalone: Any | None = ...): ... else: - def toxml(self, encoding: Optional[Any] = ...): ... - def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Optional[Any] = ...): ... + def toxml(self, encoding: Any | None = ...): ... + def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Any | None = ...): ... def hasChildNodes(self) -> bool: ... def insertBefore(self, newChild, refChild): ... def appendChild(self, node): ... @@ -39,7 +42,7 @@ class Node(xml.dom.Node): def setUserData(self, key, data, handler): ... childNodes: Any def unlink(self) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, et, ev, tb) -> None: ... class DocumentFragment(Node): @@ -57,14 +60,14 @@ class Attr(Node): attributes: Any specified: bool ownerElement: Any - namespaceURI: Optional[str] + namespaceURI: str | None childNodes: Any nodeName: Any nodeValue: str value: str prefix: Any def __init__( - self, qName: str, namespaceURI: Optional[str] = ..., localName: Optional[Any] = ..., prefix: Optional[Any] = ... + self, qName: str, namespaceURI: str | None = ..., localName: Any | None = ..., prefix: Any | None = ... ) -> None: ... def unlink(self) -> None: ... @@ -77,7 +80,7 @@ class NamedNodeMap: def keys(self): ... def keysNS(self): ... def values(self): ... - def get(self, name, value: Optional[Any] = ...): ... + def get(self, name, value: Any | None = ...): ... def __len__(self) -> int: ... def __eq__(self, other: Any) -> bool: ... def __ge__(self, other: Any) -> bool: ... @@ -108,11 +111,11 @@ class Element(Node): parentNode: Any tagName: str prefix: Any - namespaceURI: Optional[str] + namespaceURI: str | None childNodes: Any nextSibling: Any def __init__( - self, tagName, namespaceURI: Optional[str] = ..., prefix: Optional[Any] = ..., localName: Optional[Any] = ... + self, tagName, namespaceURI: str | None = ..., prefix: Any | None = ..., localName: Any | None = ... ) -> None: ... def unlink(self) -> None: ... def getAttribute(self, attname): ... @@ -243,8 +246,8 @@ class Notation(Identified, Childless, Node): class DOMImplementation(DOMImplementationLS): def hasFeature(self, feature, version) -> bool: ... - def createDocument(self, namespaceURI: str, qualifiedName: str, doctype): ... - def createDocumentType(self, qualifiedName: str, publicId, systemId): ... + def createDocument(self, namespaceURI: str | None, qualifiedName: str | None, doctype): ... + def createDocumentType(self, qualifiedName: str | None, publicId, systemId): ... def getInterface(self, feature): ... class ElementInfo: @@ -302,11 +305,11 @@ class Document(Node, DocumentLS): indent: str = ..., addindent: str = ..., newl: str = ..., - encoding: Optional[Any] = ..., - standalone: Optional[Any] = ..., + encoding: Any | None = ..., + standalone: Any | None = ..., ) -> None: ... else: def writexml( - self, writer, indent: str = ..., addindent: str = ..., newl: str = ..., encoding: Optional[Any] = ... + self, writer, indent: str = ..., addindent: str = ..., newl: str = ..., encoding: Any | None = ... ) -> None: ... def renameNode(self, n, namespaceURI: str, name): ... diff --git a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi index 964e6fa3f426..ce8816b4a98a 100644 --- a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi @@ -1,3 +1,87 @@ -from typing import Any +from typing import IO, Any, Sequence, Tuple, Union +from typing_extensions import Literal +from xml.dom.minidom import Document, DOMImplementation, Element, Text +from xml.sax.handler import ContentHandler +from xml.sax.xmlreader import XMLReader -def __getattr__(name: str) -> Any: ... # incomplete +START_ELEMENT: Literal["START_ELEMENT"] +END_ELEMENT: Literal["END_ELEMENT"] +COMMENT: Literal["COMMENT"] +START_DOCUMENT: Literal["START_DOCUMENT"] +END_DOCUMENT: Literal["END_DOCUMENT"] +PROCESSING_INSTRUCTION: Literal["PROCESSING_INSTRUCTION"] +IGNORABLE_WHITESPACE: Literal["IGNORABLE_WHITESPACE"] +CHARACTERS: Literal["CHARACTERS"] + +_DocumentFactory = Union[DOMImplementation, None] +_Node = Union[Document, Element, Text] + +_Event = Tuple[ + Literal[ + Literal["START_ELEMENT"], + Literal["END_ELEMENT"], + Literal["COMMENT"], + Literal["START_DOCUMENT"], + Literal["END_DOCUMENT"], + Literal["PROCESSING_INSTRUCTION"], + Literal["IGNORABLE_WHITESPACE"], + Literal["CHARACTERS"], + ], + _Node, +] + +class PullDOM(ContentHandler): + document: Document | None + documentFactory: _DocumentFactory + firstEvent: Any + lastEvent: Any + elementStack: Sequence[Any] + pending_events: Sequence[Any] + def __init__(self, documentFactory: _DocumentFactory = ...) -> None: ... + def pop(self) -> Element: ... + def setDocumentLocator(self, locator) -> None: ... + def startPrefixMapping(self, prefix, uri) -> None: ... + def endPrefixMapping(self, prefix) -> None: ... + def startElementNS(self, name, tagName, attrs) -> None: ... + def endElementNS(self, name, tagName) -> None: ... + def startElement(self, name, attrs) -> None: ... + def endElement(self, name) -> None: ... + def comment(self, s) -> None: ... + def processingInstruction(self, target, data) -> None: ... + def ignorableWhitespace(self, chars) -> None: ... + def characters(self, chars) -> None: ... + def startDocument(self) -> None: ... + def buildDocument(self, uri, tagname): ... + def endDocument(self) -> None: ... + def clear(self) -> None: ... + +class ErrorHandler: + def warning(self, exception) -> None: ... + def error(self, exception) -> None: ... + def fatalError(self, exception) -> None: ... + +class DOMEventStream: + stream: IO[bytes] + parser: XMLReader + bufsize: int + def __init__(self, stream: IO[bytes], parser: XMLReader, bufsize: int) -> None: ... + pulldom: Any + def __getitem__(self, pos): ... + def __next__(self): ... + def __iter__(self): ... + def getEvent(self) -> _Event: ... + def expandNode(self, node: _Node) -> None: ... + def reset(self) -> None: ... + def clear(self) -> None: ... + +class SAX2DOM(PullDOM): + def startElementNS(self, name, tagName, attrs) -> None: ... + def startElement(self, name, attrs) -> None: ... + def processingInstruction(self, target, data) -> None: ... + def ignorableWhitespace(self, chars) -> None: ... + def characters(self, chars) -> None: ... + +default_bufsize: int + +def parse(stream_or_string: str | IO[bytes], parser: XMLReader | None = ..., bufsize: int | None = ...) -> DOMEventStream: ... +def parseString(string: str, parser: XMLReader | None = ...) -> DOMEventStream: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi index 4aa0173fa82f..0ccccce4f3d0 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable, Optional, Union +from typing import Callable from xml.etree.ElementTree import Element XINCLUDE: str @@ -8,18 +8,15 @@ XINCLUDE_FALLBACK: str class FatalIncludeError(SyntaxError): ... -def default_loader(href: Union[str, bytes, int], parse: str, encoding: Optional[str] = ...) -> Union[str, Element]: ... +def default_loader(href: str | bytes | int, parse: str, encoding: str | None = ...) -> str | Element: ... # TODO: loader is of type default_loader ie it takes a callable that has the # same signature as default_loader. But default_loader has a keyword argument # Which can't be represented using Callable... if sys.version_info >= (3, 9): def include( - elem: Element, - loader: Optional[Callable[..., Union[str, Element]]] = ..., - base_url: Optional[str] = ..., - max_depth: Optional[int] = ..., + elem: Element, loader: Callable[..., str | Element] | None = ..., base_url: str | None = ..., max_depth: int | None = ... ) -> None: ... else: - def include(elem: Element, loader: Optional[Callable[..., Union[str, Element]]] = ...) -> None: ... + def include(elem: Element, loader: Callable[..., str | Element] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi index de49ffcf1209..db4bd6a4e958 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi @@ -1,4 +1,4 @@ -from typing import Callable, Dict, Generator, List, Optional, Pattern, Tuple, TypeVar, Union +from typing import Callable, Generator, List, Pattern, Tuple, TypeVar from xml.etree.ElementTree import Element xpath_tokenizer_re: Pattern[str] @@ -7,8 +7,8 @@ _token = Tuple[str, str] _next = Callable[[], _token] _callback = Callable[[_SelectorContext, List[Element]], Generator[Element, None, None]] -def xpath_tokenizer(pattern: str, namespaces: Optional[Dict[str, str]] = ...) -> Generator[_token, None, None]: ... -def get_parent_map(context: _SelectorContext) -> Dict[Element, Element]: ... +def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = ...) -> Generator[_token, None, None]: ... +def get_parent_map(context: _SelectorContext) -> dict[Element, Element]: ... def prepare_child(next: _next, token: _token) -> _callback: ... def prepare_star(next: _next, token: _token) -> _callback: ... def prepare_self(next: _next, token: _token) -> _callback: ... @@ -16,18 +16,16 @@ def prepare_descendant(next: _next, token: _token) -> _callback: ... def prepare_parent(next: _next, token: _token) -> _callback: ... def prepare_predicate(next: _next, token: _token) -> _callback: ... -ops: Dict[str, Callable[[_next, _token], _callback]] +ops: dict[str, Callable[[_next, _token], _callback]] class _SelectorContext: - parent_map: Optional[Dict[Element, Element]] + parent_map: dict[Element, Element] | None root: Element def __init__(self, root: Element) -> None: ... _T = TypeVar("_T") -def iterfind(elem: Element, path: str, namespaces: Optional[Dict[str, str]] = ...) -> Generator[Element, None, None]: ... -def find(elem: Element, path: str, namespaces: Optional[Dict[str, str]] = ...) -> Optional[Element]: ... -def findall(elem: Element, path: str, namespaces: Optional[Dict[str, str]] = ...) -> List[Element]: ... -def findtext( - elem: Element, path: str, default: Optional[_T] = ..., namespaces: Optional[Dict[str, str]] = ... -) -> Union[_T, str]: ... +def iterfind(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... +def find(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> Element | None: ... +def findall(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> list[Element]: ... +def findtext(elem: Element, path: str, default: _T | None = ..., namespaces: dict[str, str] | None = ...) -> _T | str: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index ca4e3832f37e..03a20dcad4cb 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -1,5 +1,5 @@ import sys -from _typeshed import AnyPath, FileDescriptor, SupportsWrite +from _typeshed import FileDescriptor, StrOrBytesPath, SupportsWrite from typing import ( IO, Any, @@ -10,134 +10,84 @@ from typing import ( Iterable, Iterator, KeysView, - List, MutableSequence, - Optional, Sequence, - Text, - Tuple, TypeVar, Union, overload, ) from typing_extensions import Literal +_T = TypeVar("_T") +_File = Union[StrOrBytesPath, FileDescriptor, IO[Any]] + VERSION: str class ParseError(SyntaxError): code: int - position: Tuple[int, int] + position: tuple[int, int] def iselement(element: object) -> bool: ... -_T = TypeVar("_T") - -# Type for parser inputs. Parser will accept any unicode/str/bytes and coerce, -# and this is true in py2 and py3 (even fromstringlist() in python3 can be -# called with a heterogeneous list) -_parser_input_type = Union[bytes, Text] - -# Type for individual tag/attr/ns/text values in args to most functions. -# In py2, the library accepts str or unicode everywhere and coerces -# aggressively. -# In py3, bytes is not coerced to str and so use of bytes is probably an error, -# so we exclude it. (why? the parser never produces bytes when it parses XML, -# so e.g., element.get(b'name') will always return None for parsed XML, even if -# there is a 'name' attribute.) -_str_argument_type = Union[str, Text] - -# Type for return values from individual tag/attr/text values -if sys.version_info >= (3,): - # note: in python3, everything comes out as str, yay: - _str_result_type = str -else: - # in python2, if the tag/attribute/text wasn't decode-able as ascii, it - # comes out as a unicode string; otherwise it comes out as str. (see - # _fixtext function in the source). Client code knows best: - _str_result_type = Any - -_file_or_filename = Union[AnyPath, FileDescriptor, IO[Any]] - if sys.version_info >= (3, 8): @overload def canonicalize( - xml_data: Optional[_parser_input_type] = ..., + xml_data: str | bytes | None = ..., *, out: None = ..., - from_file: Optional[_file_or_filename] = ..., + from_file: _File | None = ..., with_comments: bool = ..., strip_text: bool = ..., rewrite_prefixes: bool = ..., - qname_aware_tags: Optional[Iterable[str]] = ..., - qname_aware_attrs: Optional[Iterable[str]] = ..., - exclude_attrs: Optional[Iterable[str]] = ..., - exclude_tags: Optional[Iterable[str]] = ..., + qname_aware_tags: Iterable[str] | None = ..., + qname_aware_attrs: Iterable[str] | None = ..., + exclude_attrs: Iterable[str] | None = ..., + exclude_tags: Iterable[str] | None = ..., ) -> str: ... @overload def canonicalize( - xml_data: Optional[_parser_input_type] = ..., + xml_data: str | bytes | None = ..., *, out: SupportsWrite[str], - from_file: Optional[_file_or_filename] = ..., + from_file: _File | None = ..., with_comments: bool = ..., strip_text: bool = ..., rewrite_prefixes: bool = ..., - qname_aware_tags: Optional[Iterable[str]] = ..., - qname_aware_attrs: Optional[Iterable[str]] = ..., - exclude_attrs: Optional[Iterable[str]] = ..., - exclude_tags: Optional[Iterable[str]] = ..., + qname_aware_tags: Iterable[str] | None = ..., + qname_aware_attrs: Iterable[str] | None = ..., + exclude_attrs: Iterable[str] | None = ..., + exclude_tags: Iterable[str] | None = ..., ) -> None: ... class Element(MutableSequence[Element]): - tag: _str_result_type - attrib: Dict[_str_result_type, _str_result_type] - text: Optional[_str_result_type] - tail: Optional[_str_result_type] - def __init__( - self, - tag: Union[_str_argument_type, Callable[..., Element]], - attrib: Dict[_str_argument_type, _str_argument_type] = ..., - **extra: _str_argument_type, - ) -> None: ... + tag: str + attrib: dict[str, str] + text: str | None + tail: str | None + def __init__(self, tag: str | Callable[..., Element], attrib: dict[str, str] = ..., **extra: str) -> None: ... def append(self, __subelement: Element) -> None: ... def clear(self) -> None: ... def extend(self, __elements: Iterable[Element]) -> None: ... - def find( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Optional[Element]: ... - def findall( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> List[Element]: ... + def find(self, path: str, namespaces: dict[str, str] | None = ...) -> Element | None: ... + def findall(self, path: str, namespaces: dict[str, str] | None = ...) -> list[Element]: ... @overload - def findtext( - self, - path: _str_argument_type, - default: None = ..., - namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ..., - ) -> Optional[_str_result_type]: ... + def findtext(self, path: str, default: None = ..., namespaces: dict[str, str] | None = ...) -> str | None: ... @overload - def findtext( - self, path: _str_argument_type, default: _T, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Union[_T, _str_result_type]: ... + def findtext(self, path: str, default: _T, namespaces: dict[str, str] | None = ...) -> _T | str: ... @overload - def get(self, key: _str_argument_type, default: None = ...) -> Optional[_str_result_type]: ... + def get(self, key: str, default: None = ...) -> str | None: ... @overload - def get(self, key: _str_argument_type, default: _T) -> Union[_str_result_type, _T]: ... - if sys.version_info >= (3, 2): - def insert(self, __index: int, __subelement: Element) -> None: ... - else: - def insert(self, __index: int, __element: Element) -> None: ... - def items(self) -> ItemsView[_str_result_type, _str_result_type]: ... - def iter(self, tag: Optional[_str_argument_type] = ...) -> Generator[Element, None, None]: ... - def iterfind( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Generator[Element, None, None]: ... - def itertext(self) -> Generator[_str_result_type, None, None]: ... - def keys(self) -> KeysView[_str_result_type]: ... - def makeelement(self, __tag: _str_argument_type, __attrib: Dict[_str_argument_type, _str_argument_type]) -> Element: ... + def get(self, key: str, default: _T) -> str | _T: ... + def insert(self, __index: int, __subelement: Element) -> None: ... + def items(self) -> ItemsView[str, str]: ... + def iter(self, tag: str | None = ...) -> Generator[Element, None, None]: ... + def iterfind(self, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... + def itertext(self) -> Generator[str, None, None]: ... + def keys(self) -> KeysView[str]: ... + def makeelement(self, __tag: str, __attrib: dict[str, str]) -> Element: ... def remove(self, __subelement: Element) -> None: ... - def set(self, __key: _str_argument_type, __value: _str_argument_type) -> None: ... - def __delitem__(self, i: Union[int, slice]) -> None: ... + def set(self, __key: str, __value: str) -> None: ... + def __delitem__(self, i: int | slice) -> None: ... @overload def __getitem__(self, i: int) -> Element: ... @overload @@ -148,189 +98,154 @@ class Element(MutableSequence[Element]): @overload def __setitem__(self, s: slice, o: Iterable[Element]) -> None: ... if sys.version_info < (3, 9): - def getchildren(self) -> List[Element]: ... - def getiterator(self, tag: Optional[_str_argument_type] = ...) -> List[Element]: ... + def getchildren(self) -> list[Element]: ... + def getiterator(self, tag: str | None = ...) -> list[Element]: ... -def SubElement( - parent: Element, - tag: _str_argument_type, - attrib: Dict[_str_argument_type, _str_argument_type] = ..., - **extra: _str_argument_type, -) -> Element: ... -def Comment(text: Optional[_str_argument_type] = ...) -> Element: ... -def ProcessingInstruction(target: _str_argument_type, text: Optional[_str_argument_type] = ...) -> Element: ... +def SubElement(parent: Element, tag: str, attrib: dict[str, str] = ..., **extra: str) -> Element: ... +def Comment(text: str | None = ...) -> Element: ... +def ProcessingInstruction(target: str, text: str | None = ...) -> Element: ... PI: Callable[..., Element] class QName: text: str - def __init__(self, text_or_uri: _str_argument_type, tag: Optional[_str_argument_type] = ...) -> None: ... + def __init__(self, text_or_uri: str, tag: str | None = ...) -> None: ... class ElementTree: - def __init__(self, element: Optional[Element] = ..., file: Optional[_file_or_filename] = ...) -> None: ... + def __init__(self, element: Element | None = ..., file: _File | None = ...) -> None: ... def getroot(self) -> Element: ... - def parse(self, source: _file_or_filename, parser: Optional[XMLParser] = ...) -> Element: ... - def iter(self, tag: Optional[_str_argument_type] = ...) -> Generator[Element, None, None]: ... + def parse(self, source: _File, parser: XMLParser | None = ...) -> Element: ... + def iter(self, tag: str | None = ...) -> Generator[Element, None, None]: ... if sys.version_info < (3, 9): - def getiterator(self, tag: Optional[_str_argument_type] = ...) -> List[Element]: ... - def find( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Optional[Element]: ... + def getiterator(self, tag: str | None = ...) -> list[Element]: ... + def find(self, path: str, namespaces: dict[str, str] | None = ...) -> Element | None: ... @overload - def findtext( - self, - path: _str_argument_type, - default: None = ..., - namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ..., - ) -> Optional[_str_result_type]: ... + def findtext(self, path: str, default: None = ..., namespaces: dict[str, str] | None = ...) -> str | None: ... @overload - def findtext( - self, path: _str_argument_type, default: _T, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Union[_T, _str_result_type]: ... - def findall( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> List[Element]: ... - def iterfind( - self, path: _str_argument_type, namespaces: Optional[Dict[_str_argument_type, _str_argument_type]] = ... - ) -> Generator[Element, None, None]: ... - if sys.version_info >= (3, 4): - def write( - self, - file_or_filename: _file_or_filename, - encoding: Optional[str] = ..., - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., - method: Optional[str] = ..., - *, - short_empty_elements: bool = ..., - ) -> None: ... - else: - def write( - self, - file_or_filename: _file_or_filename, - encoding: Optional[str] = ..., - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., - method: Optional[str] = ..., - ) -> None: ... - def write_c14n(self, file: _file_or_filename) -> None: ... + def findtext(self, path: str, default: _T, namespaces: dict[str, str] | None = ...) -> _T | str: ... + def findall(self, path: str, namespaces: dict[str, str] | None = ...) -> list[Element]: ... + def iterfind(self, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... + def write( + self, + file_or_filename: _File, + encoding: str | None = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., + method: str | None = ..., + *, + short_empty_elements: bool = ..., + ) -> None: ... + def write_c14n(self, file: _File) -> None: ... -def register_namespace(prefix: _str_argument_type, uri: _str_argument_type) -> None: ... +def register_namespace(prefix: str, uri: str) -> None: ... if sys.version_info >= (3, 8): @overload def tostring( element: Element, encoding: None = ..., - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., ) -> bytes: ... @overload def tostring( element: Element, encoding: Literal["unicode"], - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., ) -> str: ... @overload def tostring( element: Element, encoding: str, - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., ) -> Any: ... @overload def tostringlist( element: Element, encoding: None = ..., - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., - ) -> List[bytes]: ... + ) -> list[bytes]: ... @overload def tostringlist( element: Element, encoding: Literal["unicode"], - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., - ) -> List[str]: ... + ) -> list[str]: ... @overload def tostringlist( element: Element, encoding: str, - method: Optional[str] = ..., + method: str | None = ..., *, - xml_declaration: Optional[bool] = ..., - default_namespace: Optional[_str_argument_type] = ..., + xml_declaration: bool | None = ..., + default_namespace: str | None = ..., short_empty_elements: bool = ..., - ) -> List[Any]: ... + ) -> list[Any]: ... -elif sys.version_info >= (3,): +else: @overload def tostring( - element: Element, encoding: None = ..., method: Optional[str] = ..., *, short_empty_elements: bool = ... + element: Element, encoding: None = ..., method: str | None = ..., *, short_empty_elements: bool = ... ) -> bytes: ... @overload def tostring( - element: Element, encoding: Literal["unicode"], method: Optional[str] = ..., *, short_empty_elements: bool = ... + element: Element, encoding: Literal["unicode"], method: str | None = ..., *, short_empty_elements: bool = ... ) -> str: ... @overload - def tostring(element: Element, encoding: str, method: Optional[str] = ..., *, short_empty_elements: bool = ...) -> Any: ... + def tostring(element: Element, encoding: str, method: str | None = ..., *, short_empty_elements: bool = ...) -> Any: ... @overload def tostringlist( - element: Element, encoding: None = ..., method: Optional[str] = ..., *, short_empty_elements: bool = ... - ) -> List[bytes]: ... + element: Element, encoding: None = ..., method: str | None = ..., *, short_empty_elements: bool = ... + ) -> list[bytes]: ... @overload def tostringlist( - element: Element, encoding: Literal["unicode"], method: Optional[str] = ..., *, short_empty_elements: bool = ... - ) -> List[str]: ... + element: Element, encoding: Literal["unicode"], method: str | None = ..., *, short_empty_elements: bool = ... + ) -> list[str]: ... @overload def tostringlist( - element: Element, encoding: str, method: Optional[str] = ..., *, short_empty_elements: bool = ... - ) -> List[Any]: ... - -else: - def tostring(element: Element, encoding: Optional[str] = ..., method: Optional[str] = ...) -> bytes: ... - def tostringlist(element: Element, encoding: Optional[str] = ..., method: Optional[str] = ...) -> List[bytes]: ... + element: Element, encoding: str, method: str | None = ..., *, short_empty_elements: bool = ... + ) -> list[Any]: ... def dump(elem: Element) -> None: ... if sys.version_info >= (3, 9): - def indent(tree: Union[Element, ElementTree], space: str = ..., level: int = ...) -> None: ... + def indent(tree: Element | ElementTree, space: str = ..., level: int = ...) -> None: ... -def parse(source: _file_or_filename, parser: Optional[XMLParser] = ...) -> ElementTree: ... -def iterparse( - source: _file_or_filename, events: Optional[Sequence[str]] = ..., parser: Optional[XMLParser] = ... -) -> Iterator[Tuple[str, Any]]: ... +def parse(source: _File, parser: XMLParser | None = ...) -> ElementTree: ... +def iterparse(source: _File, events: Sequence[str] | None = ..., parser: XMLParser | None = ...) -> Iterator[tuple[str, Any]]: ... -if sys.version_info >= (3, 4): - class XMLPullParser: - def __init__(self, events: Optional[Sequence[str]] = ..., *, _parser: Optional[XMLParser] = ...) -> None: ... - def feed(self, data: bytes) -> None: ... - def close(self) -> None: ... - def read_events(self) -> Iterator[Tuple[str, Element]]: ... +class XMLPullParser: + def __init__(self, events: Sequence[str] | None = ..., *, _parser: XMLParser | None = ...) -> None: ... + def feed(self, data: bytes) -> None: ... + def close(self) -> None: ... + def read_events(self) -> Iterator[tuple[str, Element]]: ... -def XML(text: _parser_input_type, parser: Optional[XMLParser] = ...) -> Element: ... -def XMLID(text: _parser_input_type, parser: Optional[XMLParser] = ...) -> Tuple[Element, Dict[_str_result_type, Element]]: ... +def XML(text: str | bytes, parser: XMLParser | None = ...) -> Element: ... +def XMLID(text: str | bytes, parser: XMLParser | None = ...) -> tuple[Element, dict[str, Element]]: ... # This is aliased to XML in the source. fromstring = XML -def fromstringlist(sequence: Sequence[_parser_input_type], parser: Optional[XMLParser] = ...) -> Element: ... +def fromstringlist(sequence: Sequence[str | bytes], parser: XMLParser | None = ...) -> Element: ... # This type is both not precise enough and too precise. The TreeBuilder # requires the elementfactory to accept tag and attrs in its args and produce @@ -344,11 +259,11 @@ def fromstringlist(sequence: Sequence[_parser_input_type], parser: Optional[XMLP _ElementFactory = Callable[[Any, Dict[Any, Any]], Element] class TreeBuilder: - def __init__(self, element_factory: Optional[_ElementFactory] = ...) -> None: ... + def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... def close(self) -> Element: ... - def data(self, __data: _parser_input_type) -> None: ... - def start(self, __tag: _parser_input_type, __attrs: Dict[_parser_input_type, _parser_input_type]) -> Element: ... - def end(self, __tag: _parser_input_type) -> Element: ... + def data(self, __data: str | bytes) -> None: ... + def start(self, __tag: str | bytes, __attrs: dict[str | bytes, str | bytes]) -> Element: ... + def end(self, __tag: str | bytes) -> Element: ... if sys.version_info >= (3, 8): class C14NWriterTarget: @@ -359,10 +274,10 @@ if sys.version_info >= (3, 8): with_comments: bool = ..., strip_text: bool = ..., rewrite_prefixes: bool = ..., - qname_aware_tags: Optional[Iterable[str]] = ..., - qname_aware_attrs: Optional[Iterable[str]] = ..., - exclude_attrs: Optional[Iterable[str]] = ..., - exclude_tags: Optional[Iterable[str]] = ..., + qname_aware_tags: Iterable[str] | None = ..., + qname_aware_attrs: Iterable[str] | None = ..., + exclude_attrs: Iterable[str] | None = ..., + exclude_tags: Iterable[str] | None = ..., ) -> None: ... class XMLParser: @@ -372,9 +287,9 @@ class XMLParser: entity: Any version: str if sys.version_info >= (3, 8): - def __init__(self, *, target: Any = ..., encoding: Optional[str] = ...) -> None: ... + def __init__(self, *, target: Any = ..., encoding: str | None = ...) -> None: ... else: - def __init__(self, html: int = ..., target: Any = ..., encoding: Optional[str] = ...) -> None: ... + def __init__(self, html: int = ..., target: Any = ..., encoding: str | None = ...) -> None: ... def doctype(self, __name: str, __pubid: str, __system: str) -> None: ... def close(self) -> Any: ... - def feed(self, __data: _parser_input_type) -> None: ... + def feed(self, __data: str | bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/sax/__init__.pyi b/mypy/typeshed/stdlib/xml/sax/__init__.pyi index a95fde106535..a123e7e894e2 100644 --- a/mypy/typeshed/stdlib/xml/sax/__init__.pyi +++ b/mypy/typeshed/stdlib/xml/sax/__init__.pyi @@ -1,10 +1,10 @@ import sys -from typing import IO, Any, Iterable, List, NoReturn, Optional, Text, Union +from typing import IO, Any, Iterable, NoReturn from xml.sax.handler import ContentHandler, ErrorHandler from xml.sax.xmlreader import Locator, XMLReader class SAXException(Exception): - def __init__(self, msg: str, exception: Optional[Exception] = ...) -> None: ... + def __init__(self, msg: str, exception: Exception | None = ...) -> None: ... def getMessage(self) -> str: ... def getException(self) -> Exception: ... def __getitem__(self, ix: Any) -> NoReturn: ... @@ -20,14 +20,14 @@ class SAXNotRecognizedException(SAXException): ... class SAXNotSupportedException(SAXException): ... class SAXReaderNotAvailable(SAXNotSupportedException): ... -default_parser_list: List[str] +default_parser_list: list[str] if sys.version_info >= (3, 8): def make_parser(parser_list: Iterable[str] = ...) -> XMLReader: ... else: - def make_parser(parser_list: List[str] = ...) -> XMLReader: ... + def make_parser(parser_list: list[str] = ...) -> XMLReader: ... -def parse(source: Union[str, IO[str], IO[bytes]], handler: ContentHandler, errorHandler: ErrorHandler = ...) -> None: ... -def parseString(string: Union[bytes, Text], handler: ContentHandler, errorHandler: Optional[ErrorHandler] = ...) -> None: ... +def parse(source: str | IO[str] | IO[bytes], handler: ContentHandler, errorHandler: ErrorHandler = ...) -> None: ... +def parseString(string: bytes | str, handler: ContentHandler, errorHandler: ErrorHandler | None = ...) -> None: ... def _create_parser(parser_name: str) -> XMLReader: ... diff --git a/mypy/typeshed/stdlib/xml/sax/saxutils.pyi b/mypy/typeshed/stdlib/xml/sax/saxutils.pyi index 8ae2b80d2a26..c7304f4b5261 100644 --- a/mypy/typeshed/stdlib/xml/sax/saxutils.pyi +++ b/mypy/typeshed/stdlib/xml/sax/saxutils.pyi @@ -1,28 +1,20 @@ -import sys from _typeshed import SupportsWrite from codecs import StreamReaderWriter, StreamWriter from io import RawIOBase, TextIOBase -from typing import Mapping, Optional, Text, Union +from typing import Mapping from xml.sax import handler, xmlreader -def escape(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... -def unescape(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... -def quoteattr(data: Text, entities: Mapping[Text, Text] = ...) -> Text: ... +def escape(data: str, entities: Mapping[str, str] = ...) -> str: ... +def unescape(data: str, entities: Mapping[str, str] = ...) -> str: ... +def quoteattr(data: str, entities: Mapping[str, str] = ...) -> str: ... class XMLGenerator(handler.ContentHandler): - if sys.version_info >= (3, 0): - def __init__( - self, - out: Optional[Union[TextIOBase, RawIOBase, StreamWriter, StreamReaderWriter, SupportsWrite[str]]] = ..., - encoding: str = ..., - short_empty_elements: bool = ..., - ) -> None: ... - else: - def __init__( - self, - out: Optional[Union[TextIOBase, RawIOBase, StreamWriter, StreamReaderWriter, SupportsWrite[str]]] = ..., - encoding: Text = ..., - ) -> None: ... + def __init__( + self, + out: TextIOBase | RawIOBase | StreamWriter | StreamReaderWriter | SupportsWrite[str] | None = ..., + encoding: str = ..., + short_empty_elements: bool = ..., + ) -> None: ... def startDocument(self): ... def endDocument(self): ... def startPrefixMapping(self, prefix, uri): ... @@ -36,7 +28,7 @@ class XMLGenerator(handler.ContentHandler): def processingInstruction(self, target, data): ... class XMLFilterBase(xmlreader.XMLReader): - def __init__(self, parent: Optional[xmlreader.XMLReader] = ...) -> None: ... + def __init__(self, parent: xmlreader.XMLReader | None = ...) -> None: ... def error(self, exception): ... def fatalError(self, exception): ... def warning(self, exception): ... diff --git a/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi b/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi index 9dd6b75fd52f..684e9cef1f42 100644 --- a/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi +++ b/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi @@ -1,4 +1,4 @@ -from typing import Mapping, Optional, Tuple +from typing import Mapping class XMLReader: def __init__(self) -> None: ... @@ -32,7 +32,7 @@ class Locator: def getSystemId(self): ... class InputSource: - def __init__(self, system_id: Optional[str] = ...) -> None: ... + def __init__(self, system_id: str | None = ...) -> None: ... def setPublicId(self, public_id): ... def getPublicId(self): ... def setSystemId(self, system_id): ... @@ -64,7 +64,7 @@ class AttributesImpl: def values(self): ... class AttributesNSImpl(AttributesImpl): - def __init__(self, attrs: Mapping[Tuple[str, str], str], qnames: Mapping[Tuple[str, str], str]) -> None: ... + def __init__(self, attrs: Mapping[tuple[str, str], str], qnames: Mapping[tuple[str, str], str]) -> None: ... def getValueByQName(self, name): ... def getNameByQName(self, name): ... def getQNameByName(self, name): ... diff --git a/mypy/typeshed/stdlib/xmlrpc/client.pyi b/mypy/typeshed/stdlib/xmlrpc/client.pyi index b0c615063729..061df849eff2 100644 --- a/mypy/typeshed/stdlib/xmlrpc/client.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/client.pyi @@ -2,11 +2,11 @@ import gzip import http.client import sys import time -from _typeshed import SupportsRead, SupportsWrite +from _typeshed import Self, SupportsRead, SupportsWrite from datetime import datetime from io import BytesIO from types import TracebackType -from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Protocol, Tuple, Type, Union, overload +from typing import Any, Callable, Dict, Iterable, List, Mapping, Protocol, Tuple, Type, Union, overload from typing_extensions import Literal class _SupportsTimeTuple(Protocol): @@ -43,8 +43,8 @@ class ProtocolError(Error): url: str errcode: int errmsg: str - headers: Dict[str, str] - def __init__(self, url: str, errcode: int, errmsg: str, headers: Dict[str, str]) -> None: ... + headers: dict[str, str] + def __init__(self, url: str, errcode: int, errmsg: str, headers: dict[str, str]) -> None: ... class ResponseError(Error): ... @@ -63,13 +63,13 @@ def _strftime(value: _XMLDate) -> str: ... # undocumented class DateTime: value: str # undocumented - def __init__(self, value: Union[int, str, datetime, time.struct_time, Tuple[int, ...]] = ...) -> None: ... + def __init__(self, value: int | str | datetime | time.struct_time | Tuple[int, ...] = ...) -> None: ... def __lt__(self, other: _DateTimeComparable) -> bool: ... def __le__(self, other: _DateTimeComparable) -> bool: ... def __gt__(self, other: _DateTimeComparable) -> bool: ... def __ge__(self, other: _DateTimeComparable) -> bool: ... def __eq__(self, other: _DateTimeComparable) -> bool: ... # type: ignore - def make_comparable(self, other: _DateTimeComparable) -> Tuple[str, str]: ... # undocumented + def make_comparable(self, other: _DateTimeComparable) -> tuple[str, str]: ... # undocumented def timetuple(self) -> time.struct_time: ... # undocumented def decode(self, data: Any) -> None: ... def encode(self, out: SupportsWrite[str]) -> None: ... @@ -80,32 +80,32 @@ def _datetime_type(data: str) -> datetime: ... # undocumented class Binary: data: bytes - def __init__(self, data: Optional[bytes] = ...) -> None: ... + def __init__(self, data: bytes | None = ...) -> None: ... def decode(self, data: bytes) -> None: ... def encode(self, out: SupportsWrite[str]) -> None: ... def _binary(data: bytes) -> Binary: ... # undocumented -WRAPPERS: Tuple[Type[DateTime], Type[Binary]] # undocumented +WRAPPERS: tuple[Type[DateTime], Type[Binary]] # undocumented class ExpatParser: # undocumented def __init__(self, target: Unmarshaller) -> None: ... - def feed(self, data: Union[str, bytes]) -> None: ... + def feed(self, data: str | bytes) -> None: ... def close(self) -> None: ... class Marshaller: - dispatch: Dict[ + dispatch: dict[ Type[Any], Callable[[Marshaller, Any, Callable[[str], Any]], None] - ] = ... # TODO: Replace 'Any' with some kind of binding + ] # TODO: Replace 'Any' with some kind of binding - memo: Dict[Any, None] + memo: dict[Any, None] data: None - encoding: Optional[str] + encoding: str | None allow_none: bool - def __init__(self, encoding: Optional[str] = ..., allow_none: bool = ...) -> None: ... - def dumps(self, values: Union[Fault, Iterable[_Marshallable]]) -> str: ... - def __dump(self, value: Union[_Marshallable], write: Callable[[str], Any]) -> None: ... # undocumented + def __init__(self, encoding: str | None = ..., allow_none: bool = ...) -> None: ... + def dumps(self, values: Fault | Iterable[_Marshallable]) -> str: ... + def __dump(self, value: _Marshallable, write: Callable[[str], Any]) -> None: ... # undocumented def dump_nil(self, value: None, write: Callable[[str], Any]) -> None: ... def dump_bool(self, value: bool, write: Callable[[str], Any]) -> None: ... def dump_long(self, value: int, write: Callable[[str], Any]) -> None: ... @@ -122,23 +122,23 @@ class Marshaller: class Unmarshaller: - dispatch: Dict[str, Callable[[Unmarshaller, str], None]] = ... + dispatch: dict[str, Callable[[Unmarshaller, str], None]] - _type: Optional[str] - _stack: List[_Marshallable] - _marks: List[int] - _data: List[str] + _type: str | None + _stack: list[_Marshallable] + _marks: list[int] + _data: list[str] _value: bool - _methodname: Optional[str] + _methodname: str | None _encoding: str append: Callable[[Any], None] _use_datetime: bool _use_builtin_types: bool def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ...) -> None: ... def close(self) -> Tuple[_Marshallable, ...]: ... - def getmethodname(self) -> Optional[str]: ... + def getmethodname(self) -> str | None: ... def xml(self, encoding: str, standalone: Any) -> None: ... # Standalone is ignored - def start(self, tag: str, attrs: Dict[str, str]) -> None: ... + def start(self, tag: str, attrs: dict[str, str]) -> None: ... def data(self, text: str) -> None: ... def end(self, tag: str) -> None: ... def end_dispatch(self, tag: str, data: str) -> None: ... @@ -159,42 +159,40 @@ class Unmarshaller: class _MultiCallMethod: # undocumented - __call_list: List[Tuple[str, Tuple[_Marshallable, ...]]] + __call_list: list[tuple[str, Tuple[_Marshallable, ...]]] __name: str - def __init__(self, call_list: List[Tuple[str, _Marshallable]], name: str) -> None: ... + def __init__(self, call_list: list[tuple[str, _Marshallable]], name: str) -> None: ... def __getattr__(self, name: str) -> _MultiCallMethod: ... def __call__(self, *args: _Marshallable) -> None: ... class MultiCallIterator: # undocumented - results: List[List[_Marshallable]] - def __init__(self, results: List[List[_Marshallable]]) -> None: ... + results: list[list[_Marshallable]] + def __init__(self, results: list[list[_Marshallable]]) -> None: ... def __getitem__(self, i: int) -> _Marshallable: ... class MultiCall: __server: ServerProxy - __call_list: List[Tuple[str, Tuple[_Marshallable, ...]]] + __call_list: list[tuple[str, Tuple[_Marshallable, ...]]] def __init__(self, server: ServerProxy) -> None: ... def __getattr__(self, item: str) -> _MultiCallMethod: ... def __call__(self) -> MultiCallIterator: ... # A little white lie -FastMarshaller: Optional[Marshaller] -FastParser: Optional[ExpatParser] -FastUnmarshaller: Optional[Unmarshaller] +FastMarshaller: Marshaller | None +FastParser: ExpatParser | None +FastUnmarshaller: Unmarshaller | None -def getparser(use_datetime: bool = ..., use_builtin_types: bool = ...) -> Tuple[ExpatParser, Unmarshaller]: ... +def getparser(use_datetime: bool = ..., use_builtin_types: bool = ...) -> tuple[ExpatParser, Unmarshaller]: ... def dumps( - params: Union[Fault, Tuple[_Marshallable, ...]], - methodname: Optional[str] = ..., - methodresponse: Optional[bool] = ..., - encoding: Optional[str] = ..., + params: Fault | Tuple[_Marshallable, ...], + methodname: str | None = ..., + methodresponse: bool | None = ..., + encoding: str | None = ..., allow_none: bool = ..., ) -> str: ... -def loads( - data: str, use_datetime: bool = ..., use_builtin_types: bool = ... -) -> Tuple[Tuple[_Marshallable, ...], Optional[str]]: ... +def loads(data: str, use_datetime: bool = ..., use_builtin_types: bool = ...) -> tuple[Tuple[_Marshallable, ...], str | None]: ... def gzip_encode(data: bytes) -> bytes: ... # undocumented def gzip_decode(data: bytes, max_decode: int = ...) -> bytes: ... # undocumented @@ -214,19 +212,19 @@ class _Method: # undocumented class Transport: - user_agent: str = ... - accept_gzip_encoding: bool = ... - encode_threshold: Optional[int] = ... + user_agent: str + accept_gzip_encoding: bool + encode_threshold: int | None _use_datetime: bool _use_builtin_types: bool - _connection: Tuple[Optional[_HostType], Optional[http.client.HTTPConnection]] - _headers: List[Tuple[str, str]] - _extra_headers: List[Tuple[str, str]] + _connection: tuple[_HostType | None, http.client.HTTPConnection | None] + _headers: list[tuple[str, str]] + _extra_headers: list[tuple[str, str]] if sys.version_info >= (3, 8): def __init__( - self, use_datetime: bool = ..., use_builtin_types: bool = ..., *, headers: Iterable[Tuple[str, str]] = ... + self, use_datetime: bool = ..., use_builtin_types: bool = ..., *, headers: Iterable[tuple[str, str]] = ... ) -> None: ... else: def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ...) -> None: ... @@ -234,12 +232,12 @@ class Transport: def single_request( self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ... ) -> Tuple[_Marshallable, ...]: ... - def getparser(self) -> Tuple[ExpatParser, Unmarshaller]: ... - def get_host_info(self, host: _HostType) -> Tuple[str, List[Tuple[str, str]], Dict[str, str]]: ... + def getparser(self) -> tuple[ExpatParser, Unmarshaller]: ... + def get_host_info(self, host: _HostType) -> tuple[str, list[tuple[str, str]], dict[str, str]]: ... def make_connection(self, host: _HostType) -> http.client.HTTPConnection: ... def close(self) -> None: ... def send_request(self, host: _HostType, handler: str, request_body: bytes, debug: bool) -> http.client.HTTPConnection: ... - def send_headers(self, connection: http.client.HTTPConnection, headers: List[Tuple[str, str]]) -> None: ... + def send_headers(self, connection: http.client.HTTPConnection, headers: list[tuple[str, str]]) -> None: ... def send_content(self, connection: http.client.HTTPConnection, request_body: bytes) -> None: ... def parse_response(self, response: http.client.HTTPResponse) -> Tuple[_Marshallable, ...]: ... @@ -251,11 +249,11 @@ class SafeTransport(Transport): use_datetime: bool = ..., use_builtin_types: bool = ..., *, - headers: Iterable[Tuple[str, str]] = ..., - context: Optional[Any] = ..., + headers: Iterable[tuple[str, str]] = ..., + context: Any | None = ..., ) -> None: ... else: - def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ..., *, context: Optional[Any] = ...) -> None: ... + def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ..., *, context: Any | None = ...) -> None: ... def make_connection(self, host: _HostType) -> http.client.HTTPSConnection: ... class ServerProxy: @@ -271,28 +269,28 @@ class ServerProxy: def __init__( self, uri: str, - transport: Optional[Transport] = ..., - encoding: Optional[str] = ..., + transport: Transport | None = ..., + encoding: str | None = ..., verbose: bool = ..., allow_none: bool = ..., use_datetime: bool = ..., use_builtin_types: bool = ..., *, - headers: Iterable[Tuple[str, str]] = ..., - context: Optional[Any] = ..., + headers: Iterable[tuple[str, str]] = ..., + context: Any | None = ..., ) -> None: ... else: def __init__( self, uri: str, - transport: Optional[Transport] = ..., - encoding: Optional[str] = ..., + transport: Transport | None = ..., + encoding: str | None = ..., verbose: bool = ..., allow_none: bool = ..., use_datetime: bool = ..., use_builtin_types: bool = ..., *, - context: Optional[Any] = ..., + context: Any | None = ..., ) -> None: ... def __getattr__(self, name: str) -> _Method: ... @overload @@ -300,10 +298,10 @@ class ServerProxy: @overload def __call__(self, attr: Literal["transport"]) -> Transport: ... @overload - def __call__(self, attr: str) -> Union[Callable[[], None], Transport]: ... - def __enter__(self) -> ServerProxy: ... + def __call__(self, attr: str) -> Callable[[], None] | Transport: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __close(self) -> None: ... # undocumented def __request(self, methodname: str, params: Tuple[_Marshallable, ...]) -> Tuple[_Marshallable, ...]: ... # undocumented diff --git a/mypy/typeshed/stdlib/xmlrpc/server.pyi b/mypy/typeshed/stdlib/xmlrpc/server.pyi index f6a097d91d06..bf5611fbaa96 100644 --- a/mypy/typeshed/stdlib/xmlrpc/server.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/server.pyi @@ -3,12 +3,11 @@ import pydoc import socketserver import sys from datetime import datetime -from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Pattern, Protocol, Tuple, Type, Union +from typing import Any, Callable, Dict, Iterable, List, Mapping, Pattern, Protocol, Tuple, Type, Union from xmlrpc.client import Fault -_Marshallable = Union[ - None, bool, int, float, str, bytes, Tuple[Any, ...], List[Any], Dict[Any, Any], datetime -] # TODO: Recursive type on tuple, list, dict +# TODO: Recursive type on tuple, list, dict +_Marshallable = Union[None, bool, int, float, str, bytes, Tuple[Any, ...], List[Any], Dict[Any, Any], datetime] # The dispatch accepts anywhere from 0 to N arguments, no easy way to allow this in mypy class _DispatchArity0(Protocol): @@ -34,78 +33,74 @@ class _DispatchArityN(Protocol): _DispatchProtocol = Union[_DispatchArity0, _DispatchArity1, _DispatchArity2, _DispatchArity3, _DispatchArity4, _DispatchArityN] def resolve_dotted_attribute(obj: Any, attr: str, allow_dotted_names: bool = ...) -> Any: ... # undocumented -def list_public_methods(obj: Any) -> List[str]: ... # undocumented +def list_public_methods(obj: Any) -> list[str]: ... # undocumented class SimpleXMLRPCDispatcher: # undocumented - funcs: Dict[str, _DispatchProtocol] - instance: Optional[Any] + funcs: dict[str, _DispatchProtocol] + instance: Any | None allow_none: bool encoding: str use_builtin_types: bool - def __init__(self, allow_none: bool = ..., encoding: Optional[str] = ..., use_builtin_types: bool = ...) -> None: ... + def __init__(self, allow_none: bool = ..., encoding: str | None = ..., use_builtin_types: bool = ...) -> None: ... def register_instance(self, instance: Any, allow_dotted_names: bool = ...) -> None: ... if sys.version_info >= (3, 7): - def register_function( - self, function: Optional[_DispatchProtocol] = ..., name: Optional[str] = ... - ) -> Callable[..., Any]: ... + def register_function(self, function: _DispatchProtocol | None = ..., name: str | None = ...) -> Callable[..., Any]: ... else: - def register_function(self, function: _DispatchProtocol, name: Optional[str] = ...) -> Callable[..., Any]: ... + def register_function(self, function: _DispatchProtocol, name: str | None = ...) -> Callable[..., Any]: ... def register_introspection_functions(self) -> None: ... def register_multicall_functions(self) -> None: ... def _marshaled_dispatch( self, data: str, - dispatch_method: Optional[ - Callable[[Optional[str], Tuple[_Marshallable, ...]], Union[Fault, Tuple[_Marshallable, ...]]] - ] = ..., - path: Optional[Any] = ..., + dispatch_method: Callable[[str | None, Tuple[_Marshallable, ...]], Fault | Tuple[_Marshallable, ...]] | None = ..., + path: Any | None = ..., ) -> str: ... # undocumented - def system_listMethods(self) -> List[str]: ... # undocumented + def system_listMethods(self) -> list[str]: ... # undocumented def system_methodSignature(self, method_name: str) -> str: ... # undocumented def system_methodHelp(self, method_name: str) -> str: ... # undocumented - def system_multicall(self, call_list: List[Dict[str, _Marshallable]]) -> List[_Marshallable]: ... # undocumented + def system_multicall(self, call_list: list[dict[str, _Marshallable]]) -> list[_Marshallable]: ... # undocumented def _dispatch(self, method: str, params: Iterable[_Marshallable]) -> _Marshallable: ... # undocumented class SimpleXMLRPCRequestHandler(http.server.BaseHTTPRequestHandler): - rpc_paths: Tuple[str, str] = ... - encode_threshold: int = ... # undocumented + rpc_paths: tuple[str, str] + encode_threshold: int # undocumented aepattern: Pattern[str] # undocumented - def accept_encodings(self) -> Dict[str, float]: ... + def accept_encodings(self) -> dict[str, float]: ... def is_rpc_path_valid(self) -> bool: ... def do_POST(self) -> None: ... - def decode_request_content(self, data: bytes) -> Optional[bytes]: ... + def decode_request_content(self, data: bytes) -> bytes | None: ... def report_404(self) -> None: ... - def log_request(self, code: Union[int, str] = ..., size: Union[int, str] = ...) -> None: ... + def log_request(self, code: int | str = ..., size: int | str = ...) -> None: ... class SimpleXMLRPCServer(socketserver.TCPServer, SimpleXMLRPCDispatcher): - allow_reuse_address: bool = ... - _send_traceback_handler: bool = ... + allow_reuse_address: bool + _send_traceback_handler: bool def __init__( self, - addr: Tuple[str, int], + addr: tuple[str, int], requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., bind_and_activate: bool = ..., use_builtin_types: bool = ..., ) -> None: ... class MultiPathXMLRPCServer(SimpleXMLRPCServer): # undocumented - dispatchers: Dict[str, SimpleXMLRPCDispatcher] + dispatchers: dict[str, SimpleXMLRPCDispatcher] allow_none: bool encoding: str def __init__( self, - addr: Tuple[str, int], + addr: tuple[str, int], requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., bind_and_activate: bool = ..., use_builtin_types: bool = ..., ) -> None: ... @@ -114,21 +109,19 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): # undocumented def _marshaled_dispatch( self, data: str, - dispatch_method: Optional[ - Callable[[Optional[str], Tuple[_Marshallable, ...]], Union[Fault, Tuple[_Marshallable, ...]]] - ] = ..., - path: Optional[Any] = ..., + dispatch_method: Callable[[str | None, Tuple[_Marshallable, ...]], Fault | Tuple[_Marshallable, ...]] | None = ..., + path: Any | None = ..., ) -> str: ... class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): - def __init__(self, allow_none: bool = ..., encoding: Optional[str] = ..., use_builtin_types: bool = ...) -> None: ... + def __init__(self, allow_none: bool = ..., encoding: str | None = ..., use_builtin_types: bool = ...) -> None: ... def handle_xmlrpc(self, request_text: str) -> None: ... def handle_get(self) -> None: ... - def handle_request(self, request_text: Optional[str] = ...) -> None: ... + def handle_request(self, request_text: str | None = ...) -> None: ... class ServerHTMLDoc(pydoc.HTMLDoc): # undocumented - def docroutine(self, object: object, name: str, mod: Optional[str] = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., cl: Optional[type] = ...) -> str: ... # type: ignore - def docserver(self, server_name: str, package_documentation: str, methods: Dict[str, str]) -> str: ... + def docroutine(self, object: object, name: str, mod: str | None = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., cl: type | None = ...) -> str: ... # type: ignore + def docserver(self, server_name: str, package_documentation: str, methods: dict[str, str]) -> str: ... class XMLRPCDocGenerator: # undocumented @@ -147,11 +140,11 @@ class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): class DocXMLRPCServer(SimpleXMLRPCServer, XMLRPCDocGenerator): def __init__( self, - addr: Tuple[str, int], + addr: tuple[str, int], requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., - encoding: Optional[str] = ..., + encoding: str | None = ..., bind_and_activate: bool = ..., use_builtin_types: bool = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/zipapp.pyi b/mypy/typeshed/stdlib/zipapp.pyi index e1b38e9711b6..581d2b72a664 100644 --- a/mypy/typeshed/stdlib/zipapp.pyi +++ b/mypy/typeshed/stdlib/zipapp.pyi @@ -1,6 +1,6 @@ import sys from pathlib import Path -from typing import BinaryIO, Callable, Optional, Union +from typing import BinaryIO, Callable, Union _Path = Union[str, Path, BinaryIO] @@ -9,16 +9,16 @@ class ZipAppError(ValueError): ... if sys.version_info >= (3, 7): def create_archive( source: _Path, - target: Optional[_Path] = ..., - interpreter: Optional[str] = ..., - main: Optional[str] = ..., - filter: Optional[Callable[[Path], bool]] = ..., + target: _Path | None = ..., + interpreter: str | None = ..., + main: str | None = ..., + filter: Callable[[Path], bool] | None = ..., compressed: bool = ..., ) -> None: ... else: def create_archive( - source: _Path, target: Optional[_Path] = ..., interpreter: Optional[str] = ..., main: Optional[str] = ... + source: _Path, target: _Path | None = ..., interpreter: str | None = ..., main: str | None = ... ) -> None: ... def get_interpreter(archive: _Path) -> str: ... diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index 91727aa540fb..2335428549dc 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -1,165 +1,197 @@ import io import sys -from _typeshed import StrPath +from _typeshed import Self, StrPath +from os import PathLike from types import TracebackType -from typing import ( - IO, - Any, - Callable, - Dict, - Iterable, - Iterator, - List, - Optional, - Pattern, - Protocol, - Sequence, - Text, - Tuple, - Type, - Union, -) - -_SZI = Union[Text, ZipInfo] -_DT = Tuple[int, int, int, int, int, int] - -if sys.version_info >= (3,): - class BadZipFile(Exception): ... - BadZipfile = BadZipFile -else: - class BadZipfile(Exception): ... +from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, Tuple, Type, overload +from typing_extensions import Literal +_DateTuple = Tuple[int, int, int, int, int, int] +_ReadWriteMode = Literal["r", "w"] +_ReadWriteBinaryMode = Literal["r", "w", "rb", "wb"] +_ZipFileMode = Literal["r", "w", "x", "a"] + +class BadZipFile(Exception): ... + +BadZipfile = BadZipFile error = BadZipfile class LargeZipFile(Exception): ... -class ZipExtFile(io.BufferedIOBase): - MAX_N: int = ... - MIN_READ_SIZE: int = ... +class _ZipStream(Protocol): + def read(self, __n: int) -> bytes: ... + # The following methods are optional: + # def seekable(self) -> bool: ... + # def tell(self) -> int: ... + # def seek(self, __n: int) -> object: ... - if sys.version_info < (3, 6): - PATTERN: Pattern[str] = ... +class _ClosableZipStream(_ZipStream, Protocol): + def close(self) -> object: ... + +class ZipExtFile(io.BufferedIOBase): + MAX_N: int + MIN_READ_SIZE: int if sys.version_info >= (3, 7): - MAX_SEEK_READ: int = ... + MAX_SEEK_READ: int - newlines: Optional[List[bytes]] - mode: str + newlines: list[bytes] | None + mode: _ReadWriteMode name: str if sys.version_info >= (3, 7): + @overload def __init__( - self, fileobj: IO[bytes], mode: str, zipinfo: ZipInfo, pwd: Optional[bytes] = ..., close_fileobj: bool = ... + self, + fileobj: _ClosableZipStream, + mode: _ReadWriteMode, + zipinfo: ZipInfo, + pwd: bytes | None, + close_fileobj: Literal[True], + ) -> None: ... + @overload + def __init__( + self, + fileobj: _ClosableZipStream, + mode: _ReadWriteMode, + zipinfo: ZipInfo, + pwd: bytes | None = ..., + *, + close_fileobj: Literal[True], + ) -> None: ... + @overload + def __init__( + self, + fileobj: _ZipStream, + mode: _ReadWriteMode, + zipinfo: ZipInfo, + pwd: bytes | None = ..., + close_fileobj: Literal[False] = ..., ) -> None: ... else: + @overload + def __init__( + self, + fileobj: _ClosableZipStream, + mode: _ReadWriteMode, + zipinfo: ZipInfo, + decrypter: Callable[[Sequence[int]], bytes] | None, + close_fileobj: Literal[True], + ) -> None: ... + @overload + def __init__( + self, + fileobj: _ClosableZipStream, + mode: _ReadWriteMode, + zipinfo: ZipInfo, + decrypter: Callable[[Sequence[int]], bytes] | None = ..., + *, + close_fileobj: Literal[True], + ) -> None: ... + @overload def __init__( self, - fileobj: IO[bytes], - mode: str, + fileobj: _ZipStream, + mode: _ReadWriteMode, zipinfo: ZipInfo, - decrypter: Optional[Callable[[Sequence[int]], bytes]] = ..., - close_fileobj: bool = ..., + decrypter: Callable[[Sequence[int]], bytes] | None = ..., + close_fileobj: Literal[False] = ..., ) -> None: ... - def read(self, n: Optional[int] = ...) -> bytes: ... + def read(self, n: int | None = ...) -> bytes: ... def readline(self, limit: int = ...) -> bytes: ... # type: ignore def __repr__(self) -> str: ... def peek(self, n: int = ...) -> bytes: ... - def read1(self, n: Optional[int]) -> bytes: ... # type: ignore + def read1(self, n: int | None) -> bytes: ... # type: ignore + if sys.version_info >= (3, 7): + def seek(self, offset: int, whence: int = ...) -> int: ... class _Writer(Protocol): - def write(self, __s: str) -> Any: ... + def write(self, __s: str) -> object: ... class ZipFile: - filename: Optional[Text] + filename: str | None debug: int comment: bytes - filelist: List[ZipInfo] - fp: Optional[IO[bytes]] - NameToInfo: Dict[Text, ZipInfo] + filelist: list[ZipInfo] + fp: IO[bytes] | None + NameToInfo: dict[str, ZipInfo] start_dir: int # undocumented + compression: int # undocumented + compresslevel: int | None # undocumented + mode: _ZipFileMode # undocumented + pwd: str | None # undocumented if sys.version_info >= (3, 8): def __init__( self, - file: Union[StrPath, IO[bytes]], - mode: str = ..., + file: StrPath | IO[bytes], + mode: _ZipFileMode = ..., compression: int = ..., allowZip64: bool = ..., - compresslevel: Optional[int] = ..., + compresslevel: int | None = ..., *, strict_timestamps: bool = ..., ) -> None: ... elif sys.version_info >= (3, 7): def __init__( self, - file: Union[StrPath, IO[bytes]], - mode: str = ..., + file: StrPath | IO[bytes], + mode: _ZipFileMode = ..., compression: int = ..., allowZip64: bool = ..., - compresslevel: Optional[int] = ..., + compresslevel: int | None = ..., ) -> None: ... else: def __init__( - self, file: Union[StrPath, IO[bytes]], mode: Text = ..., compression: int = ..., allowZip64: bool = ... + self, file: StrPath | IO[bytes], mode: _ZipFileMode = ..., compression: int = ..., allowZip64: bool = ... ) -> None: ... - def __enter__(self) -> ZipFile: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType] + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def close(self) -> None: ... - def getinfo(self, name: Text) -> ZipInfo: ... - def infolist(self) -> List[ZipInfo]: ... - def namelist(self) -> List[Text]: ... - def open(self, name: _SZI, mode: Text = ..., pwd: Optional[bytes] = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... - def extract(self, member: _SZI, path: Optional[StrPath] = ..., pwd: Optional[bytes] = ...) -> str: ... + def getinfo(self, name: str) -> ZipInfo: ... + def infolist(self) -> list[ZipInfo]: ... + def namelist(self) -> list[str]: ... + def open( + self, name: str | ZipInfo, mode: _ReadWriteMode = ..., pwd: bytes | None = ..., *, force_zip64: bool = ... + ) -> IO[bytes]: ... + def extract(self, member: str | ZipInfo, path: StrPath | None = ..., pwd: bytes | None = ...) -> str: ... def extractall( - self, path: Optional[StrPath] = ..., members: Optional[Iterable[Text]] = ..., pwd: Optional[bytes] = ... + self, path: StrPath | None = ..., members: Iterable[str | ZipInfo] | None = ..., pwd: bytes | None = ... ) -> None: ... - if sys.version_info >= (3,): - def printdir(self, file: Optional[_Writer] = ...) -> None: ... - else: - def printdir(self) -> None: ... + def printdir(self, file: _Writer | None = ...) -> None: ... def setpassword(self, pwd: bytes) -> None: ... - def read(self, name: _SZI, pwd: Optional[bytes] = ...) -> bytes: ... - def testzip(self) -> Optional[str]: ... + def read(self, name: str | ZipInfo, pwd: bytes | None = ...) -> bytes: ... + def testzip(self) -> str | None: ... if sys.version_info >= (3, 7): def write( self, filename: StrPath, - arcname: Optional[StrPath] = ..., - compress_type: Optional[int] = ..., - compresslevel: Optional[int] = ..., + arcname: StrPath | None = ..., + compress_type: int | None = ..., + compresslevel: int | None = ..., ) -> None: ... else: - def write(self, filename: StrPath, arcname: Optional[StrPath] = ..., compress_type: Optional[int] = ...) -> None: ... + def write(self, filename: StrPath, arcname: StrPath | None = ..., compress_type: int | None = ...) -> None: ... if sys.version_info >= (3, 7): def writestr( self, - zinfo_or_arcname: _SZI, - data: Union[bytes, str], - compress_type: Optional[int] = ..., - compresslevel: Optional[int] = ..., + zinfo_or_arcname: str | ZipInfo, + data: bytes | str, + compress_type: int | None = ..., + compresslevel: int | None = ..., ) -> None: ... - elif sys.version_info >= (3,): - def writestr(self, zinfo_or_arcname: _SZI, data: Union[bytes, str], compress_type: Optional[int] = ...) -> None: ... else: - def writestr(self, zinfo_or_arcname: _SZI, bytes: bytes, compress_type: Optional[int] = ...) -> None: ... + def writestr(self, zinfo_or_arcname: str | ZipInfo, data: bytes | str, compress_type: int | None = ...) -> None: ... class PyZipFile(ZipFile): - if sys.version_info >= (3,): - def __init__( - self, - file: Union[str, IO[bytes]], - mode: str = ..., - compression: int = ..., - allowZip64: bool = ..., - optimize: int = ..., - ) -> None: ... - def writepy(self, pathname: str, basename: str = ..., filterfunc: Optional[Callable[[str], bool]] = ...) -> None: ... - else: - def writepy(self, pathname: Text, basename: Text = ...) -> None: ... + def __init__( + self, file: str | IO[bytes], mode: _ZipFileMode = ..., compression: int = ..., allowZip64: bool = ..., optimize: int = ... + ) -> None: ... + def writepy(self, pathname: str, basename: str = ..., filterfunc: Callable[[str], bool] | None = ...) -> None: ... class ZipInfo: - filename: Text - date_time: _DT + filename: str + date_time: _DateTuple compress_type: int comment: bytes extra: bytes @@ -175,29 +207,32 @@ class ZipInfo: CRC: int compress_size: int file_size: int - def __init__(self, filename: Optional[Text] = ..., date_time: Optional[_DT] = ...) -> None: ... + orig_filename: str # undocumented + def __init__(self, filename: str = ..., date_time: _DateTuple = ...) -> None: ... if sys.version_info >= (3, 8): @classmethod - def from_file(cls, filename: StrPath, arcname: Optional[StrPath] = ..., *, strict_timestamps: bool = ...) -> ZipInfo: ... - elif sys.version_info >= (3, 6): + def from_file(cls, filename: StrPath, arcname: StrPath | None = ..., *, strict_timestamps: bool = ...) -> ZipInfo: ... + else: @classmethod - def from_file(cls, filename: StrPath, arcname: Optional[StrPath] = ...) -> ZipInfo: ... - if sys.version_info >= (3, 6): - def is_dir(self) -> bool: ... - def FileHeader(self, zip64: Optional[bool] = ...) -> bytes: ... + def from_file(cls, filename: StrPath, arcname: StrPath | None = ...) -> ZipInfo: ... + def is_dir(self) -> bool: ... + def FileHeader(self, zip64: bool | None = ...) -> bytes: ... class _PathOpenProtocol(Protocol): - def __call__(self, mode: str = ..., pwd: Optional[bytes] = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... + def __call__(self, mode: _ReadWriteMode = ..., pwd: bytes | None = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... if sys.version_info >= (3, 8): class Path: @property def name(self) -> str: ... @property - def parent(self) -> Path: ... # undocumented - def __init__(self, root: Union[ZipFile, StrPath, IO[bytes]], at: str = ...) -> None: ... + def parent(self) -> PathLike[str]: ... # undocumented + if sys.version_info >= (3, 10): + @property + def filename(self) -> PathLike[str]: ... # undocumented + def __init__(self, root: ZipFile | StrPath | IO[bytes], at: str = ...) -> None: ... if sys.version_info >= (3, 9): - def open(self, mode: str = ..., pwd: Optional[bytes] = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... + def open(self, mode: _ReadWriteBinaryMode = ..., *args: Any, pwd: bytes | None = ..., **kwargs: Any) -> IO[bytes]: ... else: @property def open(self) -> _PathOpenProtocol: ... @@ -207,23 +242,25 @@ if sys.version_info >= (3, 8): def exists(self) -> bool: ... def read_text( self, - encoding: Optional[str] = ..., - errors: Optional[str] = ..., - newline: Optional[str] = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., line_buffering: bool = ..., write_through: bool = ..., ) -> str: ... def read_bytes(self) -> bytes: ... - def joinpath(self, add: StrPath) -> Path: ... # undocumented + if sys.version_info >= (3, 10): + def joinpath(self, *other: StrPath) -> Path: ... + else: + def joinpath(self, add: StrPath) -> Path: ... # undocumented def __truediv__(self, add: StrPath) -> Path: ... -def is_zipfile(filename: Union[StrPath, IO[bytes]]) -> bool: ... +def is_zipfile(filename: StrPath | IO[bytes]) -> bool: ... ZIP_STORED: int ZIP_DEFLATED: int ZIP64_LIMIT: int ZIP_FILECOUNT_LIMIT: int ZIP_MAX_COMMENT: int -if sys.version_info >= (3, 3): - ZIP_BZIP2: int - ZIP_LZMA: int +ZIP_BZIP2: int +ZIP_LZMA: int diff --git a/mypy/typeshed/stdlib/zipimport.pyi b/mypy/typeshed/stdlib/zipimport.pyi index 0d1a330942d4..155b9742aa57 100644 --- a/mypy/typeshed/stdlib/zipimport.pyi +++ b/mypy/typeshed/stdlib/zipimport.pyi @@ -1,7 +1,7 @@ import os import sys from types import CodeType, ModuleType -from typing import Any, List, Optional, Tuple, Union +from typing import Any if sys.version_info >= (3, 7): from importlib.abc import ResourceReader @@ -11,20 +11,14 @@ class ZipImportError(ImportError): ... class zipimporter(object): archive: str prefix: str - if sys.version_info >= (3, 6): - def __init__(self, path: Union[str, bytes, os.PathLike[Any]]) -> None: ... - else: - def __init__(self, path: Union[str, bytes]) -> None: ... - if sys.version_info >= (3,): - def find_loader( - self, fullname: str, path: Optional[str] = ... - ) -> Tuple[Optional[zipimporter], List[str]]: ... # undocumented - def find_module(self, fullname: str, path: Optional[str] = ...) -> Optional[zipimporter]: ... + def __init__(self, path: str | bytes | os.PathLike[Any]) -> None: ... + def find_loader(self, fullname: str, path: str | None = ...) -> tuple[zipimporter | None, list[str]]: ... # undocumented + def find_module(self, fullname: str, path: str | None = ...) -> zipimporter | None: ... def get_code(self, fullname: str) -> CodeType: ... def get_data(self, pathname: str) -> str: ... def get_filename(self, fullname: str) -> str: ... if sys.version_info >= (3, 7): - def get_resource_reader(self, fullname: str) -> Optional[ResourceReader]: ... # undocumented - def get_source(self, fullname: str) -> Optional[str]: ... + def get_resource_reader(self, fullname: str) -> ResourceReader | None: ... # undocumented + def get_source(self, fullname: str) -> str | None: ... def is_package(self, fullname: str) -> bool: ... def load_module(self, fullname: str) -> ModuleType: ... diff --git a/mypy/typeshed/stdlib/zlib.pyi b/mypy/typeshed/stdlib/zlib.pyi index 81a9f87ce42e..5acc4190f1fe 100644 --- a/mypy/typeshed/stdlib/zlib.pyi +++ b/mypy/typeshed/stdlib/zlib.pyi @@ -1,6 +1,5 @@ -import sys from array import array -from typing import Any, Optional, Union +from typing import Any DEFLATED: int DEF_MEM_LEVEL: int @@ -18,9 +17,8 @@ Z_HUFFMAN_ONLY: int Z_NO_FLUSH: int Z_RLE: int Z_SYNC_FLUSH: int -if sys.version_info >= (3,): - DEF_BUF_SIZE: int - ZLIB_RUNTIME_VERSION: str +DEF_BUF_SIZE: int +ZLIB_RUNTIME_VERSION: str class error(Exception): ... @@ -32,35 +30,16 @@ class _Compress: class _Decompress: unused_data: bytes unconsumed_tail: bytes - if sys.version_info >= (3,): - eof: bool + eof: bool def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... def flush(self, length: int = ...) -> bytes: ... def copy(self) -> _Decompress: ... def adler32(__data: bytes, __value: int = ...) -> int: ... def compress(__data: bytes, level: int = ...) -> bytes: ... - -if sys.version_info >= (3,): - def compressobj( - level: int = ..., - method: int = ..., - wbits: int = ..., - memLevel: int = ..., - strategy: int = ..., - zdict: Optional[bytes] = ..., - ) -> _Compress: ... - -else: - def compressobj( - level: int = ..., method: int = ..., wbits: int = ..., memlevel: int = ..., strategy: int = ... - ) -> _Compress: ... - -def crc32(__data: Union[array[Any], bytes], __value: int = ...) -> int: ... +def compressobj( + level: int = ..., method: int = ..., wbits: int = ..., memLevel: int = ..., strategy: int = ..., zdict: bytes | None = ... +) -> _Compress: ... +def crc32(__data: array[Any] | bytes, __value: int = ...) -> int: ... def decompress(__data: bytes, wbits: int = ..., bufsize: int = ...) -> bytes: ... - -if sys.version_info >= (3,): - def decompressobj(wbits: int = ..., zdict: bytes = ...) -> _Decompress: ... - -else: - def decompressobj(wbits: int = ...) -> _Decompress: ... +def decompressobj(wbits: int = ..., zdict: bytes = ...) -> _Decompress: ... diff --git a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi index 46cd6b871555..4f924e0cc4bf 100644 --- a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi +++ b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi @@ -1,7 +1,7 @@ -import os import typing +from _typeshed import StrPath from datetime import tzinfo -from typing import Any, AnyStr, Iterable, Optional, Protocol, Sequence, Set, Type, Union +from typing import Any, Iterable, Protocol, Sequence, Type _T = typing.TypeVar("_T", bound="ZoneInfo") @@ -16,15 +16,15 @@ class ZoneInfo(tzinfo): @classmethod def no_cache(cls: Type[_T], key: str) -> _T: ... @classmethod - def from_file(cls: Type[_T], __fobj: _IOBytes, key: Optional[str] = ...) -> _T: ... + def from_file(cls: Type[_T], __fobj: _IOBytes, key: str | None = ...) -> _T: ... @classmethod def clear_cache(cls, *, only_keys: Iterable[str] = ...) -> None: ... # Note: Both here and in clear_cache, the types allow the use of `str` where # a sequence of strings is required. This should be remedied if a solution # to this typing bug is found: https://github.com/python/typing/issues/256 -def reset_tzpath(to: Optional[Sequence[Union[os.PathLike[AnyStr], str]]] = ...) -> None: ... -def available_timezones() -> Set[str]: ... +def reset_tzpath(to: Sequence[StrPath] | None = ...) -> None: ... +def available_timezones() -> set[str]: ... TZPATH: Sequence[str] diff --git a/mypy/typeshed/stubs/mypy-extensions/@tests/stubtest_allowlist.txt b/mypy/typeshed/stubs/mypy-extensions/@tests/stubtest_allowlist.txt new file mode 100644 index 000000000000..bffaebc697dc --- /dev/null +++ b/mypy/typeshed/stubs/mypy-extensions/@tests/stubtest_allowlist.txt @@ -0,0 +1,2 @@ +mypy_extensions.FlexibleAlias +mypy_extensions.TypedDict diff --git a/mypy/typeshed/stubs/mypy-extensions/METADATA.toml b/mypy/typeshed/stubs/mypy-extensions/METADATA.toml index 8732c02c405f..79b51931ee0b 100644 --- a/mypy/typeshed/stubs/mypy-extensions/METADATA.toml +++ b/mypy/typeshed/stubs/mypy-extensions/METADATA.toml @@ -1,2 +1,2 @@ -version = "0.4" +version = "0.4.*" python2 = true diff --git a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi index a7bd0711f6d5..fc6de37d07d1 100644 --- a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi +++ b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi @@ -1,6 +1,6 @@ import abc import sys -from typing import Any, Callable, Dict, Generic, ItemsView, KeysView, Mapping, Optional, Type, TypeVar, Union, ValuesView +from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, Type, TypeVar, Union, ValuesView _T = TypeVar("_T") _U = TypeVar("_U") @@ -25,11 +25,11 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def viewvalues(self) -> ValuesView[object]: ... def __delitem__(self, k: NoReturn) -> None: ... -def TypedDict(typename: str, fields: Dict[str, Type[Any]], total: bool = ...) -> Type[Dict[str, Any]]: ... -def Arg(type: _T = ..., name: Optional[str] = ...) -> _T: ... -def DefaultArg(type: _T = ..., name: Optional[str] = ...) -> _T: ... -def NamedArg(type: _T = ..., name: Optional[str] = ...) -> _T: ... -def DefaultNamedArg(type: _T = ..., name: Optional[str] = ...) -> _T: ... +def TypedDict(typename: str, fields: dict[str, Type[Any]], total: bool = ...) -> Type[dict[str, Any]]: ... +def Arg(type: _T = ..., name: str | None = ...) -> _T: ... +def DefaultArg(type: _T = ..., name: str | None = ...) -> _T: ... +def NamedArg(type: _T = ..., name: str | None = ...) -> _T: ... +def DefaultNamedArg(type: _T = ..., name: str | None = ...) -> _T: ... def VarArg(type: _T = ...) -> _T: ... def KwArg(type: _T = ...) -> _T: ... diff --git a/mypy/typestate.py b/mypy/typestate.py index 39eca3e318ef..4cf2e19a1d26 100644 --- a/mypy/typestate.py +++ b/mypy/typestate.py @@ -4,7 +4,7 @@ """ from typing import Dict, Set, Tuple, Optional, List -from typing_extensions import ClassVar, Final +from typing_extensions import ClassVar, Final, TypeAlias as _TypeAlias from mypy.nodes import TypeInfo from mypy.types import Instance, TypeAliasType, get_proper_type, Type @@ -12,15 +12,15 @@ from mypy import state # Represents that the 'left' instance is a subtype of the 'right' instance -SubtypeRelationship = Tuple[Instance, Instance] +SubtypeRelationship: _TypeAlias = Tuple[Instance, Instance] # A tuple encoding the specific conditions under which we performed the subtype check. # (e.g. did we want a proper subtype? A regular subtype while ignoring variance?) -SubtypeKind = Tuple[bool, ...] +SubtypeKind: _TypeAlias = Tuple[bool, ...] # A cache that keeps track of whether the given TypeInfo is a part of a particular # subtype relationship -SubtypeCache = Dict[TypeInfo, Dict[SubtypeKind, Set[SubtypeRelationship]]] +SubtypeCache: _TypeAlias = Dict[TypeInfo, Dict[SubtypeKind, Set[SubtypeRelationship]]] class TypeState: @@ -38,7 +38,7 @@ class TypeState: # was done in strict optional mode and of the specific *kind* of subtyping relationship, # which we represent as an arbitrary hashable tuple. # We need the caches, since subtype checks for structural types are very slow. - _subtype_caches = {} # type: Final[SubtypeCache] + _subtype_caches: Final[SubtypeCache] = {} # This contains protocol dependencies generated after running a full build, # or after an update. These dependencies are special because: @@ -51,7 +51,7 @@ class TypeState: # A blocking error will be generated in this case, since we can't proceed safely. # For the description of kinds of protocol dependencies and corresponding examples, # see _snapshot_protocol_deps. - proto_deps = {} # type: ClassVar[Optional[Dict[str, Set[str]]]] + proto_deps: ClassVar[Optional[Dict[str, Set[str]]]] = {} # Protocols (full names) a given class attempted to implement. # Used to calculate fine grained protocol dependencies and optimize protocol @@ -59,13 +59,13 @@ class TypeState: # of type a.A to a function expecting something compatible with protocol p.P, # we'd have 'a.A' -> {'p.P', ...} in the map. This map is flushed after every incremental # update. - _attempted_protocols = {} # type: Final[Dict[str, Set[str]]] + _attempted_protocols: Final[Dict[str, Set[str]]] = {} # We also snapshot protocol members of the above protocols. For example, if we pass # a value of type a.A to a function expecting something compatible with Iterable, we'd have # 'a.A' -> {'__iter__', ...} in the map. This map is also flushed after every incremental # update. This map is needed to only generate dependencies like -> # instead of a wildcard to avoid unnecessarily invalidating classes. - _checked_against_members = {} # type: Final[Dict[str, Set[str]]] + _checked_against_members: Final[Dict[str, Set[str]]] = {} # TypeInfos that appeared as a left type (subtype) in a subtype check since latest # dependency snapshot update. This is an optimisation for fine grained mode; during a full # run we only take a dependency snapshot at the very end, so this set will contain all @@ -73,16 +73,16 @@ class TypeState: # dependencies generated from (typically) few TypeInfos that were subtype-checked # (i.e. appeared as r.h.s. in an assignment or an argument in a function call in # a re-checked target) during the update. - _rechecked_types = set() # type: Final[Set[TypeInfo]] + _rechecked_types: Final[Set[TypeInfo]] = set() # The two attributes below are assumption stacks for subtyping relationships between # recursive type aliases. Normally, one would pass type assumptions as an additional # arguments to is_subtype(), but this would mean updating dozens of related functions # threading this through all callsites (see also comment for TypeInfo.assuming). - _assuming = [] # type: Final[List[Tuple[TypeAliasType, TypeAliasType]]] - _assuming_proper = [] # type: Final[List[Tuple[TypeAliasType, TypeAliasType]]] + _assuming: Final[List[Tuple[TypeAliasType, TypeAliasType]]] = [] + _assuming_proper: Final[List[Tuple[TypeAliasType, TypeAliasType]]] = [] # Ditto for inference of generic constraints against recursive type aliases. - _inferring = [] # type: Final[List[TypeAliasType]] + _inferring: Final[List[TypeAliasType]] = [] # N.B: We do all of the accesses to these properties through # TypeState, instead of making these classmethods and accessing @@ -187,7 +187,7 @@ def __iter__(self) -> Iterator[int]: proper subtype checks, and calculating meets and joins, if this involves calling 'subtypes.is_protocol_implementation'). """ - deps = {} # type: Dict[str, Set[str]] + deps: Dict[str, Set[str]] = {} for info in TypeState._rechecked_types: for attr in TypeState._checked_against_members[info.fullname]: # The need for full MRO here is subtle, during an update, base classes of diff --git a/mypy/typetraverser.py b/mypy/typetraverser.py index e8f22a62e7c4..a03784b0406e 100644 --- a/mypy/typetraverser.py +++ b/mypy/typetraverser.py @@ -6,7 +6,7 @@ Type, SyntheticTypeVisitor, AnyType, UninhabitedType, NoneType, ErasedType, DeletedType, TypeVarType, LiteralType, Instance, CallableType, TupleType, TypedDictType, UnionType, Overloaded, TypeType, CallableArgument, UnboundType, TypeList, StarType, EllipsisType, - PlaceholderType, PartialType, RawExpressionType, TypeAliasType, TypeGuardType + PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType ) @@ -37,6 +37,9 @@ def visit_type_var(self, t: TypeVarType) -> None: # definition. We want to traverse everything just once. pass + def visit_param_spec(self, t: ParamSpecType) -> None: + pass + def visit_literal_type(self, t: LiteralType) -> None: t.fallback.accept(self) @@ -62,11 +65,8 @@ def visit_typeddict_type(self, t: TypedDictType) -> None: def visit_union_type(self, t: UnionType) -> None: self.traverse_types(t.items) - def visit_type_guard_type(self, t: TypeGuardType) -> None: - t.type_guard.accept(self) - def visit_overloaded(self, t: Overloaded) -> None: - self.traverse_types(t.items()) + self.traverse_types(t.items) def visit_type_type(self, t: TypeType) -> None: t.item.accept(self) diff --git a/mypy/typevars.py b/mypy/typevars.py index 113569874ceb..b49194f342e0 100644 --- a/mypy/typevars.py +++ b/mypy/typevars.py @@ -3,7 +3,7 @@ from mypy.nodes import TypeInfo from mypy.erasetype import erase_typevars -from mypy.types import Instance, TypeVarType, TupleType, Type, TypeOfAny, AnyType +from mypy.types import Instance, TypeVarType, TupleType, Type, TypeOfAny, AnyType, ParamSpecType def fill_typevars(typ: TypeInfo) -> Union[Instance, TupleType]: @@ -11,11 +11,22 @@ def fill_typevars(typ: TypeInfo) -> Union[Instance, TupleType]: For a generic G type with parameters T1, .., Tn, return G[T1, ..., Tn]. """ - tv = [] # type: List[Type] + tvs: List[Type] = [] # TODO: why do we need to keep both typ.type_vars and typ.defn.type_vars? for i in range(len(typ.defn.type_vars)): - tv.append(TypeVarType(typ.defn.type_vars[i])) - inst = Instance(typ, tv) + tv = typ.defn.type_vars[i] + # Change the line number + if isinstance(tv, TypeVarType): + tv = TypeVarType( + tv.name, tv.fullname, tv.id, tv.values, + tv.upper_bound, tv.variance, line=-1, column=-1, + ) + else: + assert isinstance(tv, ParamSpecType) + tv = ParamSpecType(tv.name, tv.fullname, tv.id, tv.flavor, tv.upper_bound, + line=-1, column=-1) + tvs.append(tv) + inst = Instance(typ, tvs) if typ.tuple_type is None: return inst return typ.tuple_type.copy_modified(fallback=inst) diff --git a/mypy/util.py b/mypy/util.py index e34dffcd3ab0..533e9c6bee6e 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -23,25 +23,28 @@ T = TypeVar('T') -ENCODING_RE = \ - re.compile(br'([ \t\v]*#.*(\r\n?|\n))??[ \t\v]*#.*coding[:=][ \t]*([-\w.]+)') # type: Final +ENCODING_RE: Final = re.compile(br"([ \t\v]*#.*(\r\n?|\n))??[ \t\v]*#.*coding[:=][ \t]*([-\w.]+)") -DEFAULT_SOURCE_OFFSET = 4 # type: Final -DEFAULT_COLUMNS = 80 # type: Final +DEFAULT_SOURCE_OFFSET: Final = 4 +DEFAULT_COLUMNS: Final = 80 # At least this number of columns will be shown on each side of # error location when printing source code snippet. -MINIMUM_WIDTH = 20 +MINIMUM_WIDTH: Final = 20 # VT100 color code processing was added in Windows 10, but only the second major update, # Threshold 2. Fortunately, everyone (even on LTSB, Long Term Support Branch) should # have a version of Windows 10 newer than this. Note that Windows 8 and below are not # supported, but are either going out of support, or make up only a few % of the market. -MINIMUM_WINDOWS_MAJOR_VT100 = 10 -MINIMUM_WINDOWS_BUILD_VT100 = 10586 +MINIMUM_WINDOWS_MAJOR_VT100: Final = 10 +MINIMUM_WINDOWS_BUILD_VT100: Final = 10586 -default_python2_interpreter = \ - ['python2', 'python', '/usr/bin/python', 'C:\\Python27\\python.exe'] # type: Final +default_python2_interpreter: Final = [ + "python2", + "python", + "/usr/bin/python", + "C:\\Python27\\python.exe", +] def split_module_names(mod_name: str) -> List[str]: @@ -65,7 +68,7 @@ def module_prefix(modules: Iterable[str], target: str) -> Optional[str]: def split_target(modules: Iterable[str], target: str) -> Optional[Tuple[str, str]]: - remaining = [] # type: List[str] + remaining: List[str] = [] while True: if target in modules: return target, '.'.join(remaining) @@ -193,7 +196,7 @@ def get_mypy_comments(source: str) -> List[Tuple[int, str]]: return results -_python2_interpreter = None # type: Optional[str] +_python2_interpreter: Optional[str] = None def try_find_python2_interpreter() -> Optional[str]: @@ -214,28 +217,28 @@ def try_find_python2_interpreter() -> Optional[str]: return None -PASS_TEMPLATE = """ +PASS_TEMPLATE: Final = """ -""" # type: Final +""" -FAIL_TEMPLATE = """ +FAIL_TEMPLATE: Final = """ {text} -""" # type: Final +""" -ERROR_TEMPLATE = """ +ERROR_TEMPLATE: Final = """ {text} -""" # type: Final +""" def write_junit_xml(dt: float, serious: bool, messages: List[str], path: str, @@ -269,7 +272,7 @@ class IdMapper: """ def __init__(self) -> None: - self.id_map = {} # type: Dict[object, int] + self.id_map: Dict[object, int] = {} self.next_id = 0 def id(self, o: object) -> int: @@ -284,6 +287,17 @@ def get_prefix(fullname: str) -> str: return fullname.rsplit('.', 1)[0] +def get_top_two_prefixes(fullname: str) -> Tuple[str, str]: + """Return one and two component prefixes of a fully qualified name. + + Given 'a.b.c.d', return ('a', 'a.b'). + + If fullname has only one component, return (fullname, fullname). + """ + components = fullname.split('.', 3) + return components[0], '.'.join(components[:2]) + + def correct_relative_import(cur_mod_id: str, relative: int, target: str, @@ -300,7 +314,7 @@ def correct_relative_import(cur_mod_id: str, return cur_mod_id + (("." + target) if target else ""), ok -fields_cache = {} # type: Final[Dict[Type[object], List[str]]] +fields_cache: Final[Dict[Type[object], List[str]]] = {} def get_class_descriptors(cls: 'Type[object]') -> Sequence[str]: @@ -382,13 +396,9 @@ def get_unique_redefinition_name(name: str, existing: Container[str]) -> str: def check_python_version(program: str) -> None: """Report issues with the Python used to run mypy, dmypy, or stubgen""" # Check for known bad Python versions. - if sys.version_info[:2] < (3, 5): - sys.exit("Running {name} with Python 3.4 or lower is not supported; " - "please upgrade to 3.5 or newer".format(name=program)) - # this can be deleted once we drop support for 3.5 - if sys.version_info[:3] == (3, 5, 0): - sys.exit("Running {name} with Python 3.5.0 is not supported; " - "please upgrade to 3.5.1 or newer".format(name=program)) + if sys.version_info[:2] < (3, 6): + sys.exit("Running {name} with Python 3.5 or lower is not supported; " + "please upgrade to 3.6 or newer".format(name=program)) def count_stats(errors: List[str]) -> Tuple[int, int]: @@ -401,7 +411,7 @@ def count_stats(errors: List[str]) -> Tuple[int, int]: def split_words(msg: str) -> List[str]: """Split line of text into words (but not within quoted groups).""" next_word = '' - res = [] # type: List[str] + res: List[str] = [] allow_break = True for c in msg: if c == ' ' and allow_break: @@ -444,7 +454,7 @@ def soft_wrap(msg: str, max_len: int, first_offset: int, """ words = split_words(msg) next_line = words.pop(0) - lines = [] # type: List[str] + lines: List[str] = [] while words: next_word = words.pop(0) max_line_len = max_len - num_indent if lines else max_len - first_offset @@ -556,11 +566,12 @@ def initialize_unix_colors(self) -> bool: under = curses.tigetstr('smul') set_color = curses.tigetstr('setaf') set_eseq = curses.tigetstr('cup') + normal = curses.tigetstr('sgr0') - if not (bold and under and set_color and set_eseq): + if not (bold and under and set_color and set_eseq and normal): return False - self.NORMAL = curses.tigetstr('sgr0').decode() + self.NORMAL = normal.decode() self.BOLD = bold.decode() self.UNDER = under.decode() self.DIM = parse_gray_color(set_eseq) @@ -711,3 +722,7 @@ def is_stub_package_file(file: str) -> bool: return False return any(component.endswith('-stubs') for component in os.path.abspath(file).split(os.sep)) + + +def unnamed_function(name: Optional[str]) -> bool: + return name is not None and name == "_" diff --git a/mypy/version.py b/mypy/version.py index 3f16ed69c395..e6188ccf96c1 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.820+dev' +__version__ = '0.930' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff --git a/mypy_self_check.ini b/mypy_self_check.ini index 452fd209bdf0..8fbdf9b96500 100644 --- a/mypy_self_check.ini +++ b/mypy_self_check.ini @@ -19,4 +19,4 @@ pretty = True always_false = MYPYC plugins = misc/proper_plugin.py python_version = 3.6 -exclude = /mypy/typeshed/ +exclude = mypy/typeshed/|mypyc/test-data/|mypyc/lib-rt/ diff --git a/scripts/mypyc b/mypyc/__main__.py old mode 100755 new mode 100644 similarity index 84% rename from scripts/mypyc rename to mypyc/__main__.py index e693c4cc58c0..aaaf9a83c8c5 --- a/scripts/mypyc +++ b/mypyc/__main__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 """Mypyc command-line tool. Usage: @@ -15,20 +14,19 @@ import os.path import subprocess import sys -import tempfile -import time base_path = os.path.join(os.path.dirname(__file__), '..') setup_format = """\ -from distutils.core import setup +from setuptools import setup from mypyc.build import mypycify setup(name='mypyc_output', - ext_modules=mypycify({}, opt_level="{}"), + ext_modules=mypycify({}, opt_level="{}", debug_level="{}"), ) """ + def main() -> None: build_dir = 'build' # can this be overridden?? try: @@ -37,10 +35,11 @@ def main() -> None: pass opt_level = os.getenv("MYPYC_OPT_LEVEL", '3') + debug_level = os.getenv("MYPYC_DEBUG_LEVEL", '1') setup_file = os.path.join(build_dir, 'setup.py') with open(setup_file, 'w') as f: - f.write(setup_format.format(sys.argv[1:], opt_level)) + f.write(setup_format.format(sys.argv[1:], opt_level, debug_level)) # We don't use run_setup (like we do in the test suite) because it throws # away the error code from distutils, and we don't care about the slight @@ -51,5 +50,6 @@ def main() -> None: cmd = subprocess.run([sys.executable, setup_file, 'build_ext', '--inplace'], env=env) sys.exit(cmd.returncode) + if __name__ == '__main__': main() diff --git a/mypyc/analysis/blockfreq.py b/mypyc/analysis/blockfreq.py new file mode 100644 index 000000000000..547fb9ce10d3 --- /dev/null +++ b/mypyc/analysis/blockfreq.py @@ -0,0 +1,32 @@ +"""Find basic blocks that are likely to be executed frequently. + +For example, this would not include blocks that have exception handlers. + +We can use different optimization heuristics for common and rare code. For +example, we can make IR fast to compile instead of fast to execute for rare +code. +""" + +from typing import Set + +from mypyc.ir.ops import BasicBlock, Goto, Branch + + +def frequently_executed_blocks(entry_point: BasicBlock) -> Set[BasicBlock]: + result: Set[BasicBlock] = set() + worklist = [entry_point] + while worklist: + block = worklist.pop() + if block in result: + continue + result.add(block) + t = block.terminator + if isinstance(t, Goto): + worklist.append(t.label) + elif isinstance(t, Branch): + if t.rare or t.traceback_entry is not None: + worklist.append(t.false) + else: + worklist.append(t.true) + worklist.append(t.false) + return result diff --git a/mypyc/analysis/dataflow.py b/mypyc/analysis/dataflow.py index 431976fae21f..9b459f77edbe 100644 --- a/mypyc/analysis/dataflow.py +++ b/mypyc/analysis/dataflow.py @@ -46,20 +46,15 @@ def get_cfg(blocks: List[BasicBlock]) -> CFG: basic block index -> (successors blocks, predecesssor blocks) """ succ_map = {} - pred_map = {} # type: Dict[BasicBlock, List[BasicBlock]] + pred_map: Dict[BasicBlock, List[BasicBlock]] = {} exits = set() for block in blocks: assert not any(isinstance(op, ControlOp) for op in block.ops[:-1]), ( "Control-flow ops must be at the end of blocks") - last = block.ops[-1] - if isinstance(last, Branch): - succ = [last.true, last.false] - elif isinstance(last, Goto): - succ = [last.label] - else: - succ = [] + succ = list(block.terminator.targets()) + if not succ: exits.add(block) # Errors can occur anywhere inside a block, which means that @@ -104,12 +99,8 @@ def cleanup_cfg(blocks: List[BasicBlock]) -> None: while changed: # First collapse any jumps to basic block that only contain a goto for block in blocks: - term = block.ops[-1] - if isinstance(term, Goto): - term.label = get_real_target(term.label) - elif isinstance(term, Branch): - term.true = get_real_target(term.true) - term.false = get_real_target(term.false) + for i, tgt in enumerate(block.terminator.targets()): + block.terminator.set_target(i, get_real_target(tgt)) # Then delete any blocks that have no predecessors changed = False @@ -236,8 +227,19 @@ class DefinedVisitor(BaseAnalysisVisitor): Note that this only deals with registers and not temporaries, on the assumption that we never access temporaries when they might be undefined. + + If strict_errors is True, then we regard any use of LoadErrorValue + as making a register undefined. Otherwise we only do if + `undefines` is set on the error value. + + This lets us only consider the things we care about during + uninitialized variable checking while capturing all possibly + undefined things for refcounting. """ + def __init__(self, strict_errors: bool = False) -> None: + self.strict_errors = strict_errors + def visit_branch(self, op: Branch) -> GenAndKill: return set(), set() @@ -252,7 +254,8 @@ def visit_register_op(self, op: RegisterOp) -> GenAndKill: def visit_assign(self, op: Assign) -> GenAndKill: # Loading an error value may undefine the register. - if isinstance(op.src, LoadErrorValue) and op.src.undefines: + if (isinstance(op.src, LoadErrorValue) + and (op.src.undefines or self.strict_errors)): return set(), {op.dest} else: return {op.dest}, set() @@ -284,7 +287,8 @@ def analyze_must_defined_regs( blocks: List[BasicBlock], cfg: CFG, initial_defined: Set[Value], - regs: Iterable[Value]) -> AnalysisResult[Value]: + regs: Iterable[Value], + strict_errors: bool = False) -> AnalysisResult[Value]: """Calculate always defined registers at each CFG location. This analysis can work before exception insertion, since it is a @@ -296,7 +300,7 @@ def analyze_must_defined_regs( """ return run_analysis(blocks=blocks, cfg=cfg, - gen_and_kill=DefinedVisitor(), + gen_and_kill=DefinedVisitor(strict_errors=strict_errors), initial=initial_defined, backward=False, kind=MUST_ANALYSIS, @@ -448,7 +452,7 @@ def analyze_live_regs(blocks: List[BasicBlock], MAYBE_ANALYSIS = 1 -# TODO the return type of this function is too complicated. Abtract it into its +# TODO the return type of this function is too complicated. Abstract it into its # own class. def run_analysis(blocks: List[BasicBlock], @@ -480,8 +484,8 @@ def run_analysis(blocks: List[BasicBlock], # Calculate kill and gen sets for entire basic blocks. for block in blocks: - gen = set() # type: Set[T] - kill = set() # type: Set[T] + gen: Set[T] = set() + kill: Set[T] = set() ops = block.ops if backward: ops = list(reversed(ops)) @@ -497,8 +501,8 @@ def run_analysis(blocks: List[BasicBlock], if not backward: worklist = worklist[::-1] # Reverse for a small performance improvement workset = set(worklist) - before = {} # type: Dict[BasicBlock, Set[T]] - after = {} # type: Dict[BasicBlock, Set[T]] + before: Dict[BasicBlock, Set[T]] = {} + after: Dict[BasicBlock, Set[T]] = {} for block in blocks: if kind == MAYBE_ANALYSIS: before[block] = set() @@ -520,7 +524,7 @@ def run_analysis(blocks: List[BasicBlock], label = worklist.pop() workset.remove(label) if pred_map[label]: - new_before = None # type: Union[Set[T], None] + new_before: Union[Set[T], None] = None for pred in pred_map[label]: if new_before is None: new_before = set(after[pred]) @@ -541,12 +545,12 @@ def run_analysis(blocks: List[BasicBlock], after[label] = new_after # Run algorithm for each basic block to generate opcode-level sets. - op_before = {} # type: Dict[Tuple[BasicBlock, int], Set[T]] - op_after = {} # type: Dict[Tuple[BasicBlock, int], Set[T]] + op_before: Dict[Tuple[BasicBlock, int], Set[T]] = {} + op_after: Dict[Tuple[BasicBlock, int], Set[T]] = {} for block in blocks: label = block cur = before[label] - ops_enum = enumerate(block.ops) # type: Iterator[Tuple[int, Op]] + ops_enum: Iterator[Tuple[int, Op]] = enumerate(block.ops) if backward: ops_enum = reversed(list(ops_enum)) for idx, op in ops_enum: diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py new file mode 100644 index 000000000000..f15beceff8ce --- /dev/null +++ b/mypyc/analysis/ircheck.py @@ -0,0 +1,165 @@ +"""Utilities for checking that internal ir is valid and consistent.""" +from typing import List, Union +from mypyc.ir.pprint import format_func +from mypyc.ir.ops import ( + OpVisitor, BasicBlock, Op, ControlOp, Goto, Branch, Return, Unreachable, + Assign, AssignMulti, LoadErrorValue, LoadLiteral, GetAttr, SetAttr, LoadStatic, + InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, + Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, + LoadMem, SetMem, GetElementPtr, LoadAddress, KeepAlive +) +from mypyc.ir.func_ir import FuncIR + + +class FnError(object): + def __init__(self, source: Union[Op, BasicBlock], desc: str) -> None: + self.source = source + self.desc = desc + + def __eq__(self, other: object) -> bool: + return isinstance(other, FnError) and self.source == other.source and \ + self.desc == other.desc + + def __repr__(self) -> str: + return f"FnError(source={self.source}, desc={self.desc})" + + +def check_func_ir(fn: FuncIR) -> List[FnError]: + """Applies validations to a given function ir and returns a list of errors found.""" + errors = [] + + for block in fn.blocks: + if not block.terminated: + errors.append(FnError( + source=block.ops[-1] if block.ops else block, + desc="Block not terminated", + )) + + op_checker = OpChecker(fn) + for block in fn.blocks: + for op in block.ops: + op.accept(op_checker) + + return errors + op_checker.errors + + +class IrCheckException(Exception): + pass + + +def assert_func_ir_valid(fn: FuncIR) -> None: + errors = check_func_ir(fn) + if errors: + raise IrCheckException("Internal error: Generated invalid IR: \n" + "\n".join( + format_func(fn, [(e.source, e.desc) for e in errors])), + ) + + +class OpChecker(OpVisitor[None]): + def __init__(self, parent_fn: FuncIR) -> None: + self.parent_fn = parent_fn + self.errors: List[FnError] = [] + + def fail(self, source: Op, desc: str) -> None: + self.errors.append(FnError(source=source, desc=desc)) + + def check_control_op_targets(self, op: ControlOp) -> None: + for target in op.targets(): + if target not in self.parent_fn.blocks: + self.fail(source=op, desc=f"Invalid control operation target: {target.label}") + + def visit_goto(self, op: Goto) -> None: + self.check_control_op_targets(op) + + def visit_branch(self, op: Branch) -> None: + self.check_control_op_targets(op) + + def visit_return(self, op: Return) -> None: + pass + + def visit_unreachable(self, op: Unreachable) -> None: + pass + + def visit_assign(self, op: Assign) -> None: + pass + + def visit_assign_multi(self, op: AssignMulti) -> None: + pass + + def visit_load_error_value(self, op: LoadErrorValue) -> None: + pass + + def visit_load_literal(self, op: LoadLiteral) -> None: + pass + + def visit_get_attr(self, op: GetAttr) -> None: + pass + + def visit_set_attr(self, op: SetAttr) -> None: + pass + + def visit_load_static(self, op: LoadStatic) -> None: + pass + + def visit_init_static(self, op: InitStatic) -> None: + pass + + def visit_tuple_get(self, op: TupleGet) -> None: + pass + + def visit_tuple_set(self, op: TupleSet) -> None: + pass + + def visit_inc_ref(self, op: IncRef) -> None: + pass + + def visit_dec_ref(self, op: DecRef) -> None: + pass + + def visit_call(self, op: Call) -> None: + pass + + def visit_method_call(self, op: MethodCall) -> None: + pass + + def visit_cast(self, op: Cast) -> None: + pass + + def visit_box(self, op: Box) -> None: + pass + + def visit_unbox(self, op: Unbox) -> None: + pass + + def visit_raise_standard_error(self, op: RaiseStandardError) -> None: + pass + + def visit_call_c(self, op: CallC) -> None: + pass + + def visit_truncate(self, op: Truncate) -> None: + pass + + def visit_load_global(self, op: LoadGlobal) -> None: + pass + + def visit_int_op(self, op: IntOp) -> None: + pass + + def visit_comparison_op(self, op: ComparisonOp) -> None: + pass + + def visit_load_mem(self, op: LoadMem) -> None: + pass + + def visit_set_mem(self, op: SetMem) -> None: + pass + + def visit_get_element_ptr(self, op: GetElementPtr) -> None: + pass + + def visit_load_address(self, op: LoadAddress) -> None: + pass + + def visit_keep_alive(self, op: KeepAlive) -> None: + pass diff --git a/mypyc/build.py b/mypyc/build.py index 088e481fc241..571fb0dd2f5a 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -4,7 +4,7 @@ modules to be passed to setup. A trivial setup.py for a mypyc built project, then, looks like: - from distutils.core import setup + from setuptools import setup from mypyc.build import mypycify setup(name='test_module', @@ -45,6 +45,13 @@ if TYPE_CHECKING: from distutils.core import Extension # noqa +try: + # Import setuptools so that it monkey-patch overrides distutils + import setuptools # type: ignore # noqa +except ImportError: + if sys.version_info >= (3, 12): + # Raise on Python 3.12, since distutils will go away forever + raise from distutils import sysconfig, ccompiler @@ -296,7 +303,7 @@ def write_file(path: str, contents: str) -> None: encoded_contents = contents.encode('utf-8') try: with open(path, 'rb') as f: - old_contents = f.read() # type: Optional[bytes] + old_contents: Optional[bytes] = f.read() except IOError: old_contents = None if old_contents != encoded_contents: @@ -328,9 +335,7 @@ def construct_groups( """ if separate is True: - groups = [ - ([source], None) for source in sources - ] # type: emitmodule.Groups + groups: emitmodule.Groups = [([source], None) for source in sources] elif isinstance(separate, list): groups = [] used_sources = set() @@ -362,7 +367,7 @@ def get_header_deps(cfiles: List[Tuple[str, str]]) -> List[str]: Arguments: cfiles: A list of (file name, file contents) pairs. """ - headers = set() # type: Set[str] + headers: Set[str] = set() for _, contents in cfiles: headers.update(re.findall(r'#include "(.*)"', contents)) @@ -406,7 +411,7 @@ def mypyc_build( # Write out the generated C and collect the files for each group # Should this be here?? - group_cfilenames = [] # type: List[Tuple[List[str], List[str]]] + group_cfilenames: List[Tuple[List[str], List[str]]] = [] for cfiles in group_cfiles: cfilenames = [] for cfile, ctext in cfiles: @@ -426,7 +431,8 @@ def mypycify( *, only_compile_paths: Optional[Iterable[str]] = None, verbose: bool = False, - opt_level: str = '3', + opt_level: str = "3", + debug_level: str = "1", strip_asserts: bool = False, multi_file: bool = False, separate: Union[bool, List[Tuple[List[str], Optional[str]]]] = False, @@ -449,6 +455,7 @@ def mypycify( verbose: Should mypyc be more verbose. Defaults to false. opt_level: The optimization level, as a string. Defaults to '3' (meaning '-O3'). + debug_level: The debug level, as a string. Defaults to '1' (meaning '-g1'). strip_asserts: Should asserts be stripped from the generated code. multi_file: Should each Python module be compiled into its own C source file. @@ -496,21 +503,23 @@ def mypycify( setup_mypycify_vars() # Create a compiler object so we can make decisions based on what - # compiler is being used. typeshed is missing some attribues on the + # compiler is being used. typeshed is missing some attributes on the # compiler object so we give it type Any - compiler = ccompiler.new_compiler() # type: Any + compiler: Any = ccompiler.new_compiler() sysconfig.customize_compiler(compiler) build_dir = compiler_options.target_dir - cflags = [] # type: List[str] + cflags: List[str] = [] if compiler.compiler_type == 'unix': cflags += [ - '-O{}'.format(opt_level), '-Werror', '-Wno-unused-function', '-Wno-unused-label', + '-O{}'.format(opt_level), + '-g{}'.format(debug_level), + '-Werror', '-Wno-unused-function', '-Wno-unused-label', '-Wno-unreachable-code', '-Wno-unused-variable', '-Wno-unused-command-line-argument', '-Wno-unknown-warning-option', ] - if 'gcc' in compiler.compiler[0]: + if 'gcc' in compiler.compiler[0] or 'gnu-cc' in compiler.compiler[0]: # This flag is needed for gcc but does not exist on clang. cflags += ['-Wno-unused-but-set-variable'] elif compiler.compiler_type == 'msvc': diff --git a/mypyc/codegen/cstring.py b/mypyc/codegen/cstring.py index 424a66e6f5ac..3626d2625e84 100644 --- a/mypyc/codegen/cstring.py +++ b/mypyc/codegen/cstring.py @@ -23,7 +23,7 @@ from typing_extensions import Final -CHAR_MAP = ['\\{:03o}'.format(i) for i in range(256)] # type: Final +CHAR_MAP: Final = ["\\{:03o}".format(i) for i in range(256)] # It is safe to use string.printable as it always uses the C locale. for c in string.printable: diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index e8b3c77be9d6..531121134b03 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -1,6 +1,6 @@ """Utilities for emitting C code.""" -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import List, Set, Dict, Optional, Callable, Union, Tuple import sys @@ -15,7 +15,7 @@ is_list_rprimitive, is_dict_rprimitive, is_set_rprimitive, is_tuple_rprimitive, is_none_rprimitive, is_object_rprimitive, object_rprimitive, is_str_rprimitive, int_rprimitive, is_optional_type, optional_value_type, is_int32_rprimitive, - is_int64_rprimitive, is_bit_rprimitive + is_int64_rprimitive, is_bit_rprimitive, is_range_rprimitive, is_bytes_rprimitive ) from mypyc.ir.func_ir import FuncDecl from mypyc.ir.class_ir import ClassIR, all_concrete_classes @@ -75,7 +75,7 @@ def __init__(self, self.group_name = group_name self.group_map = group_map or {} # Groups that this group depends on - self.group_deps = set() # type: Set[str] + self.group_deps: Set[str] = set() # The map below is used for generating declarations and # definitions at the top of the C file. The main idea is that they can @@ -84,11 +84,33 @@ def __init__(self, # A map of a C identifier to whatever the C identifier declares. Currently this is # used for declaring structs and the key corresponds to the name of the struct. # The declaration contains the body of the struct. - self.declarations = OrderedDict() # type: Dict[str, HeaderDeclaration] + self.declarations: Dict[str, HeaderDeclaration] = OrderedDict() self.literals = Literals() +class ErrorHandler: + """Describes handling errors in unbox/cast operations.""" + + +class AssignHandler(ErrorHandler): + """Assign an error value on error.""" + + +class GotoHandler(ErrorHandler): + """Goto label on error.""" + + def __init__(self, label: str) -> None: + self.label = label + + +class ReturnHandler(ErrorHandler): + """Return a constant value on error.""" + + def __init__(self, value: str) -> None: + self.value = value + + class Emitter: """Helper for C code generation.""" @@ -101,7 +123,7 @@ def __init__(self, self.capi_version = capi_version or sys.version_info[:2] self.names = context.names self.value_names = value_names or {} - self.fragments = [] # type: List[str] + self.fragments: List[str] = [] self._indent = 0 # Low-level operations @@ -326,35 +348,56 @@ def declare_tuple_struct(self, tuple_type: RTuple) -> None: is_type=True, ) - def emit_inc_ref(self, dest: str, rtype: RType) -> None: + def emit_inc_ref(self, dest: str, rtype: RType, *, rare: bool = False) -> None: """Increment reference count of C expression `dest`. For composite unboxed structures (e.g. tuples) recursively increment reference counts for each component. + + If rare is True, optimize for code size and compilation speed. """ if is_int_rprimitive(rtype): - self.emit_line('CPyTagged_IncRef(%s);' % dest) + if rare: + self.emit_line('CPyTagged_IncRef(%s);' % dest) + else: + self.emit_line('CPyTagged_INCREF(%s);' % dest) elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): self.emit_inc_ref('{}.f{}'.format(dest, i), item_type) elif not rtype.is_unboxed: + # Always inline, since this is a simple op self.emit_line('CPy_INCREF(%s);' % dest) # Otherwise assume it's an unboxed, pointerless value and do nothing. - def emit_dec_ref(self, dest: str, rtype: RType, is_xdec: bool = False) -> None: + def emit_dec_ref(self, + dest: str, + rtype: RType, + *, + is_xdec: bool = False, + rare: bool = False) -> None: """Decrement reference count of C expression `dest`. For composite unboxed structures (e.g. tuples) recursively decrement reference counts for each component. + + If rare is True, optimize for code size and compilation speed. """ x = 'X' if is_xdec else '' if is_int_rprimitive(rtype): - self.emit_line('CPyTagged_%sDecRef(%s);' % (x, dest)) + if rare: + self.emit_line('CPyTagged_%sDecRef(%s);' % (x, dest)) + else: + # Inlined + self.emit_line('CPyTagged_%sDECREF(%s);' % (x, dest)) elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): - self.emit_dec_ref('{}.f{}'.format(dest, i), item_type, is_xdec) + self.emit_dec_ref('{}.f{}'.format(dest, i), item_type, is_xdec=is_xdec, rare=rare) elif not rtype.is_unboxed: - self.emit_line('CPy_%sDecRef(%s);' % (x, dest)) + if rare: + self.emit_line('CPy_%sDecRef(%s);' % (x, dest)) + else: + # Inlined + self.emit_line('CPy_%sDECREF(%s);' % (x, dest)) # Otherwise assume it's an unboxed, pointerless value and do nothing. def pretty_name(self, typ: RType) -> str: @@ -363,8 +406,15 @@ def pretty_name(self, typ: RType) -> str: return '%s or None' % self.pretty_name(value_type) return str(typ) - def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, - custom_message: Optional[str] = None, optional: bool = False, + def emit_cast(self, + src: str, + dest: str, + typ: RType, + *, + declare_dest: bool = False, + error: Optional[ErrorHandler] = None, + raise_exception: bool = True, + optional: bool = False, src_type: Optional[RType] = None, likely: bool = True) -> None: """Emit code for casting a value of given type. @@ -373,21 +423,34 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, operates on boxed versions. This is necessary to properly handle types such as Optional[int] in compatibility glue. - Assign NULL (error value) to dest if the value has an incompatible type. + By default, assign NULL (error value) to dest if the value has + an incompatible type and raise TypeError. These can be customized + using 'error' and 'raise_exception'. - Always copy/steal the reference in src. + Always copy/steal the reference in 'src'. Args: src: Name of source C variable dest: Name of target C variable typ: Type of value declare_dest: If True, also declare the variable 'dest' + error: What happens on error + raise_exception: If True, also raise TypeError on failure likely: If the cast is likely to succeed (can be False for unions) """ - if custom_message is not None: - err = custom_message + error = error or AssignHandler() + if isinstance(error, AssignHandler): + handle_error = '%s = NULL;' % dest + elif isinstance(error, GotoHandler): + handle_error = 'goto %s;' % error.label else: - err = 'CPy_TypeError("{}", {});'.format(self.pretty_name(typ), src) + assert isinstance(error, ReturnHandler) + handle_error = 'return %s;' % error.value + if raise_exception: + raise_exc = 'CPy_TypeError("{}", {}); '.format(self.pretty_name(typ), src) + err = raise_exc + handle_error + else: + err = handle_error # Special case casting *from* optional if src_type and is_optional_type(src_type) and not is_object_rprimitive(typ): @@ -404,14 +467,13 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, ' {} = {};'.format(dest, src), 'else {', err, - '{} = NULL;'.format(dest), '}') return # TODO: Verify refcount handling. if (is_list_rprimitive(typ) or is_dict_rprimitive(typ) or is_set_rprimitive(typ) - or is_float_rprimitive(typ) or is_str_rprimitive(typ) or is_int_rprimitive(typ) - or is_bool_rprimitive(typ)): + or is_str_rprimitive(typ) or is_range_rprimitive(typ) or is_float_rprimitive(typ) + or is_int_rprimitive(typ) or is_bool_rprimitive(typ) or is_bit_rprimitive(typ)): if declare_dest: self.emit_line('PyObject *{};'.format(dest)) if is_list_rprimitive(typ): @@ -420,10 +482,12 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, prefix = 'PyDict' elif is_set_rprimitive(typ): prefix = 'PySet' - elif is_float_rprimitive(typ): - prefix = 'CPyFloat' elif is_str_rprimitive(typ): prefix = 'PyUnicode' + elif is_range_rprimitive(typ): + prefix = 'PyRange' + elif is_float_rprimitive(typ): + prefix = 'CPyFloat' elif is_int_rprimitive(typ): prefix = 'PyLong' elif is_bool_rprimitive(typ) or is_bit_rprimitive(typ): @@ -438,7 +502,18 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, ' {} = {};'.format(dest, src), 'else {', err, - '{} = NULL;'.format(dest), + '}') + elif is_bytes_rprimitive(typ): + if declare_dest: + self.emit_line('PyObject *{};'.format(dest)) + check = '(PyBytes_Check({}) || PyByteArray_Check({}))' + if likely: + check = '(likely{})'.format(check) + self.emit_arg_check(src, dest, typ, check.format(src, src), optional) + self.emit_lines( + ' {} = {};'.format(dest, src), + 'else {', + err, '}') elif is_tuple_rprimitive(typ): if declare_dest: @@ -452,7 +527,6 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, ' {} = {};'.format(dest, src), 'else {', err, - '{} = NULL;'.format(dest), '}') elif isinstance(typ, RInstance): if declare_dest: @@ -480,7 +554,6 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, ' {} = {};'.format(dest, src), 'else {', err, - '{} = NULL;'.format(dest), '}') elif is_none_rprimitive(typ): if declare_dest: @@ -494,7 +567,6 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, ' {} = {};'.format(dest, src), 'else {', err, - '{} = NULL;'.format(dest), '}') elif is_object_rprimitive(typ): if declare_dest: @@ -511,8 +583,14 @@ def emit_cast(self, src: str, dest: str, typ: RType, declare_dest: bool = False, else: assert False, 'Cast not implemented: %s' % typ - def emit_union_cast(self, src: str, dest: str, typ: RUnion, declare_dest: bool, - err: str, optional: bool, src_type: Optional[RType]) -> None: + def emit_union_cast(self, + src: str, + dest: str, + typ: RUnion, + declare_dest: bool, + err: str, + optional: bool, + src_type: Optional[RType]) -> None: """Emit cast to a union type. The arguments are similar to emit_cast. @@ -530,7 +608,7 @@ def emit_union_cast(self, src: str, dest: str, typ: RUnion, declare_dest: bool, dest, item, declare_dest=False, - custom_message='', + raise_exception=False, optional=False, likely=False) self.emit_line('if ({} != NULL) goto {};'.format(dest, good_label)) @@ -562,7 +640,7 @@ def emit_tuple_cast(self, src: str, dest: str, typ: RTuple, declare_dest: bool, dest, item, declare_dest=False, - custom_message='', + raise_exception=False, optional=False) self.emit_line('if ({} == NULL) goto {};'.format(dest, out_label)) @@ -578,31 +656,46 @@ def emit_arg_check(self, src: str, dest: str, typ: RType, check: str, optional: elif optional: self.emit_line('else {') - def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[str] = None, - declare_dest: bool = False, borrow: bool = False, - optional: bool = False) -> None: + def emit_unbox(self, + src: str, + dest: str, + typ: RType, + *, + declare_dest: bool = False, + error: Optional[ErrorHandler] = None, + raise_exception: bool = True, + optional: bool = False, + borrow: bool = False) -> None: """Emit code for unboxing a value of given type (from PyObject *). - Evaluate C code in 'failure' if the value has an incompatible type. + By default, assign error value to dest if the value has an + incompatible type and raise TypeError. These can be customized + using 'error' and 'raise_exception'. - Always generate a new reference. + Generate a new reference unless 'borrow' is True. Args: src: Name of source C variable dest: Name of target C variable typ: Type of value - failure: What happens on error declare_dest: If True, also declare the variable 'dest' + error: What happens on error + raise_exception: If True, also raise TypeError on failure borrow: If True, create a borrowed reference + """ + error = error or AssignHandler() # TODO: Verify refcount handling. - raise_exc = 'CPy_TypeError("{}", {});'.format(self.pretty_name(typ), src) - if custom_failure is not None: - failure = [raise_exc, - custom_failure] + if isinstance(error, AssignHandler): + failure = '%s = %s;' % (dest, self.c_error_value(typ)) + elif isinstance(error, GotoHandler): + failure = 'goto %s;' % error.label else: - failure = [raise_exc, - '%s = %s;' % (dest, self.c_error_value(typ))] + assert isinstance(error, ReturnHandler) + failure = 'return %s;' % error.value + if raise_exception: + raise_exc = 'CPy_TypeError("{}", {}); '.format(self.pretty_name(typ), src) + failure = raise_exc + failure if is_int_rprimitive(typ) or is_short_int_rprimitive(typ): if declare_dest: self.emit_line('CPyTagged {};'.format(dest)) @@ -613,7 +706,7 @@ def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[s else: self.emit_line(' {} = CPyTagged_FromObject({});'.format(dest, src)) self.emit_line('else {') - self.emit_lines(*failure) + self.emit_line(failure) self.emit_line('}') elif is_bool_rprimitive(typ) or is_bit_rprimitive(typ): # Whether we are borrowing or not makes no difference. @@ -621,7 +714,7 @@ def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[s self.emit_line('char {};'.format(dest)) self.emit_arg_check(src, dest, typ, '(unlikely(!PyBool_Check({}))) {{'.format(src), optional) - self.emit_lines(*failure) + self.emit_line(failure) self.emit_line('} else') conversion = '{} == Py_True'.format(src) self.emit_line(' {} = {};'.format(dest, conversion)) @@ -631,7 +724,7 @@ def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[s self.emit_line('char {};'.format(dest)) self.emit_arg_check(src, dest, typ, '(unlikely({} != Py_None)) {{'.format(src), optional) - self.emit_lines(*failure) + self.emit_line(failure) self.emit_line('} else') self.emit_line(' {} = 1;'.format(dest)) elif isinstance(typ, RTuple): @@ -653,7 +746,7 @@ def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[s # self.emit_arg_check(src, dest, typ, # '(!PyTuple_Check({}) || PyTuple_Size({}) != {}) {{'.format( # src, src, len(typ.types)), optional) - self.emit_lines(*failure) # TODO: Decrease refcount? + self.emit_line(failure) # TODO: Decrease refcount? self.emit_line('} else {') if not typ.types: self.emit_line('{}.empty_struct_error_flag = 0;'.format(dest)) @@ -664,7 +757,12 @@ def emit_unbox(self, src: str, dest: str, typ: RType, custom_failure: Optional[s temp2 = self.temp_name() # Unbox or check the item. if item_type.is_unboxed: - self.emit_unbox(temp, temp2, item_type, custom_failure, declare_dest=True, + self.emit_unbox(temp, + temp2, + item_type, + raise_exception=raise_exception, + error=error, + declare_dest=True, borrow=borrow) else: if not borrow: diff --git a/mypyc/codegen/emitclass.py b/mypyc/codegen/emitclass.py index 0cfaab07b573..9c960cf80bdd 100644 --- a/mypyc/codegen/emitclass.py +++ b/mypyc/codegen/emitclass.py @@ -2,15 +2,15 @@ from typing import Optional, List, Tuple, Dict, Callable, Mapping, Set -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from mypyc.common import PREFIX, NATIVE_PREFIX, REG_PREFIX, use_fastcall -from mypyc.codegen.emit import Emitter, HeaderDeclaration +from mypyc.codegen.emit import Emitter, HeaderDeclaration, ReturnHandler from mypyc.codegen.emitfunc import native_function_header from mypyc.codegen.emitwrapper import ( generate_dunder_wrapper, generate_hash_wrapper, generate_richcompare_wrapper, generate_bool_wrapper, generate_get_wrapper, generate_len_wrapper, - generate_set_del_item_wrapper, generate_contains_wrapper + generate_set_del_item_wrapper, generate_contains_wrapper, generate_bin_op_wrapper ) from mypyc.ir.rtypes import RType, RTuple, object_rprimitive from mypyc.ir.func_ir import FuncIR, FuncDecl, FUNC_STATICMETHOD, FUNC_CLASSMETHOD @@ -34,7 +34,7 @@ def wrapper_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: SlotGenerator = Callable[[ClassIR, FuncIR, Emitter], str] SlotTable = Mapping[str, Tuple[str, SlotGenerator]] -SLOT_DEFS = { +SLOT_DEFS: SlotTable = { '__init__': ('tp_init', lambda c, t, e: generate_init_for_class(c, t, e)), '__call__': ('tp_call', lambda c, t, e: generate_call_wrapper(c, t, e)), '__str__': ('tp_str', native_slot), @@ -43,28 +43,68 @@ def wrapper_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: '__iter__': ('tp_iter', native_slot), '__hash__': ('tp_hash', generate_hash_wrapper), '__get__': ('tp_descr_get', generate_get_wrapper), -} # type: SlotTable +} -AS_MAPPING_SLOT_DEFS = { +AS_MAPPING_SLOT_DEFS: SlotTable = { '__getitem__': ('mp_subscript', generate_dunder_wrapper), '__setitem__': ('mp_ass_subscript', generate_set_del_item_wrapper), '__delitem__': ('mp_ass_subscript', generate_set_del_item_wrapper), '__len__': ('mp_length', generate_len_wrapper), -} # type: SlotTable +} -AS_SEQUENCE_SLOT_DEFS = { +AS_SEQUENCE_SLOT_DEFS: SlotTable = { '__contains__': ('sq_contains', generate_contains_wrapper), -} # type: SlotTable +} -AS_NUMBER_SLOT_DEFS = { +AS_NUMBER_SLOT_DEFS: SlotTable = { '__bool__': ('nb_bool', generate_bool_wrapper), -} # type: SlotTable + '__neg__': ('nb_negative', generate_dunder_wrapper), + '__invert__': ('nb_invert', generate_dunder_wrapper), + '__int__': ('nb_int', generate_dunder_wrapper), + '__float__': ('nb_float', generate_dunder_wrapper), + '__add__': ('nb_add', generate_bin_op_wrapper), + '__radd__': ('nb_add', generate_bin_op_wrapper), + '__sub__': ('nb_subtract', generate_bin_op_wrapper), + '__rsub__': ('nb_subtract', generate_bin_op_wrapper), + '__mul__': ('nb_multiply', generate_bin_op_wrapper), + '__rmul__': ('nb_multiply', generate_bin_op_wrapper), + '__mod__': ('nb_remainder', generate_bin_op_wrapper), + '__rmod__': ('nb_remainder', generate_bin_op_wrapper), + '__truediv__': ('nb_true_divide', generate_bin_op_wrapper), + '__rtruediv__': ('nb_true_divide', generate_bin_op_wrapper), + '__floordiv__': ('nb_floor_divide', generate_bin_op_wrapper), + '__rfloordiv__': ('nb_floor_divide', generate_bin_op_wrapper), + '__lshift__': ('nb_lshift', generate_bin_op_wrapper), + '__rlshift__': ('nb_lshift', generate_bin_op_wrapper), + '__rshift__': ('nb_rshift', generate_bin_op_wrapper), + '__rrshift__': ('nb_rshift', generate_bin_op_wrapper), + '__and__': ('nb_and', generate_bin_op_wrapper), + '__rand__': ('nb_and', generate_bin_op_wrapper), + '__or__': ('nb_or', generate_bin_op_wrapper), + '__ror__': ('nb_or', generate_bin_op_wrapper), + '__xor__': ('nb_xor', generate_bin_op_wrapper), + '__rxor__': ('nb_xor', generate_bin_op_wrapper), + '__matmul__': ('nb_matrix_multiply', generate_bin_op_wrapper), + '__rmatmul__': ('nb_matrix_multiply', generate_bin_op_wrapper), + '__iadd__': ('nb_inplace_add', generate_dunder_wrapper), + '__isub__': ('nb_inplace_subtract', generate_dunder_wrapper), + '__imul__': ('nb_inplace_multiply', generate_dunder_wrapper), + '__imod__': ('nb_inplace_remainder', generate_dunder_wrapper), + '__itruediv__': ('nb_inplace_true_divide', generate_dunder_wrapper), + '__ifloordiv__': ('nb_inplace_floor_divide', generate_dunder_wrapper), + '__ilshift__': ('nb_inplace_lshift', generate_dunder_wrapper), + '__irshift__': ('nb_inplace_rshift', generate_dunder_wrapper), + '__iand__': ('nb_inplace_and', generate_dunder_wrapper), + '__ior__': ('nb_inplace_or', generate_dunder_wrapper), + '__ixor__': ('nb_inplace_xor', generate_dunder_wrapper), + '__imatmul__': ('nb_inplace_matrix_multiply', generate_dunder_wrapper), +} -AS_ASYNC_SLOT_DEFS = { +AS_ASYNC_SLOT_DEFS: SlotTable = { '__await__': ('am_await', native_slot), '__aiter__': ('am_aiter', native_slot), '__anext__': ('am_anext', native_slot), -} # type: SlotTable +} SIDE_TABLES = [ ('as_mapping', 'PyMappingMethods', AS_MAPPING_SLOT_DEFS), @@ -89,11 +129,21 @@ def generate_call_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: return wrapper_slot(cl, fn, emitter) +def slot_key(attr: str) -> str: + """Map dunder method name to sort key. + + Sort reverse operator methods and __delitem__ after others ('x' > '_'). + """ + if (attr.startswith('__r') and attr != '__rshift__') or attr == '__delitem__': + return 'x' + attr + return attr + + def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]: - fields = OrderedDict() # type: Dict[str, str] - generated = {} # type: Dict[str, str] + fields: Dict[str, str] = OrderedDict() + generated: Dict[str, str] = {} # Sort for determinism on Python 3.5 - for name, (slot, generator) in sorted(table.items(), reverse=True): + for name, (slot, generator) in sorted(table.items(), key=lambda x: slot_key(x[0])): method_cls = cl.get_method_and_class(name) if method_cls and (method_cls[1] == cl or name in ALWAYS_FILL): if slot in generated: @@ -149,11 +199,11 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None: methods_name = '{}_methods'.format(name_prefix) vtable_setup_name = '{}_trait_vtable_setup'.format(name_prefix) - fields = OrderedDict() # type: Dict[str, str] + fields: Dict[str, str] = OrderedDict() fields['tp_name'] = '"{}"'.format(name) generate_full = not cl.is_trait and not cl.builtin_base - needs_getseters = not cl.is_generated + needs_getseters = cl.needs_getseters or not cl.is_generated if not cl.builtin_base: fields['tp_new'] = new_name @@ -244,9 +294,9 @@ def emit_line() -> None: emit_line() if cl.allow_interpreted_subclasses: - shadow_vtable_name = generate_vtables( + shadow_vtable_name: Optional[str] = generate_vtables( cl, vtable_setup_name + "_shadow", vtable_name + "_shadow", emitter, shadow=True - ) # type: Optional[str] + ) emit_line() else: shadow_vtable_name = None @@ -302,8 +352,8 @@ def setter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str: def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None: - seen_attrs = set() # type: Set[Tuple[str, RType]] - lines = [] # type: List[str] + seen_attrs: Set[Tuple[str, RType]] = set() + lines: List[str] = [] lines += ['typedef struct {', 'PyObject_HEAD', 'CPyVTableItem *vtable;'] @@ -818,14 +868,26 @@ def generate_setter(cl: ClassIR, setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') + + deletable = cl.is_deletable(attr) + if not deletable: + emitter.emit_line('if (value == NULL) {') + emitter.emit_line('PyErr_SetString(PyExc_AttributeError,') + emitter.emit_line(' "{} object attribute {} cannot be deleted");'.format(repr(cl.name), + repr(attr))) + emitter.emit_line('return -1;') + emitter.emit_line('}') + if rtype.is_refcounted: attr_expr = 'self->{}'.format(attr_field) emitter.emit_undefined_attr_check(rtype, attr_expr, '!=') emitter.emit_dec_ref('self->{}'.format(attr_field), rtype) emitter.emit_line('}') - emitter.emit_line('if (value != NULL) {') + + if deletable: + emitter.emit_line('if (value != NULL) {') if rtype.is_unboxed: - emitter.emit_unbox('value', 'tmp', rtype, custom_failure='return -1;', declare_dest=True) + emitter.emit_unbox('value', 'tmp', rtype, error=ReturnHandler('-1'), declare_dest=True) elif is_same_type(rtype, object_rprimitive): emitter.emit_line('PyObject *tmp = value;') else: @@ -834,8 +896,10 @@ def generate_setter(cl: ClassIR, ' return -1;') emitter.emit_inc_ref('tmp', rtype) emitter.emit_line('self->{} = tmp;'.format(attr_field)) - emitter.emit_line('} else') - emitter.emit_line(' self->{} = {};'.format(attr_field, emitter.c_undefined_value(rtype))) + if deletable: + emitter.emit_line('} else') + emitter.emit_line(' self->{} = {};'.format(attr_field, + emitter.c_undefined_value(rtype))) emitter.emit_line('return 0;') emitter.emit_line('}') @@ -872,7 +936,7 @@ def generate_property_setter(cl: ClassIR, cl.struct_name(emitter.names))) emitter.emit_line('{') if arg_type.is_unboxed: - emitter.emit_unbox('value', 'tmp', arg_type, custom_failure='return -1;', + emitter.emit_unbox('value', 'tmp', arg_type, error=ReturnHandler('-1'), declare_dest=True) emitter.emit_line('{}{}((PyObject *) self, tmp);'.format( NATIVE_PREFIX, diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index dbdc445f5627..3b94c5648769 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -21,6 +21,7 @@ from mypyc.ir.func_ir import FuncIR, FuncDecl, FUNC_STATICMETHOD, FUNC_CLASSMETHOD, all_values from mypyc.ir.class_ir import ClassIR from mypyc.ir.pprint import generate_names_for_ir +from mypyc.analysis.blockfreq import frequently_executed_blocks # Whether to insert debug asserts for all error handling, to quickly # catch errors propagating without exceptions set. @@ -77,8 +78,11 @@ def generate_native_function(fn: FuncIR, for i, block in enumerate(blocks): block.label = i + common = frequently_executed_blocks(fn.blocks[0]) + for i in range(len(blocks)): block = blocks[i] + visitor.rare = block not in common next_block = None if i + 1 < len(blocks): next_block = blocks[i + 1] @@ -105,7 +109,8 @@ def __init__(self, self.source_path = source_path self.module_name = module_name self.literals = emitter.context.literals - self.next_block = None # type: Optional[BasicBlock] + self.rare = False + self.next_block: Optional[BasicBlock] = None def temp_name(self) -> str: return self.emitter.temp_name() @@ -327,11 +332,11 @@ def visit_set_attr(self, op: SetAttr) -> None: '{} = 1;'.format(dest), ) - PREFIX_MAP = { + PREFIX_MAP: Final = { NAMESPACE_STATIC: STATIC_PREFIX, NAMESPACE_TYPE: TYPE_PREFIX, NAMESPACE_MODULE: MODULE_PREFIX, - } # type: Final + } def visit_load_static(self, op: LoadStatic) -> None: dest = self.reg(op) @@ -416,7 +421,7 @@ def visit_inc_ref(self, op: IncRef) -> None: def visit_dec_ref(self, op: DecRef) -> None: src = self.reg(op.src) - self.emit_dec_ref(src, op.src.type, op.is_xdec) + self.emit_dec_ref(src, op.src.type, is_xdec=op.is_xdec) def visit_box(self, op: Box) -> None: self.emitter.emit_box(self.reg(op.src), self.reg(op), op.src.type, can_borrow=True) @@ -483,14 +488,20 @@ def visit_comparison_op(self, op: ComparisonOp) -> None: rhs = self.reg(op.rhs) lhs_cast = "" rhs_cast = "" - signed_op = {ComparisonOp.SLT, ComparisonOp.SGT, ComparisonOp.SLE, ComparisonOp.SGE} - unsigned_op = {ComparisonOp.ULT, ComparisonOp.UGT, ComparisonOp.ULE, ComparisonOp.UGE} - if op.op in signed_op: + if op.op in (ComparisonOp.SLT, ComparisonOp.SGT, ComparisonOp.SLE, ComparisonOp.SGE): + # Always signed comparison op lhs_cast = self.emit_signed_int_cast(op.lhs.type) rhs_cast = self.emit_signed_int_cast(op.rhs.type) - elif op.op in unsigned_op: + elif op.op in (ComparisonOp.ULT, ComparisonOp.UGT, ComparisonOp.ULE, ComparisonOp.UGE): + # Always unsigned comparison op lhs_cast = self.emit_unsigned_int_cast(op.lhs.type) rhs_cast = self.emit_unsigned_int_cast(op.rhs.type) + elif isinstance(op.lhs, Integer) and op.lhs.value < 0: + # Force signed ==/!= with negative operand + rhs_cast = self.emit_signed_int_cast(op.rhs.type) + elif isinstance(op.rhs, Integer) and op.rhs.value < 0: + # Force signed ==/!= with negative operand + lhs_cast = self.emit_signed_int_cast(op.lhs.type) self.emit_line('%s = %s%s %s %s%s;' % (dest, lhs_cast, lhs, op.op_str[op.op], rhs_cast, rhs)) @@ -542,7 +553,12 @@ def reg(self, reg: Value) -> str: s = str(val) if val >= (1 << 31): # Avoid overflowing signed 32-bit int - s += 'U' + s += 'ULL' + elif val == -(1 << 63): + # Avoid overflowing C integer literal + s = '(-9223372036854775807LL - 1)' + elif val <= -(1 << 31): + s += 'LL' return s else: return self.emitter.reg(reg) @@ -563,10 +579,10 @@ def emit_lines(self, *lines: str) -> None: self.emitter.emit_lines(*lines) def emit_inc_ref(self, dest: str, rtype: RType) -> None: - self.emitter.emit_inc_ref(dest, rtype) + self.emitter.emit_inc_ref(dest, rtype, rare=self.rare) def emit_dec_ref(self, dest: str, rtype: RType, is_xdec: bool) -> None: - self.emitter.emit_dec_ref(dest, rtype, is_xdec) + self.emitter.emit_dec_ref(dest, rtype, is_xdec=is_xdec, rare=self.rare) def emit_declaration(self, line: str) -> None: self.declarations.emit_line(line) diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index 476c435712bd..35aa0046dcf9 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -5,7 +5,7 @@ import os import json -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import List, Tuple, Dict, Iterable, Set, TypeVar, Optional from mypy.nodes import MypyFile @@ -23,7 +23,7 @@ from mypyc.irbuild.prepare import load_type_map from mypyc.irbuild.mapper import Mapper from mypyc.common import ( - PREFIX, TOP_LEVEL_NAME, MODULE_PREFIX, RUNTIME_C_FILES, use_fastcall, + PREFIX, TOP_LEVEL_NAME, MODULE_PREFIX, RUNTIME_C_FILES, short_id_from_name, use_fastcall, use_vectorcall, shared_lib_name, ) from mypyc.codegen.cstring import c_string_initializer @@ -97,7 +97,7 @@ class MypycPlugin(Plugin): def __init__( self, options: Options, compiler_options: CompilerOptions, groups: Groups) -> None: super().__init__(options) - self.group_map = {} # type: Dict[str, Tuple[Optional[str], List[str]]] + self.group_map: Dict[str, Tuple[Optional[str], List[str]]] = {} for sources, name in groups: modules = sorted(source.module for source in sources) for id in modules: @@ -280,7 +280,7 @@ def compile_ir_to_c( # Generate C code for each compilation group. Each group will be # compiled into a separate extension module. - ctext = {} # type: Dict[Optional[str], List[Tuple[str, str]]] + ctext: Dict[Optional[str], List[Tuple[str, str]]] = {} for group_sources, group_name in groups: group_modules = [(source.module, modules[source.module]) for source in group_sources if source.module in modules] @@ -407,6 +407,10 @@ def compile_modules_to_c( group_map = {source.module: lib_name for group, lib_name in groups for source in group} mapper = Mapper(group_map) + # Sometimes when we call back into mypy, there might be errors. + # We don't want to crash when that happens. + result.manager.errors.set_file('', module=None, scope=None) + modules = compile_modules_to_ir(result, mapper, compiler_options, errors) ctext = compile_ir_to_c(groups, modules, result, mapper, compiler_options) @@ -474,7 +478,7 @@ def __init__(self, self.names = names # Initializations of globals to simple values that we can't # do statically because the windows loader is bad. - self.simple_inits = [] # type: List[Tuple[str, str]] + self.simple_inits: List[Tuple[str, str]] = [] self.group_name = group_name self.use_shared_lib = group_name is not None self.compiler_options = compiler_options @@ -838,6 +842,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module for fn in module.functions: if fn.class_name is not None or fn.name == TOP_LEVEL_NAME: continue + name = short_id_from_name(fn.name, fn.decl.shortname, fn.line) if is_fastcall_supported(fn, emitter.capi_version): flag = 'METH_FASTCALL' else: @@ -845,7 +850,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module emitter.emit_line( ('{{"{name}", (PyCFunction){prefix}{cname}, {flag} | METH_KEYWORDS, ' 'NULL /* docstring */}},').format( - name=fn.name, + name=name, cname=fn.cname(emitter.names), prefix=PREFIX, flag=flag)) @@ -874,6 +879,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module declaration = 'PyObject *CPyInit_{}(void)'.format(exported_name(module_name)) emitter.emit_lines(declaration, '{') + emitter.emit_line('PyObject* modname = NULL;') # Store the module reference in a static and return it when necessary. # This is separate from the *global* reference to the module that will # be populated when it is imported by a compiled module. We want that @@ -888,35 +894,50 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module emitter.emit_lines('{} = PyModule_Create(&{}module);'.format(module_static, module_prefix), 'if (unlikely({} == NULL))'.format(module_static), - ' return NULL;') + ' goto fail;') emitter.emit_line( - 'PyObject *modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format( + 'modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format( module_static)) module_globals = emitter.static_name('globals', module_name) emitter.emit_lines('{} = PyModule_GetDict({});'.format(module_globals, module_static), 'if (unlikely({} == NULL))'.format(module_globals), - ' return NULL;') + ' goto fail;') # HACK: Manually instantiate generated classes here + type_structs: List[str] = [] for cl in module.classes: + type_struct = emitter.type_struct_name(cl) + type_structs.append(type_struct) if cl.is_generated: - type_struct = emitter.type_struct_name(cl) emitter.emit_lines( '{t} = (PyTypeObject *)CPyType_FromTemplate(' '(PyObject *){t}_template, NULL, modname);' .format(t=type_struct)) emitter.emit_lines('if (unlikely(!{}))'.format(type_struct), - ' return NULL;') + ' goto fail;') emitter.emit_lines('if (CPyGlobalsInit() < 0)', - ' return NULL;') + ' goto fail;') self.generate_top_level_call(module, emitter) emitter.emit_lines('Py_DECREF(modname);') emitter.emit_line('return {};'.format(module_static)) + emitter.emit_lines('fail:', + 'Py_CLEAR({});'.format(module_static), + 'Py_CLEAR(modname);') + for name, typ in module.final_names: + static_name = emitter.static_name(name, module_name) + emitter.emit_dec_ref(static_name, typ, is_xdec=True) + undef = emitter.c_undefined_value(typ) + emitter.emit_line('{} = {};'.format(static_name, undef)) + # the type objects returned from CPyType_FromTemplate are all new references + # so we have to decref them + for t in type_structs: + emitter.emit_line('Py_CLEAR({});'.format(t)) + emitter.emit_line('return NULL;') emitter.emit_line('}') def generate_top_level_call(self, module: ModuleIR, emitter: Emitter) -> None: @@ -927,7 +948,7 @@ def generate_top_level_call(self, module: ModuleIR, emitter: Emitter) -> None: emitter.emit_lines( 'char result = {}();'.format(emitter.native_function_name(fn.decl)), 'if (result == 2)', - ' return NULL;', + ' goto fail;', ) break @@ -941,7 +962,7 @@ def toposort_declarations(self) -> List[HeaderDeclaration]: This runs in O(V + E). """ result = [] - marked_declarations = OrderedDict() # type: Dict[str, MarkedDeclaration] + marked_declarations: Dict[str, MarkedDeclaration] = OrderedDict() for k, v in self.context.declarations.items(): marked_declarations[k] = MarkedDeclaration(v, False) @@ -1030,7 +1051,7 @@ def declare_static_pyobject(self, identifier: str, emitter: Emitter) -> None: def sort_classes(classes: List[Tuple[str, ClassIR]]) -> List[Tuple[str, ClassIR]]: mod_name = {ir: name for name, ir in classes} irs = [ir for _, ir in classes] - deps = OrderedDict() # type: Dict[ClassIR, Set[ClassIR]] + deps: Dict[ClassIR, Set[ClassIR]] = OrderedDict() for ir in irs: if ir not in deps: deps[ir] = set() @@ -1050,7 +1071,7 @@ def toposort(deps: Dict[T, Set[T]]) -> List[T]: This runs in O(V + E). """ result = [] - visited = set() # type: Set[T] + visited: Set[T] = set() def visit(item: T) -> None: if item in visited: @@ -1103,7 +1124,7 @@ def c_array_initializer(components: List[str]) -> str: If the result is long, split it into multiple lines. """ res = [] - current = [] # type: List[str] + current: List[str] = [] cur_len = 0 for c in components: if not current or cur_len + 2 + len(c) < 70: diff --git a/mypyc/codegen/emitwrapper.py b/mypyc/codegen/emitwrapper.py index 62368f228a0d..bbee8fea0d91 100644 --- a/mypyc/codegen/emitwrapper.py +++ b/mypyc/codegen/emitwrapper.py @@ -10,14 +10,16 @@ or methods in a single compilation unit. """ -from typing import List, Optional, Sequence +from typing import List, Dict, Optional, Sequence -from mypy.nodes import ARG_POS, ARG_OPT, ARG_NAMED_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2 +from mypy.nodes import ArgKind, ARG_POS, ARG_OPT, ARG_NAMED_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2 +from mypy.operators import op_methods_to_symbols, reverse_op_methods, reverse_op_method_names from mypyc.common import PREFIX, NATIVE_PREFIX, DUNDER_PREFIX, use_vectorcall -from mypyc.codegen.emit import Emitter +from mypyc.codegen.emit import Emitter, ErrorHandler, GotoHandler, AssignHandler, ReturnHandler from mypyc.ir.rtypes import ( - RType, is_object_rprimitive, is_int_rprimitive, is_bool_rprimitive, object_rprimitive + RType, RInstance, is_object_rprimitive, is_int_rprimitive, is_bool_rprimitive, + object_rprimitive ) from mypyc.ir.func_ir import FuncIR, RuntimeArg, FUNC_STATICMETHOD from mypyc.ir.class_ir import ClassIR @@ -73,12 +75,12 @@ def generate_traceback_code(fn: FuncIR, return traceback_code -def make_arg_groups(args: List[RuntimeArg]) -> List[List[RuntimeArg]]: +def make_arg_groups(args: List[RuntimeArg]) -> Dict[ArgKind, List[RuntimeArg]]: """Group arguments by kind.""" - return [[arg for arg in args if arg.kind == k] for k in range(ARG_NAMED_OPT + 1)] + return {k: [arg for arg in args if arg.kind == k] for k in ArgKind} -def reorder_arg_groups(groups: List[List[RuntimeArg]]) -> List[RuntimeArg]: +def reorder_arg_groups(groups: Dict[ArgKind, List[RuntimeArg]]) -> List[RuntimeArg]: """Reorder argument groups to match their order in a format string.""" return groups[ARG_POS] + groups[ARG_OPT] + groups[ARG_NAMED_OPT] + groups[ARG_NAMED] @@ -88,7 +90,7 @@ def make_static_kwlist(args: List[RuntimeArg]) -> str: return 'static const char * const kwlist[] = {{{}0}};'.format(arg_names) -def make_format_string(func_name: Optional[str], groups: List[List[RuntimeArg]]) -> str: +def make_format_string(func_name: Optional[str], groups: Dict[ArgKind, List[RuntimeArg]]) -> str: """Return a format string that specifies the accepted arguments. The format string is an extended subset of what is supported by @@ -153,7 +155,7 @@ def generate_wrapper_function(fn: FuncIR, cleanups = ['CPy_DECREF(obj_{});'.format(arg.name) for arg in groups[ARG_STAR] + groups[ARG_STAR2]] - arg_ptrs = [] # type: List[str] + arg_ptrs: List[str] = [] if groups[ARG_STAR] or groups[ARG_STAR2]: arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR][0].name) if groups[ARG_STAR] else 'NULL'] arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR2][0].name) if groups[ARG_STAR2] else 'NULL'] @@ -232,7 +234,7 @@ def generate_legacy_wrapper_function(fn: FuncIR, cleanups = ['CPy_DECREF(obj_{});'.format(arg.name) for arg in groups[ARG_STAR] + groups[ARG_STAR2]] - arg_ptrs = [] # type: List[str] + arg_ptrs: List[str] = [] if groups[ARG_STAR] or groups[ARG_STAR2]: arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR][0].name) if groups[ARG_STAR] else 'NULL'] arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR2][0].name) if groups[ARG_STAR2] else 'NULL'] @@ -259,16 +261,128 @@ def generate_dunder_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: protocol slot. This specifically means that the arguments are taken as *PyObjects and returned as *PyObjects. """ - input_args = ', '.join('PyObject *obj_{}'.format(arg.name) for arg in fn.args) - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) - emitter.emit_line('static PyObject *{name}({input_args}) {{'.format( - name=name, - input_args=input_args, - )) - generate_wrapper_core(fn, emitter) - emitter.emit_line('}') + gen = WrapperGenerator(cl, emitter) + gen.set_target(fn) + gen.emit_header() + gen.emit_arg_processing() + gen.emit_call() + gen.finish() + return gen.wrapper_name() - return name + +def generate_bin_op_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: + """Generates a wrapper for a native binary dunder method. + + The same wrapper that handles the forward method (e.g. __add__) also handles + the corresponding reverse method (e.g. __radd__), if defined. + + Both arguments and the return value are PyObject *. + """ + gen = WrapperGenerator(cl, emitter) + gen.set_target(fn) + gen.arg_names = ['left', 'right'] + wrapper_name = gen.wrapper_name() + + gen.emit_header() + if fn.name not in reverse_op_methods and fn.name in reverse_op_method_names: + # There's only a reverse operator method. + generate_bin_op_reverse_only_wrapper(cl, fn, emitter, gen) + else: + rmethod = reverse_op_methods[fn.name] + fn_rev = cl.get_method(rmethod) + if fn_rev is None: + # There's only a forward operator method. + generate_bin_op_forward_only_wrapper(cl, fn, emitter, gen) + else: + # There's both a forward and a reverse operator method. + generate_bin_op_both_wrappers(cl, fn, fn_rev, emitter, gen) + return wrapper_name + + +def generate_bin_op_forward_only_wrapper(cl: ClassIR, + fn: FuncIR, + emitter: Emitter, + gen: 'WrapperGenerator') -> None: + gen.emit_arg_processing(error=GotoHandler('typefail'), raise_exception=False) + gen.emit_call(not_implemented_handler='goto typefail;') + gen.emit_error_handling() + emitter.emit_label('typefail') + # If some argument has an incompatible type, treat this the same as + # returning NotImplemented, and try to call the reverse operator method. + # + # Note that in normal Python you'd instead of an explicit + # return of NotImplemented, but it doesn't generally work here + # the body won't be executed at all if there is an argument + # type check failure. + # + # The recommended way is to still use a type check in the + # body. This will only be used in interpreted mode: + # + # def __add__(self, other: int) -> Foo: + # if not isinstance(other, int): + # return NotImplemented + # ... + rmethod = reverse_op_methods[fn.name] + emitter.emit_line('_Py_IDENTIFIER({});'.format(rmethod)) + emitter.emit_line( + 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format( + op_methods_to_symbols[fn.name], + rmethod)) + gen.finish() + + +def generate_bin_op_reverse_only_wrapper(cl: ClassIR, + fn_rev: FuncIR, + emitter: Emitter, + gen: 'WrapperGenerator') -> None: + gen.arg_names = ['right', 'left'] + gen.emit_arg_processing(error=GotoHandler('typefail'), raise_exception=False) + gen.emit_call() + gen.emit_error_handling() + emitter.emit_label('typefail') + emitter.emit_line('Py_INCREF(Py_NotImplemented);') + emitter.emit_line('return Py_NotImplemented;') + gen.finish() + + +def generate_bin_op_both_wrappers(cl: ClassIR, + fn: FuncIR, + fn_rev: FuncIR, + emitter: Emitter, + gen: 'WrapperGenerator') -> None: + # There's both a forward and a reverse operator method. First + # check if we should try calling the forward one. If the + # argument type check fails, fall back to the reverse method. + # + # Similar to above, we can't perfectly match Python semantics. + # In regular Python code you'd return NotImplemented if the + # operand has the wrong type, but in compiled code we'll never + # get to execute the type check. + emitter.emit_line('if (PyObject_IsInstance(obj_left, (PyObject *){})) {{'.format( + emitter.type_struct_name(cl))) + gen.emit_arg_processing(error=GotoHandler('typefail'), raise_exception=False) + gen.emit_call(not_implemented_handler='goto typefail;') + gen.emit_error_handling() + emitter.emit_line('}') + emitter.emit_label('typefail') + emitter.emit_line('if (PyObject_IsInstance(obj_right, (PyObject *){})) {{'.format( + emitter.type_struct_name(cl))) + gen.set_target(fn_rev) + gen.arg_names = ['right', 'left'] + gen.emit_arg_processing(error=GotoHandler('typefail2'), raise_exception=False) + gen.emit_call() + gen.emit_error_handling() + emitter.emit_line('} else {') + emitter.emit_line('_Py_IDENTIFIER({});'.format(fn_rev.name)) + emitter.emit_line( + 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format( + op_methods_to_symbols[fn.name], + fn_rev.name)) + emitter.emit_line('}') + emitter.emit_label('typefail2') + emitter.emit_line('Py_INCREF(Py_NotImplemented);') + emitter.emit_line('return Py_NotImplemented;') + gen.finish() RICHCOMPARE_OPS = { @@ -485,7 +599,7 @@ def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> def generate_set_del_item_wrapper_inner(fn: FuncIR, emitter: Emitter, args: Sequence[RuntimeArg]) -> None: for arg in args: - generate_arg_check(arg.name, arg.type, emitter, 'goto fail;', False) + generate_arg_check(arg.name, arg.type, emitter, GotoHandler('fail')) native_args = ', '.join('arg_{}'.format(arg.name) for arg in args) emitter.emit_line('{}val = {}{}({});'.format(emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX, @@ -505,7 +619,7 @@ def generate_contains_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: emitter.emit_line( 'static int {name}(PyObject *self, PyObject *obj_item) {{'. format(name=name)) - generate_arg_check('item', fn.args[1].type, emitter, 'return -1;', False) + generate_arg_check('item', fn.args[1].type, emitter, ReturnHandler('-1')) emitter.emit_line('{}val = {}{}(self, arg_item);'.format(emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX, fn.cname(emitter.names))) @@ -524,7 +638,8 @@ def generate_contains_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: # Helpers -def generate_wrapper_core(fn: FuncIR, emitter: Emitter, +def generate_wrapper_core(fn: FuncIR, + emitter: Emitter, optional_args: Optional[List[RuntimeArg]] = None, arg_names: Optional[List[str]] = None, cleanups: Optional[List[str]] = None, @@ -539,13 +654,17 @@ def generate_wrapper_core(fn: FuncIR, emitter: Emitter, optional_args = optional_args or [] cleanups = cleanups or [] use_goto = bool(cleanups or traceback_code) - error_code = 'return NULL;' if not use_goto else 'goto fail;' + error = ReturnHandler('NULL') if not use_goto else GotoHandler('fail') arg_names = arg_names or [arg.name for arg in fn.args] for arg_name, arg in zip(arg_names, fn.args): # Suppress the argument check for *args/**kwargs, since we know it must be right. typ = arg.type if arg.kind not in (ARG_STAR, ARG_STAR2) else object_rprimitive - generate_arg_check(arg_name, typ, emitter, error_code, arg in optional_args) + generate_arg_check(arg_name, + typ, + emitter, + error, + optional=arg in optional_args) native_args = ', '.join('arg_{}'.format(arg) for arg in arg_names) if fn.ret_type.is_unboxed or use_goto: # TODO: The Py_RETURN macros return the correct PyObject * with reference count handling. @@ -574,18 +693,30 @@ def generate_wrapper_core(fn: FuncIR, emitter: Emitter, emitter.emit_lines('return NULL;') -def generate_arg_check(name: str, typ: RType, emitter: Emitter, - error_code: str, optional: bool = False) -> None: +def generate_arg_check(name: str, + typ: RType, + emitter: Emitter, + error: Optional[ErrorHandler] = None, + *, + optional: bool = False, + raise_exception: bool = True) -> None: """Insert a runtime check for argument and unbox if necessary. The object is named PyObject *obj_{}. This is expected to generate a value of name arg_{} (unboxed if necessary). For each primitive a runtime check ensures the correct type. """ + error = error or AssignHandler() if typ.is_unboxed: # Borrow when unboxing to avoid reference count manipulation. - emitter.emit_unbox('obj_{}'.format(name), 'arg_{}'.format(name), typ, - error_code, declare_dest=True, borrow=True, optional=optional) + emitter.emit_unbox('obj_{}'.format(name), + 'arg_{}'.format(name), + typ, + declare_dest=True, + raise_exception=raise_exception, + error=error, + borrow=True, + optional=optional) elif is_object_rprimitive(typ): # Object is trivial since any object is valid if optional: @@ -596,10 +727,129 @@ def generate_arg_check(name: str, typ: RType, emitter: Emitter, else: emitter.emit_line('PyObject *arg_{} = obj_{};'.format(name, name)) else: - emitter.emit_cast('obj_{}'.format(name), 'arg_{}'.format(name), typ, - declare_dest=True, optional=optional) - if optional: - emitter.emit_line('if (obj_{} != NULL && arg_{} == NULL) {}'.format( - name, name, error_code)) + emitter.emit_cast('obj_{}'.format(name), + 'arg_{}'.format(name), + typ, + declare_dest=True, + raise_exception=raise_exception, + error=error, + optional=optional) + + +class WrapperGenerator: + """Helper that simplifies the generation of wrapper functions.""" + + # TODO: Use this for more wrappers + + def __init__(self, cl: ClassIR, emitter: Emitter) -> None: + self.cl = cl + self.emitter = emitter + self.cleanups: List[str] = [] + self.optional_args: List[RuntimeArg] = [] + self.traceback_code = '' + + def set_target(self, fn: FuncIR) -> None: + """Set the wrapped function. + + It's fine to modify the attributes initialized here later to customize + the wrapper function. + """ + self.target_name = fn.name + self.target_cname = fn.cname(self.emitter.names) + self.arg_names = [arg.name for arg in fn.args] + self.args = fn.args[:] + self.ret_type = fn.ret_type + + def wrapper_name(self) -> str: + """Return the name of the wrapper function.""" + return '{}{}{}'.format(DUNDER_PREFIX, + self.target_name, + self.cl.name_prefix(self.emitter.names)) + + def use_goto(self) -> bool: + """Do we use a goto for error handling (instead of straight return)?""" + return bool(self.cleanups or self.traceback_code) + + def emit_header(self) -> None: + """Emit the function header of the wrapper implementation.""" + input_args = ', '.join('PyObject *obj_{}'.format(arg) for arg in self.arg_names) + self.emitter.emit_line('static PyObject *{name}({input_args}) {{'.format( + name=self.wrapper_name(), + input_args=input_args, + )) + + def emit_arg_processing(self, + error: Optional[ErrorHandler] = None, + raise_exception: bool = True) -> None: + """Emit validation and unboxing of arguments.""" + error = error or self.error() + for arg_name, arg in zip(self.arg_names, self.args): + # Suppress the argument check for *args/**kwargs, since we know it must be right. + typ = arg.type if arg.kind not in (ARG_STAR, ARG_STAR2) else object_rprimitive + generate_arg_check(arg_name, + typ, + self.emitter, + error, + raise_exception=raise_exception, + optional=arg in self.optional_args) + + def emit_call(self, not_implemented_handler: str = '') -> None: + """Emit call to the wrapper function. + + If not_implemented_handler is non-empty, use this C code to handle + a NotImplemented return value (if it's possible based on the return type). + """ + native_args = ', '.join('arg_{}'.format(arg) for arg in self.arg_names) + ret_type = self.ret_type + emitter = self.emitter + if ret_type.is_unboxed or self.use_goto(): + # TODO: The Py_RETURN macros return the correct PyObject * with reference count + # handling. Are they relevant? + emitter.emit_line('{}retval = {}{}({});'.format(emitter.ctype_spaced(ret_type), + NATIVE_PREFIX, + self.target_cname, + native_args)) + emitter.emit_lines(*self.cleanups) + if ret_type.is_unboxed: + emitter.emit_error_check('retval', ret_type, 'return NULL;') + emitter.emit_box('retval', 'retbox', ret_type, declare_dest=True) + + emitter.emit_line( + 'return {};'.format('retbox' if ret_type.is_unboxed else 'retval')) + else: + if not_implemented_handler and not isinstance(ret_type, RInstance): + # The return value type may overlap with NotImplemented. + emitter.emit_line('PyObject *retbox = {}{}({});'.format(NATIVE_PREFIX, + self.target_cname, + native_args)) + emitter.emit_lines('if (retbox == Py_NotImplemented) {', + not_implemented_handler, + '}', + 'return retbox;') + else: + emitter.emit_line('return {}{}({});'.format(NATIVE_PREFIX, + self.target_cname, + native_args)) + # TODO: Tracebacks? + + def error(self) -> ErrorHandler: + """Figure out how to deal with errors in the wrapper.""" + if self.cleanups or self.traceback_code: + # We'll have a label at the end with error handling code. + return GotoHandler('fail') else: - emitter.emit_line('if (arg_{} == NULL) {}'.format(name, error_code)) + # Nothing special needs to done to handle errors, so just return. + return ReturnHandler('NULL') + + def emit_error_handling(self) -> None: + """Emit error handling block at the end of the wrapper, if needed.""" + emitter = self.emitter + if self.use_goto(): + emitter.emit_label('fail') + emitter.emit_lines(*self.cleanups) + if self.traceback_code: + emitter.emit_line(self.traceback_code) + emitter.emit_line('return NULL;') + + def finish(self) -> None: + self.emitter.emit_line('}') diff --git a/mypyc/codegen/literals.py b/mypyc/codegen/literals.py index f890c06a0713..2bbc5e6f585c 100644 --- a/mypyc/codegen/literals.py +++ b/mypyc/codegen/literals.py @@ -9,7 +9,7 @@ # Some literals are singletons and handled specially (None, False and True) -NUM_SINGLETONS = 3 # type: Final +NUM_SINGLETONS: Final = 3 class Literals: @@ -17,12 +17,12 @@ class Literals: def __init__(self) -> None: # Each dict maps value to literal index (0, 1, ...) - self.str_literals = {} # type: Dict[str, int] - self.bytes_literals = {} # type: Dict[bytes, int] - self.int_literals = {} # type: Dict[int, int] - self.float_literals = {} # type: Dict[float, int] - self.complex_literals = {} # type: Dict[complex, int] - self.tuple_literals = {} # type: Dict[Tuple[object, ...], int] + self.str_literals: Dict[str, int] = {} + self.bytes_literals: Dict[bytes, int] = {} + self.int_literals: Dict[int, int] = {} + self.float_literals: Dict[float, int] = {} + self.complex_literals: Dict[complex, int] = {} + self.tuple_literals: Dict[Tuple[object, ...], int] = {} def record_literal(self, value: LiteralValue) -> None: """Ensure that the literal value is available in generated code.""" @@ -146,7 +146,7 @@ def _encode_str_values(values: Dict[str, int]) -> List[bytes]: for value, index in values.items(): value_by_index[index] = value result = [] - line = [] # type: List[bytes] + line: List[bytes] = [] line_len = 0 for i in range(len(values)): value = value_by_index[i] @@ -169,7 +169,7 @@ def _encode_bytes_values(values: Dict[bytes, int]) -> List[bytes]: for value, index in values.items(): value_by_index[index] = value result = [] - line = [] # type: List[bytes] + line: List[bytes] = [] line_len = 0 for i in range(len(values)): value = value_by_index[i] @@ -216,7 +216,7 @@ def _encode_int_values(values: Dict[int, int]) -> List[bytes]: for value, index in values.items(): value_by_index[index] = value result = [] - line = [] # type: List[bytes] + line: List[bytes] = [] line_len = 0 for i in range(len(values)): value = value_by_index[i] diff --git a/mypyc/common.py b/mypyc/common.py index f0adfe019669..6080649f7eb6 100644 --- a/mypyc/common.py +++ b/mypyc/common.py @@ -1,34 +1,34 @@ -import sys -from typing import Dict, Any, Tuple +from mypy.util import unnamed_function +from typing import Dict, Any, Optional, Tuple import sys from typing_extensions import Final -PREFIX = 'CPyPy_' # type: Final # Python wrappers -NATIVE_PREFIX = 'CPyDef_' # type: Final # Native functions etc. -DUNDER_PREFIX = 'CPyDunder_' # type: Final # Wrappers for exposing dunder methods to the API -REG_PREFIX = 'cpy_r_' # type: Final # Registers -STATIC_PREFIX = 'CPyStatic_' # type: Final # Static variables (for literals etc.) -TYPE_PREFIX = 'CPyType_' # type: Final # Type object struct -MODULE_PREFIX = 'CPyModule_' # type: Final # Cached modules -ATTR_PREFIX = '_' # type: Final # Attributes - -ENV_ATTR_NAME = '__mypyc_env__' # type: Final -NEXT_LABEL_ATTR_NAME = '__mypyc_next_label__' # type: Final -TEMP_ATTR_NAME = '__mypyc_temp__' # type: Final -LAMBDA_NAME = '__mypyc_lambda__' # type: Final -PROPSET_PREFIX = '__mypyc_setter__' # type: Final -SELF_NAME = '__mypyc_self__' # type: Final +PREFIX: Final = "CPyPy_" # Python wrappers +NATIVE_PREFIX: Final = "CPyDef_" # Native functions etc. +DUNDER_PREFIX: Final = "CPyDunder_" # Wrappers for exposing dunder methods to the API +REG_PREFIX: Final = "cpy_r_" # Registers +STATIC_PREFIX: Final = "CPyStatic_" # Static variables (for literals etc.) +TYPE_PREFIX: Final = "CPyType_" # Type object struct +MODULE_PREFIX: Final = "CPyModule_" # Cached modules +ATTR_PREFIX: Final = "_" # Attributes + +ENV_ATTR_NAME: Final = "__mypyc_env__" +NEXT_LABEL_ATTR_NAME: Final = "__mypyc_next_label__" +TEMP_ATTR_NAME: Final = "__mypyc_temp__" +LAMBDA_NAME: Final = "__mypyc_lambda__" +PROPSET_PREFIX: Final = "__mypyc_setter__" +SELF_NAME: Final = "__mypyc_self__" # Max short int we accept as a literal is based on 32-bit platforms, # so that we can just always emit the same code. -TOP_LEVEL_NAME = '__top_level__' # type: Final # Special function representing module top level +TOP_LEVEL_NAME: Final = "__top_level__" # Special function representing module top level # Maximal number of subclasses for a class to trigger fast path in isinstance() checks. -FAST_ISINSTANCE_MAX_SUBCLASSES = 2 # type: Final +FAST_ISINSTANCE_MAX_SUBCLASSES: Final = 2 -IS_32_BIT_PLATFORM = sys.maxsize < (1 << 31) # type: Final +IS_32_BIT_PLATFORM: Final = sys.maxsize < (1 << 31) PLATFORM_SIZE = 4 if IS_32_BIT_PLATFORM else 8 @@ -37,42 +37,39 @@ # wheels (for an unknown reason). # # Note that we use "in ['darwin']" because of https://github.com/mypyc/mypyc/issues/761. -IS_MIXED_32_64_BIT_BUILD = sys.platform in ['darwin'] and sys.version_info < (3, 6) # type: Final +IS_MIXED_32_64_BIT_BUILD: Final = sys.platform in ["darwin"] and sys.version_info < (3, 6) # Maximum value for a short tagged integer. -MAX_SHORT_INT = sys.maxsize >> 1 # type: Final +MAX_SHORT_INT: Final = sys.maxsize >> 1 # Maximum value for a short tagged integer represented as a C integer literal. # # Note: Assume that the compiled code uses the same bit width as mypyc, except for # Python 3.5 on macOS. -MAX_LITERAL_SHORT_INT = (sys.maxsize >> 1 if not IS_MIXED_32_64_BIT_BUILD - else 2**30 - 1) # type: Final +MAX_LITERAL_SHORT_INT: Final = sys.maxsize >> 1 if not IS_MIXED_32_64_BIT_BUILD else 2 ** 30 - 1 +MIN_LITERAL_SHORT_INT: Final = -MAX_LITERAL_SHORT_INT - 1 # Runtime C library files -RUNTIME_C_FILES = [ +RUNTIME_C_FILES: Final = [ 'init.c', 'getargs.c', 'getargsfast.c', 'int_ops.c', + 'str_ops.c', + 'bytes_ops.c', 'list_ops.c', 'dict_ops.c', - 'str_ops.c', 'set_ops.c', 'tuple_ops.c', 'exc_ops.c', 'misc_ops.c', 'generic_ops.c', -] # type: Final +] JsonDict = Dict[str, Any] -def decorator_helper_name(func_name: str) -> str: - return '__mypyc_{}_decorator_helper__'.format(func_name) - - def shared_lib_name(group_name: str) -> str: """Given a group name, return the actual name of its extension module. @@ -100,3 +97,25 @@ def use_vectorcall(capi_version: Tuple[int, int]) -> bool: def use_method_vectorcall(capi_version: Tuple[int, int]) -> bool: # We can use a dedicated vectorcall API to call methods on Python 3.9+. return capi_version >= (3, 9) + + +def get_id_from_name(name: str, fullname: str, line: int) -> str: + """Create a unique id for a function. + + This creates an id that is unique for any given function definition, so that it can be used as + a dictionary key. This is usually the fullname of the function, but this is different in that + it handles the case where the function is named '_', in which case multiple different functions + could have the same name.""" + if unnamed_function(name): + return "{}.{}".format(fullname, line) + else: + return fullname + + +def short_id_from_name(func_name: str, shortname: str, line: Optional[int]) -> str: + if unnamed_function(func_name): + assert line is not None + partial_name = "{}.{}".format(shortname, line) + else: + partial_name = shortname + return partial_name diff --git a/mypyc/doc/dev-intro.md b/mypyc/doc/dev-intro.md index 11de9cdc0c8b..bf0c1a836874 100644 --- a/mypyc/doc/dev-intro.md +++ b/mypyc/doc/dev-intro.md @@ -73,11 +73,11 @@ compiled code. For example, you may want to do interactive testing or to run benchmarks. This is also handy if you want to inspect the generated C code (see Inspecting Generated C). -Run `scripts/mypyc` to compile a module to a C extension using your +Run `mypyc` to compile a module to a C extension using your development version of mypyc: ``` -$ scripts/mypyc program.py +$ mypyc program.py ``` This will generate a C extension for `program` in the current working diff --git a/mypyc/doc/dict_operations.rst b/mypyc/doc/dict_operations.rst index eb2e5221c518..e3104172133a 100644 --- a/mypyc/doc/dict_operations.rst +++ b/mypyc/doc/dict_operations.rst @@ -13,6 +13,11 @@ Construct dict from keys and values: * ``{key: value, ...}`` +Construct empty dict: + +* ``{}`` +* ``dict()`` + Construct dict from another object: * ``dict(d: dict)`` diff --git a/mypyc/doc/list_operations.rst b/mypyc/doc/list_operations.rst index d6ae88dbc3b1..5993c0a656bd 100644 --- a/mypyc/doc/list_operations.rst +++ b/mypyc/doc/list_operations.rst @@ -13,6 +13,11 @@ Construct list with specific items: * ``[item0, ..., itemN]`` +Construct empty list: + +* ``[]`` +* ``list()`` + Construct list from iterable: * ``list(x: Iterable)`` diff --git a/mypyc/doc/native_classes.rst b/mypyc/doc/native_classes.rst index 8987d55d759b..2b4a0892b790 100644 --- a/mypyc/doc/native_classes.rst +++ b/mypyc/doc/native_classes.rst @@ -159,6 +159,39 @@ as pure native classes. If a class definition uses an unsupported class decorator, *mypyc compiles the class into a regular Python class*. +Deleting attributes +------------------- + +By default, attributes defined in native classes can't be deleted. You +can explicitly allow certain attributes to be deleted by using +``__deletable__``:: + + class Cls: + x: int = 0 + y: int = 0 + other: int = 0 + + __deletable__ = ['x', 'y'] # 'x' and 'y' can be deleted + + o = Cls() + del o.x # OK + del o.y # OK + del o.other # Error + +You must initialize the ``__deletable__`` attribute in the class body, +using a list or a tuple expression with only string literal items that +refer to attributes. These are not valid:: + + a = ['x', 'y'] + + class Cls: + x: int + y: int + + __deletable__ = a # Error: cannot use variable 'a' + + __deletable__ = ('a',) # Error: not in a class body + Other properties ---------------- diff --git a/mypyc/errors.py b/mypyc/errors.py index aac543d10ee4..3d3b8694c9d6 100644 --- a/mypyc/errors.py +++ b/mypyc/errors.py @@ -13,6 +13,9 @@ def error(self, msg: str, path: str, line: int) -> None: self._errors.report(line, None, msg, severity='error', file=path) self.num_errors += 1 + def note(self, msg: str, path: str, line: int) -> None: + self._errors.report(line, None, msg, severity='note', file=path) + def warning(self, msg: str, path: str, line: int) -> None: self._errors.report(line, None, msg, severity='warning', file=path) self.num_warnings += 1 diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index aeb0f8410c56..ade04f39edcb 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -1,7 +1,7 @@ """Intermediate representation of classes.""" from typing import List, Optional, Set, Tuple, Dict, NamedTuple -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from mypyc.common import JsonDict from mypyc.ir.ops import Value, DeserMaps @@ -18,7 +18,7 @@ # vtable. # # This makes multiple inheritance tricky, since obviously we cannot be -# an extension of multiple parent classes. We solve this by requriing +# an extension of multiple parent classes. We solve this by requiring # all but one parent to be "traits", which we can operate on in a # somewhat less efficient way. For each trait implemented by a class, # we generate a separate vtable for the methods in that trait. @@ -102,50 +102,63 @@ def __init__(self, name: str, module_name: str, is_trait: bool = False, self.has_dict = False # Do we allow interpreted subclasses? Derived from a mypyc_attr. self.allow_interpreted_subclasses = False + # Does this class need getseters to be generated for its attributes? (getseters are also + # added if is_generated is False) + self.needs_getseters = False # If this a subclass of some built-in python class, the name # of the object for that class. We currently only support this # in a few ad-hoc cases. - self.builtin_base = None # type: Optional[str] + self.builtin_base: Optional[str] = None # Default empty constructor self.ctor = FuncDecl(name, None, module_name, FuncSignature([], RInstance(self))) - self.attributes = OrderedDict() # type: OrderedDict[str, RType] + self.attributes: OrderedDict[str, RType] = OrderedDict() + # Deletable attributes + self.deletable: List[str] = [] # We populate method_types with the signatures of every method before # we generate methods, and we rely on this information being present. - self.method_decls = OrderedDict() # type: OrderedDict[str, FuncDecl] + self.method_decls: OrderedDict[str, FuncDecl] = OrderedDict() # Map of methods that are actually present in an extension class - self.methods = OrderedDict() # type: OrderedDict[str, FuncIR] + self.methods: OrderedDict[str, FuncIR] = OrderedDict() # Glue methods for boxing/unboxing when a class changes the type - # while overriding a method. Maps from (parent class overrided, method) + # while overriding a method. Maps from (parent class overridden, method) # to IR of glue method. - self.glue_methods = OrderedDict() # type: Dict[Tuple[ClassIR, str], FuncIR] + self.glue_methods: Dict[Tuple[ClassIR, str], FuncIR] = OrderedDict() # Properties are accessed like attributes, but have behavior like method calls. # They don't belong in the methods dictionary, since we don't want to expose them to # Python's method API. But we want to put them into our own vtable as methods, so that # they are properly handled and overridden. The property dictionary values are a tuple # containing a property getter and an optional property setter. - self.properties = OrderedDict() # type: OrderedDict[str, Tuple[FuncIR, Optional[FuncIR]]] + self.properties: OrderedDict[str, Tuple[FuncIR, Optional[FuncIR]]] = OrderedDict() # We generate these in prepare_class_def so that we have access to them when generating # other methods and properties that rely on these types. - self.property_types = OrderedDict() # type: OrderedDict[str, RType] + self.property_types: OrderedDict[str, RType] = OrderedDict() - self.vtable = None # type: Optional[Dict[str, int]] - self.vtable_entries = [] # type: VTableEntries - self.trait_vtables = OrderedDict() # type: OrderedDict[ClassIR, VTableEntries] + self.vtable: Optional[Dict[str, int]] = None + self.vtable_entries: VTableEntries = [] + self.trait_vtables: OrderedDict[ClassIR, VTableEntries] = OrderedDict() # N.B: base might not actually quite be the direct base. # It is the nearest concrete base, but we allow a trait in between. - self.base = None # type: Optional[ClassIR] - self.traits = [] # type: List[ClassIR] + self.base: Optional[ClassIR] = None + self.traits: List[ClassIR] = [] # Supply a working mro for most generated classes. Real classes will need to # fix it up. - self.mro = [self] # type: List[ClassIR] + self.mro: List[ClassIR] = [self] # base_mro is the chain of concrete (non-trait) ancestors - self.base_mro = [self] # type: List[ClassIR] + self.base_mro: List[ClassIR] = [self] - # Direct subclasses of this class (use subclasses() to also incude non-direct ones) + # Direct subclasses of this class (use subclasses() to also include non-direct ones) # None if separate compilation prevents this from working - self.children = [] # type: Optional[List[ClassIR]] + self.children: Optional[List[ClassIR]] = [] + + def __repr__(self) -> str: + return ( + "ClassIR(" + "name={self.name}, module_name={self.module_name}, " + "is_trait={self.is_trait}, is_generated={self.is_generated}, " + "is_abstract={self.is_abstract}, is_ext_class={self.is_ext_class}" + ")".format(self=self)) @property def fullname(self) -> str: @@ -211,6 +224,12 @@ def has_attr(self, name: str) -> bool: return False return True + def is_deletable(self, name: str) -> bool: + for ir in self.mro: + if name in ir.deletable: + return True + return False + def name_prefix(self, names: NameGenerator) -> str: return names.private_name(self.module_name, self.name) @@ -229,7 +248,7 @@ def get_method(self, name: str) -> Optional[FuncIR]: return res[0] if res else None def subclasses(self) -> Optional[Set['ClassIR']]: - """Return all subclassses of this class, both direct and indirect. + """Return all subclasses of this class, both direct and indirect. Return None if it is impossible to identify all subclasses, for example because we are performing separate compilation. @@ -255,7 +274,7 @@ def concrete_subclasses(self) -> Optional[List['ClassIR']]: return None concrete = {c for c in subs if not (c.is_trait or c.is_abstract)} # We place classes with no children first because they are more likely - # to appear in various isinstance() checks. We then sort leafs by name + # to appear in various isinstance() checks. We then sort leaves by name # to get stable order. return sorted(concrete, key=lambda c: (len(c.children or []), c.name)) @@ -271,18 +290,19 @@ def serialize(self) -> JsonDict: 'inherits_python': self.inherits_python, 'has_dict': self.has_dict, 'allow_interpreted_subclasses': self.allow_interpreted_subclasses, + 'needs_getseters': self.needs_getseters, 'builtin_base': self.builtin_base, 'ctor': self.ctor.serialize(), # We serialize dicts as lists to ensure order is preserved 'attributes': [(k, t.serialize()) for k, t in self.attributes.items()], # We try to serialize a name reference, but if the decl isn't in methods # then we can't be sure that will work so we serialize the whole decl. - 'method_decls': [(k, d.fullname if k in self.methods else d.serialize()) + 'method_decls': [(k, d.id if k in self.methods else d.serialize()) for k, d in self.method_decls.items()], # We serialize method fullnames out and put methods in a separate dict - 'methods': [(k, m.fullname) for k, m in self.methods.items()], + 'methods': [(k, m.id) for k, m in self.methods.items()], 'glue_methods': [ - ((cir.fullname, k), m.fullname) + ((cir.fullname, k), m.id) for (cir, k), m in self.glue_methods.items() ], @@ -321,6 +341,7 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'ClassIR': ir.inherits_python = data['inherits_python'] ir.has_dict = data['has_dict'] ir.allow_interpreted_subclasses = data['allow_interpreted_subclasses'] + ir.needs_getseters = data['needs_getseters'] ir.builtin_base = data['builtin_base'] ir.ctor = FuncDecl.deserialize(data['ctor'], ctx) ir.attributes = OrderedDict( @@ -375,8 +396,8 @@ def serialize_vtable_entry(entry: VTableMethod) -> JsonDict: '.class': 'VTableMethod', 'cls': entry.cls.fullname, 'name': entry.name, - 'method': entry.method.decl.fullname, - 'shadow_method': entry.shadow_method.decl.fullname if entry.shadow_method else None, + 'method': entry.method.decl.id, + 'shadow_method': entry.shadow_method.decl.id if entry.shadow_method else None, } diff --git a/mypyc/ir/func_ir.py b/mypyc/ir/func_ir.py index 8b4731f88d34..1426b0ecdf0f 100644 --- a/mypyc/ir/func_ir.py +++ b/mypyc/ir/func_ir.py @@ -3,9 +3,9 @@ from typing import List, Optional, Sequence from typing_extensions import Final -from mypy.nodes import FuncDef, Block, ARG_POS, ARG_OPT, ARG_NAMED_OPT +from mypy.nodes import FuncDef, Block, ArgKind, ARG_POS -from mypyc.common import JsonDict +from mypyc.common import JsonDict, get_id_from_name, short_id_from_name from mypyc.ir.ops import ( DeserMaps, BasicBlock, Value, Register, Assign, AssignMulti, ControlOp, LoadAddress ) @@ -19,27 +19,32 @@ class RuntimeArg: Argument kind is one of ARG_* constants defined in mypy.nodes. """ - def __init__(self, name: str, typ: RType, kind: int = ARG_POS) -> None: + def __init__( + self, name: str, typ: RType, kind: ArgKind = ARG_POS, pos_only: bool = False) -> None: self.name = name self.type = typ self.kind = kind + self.pos_only = pos_only @property def optional(self) -> bool: - return self.kind == ARG_OPT or self.kind == ARG_NAMED_OPT + return self.kind.is_optional() def __repr__(self) -> str: - return 'RuntimeArg(name=%s, type=%s, optional=%r)' % (self.name, self.type, self.optional) + return 'RuntimeArg(name=%s, type=%s, optional=%r, pos_only=%r)' % ( + self.name, self.type, self.optional, self.pos_only) def serialize(self) -> JsonDict: - return {'name': self.name, 'type': self.type.serialize(), 'kind': self.kind} + return {'name': self.name, 'type': self.type.serialize(), 'kind': int(self.kind.value), + 'pos_only': self.pos_only} @classmethod def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'RuntimeArg': return RuntimeArg( data['name'], deserialize_type(data['type'], ctx), - data['kind'], + ArgKind(data['kind']), + data['pos_only'], ) @@ -66,9 +71,9 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncSignature': ) -FUNC_NORMAL = 0 # type: Final -FUNC_STATICMETHOD = 1 # type: Final -FUNC_CLASSMETHOD = 2 # type: Final +FUNC_NORMAL: Final = 0 +FUNC_STATICMETHOD: Final = 1 +FUNC_CLASSMETHOD: Final = 2 class FuncDecl: @@ -94,13 +99,31 @@ def __init__(self, self.is_prop_setter = is_prop_setter self.is_prop_getter = is_prop_getter if class_name is None: - self.bound_sig = None # type: Optional[FuncSignature] + self.bound_sig: Optional[FuncSignature] = None else: if kind == FUNC_STATICMETHOD: self.bound_sig = sig else: self.bound_sig = FuncSignature(sig.args[1:], sig.ret_type) + # this is optional because this will be set to the line number when the corresponding + # FuncIR is created + self._line: Optional[int] = None + + @property + def line(self) -> int: + assert self._line is not None + return self._line + + @line.setter + def line(self, line: int) -> None: + self._line = line + + @property + def id(self) -> str: + assert self.line is not None + return get_id_from_name(self.name, self.fullname, self.line) + @staticmethod def compute_shortname(class_name: Optional[str], name: str) -> str: return class_name + '.' + name if class_name else name @@ -114,7 +137,8 @@ def fullname(self) -> str: return self.module_name + '.' + self.shortname def cname(self, names: NameGenerator) -> str: - return names.private_name(self.module_name, self.shortname) + partial_name = short_id_from_name(self.name, self.shortname, self._line) + return names.private_name(self.module_name, partial_name) def serialize(self) -> JsonDict: return { @@ -127,9 +151,14 @@ def serialize(self) -> JsonDict: 'is_prop_getter': self.is_prop_getter, } + # TODO: move this to FuncIR? @staticmethod - def get_name_from_json(f: JsonDict) -> str: - return f['module_name'] + '.' + FuncDecl.compute_shortname(f['class_name'], f['name']) + def get_id_from_json(func_ir: JsonDict) -> str: + """Get the id from the serialized FuncIR associated with this FuncDecl""" + decl = func_ir['decl'] + shortname = FuncDecl.compute_shortname(decl['class_name'], decl['name']) + fullname = decl['module_name'] + '.' + shortname + return get_id_from_name(decl['name'], fullname, func_ir['line']) @classmethod def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncDecl': @@ -162,12 +191,16 @@ def __init__(self, self.arg_regs = arg_regs # Body of the function self.blocks = blocks - self.line = line + self.decl.line = line # The name that should be displayed for tracebacks that # include this function. Function will be omitted from # tracebacks if None. self.traceback_name = traceback_name + @property + def line(self) -> int: + return self.decl.line + @property def args(self) -> Sequence[RuntimeArg]: return self.decl.sig.args @@ -192,6 +225,10 @@ def name(self) -> str: def fullname(self) -> str: return self.decl.fullname + @property + def id(self) -> str: + return self.decl.id + def cname(self, names: NameGenerator) -> str: return self.decl.cname(names) @@ -220,7 +257,7 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncIR': ) -INVALID_FUNC_DEF = FuncDef('', [], Block([])) # type: Final +INVALID_FUNC_DEF: Final = FuncDef("", [], Block([])) def all_values(args: List[Register], blocks: List[BasicBlock]) -> List[Value]: @@ -228,7 +265,7 @@ def all_values(args: List[Register], blocks: List[BasicBlock]) -> List[Value]: This omits registers that are only read. """ - values = list(args) # type: List[Value] + values: List[Value] = list(args) seen_registers = set(args) for block in blocks: @@ -254,13 +291,13 @@ def all_values(args: List[Register], blocks: List[BasicBlock]) -> List[Value]: def all_values_full(args: List[Register], blocks: List[BasicBlock]) -> List[Value]: """Return set of all values that are initialized or accessed.""" - values = list(args) # type: List[Value] + values: List[Value] = list(args) seen_registers = set(args) for block in blocks: for op in block.ops: for source in op.sources(): - # Look for unitialized registers that are accessed. Ignore + # Look for uninitialized registers that are accessed. Ignore # non-registers since we don't allow ops outside basic blocks. if isinstance(source, Register) and source not in seen_registers: values.append(source) diff --git a/mypyc/ir/module_ir.py b/mypyc/ir/module_ir.py index 99fcbef194c7..8fa5e522ddf0 100644 --- a/mypyc/ir/module_ir.py +++ b/mypyc/ir/module_ir.py @@ -39,7 +39,7 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'ModuleIR': return ModuleIR( data['fullname'], data['imports'], - [ctx.functions[FuncDecl.get_name_from_json(f['decl'])] for f in data['functions']], + [ctx.functions[FuncDecl.get_id_from_json(f)] for f in data['functions']], [ClassIR.deserialize(c, ctx) for c in data['classes']], [(k, deserialize_type(t, ctx)) for k, t in data['final_names']], ) @@ -72,9 +72,9 @@ def deserialize_modules(data: Dict[str, JsonDict], ctx: DeserMaps) -> Dict[str, # to the class deserialization. for method in mod['functions']: func = FuncIR.deserialize(method, ctx) - assert func.decl.fullname not in ctx.functions, ( + assert func.decl.id not in ctx.functions, ( "Method %s already in map" % func.decl.fullname) - ctx.functions[func.decl.fullname] = func + ctx.functions[func.decl.id] = func return {k: ModuleIR.deserialize(v, ctx) for k, v in data.items()} diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 33e6875aa939..22dead2f7976 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -63,8 +63,8 @@ class BasicBlock: def __init__(self, label: int = -1) -> None: self.label = label - self.ops = [] # type: List[Op] - self.error_handler = None # type: Optional[BasicBlock] + self.ops: List[Op] = [] + self.error_handler: Optional[BasicBlock] = None @property def terminated(self) -> bool: @@ -75,15 +75,21 @@ def terminated(self) -> bool: """ return bool(self.ops) and isinstance(self.ops[-1], ControlOp) + @property + def terminator(self) -> 'ControlOp': + """The terminator operation of the block.""" + assert bool(self.ops) and isinstance(self.ops[-1], ControlOp) + return self.ops[-1] + # Never generates an exception -ERR_NEVER = 0 # type: Final +ERR_NEVER: Final = 0 # Generates magic value (c_error_value) based on target RType on exception -ERR_MAGIC = 1 # type: Final +ERR_MAGIC: Final = 1 # Generates false (bool) on exception -ERR_FALSE = 2 # type: Final +ERR_FALSE: Final = 2 # Always fails -ERR_ALWAYS = 3 # type: Final +ERR_ALWAYS: Final = 3 # Hack: using this line number for an op will suppress it in tracebacks NO_TRACEBACK_LINE_NO = -10000 @@ -108,7 +114,7 @@ class Value: # Source line number (-1 for no/unknown line) line = -1 # Type of the value or the result of the operation - type = void_rtype # type: RType + type: RType = void_rtype is_borrowed = False @property @@ -197,7 +203,7 @@ def stolen(self) -> List[Value]: return [] def unique_sources(self) -> List[Value]: - result = [] # type: List[Value] + result: List[Value] = [] for reg in self.sources(): if reg not in result: result.append(reg) @@ -260,12 +266,15 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: class ControlOp(Op): - """Control flow operation. + """Control flow operation.""" - This is Basically just for class hierarchy organization. + def targets(self) -> Sequence[BasicBlock]: + """Get all basic block targets of the control operation.""" + return () - We could plausibly have a targets() method if we wanted. - """ + def set_target(self, i: int, new: BasicBlock) -> None: + """Update a basic block target.""" + raise AssertionError("Invalid set_target({}, {})".format(self, i)) class Goto(ControlOp): @@ -277,6 +286,13 @@ def __init__(self, label: BasicBlock, line: int = -1) -> None: super().__init__(line) self.label = label + def targets(self) -> Sequence[BasicBlock]: + return (self.label,) + + def set_target(self, i: int, new: BasicBlock) -> None: + assert i == 0 + self.label = new + def __repr__(self) -> str: return '' % self.label.label @@ -300,8 +316,8 @@ class Branch(ControlOp): # Branch ops never raise an exception. error_kind = ERR_NEVER - BOOL = 100 # type: Final - IS_ERROR = 101 # type: Final + BOOL: Final = 100 + IS_ERROR: Final = 101 def __init__(self, value: Value, @@ -323,10 +339,21 @@ def __init__(self, # If True, the condition is negated self.negated = False # If not None, the true label should generate a traceback entry (func name, line number) - self.traceback_entry = None # type: Optional[Tuple[str, int]] - # If True, the condition is expected to be usually False (for optimization purposes) + self.traceback_entry: Optional[Tuple[str, int]] = None + # If True, we expect to usually take the false branch (for optimization purposes); + # this is implicitly treated as true if there is a traceback entry self.rare = rare + def targets(self) -> Sequence[BasicBlock]: + return (self.true, self.false) + + def set_target(self, i: int, new: BasicBlock) -> None: + assert i == 0 or i == 1 + if i == 0: + self.true = new + elif i == 1: + self.false = new + def sources(self) -> List[Value]: return [self.value] @@ -399,7 +426,7 @@ class RegisterOp(Op): error_kind = -1 # Can this raise exception and how is it signalled; one of ERR_* - _type = None # type: Optional[RType] + _type: Optional[RType] = None def __init__(self, line: int) -> None: super().__init__(line) @@ -609,13 +636,13 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: # Default name space for statics, variables -NAMESPACE_STATIC = 'static' # type: Final +NAMESPACE_STATIC: Final = "static" # Static namespace for pointers to native type objects -NAMESPACE_TYPE = 'type' # type: Final +NAMESPACE_TYPE: Final = "type" # Namespace for modules -NAMESPACE_MODULE = 'module' # type: Final +NAMESPACE_MODULE: Final = "module" class LoadStatic(RegisterOp): @@ -809,12 +836,12 @@ class RaiseStandardError(RegisterOp): error_kind = ERR_FALSE - VALUE_ERROR = 'ValueError' # type: Final - ASSERTION_ERROR = 'AssertionError' # type: Final - STOP_ITERATION = 'StopIteration' # type: Final - UNBOUND_LOCAL_ERROR = 'UnboundLocalError' # type: Final - RUNTIME_ERROR = 'RuntimeError' # type: Final - NAME_ERROR = 'NameError' # type: Final + VALUE_ERROR: Final = "ValueError" + ASSERTION_ERROR: Final = "AssertionError" + STOP_ITERATION: Final = "StopIteration" + UNBOUND_LOCAL_ERROR: Final = "UnboundLocalError" + RUNTIME_ERROR: Final = "RuntimeError" + NAME_ERROR: Final = "NameError" def __init__(self, class_name: str, value: Optional[Union[str, Value]], line: int) -> None: super().__init__(line) @@ -950,20 +977,20 @@ class IntOp(RegisterOp): error_kind = ERR_NEVER # Arithmetic ops - ADD = 0 # type: Final - SUB = 1 # type: Final - MUL = 2 # type: Final - DIV = 3 # type: Final - MOD = 4 # type: Final + ADD: Final = 0 + SUB: Final = 1 + MUL: Final = 2 + DIV: Final = 3 + MOD: Final = 4 # Bitwise ops - AND = 200 # type: Final - OR = 201 # type: Final - XOR = 202 # type: Final - LEFT_SHIFT = 203 # type: Final - RIGHT_SHIFT = 204 # type: Final + AND: Final = 200 + OR: Final = 201 + XOR: Final = 202 + LEFT_SHIFT: Final = 203 + RIGHT_SHIFT: Final = 204 - op_str = { + op_str: Final = { ADD: '+', SUB: '-', MUL: '*', @@ -974,7 +1001,7 @@ class IntOp(RegisterOp): XOR: '^', LEFT_SHIFT: '<<', RIGHT_SHIFT: '>>', - } # type: Final + } def __init__(self, type: RType, lhs: Value, rhs: Value, op: int, line: int = -1) -> None: super().__init__(line) @@ -1007,18 +1034,18 @@ class ComparisonOp(RegisterOp): error_kind = ERR_NEVER # S for signed and U for unsigned - EQ = 100 # type: Final - NEQ = 101 # type: Final - SLT = 102 # type: Final - SGT = 103 # type: Final - SLE = 104 # type: Final - SGE = 105 # type: Final - ULT = 106 # type: Final - UGT = 107 # type: Final - ULE = 108 # type: Final - UGE = 109 # type: Final - - op_str = { + EQ: Final = 100 + NEQ: Final = 101 + SLT: Final = 102 + SGT: Final = 103 + SLE: Final = 104 + SGE: Final = 105 + ULT: Final = 106 + UGT: Final = 107 + ULE: Final = 108 + UGE: Final = 109 + + op_str: Final = { EQ: '==', NEQ: '!=', SLT: '<', @@ -1029,7 +1056,7 @@ class ComparisonOp(RegisterOp): UGT: '>', ULE: '<=', UGE: '>=', - } # type: Final + } def __init__(self, lhs: Value, rhs: Value, op: int, line: int = -1) -> None: super().__init__(line) @@ -1332,7 +1359,7 @@ def visit_keep_alive(self, op: KeepAlive) -> T: # we might need to reference. # # Because of these references, we need to maintain maps from class -# names to ClassIRs and func names to FuncIRs. +# names to ClassIRs and func IDs to FuncIRs. # # These are tracked in a DeserMaps which is passed to every # deserialization function. diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index ab4155007657..daa0fd0f86df 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -1,6 +1,7 @@ """Utilities for pretty-printing IR in a human-readable form.""" -from typing import Any, Dict, List +from collections import defaultdict +from typing import Any, Dict, List, Union, Sequence, Tuple from typing_extensions import Final @@ -10,12 +11,14 @@ LoadStatic, InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, SetMem, GetElementPtr, LoadAddress, Register, Value, OpVisitor, BasicBlock, ControlOp, LoadLiteral, - AssignMulti, KeepAlive + AssignMulti, KeepAlive, Op ) from mypyc.ir.func_ir import FuncIR, all_values_full from mypyc.ir.module_ir import ModuleIRs from mypyc.ir.rtypes import is_bool_rprimitive, is_int_rprimitive, RType +ErrorSource = Union[BasicBlock, Op] + class IRPrettyPrintVisitor(OpVisitor[str]): """Internal visitor that pretty-prints ops.""" @@ -29,10 +32,10 @@ def __init__(self, names: Dict[Value, str]) -> None: def visit_goto(self, op: Goto) -> str: return self.format('goto %l', op.label) - branch_op_names = { + branch_op_names: Final = { Branch.BOOL: ('%r', 'bool'), Branch.IS_ERROR: ('is_error(%r)', ''), - } # type: Final + } def visit_branch(self, op: Branch) -> str: fmt, typ = self.branch_op_names[op.op] @@ -269,13 +272,14 @@ def format_registers(func_ir: FuncIR, def format_blocks(blocks: List[BasicBlock], - names: Dict[Value, str]) -> List[str]: + names: Dict[Value, str], + source_to_error: Dict[ErrorSource, List[str]]) -> List[str]: """Format a list of IR basic blocks into a human-readable form.""" # First label all of the blocks for i, block in enumerate(blocks): block.label = i - handler_map = {} # type: Dict[BasicBlock, List[BasicBlock]] + handler_map: Dict[BasicBlock, List[BasicBlock]] = {} for b in blocks: if b.error_handler: handler_map.setdefault(b.error_handler, []).append(b) @@ -290,14 +294,22 @@ def format_blocks(blocks: List[BasicBlock], handler_msg = ' (handler for {})'.format(', '.join(labels)) lines.append('L%d:%s' % (block.label, handler_msg)) + if block in source_to_error: + for error in source_to_error[block]: + lines.append(f" ERR: {error}") ops = block.ops if (isinstance(ops[-1], Goto) and i + 1 < len(blocks) - and ops[-1].label == blocks[i + 1]): - # Hide the last goto if it just goes to the next basic block. + and ops[-1].label == blocks[i + 1] + and not source_to_error.get(ops[-1], [])): + # Hide the last goto if it just goes to the next basic block, + # and there are no assocatiated errors with the op. ops = ops[:-1] for op in ops: line = ' ' + op.accept(visitor) lines.append(line) + if op in source_to_error: + for error in source_to_error[op]: + lines.append(f" ERR: {error}") if not isinstance(block.ops[-1], (Goto, Branch, Return, Unreachable)): # Each basic block needs to exit somewhere. @@ -305,7 +317,7 @@ def format_blocks(blocks: List[BasicBlock], return lines -def format_func(fn: FuncIR) -> List[str]: +def format_func(fn: FuncIR, errors: Sequence[Tuple[ErrorSource, str]] = ()) -> List[str]: lines = [] cls_prefix = fn.class_name + '.' if fn.class_name else '' lines.append('def {}{}({}):'.format(cls_prefix, fn.name, @@ -313,7 +325,12 @@ def format_func(fn: FuncIR) -> List[str]: names = generate_names_for_ir(fn.arg_regs, fn.blocks) for line in format_registers(fn, names): lines.append(' ' + line) - code = format_blocks(fn.blocks, names) + + source_to_error = defaultdict(list) + for source, error in errors: + source_to_error[source].append(error) + + code = format_blocks(fn.blocks, names, source_to_error) lines.extend(code) return lines @@ -333,7 +350,7 @@ def generate_names_for_ir(args: List[Register], blocks: List[BasicBlock]) -> Dic Give names such as 'r5' to temp values in IR which are useful when pretty-printing or generating C. Ensure generated names are unique. """ - names = {} # type: Dict[Value, str] + names: Dict[Value, str] = {} used_names = set() temp_index = 0 diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index 39dce61c2c76..4bf71883b15d 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -38,18 +38,18 @@ class RType: """Abstract base class for runtime types (erased, only concrete; no generics).""" - name = None # type: str + name: str # If True, the type has a special unboxed representation. If False, the # type is represented as PyObject *. Even if True, the representation # may contain pointers. is_unboxed = False # This is the C undefined value for this type. It's used for initialization # if there's no value yet, and for function return value on error/exception. - c_undefined = None # type: str + c_undefined: str # If unboxed: does the unboxed version use reference counting? is_refcounted = True # C type; use Emitter.ctype() to access - _ctype = None # type: str + _ctype: str @abstractmethod def accept(self, visitor: 'RTypeVisitor[T]') -> T: @@ -151,7 +151,7 @@ def __hash__(self) -> int: # Singleton instance of RVoid -void_rtype = RVoid() # type: Final +void_rtype: Final = RVoid() class RPrimitive(RType): @@ -169,7 +169,7 @@ class RPrimitive(RType): """ # Map from primitive names to primitive types and is used by deserialization - primitive_map = {} # type: ClassVar[Dict[str, RPrimitive]] + primitive_map: ClassVar[Dict[str, "RPrimitive"]] = {} def __init__(self, name: str, @@ -232,12 +232,12 @@ def __hash__(self) -> int: # little as possible, as generic ops are typically slow. Other types, # including other primitive types and RInstance, are usually much # faster. -object_rprimitive = RPrimitive('builtins.object', is_unboxed=False, - is_refcounted=True) # type: Final +object_rprimitive: Final = RPrimitive("builtins.object", is_unboxed=False, is_refcounted=True) # represents a low level pointer of an object -object_pointer_rprimitive = RPrimitive('object_ptr', is_unboxed=False, - is_refcounted=False, ctype='PyObject **') # type: Final +object_pointer_rprimitive: Final = RPrimitive( + "object_ptr", is_unboxed=False, is_refcounted=False, ctype="PyObject **" +) # Arbitrary-precision integer (corresponds to Python 'int'). Small # enough values are stored unboxed, while large integers are @@ -251,25 +251,31 @@ def __hash__(self) -> int: # # This cannot represent a subclass of int. An instance of a subclass # of int is coerced to the corresponding 'int' value. -int_rprimitive = RPrimitive('builtins.int', is_unboxed=True, is_refcounted=True, - ctype='CPyTagged') # type: Final +int_rprimitive: Final = RPrimitive( + "builtins.int", is_unboxed=True, is_refcounted=True, ctype="CPyTagged" +) # An unboxed integer. The representation is the same as for unboxed # int_rprimitive (shifted left by one). These can be used when an # integer is known to be small enough to fit size_t (CPyTagged). -short_int_rprimitive = RPrimitive('short_int', is_unboxed=True, is_refcounted=False, - ctype='CPyTagged') # type: Final +short_int_rprimitive: Final = RPrimitive( + "short_int", is_unboxed=True, is_refcounted=False, ctype="CPyTagged" +) # Low level integer types (correspond to C integer types) -int32_rprimitive = RPrimitive('int32', is_unboxed=True, is_refcounted=False, - ctype='int32_t', size=4) # type: Final -int64_rprimitive = RPrimitive('int64', is_unboxed=True, is_refcounted=False, - ctype='int64_t', size=8) # type: Final -uint32_rprimitive = RPrimitive('uint32', is_unboxed=True, is_refcounted=False, - ctype='uint32_t', size=4) # type: Final -uint64_rprimitive = RPrimitive('uint64', is_unboxed=True, is_refcounted=False, - ctype='uint64_t', size=8) # type: Final +int32_rprimitive: Final = RPrimitive( + "int32", is_unboxed=True, is_refcounted=False, ctype="int32_t", size=4 +) +int64_rprimitive: Final = RPrimitive( + "int64", is_unboxed=True, is_refcounted=False, ctype="int64_t", size=8 +) +uint32_rprimitive: Final = RPrimitive( + "uint32", is_unboxed=True, is_refcounted=False, ctype="uint32_t", size=4 +) +uint64_rprimitive: Final = RPrimitive( + "uint64", is_unboxed=True, is_refcounted=False, ctype="uint64_t", size=8 +) # The C 'int' type c_int_rprimitive = int32_rprimitive @@ -277,54 +283,60 @@ def __hash__(self) -> int: if IS_32_BIT_PLATFORM: c_size_t_rprimitive = uint32_rprimitive c_pyssize_t_rprimitive = RPrimitive('native_int', is_unboxed=True, is_refcounted=False, - ctype='int32_t', size=4) + ctype='int32_t', size=4) else: c_size_t_rprimitive = uint64_rprimitive c_pyssize_t_rprimitive = RPrimitive('native_int', is_unboxed=True, is_refcounted=False, - ctype='int64_t', size=8) + ctype='int64_t', size=8) # Low level pointer, represented as integer in C backends -pointer_rprimitive = RPrimitive('ptr', is_unboxed=True, is_refcounted=False, - ctype='CPyPtr') # type: Final +pointer_rprimitive: Final = RPrimitive("ptr", is_unboxed=True, is_refcounted=False, ctype="CPyPtr") # Floats are represent as 'float' PyObject * values. (In the future # we'll likely switch to a more efficient, unboxed representation.) -float_rprimitive = RPrimitive('builtins.float', is_unboxed=False, - is_refcounted=True) # type: Final +float_rprimitive: Final = RPrimitive("builtins.float", is_unboxed=False, is_refcounted=True) # An unboxed Python bool value. This actually has three possible values # (0 -> False, 1 -> True, 2 -> error). If you only need True/False, use # bit_rprimitive instead. -bool_rprimitive = RPrimitive('builtins.bool', is_unboxed=True, is_refcounted=False, - ctype='char', size=1) # type: Final +bool_rprimitive: Final = RPrimitive( + "builtins.bool", is_unboxed=True, is_refcounted=False, ctype="char", size=1 +) # A low-level boolean value with two possible values: 0 and 1. Any # other value results in undefined behavior. Undefined or error values # are not supported. -bit_rprimitive = RPrimitive('bit', is_unboxed=True, is_refcounted=False, - ctype='char', size=1) # type: Final +bit_rprimitive: Final = RPrimitive( + "bit", is_unboxed=True, is_refcounted=False, ctype="char", size=1 +) # The 'None' value. The possible values are 0 -> None and 2 -> error. -none_rprimitive = RPrimitive('builtins.None', is_unboxed=True, is_refcounted=False, - ctype='char', size=1) # type: Final +none_rprimitive: Final = RPrimitive( + "builtins.None", is_unboxed=True, is_refcounted=False, ctype="char", size=1 +) # Python list object (or an instance of a subclass of list). -list_rprimitive = RPrimitive('builtins.list', is_unboxed=False, is_refcounted=True) # type: Final +list_rprimitive: Final = RPrimitive("builtins.list", is_unboxed=False, is_refcounted=True) # Python dict object (or an instance of a subclass of dict). -dict_rprimitive = RPrimitive('builtins.dict', is_unboxed=False, is_refcounted=True) # type: Final +dict_rprimitive: Final = RPrimitive("builtins.dict", is_unboxed=False, is_refcounted=True) # Python set object (or an instance of a subclass of set). -set_rprimitive = RPrimitive('builtins.set', is_unboxed=False, is_refcounted=True) # type: Final +set_rprimitive: Final = RPrimitive("builtins.set", is_unboxed=False, is_refcounted=True) # Python str object. At the C layer, str is referred to as unicode # (PyUnicode). -str_rprimitive = RPrimitive('builtins.str', is_unboxed=False, is_refcounted=True) # type: Final +str_rprimitive: Final = RPrimitive("builtins.str", is_unboxed=False, is_refcounted=True) + +# Python bytes object. +bytes_rprimitive: Final = RPrimitive('builtins.bytes', is_unboxed=False, is_refcounted=True) # Tuple of an arbitrary length (corresponds to Tuple[t, ...], with # explicit '...'). -tuple_rprimitive = RPrimitive('builtins.tuple', is_unboxed=False, - is_refcounted=True) # type: Final +tuple_rprimitive: Final = RPrimitive("builtins.tuple", is_unboxed=False, is_refcounted=True) + +# Python range object. +range_rprimitive: Final = RPrimitive("builtins.range", is_unboxed=False, is_refcounted=True) def is_tagged(rtype: RType) -> bool: @@ -401,10 +413,18 @@ def is_str_rprimitive(rtype: RType) -> bool: return isinstance(rtype, RPrimitive) and rtype.name == 'builtins.str' +def is_bytes_rprimitive(rtype: RType) -> bool: + return isinstance(rtype, RPrimitive) and rtype.name == 'builtins.bytes' + + def is_tuple_rprimitive(rtype: RType) -> bool: return isinstance(rtype, RPrimitive) and rtype.name == 'builtins.tuple' +def is_range_rprimitive(rtype: RType) -> bool: + return isinstance(rtype, RPrimitive) and rtype.name == 'builtins.range' + + def is_sequence_rprimitive(rtype: RType) -> bool: return isinstance(rtype, RPrimitive) and ( is_list_rprimitive(rtype) or is_tuple_rprimitive(rtype) or is_str_rprimitive(rtype) @@ -502,11 +522,11 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'RTuple': # Dictionary iterator tuple: (should continue, internal offset, key, value) # See mypyc.irbuild.for_helpers.ForDictionaryCommon for more details. dict_next_rtuple_pair = RTuple( - [bool_rprimitive, int_rprimitive, object_rprimitive, object_rprimitive] + [bool_rprimitive, short_int_rprimitive, object_rprimitive, object_rprimitive] ) # Same as above but just for key or value. dict_next_rtuple_single = RTuple( - [bool_rprimitive, int_rprimitive, object_rprimitive] + [bool_rprimitive, short_int_rprimitive, object_rprimitive] ) @@ -601,7 +621,7 @@ def accept(self, visitor: 'RTypeVisitor[T]') -> T: return visitor.visit_rstruct(self) def __str__(self) -> str: - # if not tuple(unamed structs) + # if not tuple(unnamed structs) return '%s{%s}' % (self.name, ', '.join(name + ":" + str(typ) for name, typ in zip(self.names, self.types))) @@ -805,5 +825,5 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'RArray': PyListObject = RStruct( name='PyListObject', names=['ob_base', 'ob_item', 'allocated'], - types=[PyObject, pointer_rprimitive, c_pyssize_t_rprimitive] + types=[PyVarObject, pointer_rprimitive, c_pyssize_t_rprimitive] ) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 0b2a6537c5ea..57baa8dbf574 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -10,16 +10,19 @@ example, expressions are transformed in mypyc.irbuild.expression and functions are transformed in mypyc.irbuild.function. """ +from contextlib import contextmanager -from typing import Callable, Dict, List, Tuple, Optional, Union, Sequence, Set, Any +from mypyc.irbuild.prepare import RegisterImplInfo +from typing import Callable, Dict, List, Tuple, Optional, Union, Sequence, Set, Any, Iterator from typing_extensions import overload -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from mypy.build import Graph from mypy.nodes import ( MypyFile, SymbolNode, Statement, OpExpr, IntExpr, NameExpr, LDEF, Var, UnaryExpr, CallExpr, IndexExpr, Expression, MemberExpr, RefExpr, Lvalue, TupleExpr, - TypeInfo, Decorator, OverloadedFuncDef, StarExpr, ComparisonExpr, GDEF, ARG_POS, ARG_NAMED + TypeInfo, Decorator, OverloadedFuncDef, StarExpr, ComparisonExpr, GDEF, + ArgKind, ARG_POS, ARG_NAMED, FuncDef, ) from mypy.types import ( Type, Instance, TupleType, UninhabitedType, get_proper_type @@ -35,7 +38,7 @@ SetAttr, LoadStatic, InitStatic, NAMESPACE_MODULE, RaiseStandardError ) from mypyc.ir.rtypes import ( - RType, RTuple, RInstance, int_rprimitive, dict_rprimitive, + RType, RTuple, RInstance, c_int_rprimitive, int_rprimitive, dict_rprimitive, none_rprimitive, is_none_rprimitive, object_rprimitive, is_object_rprimitive, str_rprimitive, is_tagged, is_list_rprimitive, is_tuple_rprimitive, c_pyssize_t_rprimitive ) @@ -45,7 +48,9 @@ from mypyc.primitives.list_ops import to_list, list_pop_last, list_get_item_unsafe_op from mypyc.primitives.dict_ops import dict_get_item_op, dict_set_item_op from mypyc.primitives.generic_ops import py_setattr_op, iter_op, next_op -from mypyc.primitives.misc_ops import import_op, check_unpack_count_op, get_module_dict_op +from mypyc.primitives.misc_ops import ( + import_op, check_unpack_count_op, get_module_dict_op, import_extra_args_op +) from mypyc.crash import catch_errors from mypyc.options import CompilerOptions from mypyc.errors import Errors @@ -82,23 +87,24 @@ def __init__(self, mapper: Mapper, pbv: PreBuildVisitor, visitor: IRVisitor, - options: CompilerOptions) -> None: + options: CompilerOptions, + singledispatch_impls: Dict[FuncDef, List[RegisterImplInfo]]) -> None: self.builder = LowLevelIRBuilder(current_module, mapper, options) self.builders = [self.builder] - self.symtables = [OrderedDict()] # type: List[OrderedDict[SymbolNode, SymbolTarget]] - self.runtime_args = [[]] # type: List[List[RuntimeArg]] - self.function_name_stack = [] # type: List[str] - self.class_ir_stack = [] # type: List[ClassIR] + self.symtables: List[OrderedDict[SymbolNode, SymbolTarget]] = [OrderedDict()] + self.runtime_args: List[List[RuntimeArg]] = [[]] + self.function_name_stack: List[str] = [] + self.class_ir_stack: List[ClassIR] = [] self.current_module = current_module self.mapper = mapper self.types = types self.graph = graph - self.ret_types = [] # type: List[RType] - self.functions = [] # type: List[FuncIR] - self.classes = [] # type: List[ClassIR] - self.final_names = [] # type: List[Tuple[str, RType]] - self.callable_class_names = set() # type: Set[str] + self.ret_types: List[RType] = [] + self.functions: List[FuncIR] = [] + self.classes: List[ClassIR] = [] + self.final_names: List[Tuple[str, RType]] = [] + self.callable_class_names: Set[str] = set() self.options = options # These variables keep track of the number of lambdas, implicit indices, and implicit @@ -113,6 +119,7 @@ def __init__(self, self.encapsulating_funcs = pbv.encapsulating_funcs self.nested_fitems = pbv.nested_funcs.keys() self.fdefs_to_decorators = pbv.funcs_to_decorators + self.singledispatch_impls = singledispatch_impls self.visitor = visitor @@ -122,17 +129,17 @@ def __init__(self, # be generated) is stored in that FuncInfo instance. When the function is done being # generated, its corresponding FuncInfo is popped off the stack. self.fn_info = FuncInfo(INVALID_FUNC_DEF, '', '') - self.fn_infos = [self.fn_info] # type: List[FuncInfo] + self.fn_infos: List[FuncInfo] = [self.fn_info] # This list operates as a stack of constructs that modify the # behavior of nonlocal control flow constructs. - self.nonlocal_control = [] # type: List[NonlocalControl] + self.nonlocal_control: List[NonlocalControl] = [] self.errors = errors # Notionally a list of all of the modules imported by the # module being compiled, but stored as an OrderedDict so we # can also do quick lookups. - self.imports = OrderedDict() # type: OrderedDict[str, None] + self.imports: OrderedDict[str, None] = OrderedDict() # High-level control @@ -194,6 +201,16 @@ def py_get_attr(self, obj: Value, attr: str, line: int) -> Value: def load_str(self, value: str) -> Value: return self.builder.load_str(value) + def load_bytes_from_str_literal(self, value: str) -> Value: + """Load bytes object from a string literal. + + The literal characters of BytesExpr (the characters inside b'') + are stored in BytesExpr.value, whose type is 'str' not 'bytes'. + Thus we perform a special conversion here. + """ + bytes_value = bytes(value, 'utf8').decode('unicode-escape').encode('raw-unicode-escape') + return self.builder.load_bytes(bytes_value) + def load_int(self, value: int) -> Value: return self.builder.load_int(value) @@ -235,7 +252,7 @@ def py_call(self, function: Value, arg_values: List[Value], line: int, - arg_kinds: Optional[List[int]] = None, + arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[Sequence[Optional[str]]] = None) -> Value: return self.builder.py_call(function, arg_values, line, arg_kinds, arg_names) @@ -251,7 +268,7 @@ def gen_method_call(self, arg_values: List[Value], result_type: Optional[RType], line: int, - arg_kinds: Optional[List[int]] = None, + arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[List[Optional[str]]] = None) -> Value: return self.builder.gen_method_call( base, name, arg_values, result_type, line, arg_kinds, arg_names @@ -286,19 +303,45 @@ def add_to_non_ext_dict(self, non_ext: NonExtClassInfo, key_unicode = self.load_str(key) self.call_c(dict_set_item_op, [non_ext.dict, key_unicode, val], line) + def gen_import_from(self, id: str, globals_dict: Value, + imported: List[str], line: int) -> Value: + self.imports[id] = None + + null_dict = Integer(0, dict_rprimitive, line) + names_to_import = self.new_list_op([self.load_str(name) for name in imported], line) + zero_int = Integer(0, c_int_rprimitive, line) + value = self.call_c( + import_extra_args_op, + [self.load_str(id), globals_dict, null_dict, names_to_import, zero_int], + line, + ) + self.add(InitStatic(value, id, namespace=NAMESPACE_MODULE)) + return value + def gen_import(self, id: str, line: int) -> None: self.imports[id] = None needs_import, out = BasicBlock(), BasicBlock() - first_load = self.load_module(id) - comparison = self.translate_is_op(first_load, self.none_object(), 'is not', line) - self.add_bool_branch(comparison, out, needs_import) + self.check_if_module_loaded(id, line, needs_import, out) self.activate_block(needs_import) value = self.call_c(import_op, [self.load_str(id)], line) self.add(InitStatic(value, id, namespace=NAMESPACE_MODULE)) self.goto_and_activate(out) + def check_if_module_loaded(self, id: str, line: int, + needs_import: BasicBlock, out: BasicBlock) -> None: + """Generate code that checks if the module `id` has been loaded yet. + + Arguments: + id: name of module to check if imported + line: line number that the import occurs on + needs_import: the BasicBlock that is run if the module has not been loaded yet + out: the BasicBlock that is run if the module has already been loaded""" + first_load = self.load_module(id) + comparison = self.translate_is_op(first_load, self.none_object(), 'is not', line) + self.add_bool_branch(comparison, out, needs_import) + def get_module(self, module: str, line: int) -> Value: # Python 3.7 has a nice 'PyImport_GetModule' function that we can't use :( mod_dict = self.call_c(get_module_dict_op, [], line) @@ -458,7 +501,7 @@ def get_assignment_target(self, lvalue: Lvalue, return AssignmentTargetAttr(obj, lvalue.name) elif isinstance(lvalue, TupleExpr): # Multiple assignment a, ..., b = e - star_idx = None # type: Optional[int] + star_idx: Optional[int] = None lvalues = [] for idx, item in enumerate(lvalue.items): targ = self.get_assignment_target(item) @@ -499,7 +542,7 @@ def assign(self, rvalue_reg: Value, line: int) -> None: if isinstance(target, Register): - self.add(Assign(target, rvalue_reg)) + self.add(Assign(target, self.coerce(rvalue_reg, target.type, line))) elif isinstance(target, AssignmentTargetRegister): rvalue_reg = self.coerce(rvalue_reg, target.type, line) self.add(Assign(target.register, rvalue_reg)) @@ -729,7 +772,7 @@ def _analyze_iterable_item_type(self, expr: Expression) -> Type: from mypy.join import join_types if isinstance(iterable, TupleType): - joined = UninhabitedType() # type: Type + joined: Type = UninhabitedType() for item in iterable.items: joined = join_types(joined, item) return joined @@ -825,6 +868,16 @@ def call_refexpr_with_args( callee_node = callee.node if isinstance(callee_node, OverloadedFuncDef): callee_node = callee_node.impl + # TODO: use native calls for any decorated functions which have all their decorators + # removed, not just singledispatch functions (which we don't do now just in case those + # decorated functions are callable classes or cannot be called without the python API for + # some other reason) + if ( + isinstance(callee_node, Decorator) + and callee_node.func not in self.fdefs_to_decorators + and callee_node.func in self.singledispatch_impls + ): + callee_node = callee_node.func if (callee_node is not None and callee.fullname is not None and callee_node in self.mapper.func_to_decl @@ -914,7 +967,7 @@ def flatten_classes(self, arg: Union[RefExpr, TupleExpr]) -> Optional[List[Class return [ir] return None else: - res = [] # type: List[ClassIR] + res: List[ClassIR] = [] for item in arg.items: if isinstance(item, (RefExpr, TupleExpr)): item_part = self.flatten_classes(item) @@ -952,22 +1005,18 @@ def leave(self) -> Tuple[List[Register], List[RuntimeArg], List[BasicBlock], RTy self.fn_info = self.fn_infos[-1] return builder.args, runtime_args, builder.blocks, ret_type, fn_info + @contextmanager def enter_method(self, class_ir: ClassIR, name: str, ret_type: RType, fn_info: Union[FuncInfo, str] = '', - self_type: Optional[RType] = None) -> None: - """Begin generating IR for a method. + self_type: Optional[RType] = None) -> Iterator[None]: + """Generate IR for a method. If the method takes arguments, you should immediately afterwards call add_argument() for each non-self argument (self is created implicitly). - Call leave_method() to finish the generation of the method. - - You can enter multiple methods at a time. They are maintained in a - stack, and leave_method() leaves the topmost one. - Args: class_ir: Add method to this class name: Short name of the method @@ -983,8 +1032,20 @@ def enter_method(self, if self_type is None: self_type = RInstance(class_ir) self.add_argument(SELF_NAME, self_type) - - def add_argument(self, var: Union[str, Var], typ: RType, kind: int = ARG_POS) -> Register: + try: + yield + finally: + arg_regs, args, blocks, ret_type, fn_info = self.leave() + sig = FuncSignature(args, ret_type) + name = self.function_name_stack.pop() + class_ir = self.class_ir_stack.pop() + decl = FuncDecl(name, class_ir.name, self.module_name, sig) + ir = FuncIR(decl, arg_regs, blocks) + class_ir.methods[name] = ir + class_ir.method_decls[name] = ir.decl + self.functions.append(ir) + + def add_argument(self, var: Union[str, Var], typ: RType, kind: ArgKind = ARG_POS) -> Register: """Declare an argument in the current function. You should use this instead of directly calling add_local() in new code. @@ -995,18 +1056,6 @@ def add_argument(self, var: Union[str, Var], typ: RType, kind: int = ARG_POS) -> self.runtime_args[-1].append(RuntimeArg(var.name, typ, kind)) return reg - def leave_method(self) -> None: - """Finish the generation of IR for a method.""" - arg_regs, args, blocks, ret_type, fn_info = self.leave() - sig = FuncSignature(args, ret_type) - name = self.function_name_stack.pop() - class_ir = self.class_ir_stack.pop() - decl = FuncDecl(name, class_ir.name, self.module_name, sig) - ir = FuncIR(decl, arg_regs, blocks) - class_ir.methods[name] = ir - class_ir.method_decls[name] = ir.decl - self.functions.append(ir) - def lookup(self, symbol: SymbolNode) -> SymbolTarget: return self.symtables[-1][symbol] @@ -1017,7 +1066,12 @@ def add_local(self, symbol: SymbolNode, typ: RType, is_arg: bool = False) -> 'Re is_arg: is this a function argument """ assert isinstance(symbol, SymbolNode) - reg = Register(typ, symbol.name, is_arg=is_arg, line=symbol.line) + reg = Register( + typ, + remangle_redefinition_name(symbol.name), + is_arg=is_arg, + line=symbol.line, + ) self.symtables[-1][symbol] = AssignmentTargetRegister(reg) if is_arg: self.builder.args.append(reg) @@ -1119,6 +1173,9 @@ def warning(self, msg: str, line: int) -> None: def error(self, msg: str, line: int) -> None: self.errors.error(msg, self.module_path, line) + def note(self, msg: str, line: int) -> None: + self.errors.note(msg, self.module_path, line) + def gen_arg_defaults(builder: IRBuilder) -> None: """Generate blocks for arguments that have default values. @@ -1151,3 +1208,14 @@ def get_default() -> Value: GetAttr(builder.fn_info.callable_class.self_reg, name, arg.line)) assert isinstance(target, AssignmentTargetRegister) builder.assign_if_null(target.register, get_default, arg.initializer.line) + + +def remangle_redefinition_name(name: str) -> str: + """Remangle names produced by mypy when allow-redefinition is used and a name + is used with multiple types within a single block. + + We only need to do this for locals, because the name is used as the name of the register; + for globals, the name itself is stored in a register for the purpose of doing dict + lookups. + """ + return name.replace("'", "__redef__") diff --git a/mypyc/irbuild/callable_class.py b/mypyc/irbuild/callable_class.py index 1cb79b88c354..0261332800ae 100644 --- a/mypyc/irbuild/callable_class.py +++ b/mypyc/irbuild/callable_class.py @@ -104,31 +104,27 @@ def add_call_to_callable_class(builder: IRBuilder, def add_get_to_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> None: """Generate the '__get__' method for a callable class.""" line = fn_info.fitem.line + with builder.enter_method( + fn_info.callable_class.ir, '__get__', object_rprimitive, fn_info, + self_type=object_rprimitive): + instance = builder.add_argument('instance', object_rprimitive) + builder.add_argument('owner', object_rprimitive) + + # If accessed through the class, just return the callable + # object. If accessed through an object, create a new bound + # instance method object. + instance_block, class_block = BasicBlock(), BasicBlock() + comparison = builder.translate_is_op( + builder.read(instance), builder.none_object(), 'is', line + ) + builder.add_bool_branch(comparison, class_block, instance_block) + + builder.activate_block(class_block) + builder.add(Return(builder.self())) - builder.enter_method( - fn_info.callable_class.ir, '__get__', object_rprimitive, fn_info, - self_type=object_rprimitive - ) - instance = builder.add_argument('instance', object_rprimitive) - builder.add_argument('owner', object_rprimitive) - - # If accessed through the class, just return the callable - # object. If accessed through an object, create a new bound - # instance method object. - instance_block, class_block = BasicBlock(), BasicBlock() - comparison = builder.translate_is_op( - builder.read(instance), builder.none_object(), 'is', line - ) - builder.add_bool_branch(comparison, class_block, instance_block) - - builder.activate_block(class_block) - builder.add(Return(builder.self())) - - builder.activate_block(instance_block) - builder.add(Return(builder.call_c(method_new_op, - [builder.self(), builder.read(instance)], line))) - - builder.leave_method() + builder.activate_block(instance_block) + builder.add(Return(builder.call_c(method_new_op, + [builder.self(), builder.read(instance)], line))) def instantiate_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> Value: diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 3fd56415e773..6c2958c5b8de 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -1,12 +1,14 @@ """Transform class definitions from the mypy AST form to IR.""" -from typing import List, Optional, Tuple +from abc import abstractmethod +from typing import Callable, List, Optional, Tuple from typing_extensions import Final from mypy.nodes import ( - ClassDef, FuncDef, OverloadedFuncDef, PassStmt, AssignmentStmt, NameExpr, StrExpr, - ExpressionStmt, TempNode, Decorator, Lvalue, RefExpr, is_class_var + ClassDef, FuncDef, OverloadedFuncDef, PassStmt, AssignmentStmt, CallExpr, NameExpr, StrExpr, + ExpressionStmt, TempNode, Decorator, Lvalue, MemberExpr, RefExpr, TypeInfo, is_class_var ) +from mypy.types import Instance, get_proper_type from mypyc.ir.ops import ( Value, Register, Call, LoadErrorValue, LoadStatic, InitStatic, TupleSet, SetAttr, Return, BasicBlock, Branch, MethodCall, NAMESPACE_TYPE, LoadAddress @@ -24,10 +26,10 @@ ) from mypyc.primitives.dict_ops import dict_set_item_op, dict_new_op from mypyc.irbuild.util import ( - is_dataclass_decorator, get_func_def, is_dataclass, is_constant + is_dataclass_decorator, get_func_def, is_constant, dataclass_type ) from mypyc.irbuild.builder import IRBuilder -from mypyc.irbuild.function import transform_method +from mypyc.irbuild.function import handle_ext_method, handle_non_ext_method, load_type def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None: @@ -61,34 +63,28 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None: # decorated or inherit from Enum. Classes decorated with @trait do not # apply here, and are handled in a different way. if ir.is_ext_class: - # If the class is not decorated, generate an extension class for it. - type_obj = allocate_class(builder, cdef) # type: Optional[Value] - non_ext = None # type: Optional[NonExtClassInfo] - dataclass_non_ext = dataclass_non_ext_info(builder, cdef) + cls_type = dataclass_type(cdef) + if cls_type is None: + cls_builder: ClassBuilder = ExtClassBuilder(builder, cdef) + elif cls_type in ['dataclasses', 'attr-auto']: + cls_builder = DataClassBuilder(builder, cdef) + elif cls_type == 'attr': + cls_builder = AttrsClassBuilder(builder, cdef) + else: + raise ValueError(cls_type) else: - non_ext_bases = populate_non_ext_bases(builder, cdef) - non_ext_metaclass = find_non_ext_metaclass(builder, cdef, non_ext_bases) - non_ext_dict = setup_non_ext_dict(builder, cdef, non_ext_metaclass, non_ext_bases) - # We populate __annotations__ for non-extension classes - # because dataclasses uses it to determine which attributes to compute on. - # TODO: Maybe generate more precise types for annotations - non_ext_anns = builder.call_c(dict_new_op, [], cdef.line) - non_ext = NonExtClassInfo(non_ext_dict, non_ext_bases, non_ext_anns, non_ext_metaclass) - dataclass_non_ext = None - type_obj = None - - attrs_to_cache = [] # type: List[Tuple[Lvalue, RType]] + cls_builder = NonExtClassBuilder(builder, cdef) for stmt in cdef.defs.body: if isinstance(stmt, OverloadedFuncDef) and stmt.is_property: - if not ir.is_ext_class: + if isinstance(cls_builder, NonExtClassBuilder): # properties with both getters and setters in non_extension # classes not supported builder.error("Property setters not supported in non-extension classes", - stmt.line) + stmt.line) for item in stmt.items: with builder.catch_errors(stmt.line): - transform_method(builder, cdef, non_ext, get_func_def(item)) + cls_builder.add_method(get_func_def(item)) elif isinstance(stmt, (FuncDef, Decorator, OverloadedFuncDef)): # Ignore plugin generated methods (since they have no # bodies to compile and will need to have the bodies @@ -96,7 +92,7 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None: if cdef.info.names[stmt.name].plugin_generated: continue with builder.catch_errors(stmt.line): - transform_method(builder, cdef, non_ext, get_func_def(stmt)) + cls_builder.add_method(get_func_def(stmt)) elif isinstance(stmt, PassStmt): continue elif isinstance(stmt, AssignmentStmt): @@ -106,57 +102,221 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None: lvalue = stmt.lvalues[0] if not isinstance(lvalue, NameExpr): builder.error("Only assignment to variables is supported in class bodies", - stmt.line) + stmt.line) continue # We want to collect class variables in a dictionary for both real # non-extension classes and fake dataclass ones. - var_non_ext = non_ext or dataclass_non_ext - if var_non_ext: - add_non_ext_class_attr(builder, var_non_ext, lvalue, stmt, cdef, attrs_to_cache) - if non_ext: - continue - # Variable declaration with no body - if isinstance(stmt.rvalue, TempNode): - continue - # Only treat marked class variables as class variables. - if not (is_class_var(lvalue) or stmt.is_final_def): - continue - typ = builder.load_native_type_object(cdef.fullname) - value = builder.accept(stmt.rvalue) - builder.call_c( - py_setattr_op, [typ, builder.load_str(lvalue.name), value], stmt.line) - if builder.non_function_scope() and stmt.is_final_def: - builder.init_final_static(lvalue, value, cdef.name) + cls_builder.add_attr(lvalue, stmt) + elif isinstance(stmt, ExpressionStmt) and isinstance(stmt.expr, StrExpr): # Docstring. Ignore pass else: builder.error("Unsupported statement in class body", stmt.line) - if not non_ext: # That is, an extension class - generate_attr_defaults(builder, cdef) - create_ne_from_eq(builder, cdef) - if dataclass_non_ext: - assert type_obj - dataclass_finalize(builder, cdef, dataclass_non_ext, type_obj) - else: + cls_builder.finalize(ir) + + +class ClassBuilder: + """Create IR for a class definition. + + This is an abstract base class. + """ + + def __init__(self, builder: IRBuilder, cdef: ClassDef) -> None: + self.builder = builder + self.cdef = cdef + self.attrs_to_cache: List[Tuple[Lvalue, RType]] = [] + + @abstractmethod + def add_method(self, fdef: FuncDef) -> None: + """Add a method to the class IR""" + + @abstractmethod + def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: + """Add an attribute to the class IR""" + + @abstractmethod + def finalize(self, ir: ClassIR) -> None: + """Perform any final operations to complete the class IR""" + + +class NonExtClassBuilder(ClassBuilder): + def __init__(self, builder: IRBuilder, cdef: ClassDef) -> None: + super().__init__(builder, cdef) + self.non_ext = self.create_non_ext_info() + + def create_non_ext_info(self) -> NonExtClassInfo: + non_ext_bases = populate_non_ext_bases(self.builder, self.cdef) + non_ext_metaclass = find_non_ext_metaclass(self.builder, self.cdef, non_ext_bases) + non_ext_dict = setup_non_ext_dict(self.builder, self.cdef, non_ext_metaclass, + non_ext_bases) + # We populate __annotations__ for non-extension classes + # because dataclasses uses it to determine which attributes to compute on. + # TODO: Maybe generate more precise types for annotations + non_ext_anns = self.builder.call_c(dict_new_op, [], self.cdef.line) + return NonExtClassInfo(non_ext_dict, non_ext_bases, non_ext_anns, non_ext_metaclass) + + def add_method(self, fdef: FuncDef) -> None: + handle_non_ext_method(self.builder, self.non_ext, self.cdef, fdef) + + def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: + add_non_ext_class_attr_ann(self.builder, self.non_ext, lvalue, stmt) + add_non_ext_class_attr(self.builder, self.non_ext, lvalue, stmt, self.cdef, + self.attrs_to_cache) + + def finalize(self, ir: ClassIR) -> None: # Dynamically create the class via the type constructor - non_ext_class = load_non_ext_class(builder, ir, non_ext, cdef.line) - non_ext_class = load_decorated_class(builder, cdef, non_ext_class) + non_ext_class = load_non_ext_class(self.builder, ir, self.non_ext, self.cdef.line) + non_ext_class = load_decorated_class(self.builder, self.cdef, non_ext_class) # Save the decorated class - builder.add(InitStatic(non_ext_class, cdef.name, builder.module_name, NAMESPACE_TYPE)) + self.builder.add(InitStatic(non_ext_class, self.cdef.name, self.builder.module_name, + NAMESPACE_TYPE)) # Add the non-extension class to the dict - builder.call_c(dict_set_item_op, - [ - builder.load_globals_dict(), - builder.load_str(cdef.name), - non_ext_class - ], cdef.line) + self.builder.call_c(dict_set_item_op, + [ + self.builder.load_globals_dict(), + self.builder.load_str(self.cdef.name), + non_ext_class + ], self.cdef.line) + + # Cache any cacheable class attributes + cache_class_attrs(self.builder, self.attrs_to_cache, self.cdef) + - # Cache any cachable class attributes - cache_class_attrs(builder, attrs_to_cache, cdef) +class ExtClassBuilder(ClassBuilder): + def __init__(self, builder: IRBuilder, cdef: ClassDef) -> None: + super().__init__(builder, cdef) + # If the class is not decorated, generate an extension class for it. + self.type_obj: Optional[Value] = allocate_class(builder, cdef) + + def skip_attr_default(self, name: str, stmt: AssignmentStmt) -> bool: + """Controls whether to skip generating a default for an attribute.""" + return False + + def add_method(self, fdef: FuncDef) -> None: + handle_ext_method(self.builder, self.cdef, fdef) + + def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: + # Variable declaration with no body + if isinstance(stmt.rvalue, TempNode): + return + # Only treat marked class variables as class variables. + if not (is_class_var(lvalue) or stmt.is_final_def): + return + typ = self.builder.load_native_type_object(self.cdef.fullname) + value = self.builder.accept(stmt.rvalue) + self.builder.call_c( + py_setattr_op, [typ, self.builder.load_str(lvalue.name), value], stmt.line) + if self.builder.non_function_scope() and stmt.is_final_def: + self.builder.init_final_static(lvalue, value, self.cdef.name) + + def finalize(self, ir: ClassIR) -> None: + generate_attr_defaults(self.builder, self.cdef, self.skip_attr_default) + create_ne_from_eq(self.builder, self.cdef) + + +class DataClassBuilder(ExtClassBuilder): + # controls whether an __annotations__ attribute should be added to the class + # __dict__. This is not desirable for attrs classes where auto_attribs is + # disabled, as attrs will reject it. + add_annotations_to_dict = True + + def __init__(self, builder: IRBuilder, cdef: ClassDef) -> None: + super().__init__(builder, cdef) + self.non_ext = self.create_non_ext_info() + + def create_non_ext_info(self) -> NonExtClassInfo: + """Set up a NonExtClassInfo to track dataclass attributes. + + In addition to setting up a normal extension class for dataclasses, + we also collect its class attributes like a non-extension class so + that we can hand them to the dataclass decorator. + """ + return NonExtClassInfo( + self.builder.call_c(dict_new_op, [], self.cdef.line), + self.builder.add(TupleSet([], self.cdef.line)), + self.builder.call_c(dict_new_op, [], self.cdef.line), + self.builder.add(LoadAddress(type_object_op.type, type_object_op.src, self.cdef.line)) + ) + + def skip_attr_default(self, name: str, stmt: AssignmentStmt) -> bool: + return stmt.type is not None + + def get_type_annotation(self, stmt: AssignmentStmt) -> Optional[TypeInfo]: + # We populate __annotations__ because dataclasses uses it to determine + # which attributes to compute on. + ann_type = get_proper_type(stmt.type) + if isinstance(ann_type, Instance): + return ann_type.type + return None + + def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: + add_non_ext_class_attr_ann(self.builder, self.non_ext, lvalue, stmt, + self.get_type_annotation) + add_non_ext_class_attr(self.builder, self.non_ext, lvalue, stmt, self.cdef, + self.attrs_to_cache) + super().add_attr(lvalue, stmt) + + def finalize(self, ir: ClassIR) -> None: + """Generate code to finish instantiating a dataclass. + + This works by replacing all of the attributes on the class + (which will be descriptors) with whatever they would be in a + non-extension class, calling dataclass, then switching them back. + + The resulting class is an extension class and instances of it do not + have a __dict__ (unless something else requires it). + All methods written explicitly in the source are compiled and + may be called through the vtable while the methods generated + by dataclasses are interpreted and may not be. + + (If we just called dataclass without doing this, it would think that all + of the descriptors for our attributes are default values and generate an + incorrect constructor. We need to do the switch so that dataclass gets the + appropriate defaults.) + """ + super().finalize(ir) + assert self.type_obj + add_dunders_to_non_ext_dict(self.builder, self.non_ext, self.cdef.line, + self.add_annotations_to_dict) + dec = self.builder.accept( + next(d for d in self.cdef.decorators if is_dataclass_decorator(d))) + self.builder.call_c( + dataclass_sleight_of_hand, [dec, self.type_obj, self.non_ext.dict, self.non_ext.anns], + self.cdef.line) + + +class AttrsClassBuilder(DataClassBuilder): + """Create IR for an attrs class where auto_attribs=False (the default). + + When auto_attribs is enabled, attrs classes behave similarly to dataclasses + (i.e. types are stored as annotations on the class) and are thus handled + by DataClassBuilder, but when auto_attribs is disabled the types are + provided via attr.ib(type=...) + """ + + add_annotations_to_dict = False + + def skip_attr_default(self, name: str, stmt: AssignmentStmt) -> bool: + return True + + def get_type_annotation(self, stmt: AssignmentStmt) -> Optional[TypeInfo]: + if isinstance(stmt.rvalue, CallExpr): + # find the type arg in `attr.ib(type=str)` + callee = stmt.rvalue.callee + if (isinstance(callee, MemberExpr) and + callee.fullname in ['attr.ib', 'attr.attr'] and + 'type' in stmt.rvalue.arg_names): + index = stmt.rvalue.arg_names.index('type') + type_name = stmt.rvalue.args[index] + if isinstance(type_name, NameExpr) and isinstance(type_name.node, TypeInfo): + lvalue = stmt.lvalues[0] + assert isinstance(lvalue, NameExpr) + return type_name.node + return None def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value: @@ -169,10 +329,10 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value: tp_bases = builder.add(LoadErrorValue(object_rprimitive, is_borrowed=True)) modname = builder.load_str(builder.module_name) template = builder.add(LoadStatic(object_rprimitive, cdef.name + "_template", - builder.module_name, NAMESPACE_TYPE)) + builder.module_name, NAMESPACE_TYPE)) # Create the class tp = builder.call_c(pytype_from_template_op, - [template, tp_bases, modname], cdef.line) + [template, tp_bases, modname], cdef.line) # Immediately fix up the trait vtables, before doing anything with the class. ir = builder.mapper.type_to_ir[cdef.info] if not ir.is_trait and not ir.builtin_base: @@ -191,21 +351,20 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value: # Add it to the dict builder.call_c(dict_set_item_op, - [ - builder.load_globals_dict(), + [builder.load_globals_dict(), builder.load_str(cdef.name), - tp, - ], cdef.line) + tp], + cdef.line) return tp # Mypy uses these internally as base classes of TypedDict classes. These are # lies and don't have any runtime equivalent. -MAGIC_TYPED_DICT_CLASSES = ( +MAGIC_TYPED_DICT_CLASSES: Final[Tuple[str, ...]] = ( 'typing._TypedDict', 'typing_extensions._TypedDict', -) # type: Final[Tuple[str, ...]] +) def populate_non_ext_bases(builder: IRBuilder, cdef: ClassDef) -> Value: @@ -219,7 +378,11 @@ def populate_non_ext_bases(builder: IRBuilder, cdef: ClassDef) -> Value: for cls in cdef.info.mro[1:]: if cls.fullname == 'builtins.object': continue - if is_named_tuple and cls.fullname in ('typing.Sequence', 'typing.Iterable'): + if is_named_tuple and cls.fullname in ('typing.Sequence', + 'typing.Iterable', + 'typing.Collection', + 'typing.Reversible', + 'typing.Container'): # HAX: Synthesized base classes added by mypy don't exist at runtime, so skip them. # This could break if they were added explicitly, though... continue @@ -288,8 +451,8 @@ def setup_non_ext_dict(builder: IRBuilder, """ # Check if the metaclass defines a __prepare__ method, and if so, call it. has_prepare = builder.call_c(py_hasattr_op, - [metaclass, - builder.load_str('__prepare__')], cdef.line) + [metaclass, + builder.load_str('__prepare__')], cdef.line) non_ext_dict = Register(dict_rprimitive) @@ -311,23 +474,39 @@ def setup_non_ext_dict(builder: IRBuilder, return non_ext_dict +def add_non_ext_class_attr_ann(builder: IRBuilder, + non_ext: NonExtClassInfo, + lvalue: NameExpr, + stmt: AssignmentStmt, + get_type_info: Optional[Callable[[AssignmentStmt], + Optional[TypeInfo]]] = None + ) -> None: + """Add a class attribute to __annotations__ of a non-extension class.""" + typ: Optional[Value] = None + if get_type_info is not None: + type_info = get_type_info(stmt) + if type_info: + typ = load_type(builder, type_info, stmt.line) + + if typ is None: + # FIXME: if get_type_info is not provided, don't fall back to stmt.type? + ann_type = get_proper_type(stmt.type) + if isinstance(ann_type, Instance): + typ = load_type(builder, ann_type.type, stmt.line) + else: + typ = builder.add(LoadAddress(type_object_op.type, type_object_op.src, stmt.line)) + + key = builder.load_str(lvalue.name) + builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line) + + def add_non_ext_class_attr(builder: IRBuilder, non_ext: NonExtClassInfo, lvalue: NameExpr, stmt: AssignmentStmt, cdef: ClassDef, attr_to_cache: List[Tuple[Lvalue, RType]]) -> None: - """Add a class attribute to __annotations__ of a non-extension class. - - If the attribute is initialized with a value, also add it to __dict__. - """ - # We populate __annotations__ because dataclasses uses it to determine - # which attributes to compute on. - # TODO: Maybe generate more precise types for annotations - key = builder.load_str(lvalue.name) - typ = builder.add(LoadAddress(type_object_op.type, type_object_op.src, stmt.line)) - builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line) - + """Add a class attribute to __dict__ of a non-extension class.""" # Only add the attribute to the __dict__ if the assignment is of the form: # x: type = value (don't add attributes of the form 'x: type' to the __dict__). if not isinstance(stmt.rvalue, TempNode): @@ -345,8 +524,14 @@ def add_non_ext_class_attr(builder: IRBuilder, attr_to_cache.append((lvalue, object_rprimitive)) -def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef) -> None: - """Generate an initialization method for default attr values (from class vars).""" +def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef, + skip: Optional[Callable[[str, AssignmentStmt], bool]] = None) -> None: + """Generate an initialization method for default attr values (from class vars). + + If provided, the skip arg should be a callable which will return whether + to skip generating a default for an attribute. It will be passed the name of + the attribute and the corresponding AssignmentStmt. + """ cls = builder.mapper.type_to_ir[cdef.info] if cls.builtin_base: return @@ -362,11 +547,15 @@ def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef) -> None: and isinstance(stmt.lvalues[0], NameExpr) and not is_class_var(stmt.lvalues[0]) and not isinstance(stmt.rvalue, TempNode)): - if stmt.lvalues[0].name == '__slots__': + name = stmt.lvalues[0].name + if name == '__slots__': + continue + + if name == '__deletable__': + check_deletable_declaration(builder, cls, stmt.line) continue - # Skip type annotated assignments in dataclasses - if is_dataclass(cdef) and stmt.type: + if skip is not None and skip(name, stmt): continue default_assignments.append(stmt) @@ -374,28 +563,41 @@ def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef) -> None: if not default_assignments: return - builder.enter_method(cls, '__mypyc_defaults_setup', bool_rprimitive) - - self_var = builder.self() - for stmt in default_assignments: - lvalue = stmt.lvalues[0] - assert isinstance(lvalue, NameExpr) - if not stmt.is_final_def and not is_constant(stmt.rvalue): - builder.warning('Unsupported default attribute value', stmt.rvalue.line) - - # If the attribute is initialized to None and type isn't optional, - # don't initialize it to anything. - attr_type = cls.attr_type(lvalue.name) - if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': - if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) - and not is_none_rprimitive(attr_type)): - continue - val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) - builder.add(SetAttr(self_var, lvalue.name, val, -1)) + with builder.enter_method(cls, '__mypyc_defaults_setup', bool_rprimitive): + self_var = builder.self() + for stmt in default_assignments: + lvalue = stmt.lvalues[0] + assert isinstance(lvalue, NameExpr) + if not stmt.is_final_def and not is_constant(stmt.rvalue): + builder.warning('Unsupported default attribute value', stmt.rvalue.line) + + # If the attribute is initialized to None and type isn't optional, + # don't initialize it to anything. + attr_type = cls.attr_type(lvalue.name) + if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': + if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) + and not is_none_rprimitive(attr_type)): + continue + val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) + builder.add(SetAttr(self_var, lvalue.name, val, -1)) + + builder.add(Return(builder.true())) - builder.add(Return(builder.true())) - builder.leave_method() +def check_deletable_declaration(builder: IRBuilder, cl: ClassIR, line: int) -> None: + for attr in cl.deletable: + if attr not in cl.attributes: + if not cl.has_attr(attr): + builder.error('Attribute "{}" not defined'.format(attr), line) + continue + for base in cl.mro: + if attr in base.property_types: + builder.error('Cannot make property "{}" deletable'.format(attr), line) + break + else: + _, base = cl.attr_details(attr) + builder.error(('Attribute "{}" not defined in "{}" ' + + '(defined in "{}")').format(attr, cl.name, base.name), line) def create_ne_from_eq(builder: IRBuilder, cdef: ClassDef) -> None: @@ -407,30 +609,28 @@ def create_ne_from_eq(builder: IRBuilder, cdef: ClassDef) -> None: def gen_glue_ne_method(builder: IRBuilder, cls: ClassIR, line: int) -> None: """Generate a "__ne__" method from a "__eq__" method. """ - builder.enter_method(cls, '__ne__', object_rprimitive) - rhs_arg = builder.add_argument('rhs', object_rprimitive) - - # If __eq__ returns NotImplemented, then __ne__ should also - not_implemented_block, regular_block = BasicBlock(), BasicBlock() - eqval = builder.add(MethodCall(builder.self(), '__eq__', [rhs_arg], line)) - not_implemented = builder.add(LoadAddress(not_implemented_op.type, - not_implemented_op.src, line)) - builder.add(Branch( - builder.translate_is_op(eqval, not_implemented, 'is', line), - not_implemented_block, - regular_block, - Branch.BOOL)) - - builder.activate_block(regular_block) - retval = builder.coerce( - builder.unary_op(eqval, 'not', line), object_rprimitive, line - ) - builder.add(Return(retval)) - - builder.activate_block(not_implemented_block) - builder.add(Return(not_implemented)) + with builder.enter_method(cls, '__ne__', object_rprimitive): + rhs_arg = builder.add_argument('rhs', object_rprimitive) + + # If __eq__ returns NotImplemented, then __ne__ should also + not_implemented_block, regular_block = BasicBlock(), BasicBlock() + eqval = builder.add(MethodCall(builder.self(), '__eq__', [rhs_arg], line)) + not_implemented = builder.add(LoadAddress(not_implemented_op.type, + not_implemented_op.src, line)) + builder.add(Branch( + builder.translate_is_op(eqval, not_implemented, 'is', line), + not_implemented_block, + regular_block, + Branch.BOOL)) + + builder.activate_block(regular_block) + retval = builder.coerce( + builder.unary_op(eqval, 'not', line), object_rprimitive, line + ) + builder.add(Return(retval)) - builder.leave_method() + builder.activate_block(not_implemented_block) + builder.add(Return(not_implemented)) def load_non_ext_class(builder: IRBuilder, @@ -439,7 +639,7 @@ def load_non_ext_class(builder: IRBuilder, line: int) -> Value: cls_name = builder.load_str(ir.name) - finish_non_ext_dict(builder, non_ext, line) + add_dunders_to_non_ext_dict(builder, non_ext, line) class_type_obj = builder.py_call( non_ext.metaclass, @@ -486,11 +686,11 @@ def create_mypyc_attrs_tuple(builder: IRBuilder, ir: ClassIR, line: int) -> Valu return builder.new_tuple(items, line) -def finish_non_ext_dict(builder: IRBuilder, non_ext: NonExtClassInfo, line: int) -> None: - # Add __annotations__ to the class dict. - builder.call_c(dict_set_item_op, - [non_ext.dict, builder.load_str('__annotations__'), - non_ext.anns], -1) +def add_dunders_to_non_ext_dict(builder: IRBuilder, non_ext: NonExtClassInfo, + line: int, add_annotations: bool = True) -> None: + if add_annotations: + # Add __annotations__ to the class dict. + builder.add_to_non_ext_dict(non_ext, '__annotations__', non_ext.anns, line) # We add a __doc__ attribute so if the non-extension class is decorated with the # dataclass decorator, dataclass will not try to look for __text_signature__. @@ -500,46 +700,3 @@ def finish_non_ext_dict(builder: IRBuilder, non_ext: NonExtClassInfo, line: int) non_ext, '__doc__', builder.load_str(filler_doc_str), line) builder.add_to_non_ext_dict( non_ext, '__module__', builder.load_str(builder.module_name), line) - - -def dataclass_finalize( - builder: IRBuilder, cdef: ClassDef, non_ext: NonExtClassInfo, type_obj: Value) -> None: - """Generate code to finish instantiating a dataclass. - - This works by replacing all of the attributes on the class - (which will be descriptors) with whatever they would be in a - non-extension class, calling dataclass, then switching them back. - - The resulting class is an extension class and instances of it do not - have a __dict__ (unless something else requires it). - All methods written explicitly in the source are compiled and - may be called through the vtable while the methods generated - by dataclasses are interpreted and may not be. - - (If we just called dataclass without doing this, it would think that all - of the descriptors for our attributes are default values and generate an - incorrect constructor. We need to do the switch so that dataclass gets the - appropriate defaults.) - """ - finish_non_ext_dict(builder, non_ext, cdef.line) - dec = builder.accept(next(d for d in cdef.decorators if is_dataclass_decorator(d))) - builder.call_c( - dataclass_sleight_of_hand, [dec, type_obj, non_ext.dict, non_ext.anns], cdef.line) - - -def dataclass_non_ext_info(builder: IRBuilder, cdef: ClassDef) -> Optional[NonExtClassInfo]: - """Set up a NonExtClassInfo to track dataclass attributes. - - In addition to setting up a normal extension class for dataclasses, - we also collect its class attributes like a non-extension class so - that we can hand them to the dataclass decorator. - """ - if is_dataclass(cdef): - return NonExtClassInfo( - builder.call_c(dict_new_op, [], cdef.line), - builder.add(TupleSet([], cdef.line)), - builder.call_c(dict_new_op, [], cdef.line), - builder.add(LoadAddress(type_object_op.type, type_object_op.src, cdef.line)) - ) - else: - return None diff --git a/mypyc/irbuild/constant_fold.py b/mypyc/irbuild/constant_fold.py new file mode 100644 index 000000000000..21e9ea939a3e --- /dev/null +++ b/mypyc/irbuild/constant_fold.py @@ -0,0 +1,99 @@ +"""Constant folding of IR values. + +For example, 3 + 5 can be constant folded into 8. +""" + +from typing import Optional, Union +from typing_extensions import Final + +from mypy.nodes import Expression, IntExpr, StrExpr, OpExpr, UnaryExpr, NameExpr, MemberExpr, Var +from mypyc.irbuild.builder import IRBuilder + + +# All possible result types of constant folding +ConstantValue = Union[int, str] +CONST_TYPES: Final = (int, str) + + +def constant_fold_expr(builder: IRBuilder, expr: Expression) -> Optional[ConstantValue]: + """Return the constant value of an expression for supported operations. + + Return None otherwise. + """ + if isinstance(expr, IntExpr): + return expr.value + if isinstance(expr, StrExpr): + return expr.value + elif isinstance(expr, NameExpr): + node = expr.node + if isinstance(node, Var) and node.is_final: + value = node.final_value + if isinstance(value, (CONST_TYPES)): + return value + elif isinstance(expr, MemberExpr): + final = builder.get_final_ref(expr) + if final is not None: + fn, final_var, native = final + if final_var.is_final: + value = final_var.final_value + if isinstance(value, (CONST_TYPES)): + return value + elif isinstance(expr, OpExpr): + left = constant_fold_expr(builder, expr.left) + right = constant_fold_expr(builder, expr.right) + if isinstance(left, int) and isinstance(right, int): + return constant_fold_binary_int_op(expr.op, left, right) + elif isinstance(left, str) and isinstance(right, str): + return constant_fold_binary_str_op(expr.op, left, right) + elif isinstance(expr, UnaryExpr): + value = constant_fold_expr(builder, expr.expr) + if isinstance(value, int): + return constant_fold_unary_int_op(expr.op, value) + return None + + +def constant_fold_binary_int_op(op: str, left: int, right: int) -> Optional[int]: + if op == '+': + return left + right + if op == '-': + return left - right + elif op == '*': + return left * right + elif op == '//': + if right != 0: + return left // right + elif op == '%': + if right != 0: + return left % right + elif op == '&': + return left & right + elif op == '|': + return left | right + elif op == '^': + return left ^ right + elif op == '<<': + if right >= 0: + return left << right + elif op == '>>': + if right >= 0: + return left >> right + elif op == '**': + if right >= 0: + return left ** right + return None + + +def constant_fold_unary_int_op(op: str, value: int) -> Optional[int]: + if op == '-': + return -value + elif op == '~': + return ~value + elif op == '+': + return value + return None + + +def constant_fold_binary_str_op(op: str, left: str, right: str) -> Optional[str]: + if op == '+': + return left + right + return None diff --git a/mypyc/irbuild/context.py b/mypyc/irbuild/context.py index 77976da9235e..307ce84ab584 100644 --- a/mypyc/irbuild/context.py +++ b/mypyc/irbuild/context.py @@ -7,7 +7,6 @@ from mypyc.ir.ops import Value, BasicBlock from mypyc.ir.func_ir import INVALID_FUNC_DEF from mypyc.ir.class_ir import ClassIR -from mypyc.common import decorator_helper_name from mypyc.irbuild.targets import AssignmentTarget @@ -24,23 +23,23 @@ def __init__(self, is_decorated: bool = False, in_non_ext: bool = False) -> None: self.fitem = fitem - self.name = name if not is_decorated else decorator_helper_name(name) + self.name = name self.class_name = class_name self.ns = namespace # Callable classes implement the '__call__' method, and are used to represent functions # that are nested inside of other functions. - self._callable_class = None # type: Optional[ImplicitClass] + self._callable_class: Optional[ImplicitClass] = None # Environment classes are ClassIR instances that contain attributes representing the # variables in the environment of the function they correspond to. Environment classes are # generated for functions that contain nested functions. - self._env_class = None # type: Optional[ClassIR] + self._env_class: Optional[ClassIR] = None # Generator classes implement the '__next__' method, and are used to represent generators # returned by generator functions. - self._generator_class = None # type: Optional[GeneratorClass] + self._generator_class: Optional[GeneratorClass] = None # Environment class registers are the local registers associated with instances of an # environment class, used for getting and setting attributes. curr_env_reg is the register # associated with the current environment. - self._curr_env_reg = None # type: Optional[Value] + self._curr_env_reg: Optional[Value] = None # These are flags denoting whether a given function is nested, contains a nested function, # is decorated, or is within a non-extension class. self.is_nested = is_nested @@ -57,6 +56,10 @@ def namespaced_name(self) -> str: def is_generator(self) -> bool: return self.fitem.is_generator or self.fitem.is_coroutine + @property + def is_coroutine(self) -> bool: + return self.fitem.is_coroutine + @property def callable_class(self) -> 'ImplicitClass': assert self._callable_class is not None @@ -103,13 +106,13 @@ def __init__(self, ir: ClassIR) -> None: # The ClassIR instance associated with this class. self.ir = ir # The register associated with the 'self' instance for this generator class. - self._self_reg = None # type: Optional[Value] + self._self_reg: Optional[Value] = None # Environment class registers are the local registers associated with instances of an # environment class, used for getting and setting attributes. curr_env_reg is the register # associated with the current environment. prev_env_reg is the self.__mypyc_env__ field # associated with the previous environment. - self._curr_env_reg = None # type: Optional[Value] - self._prev_env_reg = None # type: Optional[Value] + self._curr_env_reg: Optional[Value] = None + self._prev_env_reg: Optional[Value] = None @property def self_reg(self) -> Value: @@ -146,20 +149,20 @@ def __init__(self, ir: ClassIR) -> None: super().__init__(ir) # This register holds the label number that the '__next__' function should go to the next # time it is called. - self._next_label_reg = None # type: Optional[Value] - self._next_label_target = None # type: Optional[AssignmentTarget] + self._next_label_reg: Optional[Value] = None + self._next_label_target: Optional[AssignmentTarget] = None # These registers hold the error values for the generator object for the case that the # 'throw' function is called. - self.exc_regs = None # type: Optional[Tuple[Value, Value, Value]] + self.exc_regs: Optional[Tuple[Value, Value, Value]] = None # Holds the arg passed to send - self.send_arg_reg = None # type: Optional[Value] + self.send_arg_reg: Optional[Value] = None # The switch block is used to decide which instruction to go using the value held in the # next-label register. self.switch_block = BasicBlock() - self.continuation_blocks = [] # type: List[BasicBlock] + self.continuation_blocks: List[BasicBlock] = [] @property def next_label_reg(self) -> Value: diff --git a/mypyc/irbuild/env_class.py b/mypyc/irbuild/env_class.py index 3a5643d59d52..44bcccb507d0 100644 --- a/mypyc/irbuild/env_class.py +++ b/mypyc/irbuild/env_class.py @@ -78,9 +78,9 @@ def instantiate_env_class(builder: IRBuilder) -> Value: if builder.fn_info.is_nested: builder.fn_info.callable_class._curr_env_reg = curr_env_reg builder.add(SetAttr(curr_env_reg, - ENV_ATTR_NAME, - builder.fn_info.callable_class.prev_env_reg, - builder.fn_info.fitem.line)) + ENV_ATTR_NAME, + builder.fn_info.callable_class.prev_env_reg, + builder.fn_info.fitem.line)) else: builder.fn_info._curr_env_reg = curr_env_reg diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index b49170bdf2c7..6a42820b9b21 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -14,7 +14,7 @@ AssignmentExpr, Var, RefExpr, MypyFile, TypeInfo, TypeApplication, LDEF, ARG_POS ) -from mypy.types import TupleType, get_proper_type, Instance +from mypy.types import TupleType, Instance, TypeType, ProperType, get_proper_type from mypyc.common import MAX_SHORT_INT from mypyc.ir.ops import ( @@ -24,6 +24,11 @@ RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive ) from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD +from mypyc.irbuild.format_str_tokenizer import ( + tokenizer_printf_style, join_formatted_strings, convert_format_expr_to_str, + convert_format_expr_to_bytes, join_formatted_bytes +) +from mypyc.primitives.bytes_ops import bytes_slice_op from mypyc.primitives.registry import CFunctionDescription, builtin_names from mypyc.primitives.generic_ops import iter_op from mypyc.primitives.misc_ops import new_slice_op, ellipsis_op, type_op, get_module_dict_op @@ -33,12 +38,13 @@ from mypyc.primitives.set_ops import set_add_op, set_update_op from mypyc.primitives.str_ops import str_slice_op from mypyc.primitives.int_ops import int_comparison_op_mapping -from mypyc.irbuild.specialize import specializers +from mypyc.irbuild.specialize import apply_function_specialization, apply_method_specialization from mypyc.irbuild.builder import IRBuilder from mypyc.irbuild.for_helpers import ( translate_list_comprehension, translate_set_comprehension, comprehension_helper ) +from mypyc.irbuild.constant_fold import constant_fold_expr # Name and attribute references @@ -117,7 +123,7 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value: if final is not None: fullname, final_var, native = final value = builder.emit_load_final(final_var, fullname, final_var.name, native, - builder.types[expr], expr.line) + builder.types[expr], expr.line) if value is not None: return value @@ -133,9 +139,41 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value: if expr.name in fields: index = builder.builder.load_int(fields.index(expr.name)) return builder.gen_method_call(obj, '__getitem__', [index], rtype, expr.line) + + check_instance_attribute_access_through_class(builder, expr, typ) + return builder.builder.get_attr(obj, expr.name, rtype, expr.line) +def check_instance_attribute_access_through_class(builder: IRBuilder, + expr: MemberExpr, + typ: Optional[ProperType]) -> None: + """Report error if accessing an instance attribute through class object.""" + if isinstance(expr.expr, RefExpr): + node = expr.expr.node + if isinstance(typ, TypeType) and isinstance(typ.item, Instance): + # TODO: Handle other item types + node = typ.item.type + if isinstance(node, TypeInfo): + class_ir = builder.mapper.type_to_ir.get(node) + if class_ir is not None and class_ir.is_ext_class: + sym = node.get(expr.name) + if (sym is not None + and isinstance(sym.node, Var) + and not sym.node.is_classvar + and not sym.node.is_final): + builder.error( + 'Cannot access instance attribute "{}" through class object'.format( + expr.name), + expr.line + ) + builder.note( + '(Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define ' + 'a class attribute)', + expr.line + ) + + def transform_super_expr(builder: IRBuilder, o: SuperExpr) -> Value: # warning(builder, 'can not optimize super() expression', o.line) sup_val = builder.load_module_attr_by_fullname('builtins.super', o.line) @@ -147,7 +185,7 @@ def transform_super_expr(builder: IRBuilder, o: SuperExpr) -> Value: ir = builder.mapper.type_to_ir[o.info] iter_env = iter(builder.builder.args) # Grab first argument - vself = next(iter_env) # type: Value + vself: Value = next(iter_env) if builder.fn_info.is_generator: # grab sixth argument (see comment in translate_super_method_call) self_targ = list(builder.symtables[-1].values())[6] @@ -171,7 +209,8 @@ def transform_call_expr(builder: IRBuilder, expr: CallExpr) -> Value: callee = callee.analyzed.expr # Unwrap type application if isinstance(callee, MemberExpr): - return translate_method_call(builder, expr, callee) + return apply_method_specialization(builder, expr, callee) or \ + translate_method_call(builder, expr, callee) elif isinstance(callee, SuperExpr): return translate_super_method_call(builder, expr, callee) else: @@ -181,28 +220,17 @@ def transform_call_expr(builder: IRBuilder, expr: CallExpr) -> Value: def translate_call(builder: IRBuilder, expr: CallExpr, callee: Expression) -> Value: # The common case of calls is refexprs if isinstance(callee, RefExpr): - return translate_refexpr_call(builder, expr, callee) + return apply_function_specialization(builder, expr, callee) or \ + translate_refexpr_call(builder, expr, callee) function = builder.accept(callee) args = [builder.accept(arg) for arg in expr.args] return builder.py_call(function, args, expr.line, - arg_kinds=expr.arg_kinds, arg_names=expr.arg_names) + arg_kinds=expr.arg_kinds, arg_names=expr.arg_names) def translate_refexpr_call(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Value: """Translate a non-method call.""" - - # TODO: Allow special cases to have default args or named args. Currently they don't since - # they check that everything in arg_kinds is ARG_POS. - - # If there is a specializer for this function, try calling it. - # We would return the first successful one. - if callee.fullname and (callee.fullname, None) in specializers: - for specializer in specializers[callee.fullname, None]: - val = specializer(builder, expr, callee) - if val is not None: - return val - # Gen the argument values arg_values = [builder.accept(arg) for arg in expr.args] @@ -241,39 +269,37 @@ def translate_method_call(builder: IRBuilder, expr: CallExpr, callee: MemberExpr else: obj = builder.accept(callee.expr) return builder.gen_method_call(obj, - callee.name, - args, - builder.node_type(expr), - expr.line, - expr.arg_kinds, - expr.arg_names) + callee.name, + args, + builder.node_type(expr), + expr.line, + expr.arg_kinds, + expr.arg_names) elif builder.is_module_member_expr(callee): # Fall back to a PyCall for non-native module calls function = builder.accept(callee) args = [builder.accept(arg) for arg in expr.args] return builder.py_call(function, args, expr.line, - arg_kinds=expr.arg_kinds, arg_names=expr.arg_names) + arg_kinds=expr.arg_kinds, arg_names=expr.arg_names) else: receiver_typ = builder.node_type(callee.expr) # If there is a specializer for this method name/type, try calling it. # We would return the first successful one. - if (callee.name, receiver_typ) in specializers: - for specializer in specializers[callee.name, receiver_typ]: - val = specializer(builder, expr, callee) - if val is not None: - return val + val = apply_method_specialization(builder, expr, callee, receiver_typ) + if val is not None: + return val obj = builder.accept(callee.expr) args = [builder.accept(arg) for arg in expr.args] return builder.gen_method_call(obj, - callee.name, - args, - builder.node_type(expr), - expr.line, - expr.arg_kinds, - expr.arg_names) + callee.name, + args, + builder.node_type(expr), + expr.line, + expr.arg_kinds, + expr.arg_names) def translate_super_method_call(builder: IRBuilder, expr: CallExpr, callee: SuperExpr) -> Value: @@ -313,7 +339,7 @@ def translate_super_method_call(builder: IRBuilder, expr: CallExpr, callee: Supe if decl.kind != FUNC_STATICMETHOD: # Grab first argument - vself = builder.self() # type: Value + vself: Value = builder.self() if decl.kind == FUNC_CLASSMETHOD: vself = builder.call_c(type_op, [vself], expr.line) elif builder.fn_info.is_generator: @@ -341,12 +367,27 @@ def translate_cast_expr(builder: IRBuilder, expr: CastExpr) -> Value: def transform_unary_expr(builder: IRBuilder, expr: UnaryExpr) -> Value: + folded = try_constant_fold(builder, expr) + if folded: + return folded + return builder.unary_op(builder.accept(expr.expr), expr.op, expr.line) def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: if expr.op in ('and', 'or'): return builder.shortcircuit_expr(expr) + + # Special case for string formatting + if expr.op == '%' and (isinstance(expr.left, StrExpr) or isinstance(expr.left, BytesExpr)): + ret = translate_printf_style_formatting(builder, expr.left, expr.right) + if ret is not None: + return ret + + folded = try_constant_fold(builder, expr) + if folded: + return folded + return builder.binary_op( builder.accept(expr.left), builder.accept(expr.right), expr.op, expr.line ) @@ -369,6 +410,19 @@ def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: base, '__getitem__', [index_reg], builder.node_type(expr), expr.line) +def try_constant_fold(builder: IRBuilder, expr: Expression) -> Optional[Value]: + """Return the constant value of an expression if possible. + + Return None otherwise. + """ + value = constant_fold_expr(builder, expr) + if isinstance(value, int): + return builder.load_int(value) + elif isinstance(value, str): + return builder.load_str(value) + return None + + def try_gen_slice_op(builder: IRBuilder, base: Value, index: SliceExpr) -> Optional[Value]: """Generate specialized slice op for some index expressions. @@ -401,14 +455,14 @@ def try_gen_slice_op(builder: IRBuilder, base: Value, index: SliceExpr) -> Optio # Replace missing end index with the largest short integer # (a sequence can't be longer). end = builder.load_int(MAX_SHORT_INT) - candidates = [list_slice_op, tuple_slice_op, str_slice_op] + candidates = [list_slice_op, tuple_slice_op, str_slice_op, bytes_slice_op] return builder.builder.matching_call_c(candidates, [base, begin, end], index.line) return None def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Value: - if_body, else_body, next = BasicBlock(), BasicBlock(), BasicBlock() + if_body, else_body, next_block = BasicBlock(), BasicBlock(), BasicBlock() builder.process_conditional(expr.cond, if_body, else_body) expr_type = builder.node_type(expr) @@ -419,15 +473,15 @@ def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Val true_value = builder.accept(expr.if_expr) true_value = builder.coerce(true_value, expr_type, expr.line) builder.add(Assign(target, true_value)) - builder.goto(next) + builder.goto(next_block) builder.activate_block(else_body) false_value = builder.accept(expr.else_expr) false_value = builder.coerce(false_value, expr_type, expr.line) builder.add(Assign(target, false_value)) - builder.goto(next) + builder.goto(next_block) - builder.activate_block(next) + builder.activate_block(next_block) return target @@ -460,7 +514,7 @@ def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: builder.types[expr] = bool_type exprs.append(expr) - or_expr = exprs.pop(0) # type: Expression + or_expr: Expression = exprs.pop(0) for expr in exprs: or_expr = OpExpr(bin_op, or_expr, expr) builder.types[or_expr] = bool_type @@ -492,14 +546,14 @@ def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: # assuming that prev contains the value of `ei`. def go(i: int, prev: Value) -> Value: if i == len(e.operators) - 1: - return transform_basic_comparison(builder, - e.operators[i], prev, builder.accept(e.operands[i + 1]), e.line) + return transform_basic_comparison( + builder, e.operators[i], prev, builder.accept(e.operands[i + 1]), e.line) next = builder.accept(e.operands[i + 1]) return builder.builder.shortcircuit_helper( 'and', expr_type, - lambda: transform_basic_comparison(builder, - e.operators[i], prev, next, e.line), + lambda: transform_basic_comparison( + builder, e.operators[i], prev, next, e.line), lambda: go(i + 1, next), e.line) @@ -527,6 +581,33 @@ def transform_basic_comparison(builder: IRBuilder, return target +def translate_printf_style_formatting(builder: IRBuilder, + format_expr: Union[StrExpr, BytesExpr], + rhs: Expression) -> Optional[Value]: + tokens = tokenizer_printf_style(format_expr.value) + if tokens is not None: + literals, format_ops = tokens + + exprs = [] + if isinstance(rhs, TupleExpr): + exprs = rhs.items + elif isinstance(rhs, Expression): + exprs.append(rhs) + + if isinstance(format_expr, BytesExpr): + substitutions = convert_format_expr_to_bytes(builder, format_ops, + exprs, format_expr.line) + if substitutions is not None: + return join_formatted_bytes(builder, literals, substitutions, format_expr.line) + else: + substitutions = convert_format_expr_to_str(builder, format_ops, + exprs, format_expr.line) + if substitutions is not None: + return join_formatted_strings(builder, literals, substitutions, format_expr.line) + + return None + + # Literals @@ -547,8 +628,7 @@ def transform_str_expr(builder: IRBuilder, expr: StrExpr) -> Value: def transform_bytes_expr(builder: IRBuilder, expr: BytesExpr) -> Value: - value = bytes(expr.value, 'utf8').decode('unicode-escape').encode('raw-unicode-escape') - return builder.builder.load_bytes(value) + return builder.load_bytes_from_str_literal(expr.value) def transform_ellipsis(builder: IRBuilder, o: EllipsisExpr) -> Value: @@ -637,7 +717,7 @@ def _visit_display(builder: IRBuilder, else: accepted_items.append((False, builder.accept(item))) - result = None # type: Union[Value, None] + result: Union[Value, None] = None initial_items = [] for starred, value in accepted_items: if result is None and not starred and is_list: @@ -659,14 +739,21 @@ def _visit_display(builder: IRBuilder, def transform_list_comprehension(builder: IRBuilder, o: ListComprehension) -> Value: + if any(o.generator.is_async): + builder.error('async comprehensions are unimplemented', o.line) return translate_list_comprehension(builder, o.generator) def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Value: + if any(o.generator.is_async): + builder.error('async comprehensions are unimplemented', o.line) return translate_set_comprehension(builder, o.generator) def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value: + if any(o.is_async): + builder.error('async comprehensions are unimplemented', o.line) + d = builder.call_c(dict_new_op, [], o.line) loop_params = list(zip(o.indices, o.sequences, o.condlists)) @@ -696,6 +783,9 @@ def get_arg(arg: Optional[Expression]) -> Value: def transform_generator_expr(builder: IRBuilder, o: GeneratorExpr) -> Value: + if any(o.is_async): + builder.error('async comprehensions are unimplemented', o.line) + builder.warning('Treating generator comprehension as list', o.line) return builder.call_c( iter_op, [translate_list_comprehension(builder, o)], o.line diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index 8097b453b117..ae592ae91087 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -16,7 +16,7 @@ ) from mypyc.ir.rtypes import ( RType, is_short_int_rprimitive, is_list_rprimitive, is_sequence_rprimitive, - is_tuple_rprimitive, is_dict_rprimitive, + is_tuple_rprimitive, is_dict_rprimitive, is_str_rprimitive, RTuple, short_int_rprimitive, int_rprimitive ) from mypyc.primitives.registry import CFunctionDescription @@ -88,7 +88,10 @@ def for_loop_helper(builder: IRBuilder, index: Lvalue, expr: Expression, builder.activate_block(exit_block) -def for_loop_helper_with_index(builder: IRBuilder, index: Lvalue, expr: Expression, +def for_loop_helper_with_index(builder: IRBuilder, + index: Lvalue, + expr: Expression, + expr_reg: Value, body_insts: Callable[[Value], None], line: int) -> None: """Generate IR for a sequence iteration. @@ -101,7 +104,6 @@ def for_loop_helper_with_index(builder: IRBuilder, index: Lvalue, expr: Expressi body_insts: a function that generates the body of the loop. It needs a index as parameter. """ - expr_reg = builder.accept(expr) assert is_sequence_rprimitive(expr_reg.type) target_type = builder.get_sequence_type(expr) @@ -162,17 +164,17 @@ def sequence_from_generator_preallocate_helper( """ if len(gen.sequences) == 1 and len(gen.indices) == 1 and len(gen.condlists[0]) == 0: rtype = builder.node_type(gen.sequences[0]) - if is_list_rprimitive(rtype) or is_tuple_rprimitive(rtype): - - length = builder.builder.builtin_len(builder.accept(gen.sequences[0]), - gen.line, use_pyssize_t=True) + if (is_list_rprimitive(rtype) or is_tuple_rprimitive(rtype) + or is_str_rprimitive(rtype)): + sequence = builder.accept(gen.sequences[0]) + length = builder.builder.builtin_len(sequence, gen.line, use_pyssize_t=True) target_op = empty_op_llbuilder(length, gen.line) def set_item(item_index: Value) -> None: e = builder.accept(gen.left_expr) builder.call_c(set_item_op, [target_op, item_index, e], gen.line) - for_loop_helper_with_index(builder, gen.indices[0], gen.sequences[0], + for_loop_helper_with_index(builder, gen.indices[0], gen.sequences[0], sequence, set_item, gen.line) return target_op @@ -317,7 +319,7 @@ def make_for_loop_generator(builder: IRBuilder, # seem worth the hassle of supporting dynamically determining which # direction of comparison to do. if len(expr.args) == 1: - start_reg = Integer(0) # type: Value + start_reg: Value = Integer(0) end_reg = builder.accept(expr.args[0]) else: start_reg = builder.accept(expr.args[0]) @@ -376,7 +378,7 @@ def make_for_loop_generator(builder: IRBuilder, if (is_dict_rprimitive(rtype) and expr.callee.name in ('keys', 'values', 'items')): expr_reg = builder.accept(expr.callee.expr) - for_dict_type = None # type: Optional[Type[ForGenerator]] + for_dict_type: Optional[Type[ForGenerator]] = None if expr.callee.name == 'keys': target_type = builder.get_dict_key_type(expr.callee.expr) for_dict_type = ForDictionaryKeys @@ -496,7 +498,7 @@ def gen_step(self) -> None: def gen_cleanup(self) -> None: # We set the branch to go here if the conditional evaluates to true. If - # an exception was raised during the loop, then err_reg wil be set to + # an exception was raised during the loop, then err_reg will be set to # True. If no_err_occurred_op returns False, then the exception will be # propagated using the ERR_FALSE flag. self.builder.call_c(no_err_occurred_op, [], self.line) @@ -529,7 +531,7 @@ def init(self, expr_reg: Value, target_type: RType, reverse: bool) -> None: # environment class. self.expr_target = builder.maybe_spill(expr_reg) if not reverse: - index_reg = Integer(0) # type: Value + index_reg: Value = Integer(0) else: index_reg = builder.binary_op(self.load_len(self.expr_target), Integer(1), '-', self.line) @@ -599,8 +601,9 @@ class ForDictionaryCommon(ForGenerator): since they may override some iteration methods in subtly incompatible manner. The fallback logic is implemented in CPy.h via dynamic type check. """ - dict_next_op = None # type: ClassVar[CFunctionDescription] - dict_iter_op = None # type: ClassVar[CFunctionDescription] + + dict_next_op: ClassVar[CFunctionDescription] + dict_iter_op: ClassVar[CFunctionDescription] def need_cleanup(self) -> bool: # Technically, a dict subclass can raise an unrelated exception @@ -731,8 +734,9 @@ def init(self, start_reg: Value, end_reg: Value, step: int) -> None: builder.assign(index_reg, start_reg, -1) self.index_reg = builder.maybe_spill_assignable(index_reg) # Initialize loop index to 0. Assert that the index target is assignable. - self.index_target = builder.get_assignment_target( - self.index) # type: Union[Register, AssignmentTarget] + self.index_target: Union[Register, AssignmentTarget] = builder.get_assignment_target( + self.index + ) builder.assign(self.index_target, builder.read(self.index_reg, self.line), self.line) def gen_condition(self) -> None: @@ -772,8 +776,9 @@ def init(self) -> None: # initialize this register along with the loop index to 0. zero = Integer(0) self.index_reg = builder.maybe_spill_assignable(zero) - self.index_target = builder.get_assignment_target( - self.index) # type: Union[Register, AssignmentTarget] + self.index_target: Union[Register, AssignmentTarget] = builder.get_assignment_target( + self.index + ) builder.assign(self.index_target, zero, self.line) def gen_step(self) -> None: @@ -845,7 +850,7 @@ def init(self, indexes: List[Lvalue], exprs: List[Expression]) -> None: # Condition check will require multiple basic blocks, since there will be # multiple conditions to check. self.cond_blocks = [BasicBlock() for _ in range(len(indexes) - 1)] + [self.body_block] - self.gens = [] # type: List[ForGenerator] + self.gens: List[ForGenerator] = [] for index, expr, next_block in zip(indexes, exprs, self.cond_blocks): gen = make_for_loop_generator( self.builder, diff --git a/mypyc/irbuild/format_str_tokenizer.py b/mypyc/irbuild/format_str_tokenizer.py new file mode 100644 index 000000000000..721f28dbe385 --- /dev/null +++ b/mypyc/irbuild/format_str_tokenizer.py @@ -0,0 +1,239 @@ +"""Tokenizers for three string formatting methods""" + +from typing import List, Tuple, Optional +from typing_extensions import Final +from enum import Enum, unique + +from mypy.checkstrformat import ( + parse_format_value, ConversionSpecifier, parse_conversion_specifiers +) +from mypy.errors import Errors +from mypy.messages import MessageBuilder +from mypy.nodes import Context, Expression + +from mypyc.ir.ops import Value, Integer +from mypyc.ir.rtypes import ( + c_pyssize_t_rprimitive, is_str_rprimitive, is_int_rprimitive, is_short_int_rprimitive, + is_bytes_rprimitive +) +from mypyc.irbuild.builder import IRBuilder +from mypyc.primitives.bytes_ops import bytes_build_op +from mypyc.primitives.int_ops import int_to_str_op +from mypyc.primitives.str_ops import str_build_op, str_op + + +@unique +class FormatOp(Enum): + """FormatOp represents conversion operations of string formatting during + compile time. + + Compare to ConversionSpecifier, FormatOp has fewer attributes. + For example, to mark a conversion from any object to string, + ConversionSpecifier may have several representations, like '%s', '{}' + or '{:{}}'. However, there would only exist one corresponding FormatOp. + """ + STR = 's' + INT = 'd' + BYTES = 'b' + + +def generate_format_ops(specifiers: List[ConversionSpecifier]) -> Optional[List[FormatOp]]: + """Convert ConversionSpecifier to FormatOp. + + Different ConversionSpecifiers may share a same FormatOp. + """ + format_ops = [] + for spec in specifiers: + # TODO: Match specifiers instead of using whole_seq + if spec.whole_seq == '%s' or spec.whole_seq == '{:{}}': + format_op = FormatOp.STR + elif spec.whole_seq == '%d': + format_op = FormatOp.INT + elif spec.whole_seq == '%b': + format_op = FormatOp.BYTES + elif spec.whole_seq: + return None + else: + format_op = FormatOp.STR + format_ops.append(format_op) + return format_ops + + +def tokenizer_printf_style(format_str: str) -> Optional[Tuple[List[str], List[FormatOp]]]: + """Tokenize a printf-style format string using regex. + + Return: + A list of string literals and a list of FormatOps. + """ + literals: List[str] = [] + specifiers: List[ConversionSpecifier] = parse_conversion_specifiers(format_str) + format_ops = generate_format_ops(specifiers) + if format_ops is None: + return None + + last_end = 0 + for spec in specifiers: + cur_start = spec.start_pos + literals.append(format_str[last_end:cur_start]) + last_end = cur_start + len(spec.whole_seq) + literals.append(format_str[last_end:]) + + return literals, format_ops + + +# The empty Context as an argument for parse_format_value(). +# It wouldn't be used since the code has passed the type-checking. +EMPTY_CONTEXT: Final = Context() + + +def tokenizer_format_call( + format_str: str) -> Optional[Tuple[List[str], List[FormatOp]]]: + """Tokenize a str.format() format string. + + The core function parse_format_value() is shared with mypy. + With these specifiers, we then parse the literal substrings + of the original format string and convert `ConversionSpecifier` + to `FormatOp`. + + Return: + A list of string literals and a list of FormatOps. The literals + are interleaved with FormatOps and the length of returned literals + should be exactly one more than FormatOps. + Return None if it cannot parse the string. + """ + # Creates an empty MessageBuilder here. + # It wouldn't be used since the code has passed the type-checking. + specifiers = parse_format_value(format_str, EMPTY_CONTEXT, + MessageBuilder(Errors(), {})) + if specifiers is None: + return None + format_ops = generate_format_ops(specifiers) + if format_ops is None: + return None + + literals: List[str] = [] + last_end = 0 + for spec in specifiers: + # Skip { and } + literals.append(format_str[last_end:spec.start_pos - 1]) + last_end = spec.start_pos + len(spec.whole_seq) + 1 + literals.append(format_str[last_end:]) + # Deal with escaped {{ + literals = [x.replace('{{', '{').replace('}}', '}') for x in literals] + + return literals, format_ops + + +def convert_format_expr_to_str(builder: IRBuilder, format_ops: List[FormatOp], + exprs: List[Expression], line: int) -> Optional[List[Value]]: + """Convert expressions into string literal objects with the guidance + of FormatOps. Return None when fails.""" + if len(format_ops) != len(exprs): + return None + + converted = [] + for x, format_op in zip(exprs, format_ops): + node_type = builder.node_type(x) + if format_op == FormatOp.STR: + if is_str_rprimitive(node_type): + var_str = builder.accept(x) + elif is_int_rprimitive(node_type) or is_short_int_rprimitive(node_type): + var_str = builder.call_c(int_to_str_op, [builder.accept(x)], line) + else: + var_str = builder.call_c(str_op, [builder.accept(x)], line) + elif format_op == FormatOp.INT: + if is_int_rprimitive(node_type) or is_short_int_rprimitive(node_type): + var_str = builder.call_c(int_to_str_op, [builder.accept(x)], line) + else: + return None + else: + return None + converted.append(var_str) + return converted + + +def join_formatted_strings(builder: IRBuilder, literals: Optional[List[str]], + substitutions: List[Value], line: int) -> Value: + """Merge the list of literals and the list of substitutions + alternatively using 'str_build_op'. + + `substitutions` is the result value of formatting conversions. + + If the `literals` is set to None, we simply join the substitutions; + Otherwise, the `literals` is the literal substrings of the original + format string and its length should be exactly one more than + substitutions. + + For example: + (1) 'This is a %s and the value is %d' + -> literals: ['This is a ', ' and the value is', ''] + (2) '{} and the value is {}' + -> literals: ['', ' and the value is', ''] + """ + # The first parameter for str_build_op is the total size of + # the following PyObject* + result_list: List[Value] = [Integer(0, c_pyssize_t_rprimitive)] + + if literals is not None: + for a, b in zip(literals, substitutions): + if a: + result_list.append(builder.load_str(a)) + result_list.append(b) + if literals[-1]: + result_list.append(builder.load_str(literals[-1])) + else: + result_list.extend(substitutions) + + # Special case for empty string and literal string + if len(result_list) == 1: + return builder.load_str("") + if not substitutions and len(result_list) == 2: + return result_list[1] + + result_list[0] = Integer(len(result_list) - 1, c_pyssize_t_rprimitive) + return builder.call_c(str_build_op, result_list, line) + + +def convert_format_expr_to_bytes(builder: IRBuilder, format_ops: List[FormatOp], + exprs: List[Expression], line: int) -> Optional[List[Value]]: + """Convert expressions into bytes literal objects with the guidance + of FormatOps. Return None when fails.""" + if len(format_ops) != len(exprs): + return None + + converted = [] + for x, format_op in zip(exprs, format_ops): + node_type = builder.node_type(x) + # conversion type 's' is an alias of 'b' in bytes formatting + if format_op == FormatOp.BYTES or format_op == FormatOp.STR: + if is_bytes_rprimitive(node_type): + var_bytes = builder.accept(x) + else: + return None + else: + return None + converted.append(var_bytes) + return converted + + +def join_formatted_bytes(builder: IRBuilder, literals: List[str], + substitutions: List[Value], line: int) -> Value: + """Merge the list of literals and the list of substitutions + alternatively using 'bytes_build_op'.""" + result_list: List[Value] = [Integer(0, c_pyssize_t_rprimitive)] + + for a, b in zip(literals, substitutions): + if a: + result_list.append(builder.load_bytes_from_str_literal(a)) + result_list.append(b) + if literals[-1]: + result_list.append(builder.load_bytes_from_str_literal(literals[-1])) + + # Special case for empty bytes and literal + if len(result_list) == 1: + return builder.load_bytes_from_str_literal('') + if not substitutions and len(result_list) == 2: + return result_list[1] + + result_list[0] = Integer(len(result_list) - 1, c_pyssize_t_rprimitive) + return builder.call_c(bytes_build_op, result_list, line) diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 1b7319823b20..5b567251111a 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -10,29 +10,36 @@ instance of the callable class. """ -from typing import Optional, List, Tuple, Union, Dict +from typing import ( + DefaultDict, NamedTuple, Optional, List, Sequence, Tuple, Union, Dict, +) from mypy.nodes import ( ClassDef, FuncDef, OverloadedFuncDef, Decorator, Var, YieldFromExpr, AwaitExpr, YieldExpr, - FuncItem, LambdaExpr, SymbolNode, ARG_NAMED, ARG_NAMED_OPT + FuncItem, LambdaExpr, SymbolNode, ArgKind, TypeInfo ) from mypy.types import CallableType, get_proper_type from mypyc.ir.ops import ( BasicBlock, Value, Register, Return, SetAttr, Integer, GetAttr, Branch, InitStatic, - LoadAddress + LoadAddress, LoadLiteral, Unbox, Unreachable, +) +from mypyc.ir.rtypes import ( + object_rprimitive, RInstance, object_pointer_rprimitive, dict_rprimitive, int_rprimitive, + bool_rprimitive, ) -from mypyc.ir.rtypes import object_rprimitive, RInstance, object_pointer_rprimitive from mypyc.ir.func_ir import ( FuncIR, FuncSignature, RuntimeArg, FuncDecl, FUNC_CLASSMETHOD, FUNC_STATICMETHOD, FUNC_NORMAL ) from mypyc.ir.class_ir import ClassIR, NonExtClassInfo from mypyc.primitives.generic_ops import py_setattr_op, next_raw_op, iter_op -from mypyc.primitives.misc_ops import check_stop_op, yield_from_except_op, coro_op, send_op -from mypyc.primitives.dict_ops import dict_set_item_op -from mypyc.common import SELF_NAME, LAMBDA_NAME, decorator_helper_name +from mypyc.primitives.misc_ops import ( + check_stop_op, yield_from_except_op, coro_op, send_op, register_function +) +from mypyc.primitives.dict_ops import dict_set_item_op, dict_new_op, dict_get_method_with_none +from mypyc.common import SELF_NAME, LAMBDA_NAME from mypyc.sametype import is_same_method_signature -from mypyc.irbuild.util import concrete_arg_kind, is_constant +from mypyc.irbuild.util import is_constant from mypyc.irbuild.context import FuncInfo, ImplicitClass from mypyc.irbuild.targets import AssignmentTarget from mypyc.irbuild.statement import transform_try_except @@ -51,6 +58,9 @@ setup_func_for_recursive_call ) +from mypyc.primitives.registry import builtin_names +from collections import defaultdict + # Top-level transform functions @@ -62,6 +72,7 @@ def transform_func_def(builder: IRBuilder, fdef: FuncDef) -> None: # current environment or define it if it was not already defined. if func_reg: builder.assign(get_func_target(builder, fdef), func_reg, fdef.line) + maybe_insert_into_registry_dict(builder, fdef) builder.functions.append(func_ir) @@ -78,38 +89,32 @@ def transform_decorator(builder: IRBuilder, dec: Decorator) -> None: dec.func.name, builder.mapper.fdef_to_sig(dec.func) ) - - if dec.func in builder.nested_fitems: - assert func_reg is not None + decorated_func: Optional[Value] = None + if func_reg: decorated_func = load_decorated_func(builder, dec.func, func_reg) builder.assign(get_func_target(builder, dec.func), decorated_func, dec.func.line) func_reg = decorated_func - else: + # If the prebuild pass didn't put this function in the function to decorators map (for example + # if this is a registered singledispatch implementation with no other decorators), we should + # treat this function as a regular function, not a decorated function + elif dec.func in builder.fdefs_to_decorators: # Obtain the the function name in order to construct the name of the helper function. name = dec.func.fullname.split('.')[-1] - helper_name = decorator_helper_name(name) # Load the callable object representing the non-decorated function, and decorate it. - orig_func = builder.load_global_str(helper_name, dec.line) + orig_func = builder.load_global_str(name, dec.line) decorated_func = load_decorated_func(builder, dec.func, orig_func) + if decorated_func is not None: # Set the callable object representing the decorated function as a global. builder.call_c(dict_set_item_op, - [builder.load_globals_dict(), - builder.load_str(dec.func.name), decorated_func], - decorated_func.line) - - builder.functions.append(func_ir) + [builder.load_globals_dict(), + builder.load_str(dec.func.name), decorated_func], + decorated_func.line) + maybe_insert_into_registry_dict(builder, dec.func) -def transform_method(builder: IRBuilder, - cdef: ClassDef, - non_ext: Optional[NonExtClassInfo], - fdef: FuncDef) -> None: - if non_ext: - handle_non_ext_method(builder, non_ext, cdef, fdef) - else: - handle_ext_method(builder, cdef, fdef) + builder.functions.append(func_ir) def transform_lambda_expr(builder: IRBuilder, expr: LambdaExpr) -> Value: @@ -135,6 +140,9 @@ def transform_lambda_expr(builder: IRBuilder, expr: LambdaExpr) -> Value: def transform_yield_expr(builder: IRBuilder, expr: YieldExpr) -> Value: + if builder.fn_info.is_coroutine: + builder.error('async generators are unimplemented', expr.line) + if expr.expr: retval = builder.accept(expr.expr) else: @@ -195,7 +203,7 @@ def c() -> None: # TODO: do something about abstract methods. - func_reg = None # type: Optional[Value] + func_reg: Optional[Value] = None # We treat lambdas as always being nested because we always generate # a class for lambdas, no matter where they are. (It would probably also @@ -203,6 +211,7 @@ def c() -> None: is_nested = fitem in builder.nested_fitems or isinstance(fitem, LambdaExpr) contains_nested = fitem in builder.encapsulating_funcs.keys() is_decorated = fitem in builder.fdefs_to_decorators + is_singledispatch = fitem in builder.singledispatch_impls in_non_ext = False class_name = None if cdef: @@ -210,7 +219,11 @@ def c() -> None: in_non_ext = not ir.is_ext_class class_name = cdef.name - builder.enter(FuncInfo(fitem, name, class_name, gen_func_ns(builder), + if is_singledispatch: + func_name = singledispatch_main_func_name(name) + else: + func_name = name + builder.enter(FuncInfo(fitem, func_name, class_name, gen_func_ns(builder), is_nested, contains_nested, is_decorated, in_non_ext)) # Functions that contain nested functions need an environment class to store variables that @@ -227,7 +240,9 @@ def c() -> None: # Do a first-pass and generate a function that just returns a generator object. gen_generator_func(builder) args, _, blocks, ret_type, fn_info = builder.leave() - func_ir, func_reg = gen_func_ir(builder, args, blocks, sig, fn_info, cdef) + func_ir, func_reg = gen_func_ir( + builder, args, blocks, sig, fn_info, cdef, is_singledispatch, + ) # Re-enter the FuncItem and visit the body of the function this time. builder.enter(fn_info) @@ -252,7 +267,7 @@ def c() -> None: # them even if they are declared after the nested function's definition. # Note that this is done before visiting the body of this function. - env_for_func = builder.fn_info # type: Union[FuncInfo, ImplicitClass] + env_for_func: Union[FuncInfo, ImplicitClass] = builder.fn_info if builder.fn_info.is_generator: env_for_func = builder.fn_info.generator_class elif builder.fn_info.is_nested or builder.fn_info.in_non_ext: @@ -294,13 +309,22 @@ def c() -> None: add_methods_to_generator_class( builder, fn_info, sig, args, blocks, fitem.is_coroutine) else: - func_ir, func_reg = gen_func_ir(builder, args, blocks, sig, fn_info, cdef) + func_ir, func_reg = gen_func_ir( + builder, args, blocks, sig, fn_info, cdef, is_singledispatch, + ) # Evaluate argument defaults in the surrounding scope, since we # calculate them *once* when the function definition is evaluated. calculate_arg_defaults(builder, fn_info, func_reg, symtable) - return (func_ir, func_reg) + if is_singledispatch: + # add the generated main singledispatch function + builder.functions.append(func_ir) + # create the dispatch function + assert isinstance(fitem, FuncDef) + return gen_dispatch_func_ir(builder, fitem, fn_info.name, name, sig) + + return func_ir, func_reg def gen_func_ir(builder: IRBuilder, @@ -308,7 +332,8 @@ def gen_func_ir(builder: IRBuilder, blocks: List[BasicBlock], sig: FuncSignature, fn_info: FuncInfo, - cdef: Optional[ClassDef]) -> Tuple[FuncIR, Optional[Value]]: + cdef: Optional[ClassDef], + is_singledispatch_main_func: bool = False) -> Tuple[FuncIR, Optional[Value]]: """Generate the FuncIR for a function. This takes the basic blocks and function info of a particular @@ -316,7 +341,7 @@ def gen_func_ir(builder: IRBuilder, also returns the register containing the instance of the corresponding callable class. """ - func_reg = None # type: Optional[Value] + func_reg: Optional[Value] = None if fn_info.is_nested or fn_info.in_non_ext: func_ir = add_call_to_callable_class(builder, args, blocks, sig, fn_info) add_get_to_callable_class(builder, fn_info) @@ -324,7 +349,7 @@ def gen_func_ir(builder: IRBuilder, else: assert isinstance(fn_info.fitem, FuncDef) func_decl = builder.mapper.func_to_decl[fn_info.fitem] - if fn_info.is_decorated: + if fn_info.is_decorated or is_singledispatch_main_func: class_name = None if cdef is None else cdef.name func_decl = FuncDecl(fn_info.name, class_name, builder.module_name, sig, func_decl.kind, @@ -347,11 +372,10 @@ def handle_ext_method(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef) -> None if is_decorated(builder, fdef): # Obtain the the function name in order to construct the name of the helper function. _, _, name = fdef.fullname.rpartition('.') - helper_name = decorator_helper_name(name) # Read the PyTypeObject representing the class, get the callable object # representing the non-decorated method typ = builder.load_native_type_object(cdef.fullname) - orig_func = builder.py_get_attr(typ, helper_name, fdef.line) + orig_func = builder.py_get_attr(typ, name, fdef.line) # Decorate the non-decorated method decorated_func = load_decorated_func(builder, fdef, orig_func) @@ -359,12 +383,8 @@ def handle_ext_method(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef) -> None # Set the callable object representing the decorated method as an attribute of the # extension class. builder.call_c(py_setattr_op, - [ - typ, - builder.load_str(name), - decorated_func - ], - fdef.line) + [typ, builder.load_str(name), decorated_func], + fdef.line) if fdef.is_property: # If there is a property setter, it will be processed after the getter, @@ -625,6 +645,24 @@ def gen_glue(builder: IRBuilder, sig: FuncSignature, target: FuncIR, return gen_glue_method(builder, sig, target, cls, base, fdef.line, do_py_ops) +class ArgInfo(NamedTuple): + args: List[Value] + arg_names: List[Optional[str]] + arg_kinds: List[ArgKind] + + +def get_args(builder: IRBuilder, rt_args: Sequence[RuntimeArg], line: int) -> ArgInfo: + # The environment operates on Vars, so we make some up + fake_vars = [(Var(arg.name), arg.type) for arg in rt_args] + args = [builder.read(builder.add_local_reg(var, type, is_arg=True), line) + for var, type in fake_vars] + arg_names = [arg.name + if arg.kind.is_named() or (arg.kind.is_optional() and not arg.pos_only) else None + for arg in rt_args] + arg_kinds = [arg.kind for arg in rt_args] + return ArgInfo(args, arg_names, arg_kinds) + + def gen_glue_method(builder: IRBuilder, sig: FuncSignature, target: FuncIR, cls: ClassIR, base: ClassIR, line: int, do_pycall: bool, @@ -661,17 +699,27 @@ def f(builder: IRBuilder, x: object) -> int: ... if target.decl.kind == FUNC_NORMAL: rt_args[0] = RuntimeArg(sig.args[0].name, RInstance(cls)) - # The environment operates on Vars, so we make some up - fake_vars = [(Var(arg.name), arg.type) for arg in rt_args] - args = [builder.read(builder.add_local_reg(var, type, is_arg=True), line) - for var, type in fake_vars] - arg_names = [arg.name if arg.kind in (ARG_NAMED, ARG_NAMED_OPT) else None - for arg in rt_args] - arg_kinds = [concrete_arg_kind(arg.kind) for arg in rt_args] + arg_info = get_args(builder, rt_args, line) + args, arg_kinds, arg_names = arg_info.args, arg_info.arg_kinds, arg_info.arg_names + + # We can do a passthrough *args/**kwargs with a native call, but if the + # args need to get distributed out to arguments, we just let python handle it + if ( + any(kind.is_star() for kind in arg_kinds) + and any(not arg.kind.is_star() for arg in target.decl.sig.args) + ): + do_pycall = True if do_pycall: + if target.decl.kind == FUNC_STATICMETHOD: + # FIXME: this won't work if we can do interpreted subclasses + first = builder.builder.get_native_type(cls) + st = 0 + else: + first = args[0] + st = 1 retval = builder.builder.py_method_call( - args[0], target.name, args[1:], line, arg_kinds[1:], arg_names[1:]) + first, target.name, args[st:], line, arg_kinds[st:], arg_names[st:]) else: retval = builder.builder.call(target.decl, args, arg_kinds, arg_names, line) retval = builder.coerce(retval, sig.ret_type, line) @@ -736,3 +784,274 @@ def get_func_target(builder: IRBuilder, fdef: FuncDef) -> AssignmentTarget: return builder.lookup(fdef) return builder.add_local_reg(fdef, object_rprimitive) + + +def load_type(builder: IRBuilder, typ: TypeInfo, line: int) -> Value: + if typ in builder.mapper.type_to_ir: + class_ir = builder.mapper.type_to_ir[typ] + class_obj = builder.builder.get_native_type(class_ir) + elif typ.fullname in builtin_names: + builtin_addr_type, src = builtin_names[typ.fullname] + class_obj = builder.add(LoadAddress(builtin_addr_type, src, line)) + else: + class_obj = builder.load_global_str(typ.name, line) + + return class_obj + + +def load_func(builder: IRBuilder, func_name: str, fullname: Optional[str], line: int) -> Value: + if fullname is not None and not fullname.startswith(builder.current_module): + # we're calling a function in a different module + + # We can't use load_module_attr_by_fullname here because we need to load the function using + # func_name, not the name specified by fullname (which can be different for underscore + # function) + module = fullname.rsplit('.')[0] + loaded_module = builder.load_module(module) + + func = builder.py_get_attr(loaded_module, func_name, line) + else: + func = builder.load_global_str(func_name, line) + return func + + +def generate_singledispatch_dispatch_function( + builder: IRBuilder, + main_singledispatch_function_name: str, + fitem: FuncDef, +) -> None: + line = fitem.line + current_func_decl = builder.mapper.func_to_decl[fitem] + arg_info = get_args(builder, current_func_decl.sig.args, line) + + dispatch_func_obj = builder.self() + + arg_type = builder.builder.get_type_of_obj(arg_info.args[0], line) + dispatch_cache = builder.builder.get_attr( + dispatch_func_obj, 'dispatch_cache', dict_rprimitive, line + ) + call_find_impl, use_cache, call_func = BasicBlock(), BasicBlock(), BasicBlock() + get_result = builder.call_c(dict_get_method_with_none, [dispatch_cache, arg_type], line) + is_not_none = builder.translate_is_op(get_result, builder.none_object(), 'is not', line) + impl_to_use = Register(object_rprimitive) + builder.add_bool_branch(is_not_none, use_cache, call_find_impl) + + builder.activate_block(use_cache) + builder.assign(impl_to_use, get_result, line) + builder.goto(call_func) + + builder.activate_block(call_find_impl) + find_impl = builder.load_module_attr_by_fullname('functools._find_impl', line) + registry = load_singledispatch_registry(builder, dispatch_func_obj, line) + uncached_impl = builder.py_call(find_impl, [arg_type, registry], line) + builder.call_c(dict_set_item_op, [dispatch_cache, arg_type, uncached_impl], line) + builder.assign(impl_to_use, uncached_impl, line) + builder.goto(call_func) + + builder.activate_block(call_func) + gen_calls_to_correct_impl(builder, impl_to_use, arg_info, fitem, line) + + +def gen_calls_to_correct_impl( + builder: IRBuilder, + impl_to_use: Value, + arg_info: ArgInfo, + fitem: FuncDef, + line: int, +) -> None: + current_func_decl = builder.mapper.func_to_decl[fitem] + + def gen_native_func_call_and_return(fdef: FuncDef) -> None: + func_decl = builder.mapper.func_to_decl[fdef] + ret_val = builder.builder.call( + func_decl, arg_info.args, arg_info.arg_kinds, arg_info.arg_names, line + ) + coerced = builder.coerce(ret_val, current_func_decl.sig.ret_type, line) + builder.add(Return(coerced)) + + typ, src = builtin_names['builtins.int'] + int_type_obj = builder.add(LoadAddress(typ, src, line)) + is_int = builder.builder.type_is_op(impl_to_use, int_type_obj, line) + + native_call, non_native_call = BasicBlock(), BasicBlock() + builder.add_bool_branch(is_int, native_call, non_native_call) + builder.activate_block(native_call) + + passed_id = builder.add(Unbox(impl_to_use, int_rprimitive, line)) + + native_ids = get_native_impl_ids(builder, fitem) + for impl, i in native_ids.items(): + call_impl, next_impl = BasicBlock(), BasicBlock() + + current_id = builder.load_int(i) + builder.builder.compare_tagged_condition( + passed_id, + current_id, + '==', + call_impl, + next_impl, + line, + ) + + # Call the registered implementation + builder.activate_block(call_impl) + + gen_native_func_call_and_return(impl) + builder.activate_block(next_impl) + + # We've already handled all the possible integer IDs, so we should never get here + builder.add(Unreachable()) + + builder.activate_block(non_native_call) + ret_val = builder.py_call( + impl_to_use, arg_info.args, line, arg_info.arg_kinds, arg_info.arg_names + ) + coerced = builder.coerce(ret_val, current_func_decl.sig.ret_type, line) + builder.add(Return(coerced)) + + +def gen_dispatch_func_ir( + builder: IRBuilder, + fitem: FuncDef, + main_func_name: str, + dispatch_name: str, + sig: FuncSignature, +) -> Tuple[FuncIR, Value]: + """Create a dispatch function (a function that checks the first argument type and dispatches + to the correct implementation) + """ + builder.enter(FuncInfo(fitem, dispatch_name)) + setup_callable_class(builder) + builder.fn_info.callable_class.ir.attributes['registry'] = dict_rprimitive + builder.fn_info.callable_class.ir.attributes['dispatch_cache'] = dict_rprimitive + builder.fn_info.callable_class.ir.has_dict = True + builder.fn_info.callable_class.ir.needs_getseters = True + generate_singledispatch_callable_class_ctor(builder) + + generate_singledispatch_dispatch_function(builder, main_func_name, fitem) + args, _, blocks, _, fn_info = builder.leave() + dispatch_callable_class = add_call_to_callable_class(builder, args, blocks, sig, fn_info) + builder.functions.append(dispatch_callable_class) + add_get_to_callable_class(builder, fn_info) + add_register_method_to_callable_class(builder, fn_info) + func_reg = instantiate_callable_class(builder, fn_info) + dispatch_func_ir = generate_dispatch_glue_native_function( + builder, fitem, dispatch_callable_class.decl, dispatch_name + ) + + return dispatch_func_ir, func_reg + + +def generate_dispatch_glue_native_function( + builder: IRBuilder, + fitem: FuncDef, + callable_class_decl: FuncDecl, + dispatch_name: str, +) -> FuncIR: + line = fitem.line + builder.enter() + # We store the callable class in the globals dict for this function + callable_class = builder.load_global_str(dispatch_name, line) + decl = builder.mapper.func_to_decl[fitem] + arg_info = get_args(builder, decl.sig.args, line) + args = [callable_class] + arg_info.args + arg_kinds = [ArgKind.ARG_POS] + arg_info.arg_kinds + arg_names = arg_info.arg_names + arg_names.insert(0, 'self') + ret_val = builder.builder.call(callable_class_decl, args, arg_kinds, arg_names, line) + builder.add(Return(ret_val)) + arg_regs, _, blocks, _, fn_info = builder.leave() + return FuncIR(decl, arg_regs, blocks) + + +def generate_singledispatch_callable_class_ctor(builder: IRBuilder) -> None: + """Create an __init__ that sets registry and dispatch_cache to empty dicts""" + line = -1 + class_ir = builder.fn_info.callable_class.ir + with builder.enter_method(class_ir, '__init__', bool_rprimitive): + empty_dict = builder.call_c(dict_new_op, [], line) + builder.add(SetAttr(builder.self(), 'registry', empty_dict, line)) + cache_dict = builder.call_c(dict_new_op, [], line) + dispatch_cache_str = builder.load_str('dispatch_cache') + # use the py_setattr_op instead of SetAttr so that it also gets added to our __dict__ + builder.call_c(py_setattr_op, [builder.self(), dispatch_cache_str, cache_dict], line) + # the generated C code seems to expect that __init__ returns a char, so just return 1 + builder.add(Return(Integer(1, bool_rprimitive, line), line)) + + +def add_register_method_to_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> None: + line = -1 + with builder.enter_method(fn_info.callable_class.ir, 'register', object_rprimitive): + cls_arg = builder.add_argument('cls', object_rprimitive) + func_arg = builder.add_argument('func', object_rprimitive, ArgKind.ARG_OPT) + ret_val = builder.call_c(register_function, [builder.self(), cls_arg, func_arg], line) + builder.add(Return(ret_val, line)) + + +def load_singledispatch_registry(builder: IRBuilder, dispatch_func_obj: Value, line: int) -> Value: + return builder.builder.get_attr(dispatch_func_obj, 'registry', dict_rprimitive, line) + + +def singledispatch_main_func_name(orig_name: str) -> str: + return '__mypyc_singledispatch_main_function_{}__'.format(orig_name) + + +def get_registry_identifier(fitem: FuncDef) -> str: + return f'__mypyc_singledispatch_registry_{fitem.fullname}__' + + +def maybe_insert_into_registry_dict(builder: IRBuilder, fitem: FuncDef) -> None: + line = fitem.line + is_singledispatch_main_func = fitem in builder.singledispatch_impls + # dict of singledispatch_func to list of register_types (fitem is the function to register) + to_register: DefaultDict[FuncDef, List[TypeInfo]] = defaultdict(list) + for main_func, impls in builder.singledispatch_impls.items(): + for dispatch_type, impl in impls: + if fitem == impl: + to_register[main_func].append(dispatch_type) + + if not to_register and not is_singledispatch_main_func: + return + + if is_singledispatch_main_func: + main_func_name = singledispatch_main_func_name(fitem.name) + main_func_obj = load_func(builder, main_func_name, fitem.fullname, line) + + loaded_object_type = builder.load_module_attr_by_fullname('builtins.object', line) + registry_dict = builder.builder.make_dict([(loaded_object_type, main_func_obj)], line) + + dispatch_func_obj = builder.load_global_str(fitem.name, line) + builder.call_c( + py_setattr_op, [dispatch_func_obj, builder.load_str('registry'), registry_dict], line + ) + + for singledispatch_func, types in to_register.items(): + # TODO: avoid recomputing the native IDs for all the functions every time we find a new + # function + native_ids = get_native_impl_ids(builder, singledispatch_func) + if fitem not in native_ids: + to_insert = load_func(builder, fitem.name, fitem.fullname, line) + else: + current_id = native_ids[fitem] + load_literal = LoadLiteral(current_id, object_rprimitive) + to_insert = builder.add(load_literal) + # TODO: avoid reloading the registry here if we just created it + dispatch_func_obj = load_func( + builder, singledispatch_func.name, singledispatch_func.fullname, line + ) + registry = load_singledispatch_registry(builder, dispatch_func_obj, line) + for typ in types: + loaded_type = load_type(builder, typ, line) + builder.call_c(dict_set_item_op, [registry, loaded_type, to_insert], line) + dispatch_cache = builder.builder.get_attr( + dispatch_func_obj, 'dispatch_cache', dict_rprimitive, line + ) + builder.gen_method_call(dispatch_cache, 'clear', [], None, line) + + +def get_native_impl_ids(builder: IRBuilder, singledispatch_func: FuncDef) -> Dict[FuncDef, int]: + """Return a dict of registered implementation to native implementation ID for all + implementations + """ + impls = builder.singledispatch_impls[singledispatch_func] + return {impl: i for i, (typ, impl) in enumerate(impls) if not is_decorated(builder, impl)} diff --git a/mypyc/irbuild/generator.py b/mypyc/irbuild/generator.py index b3490551a5b6..39d30cf74eeb 100644 --- a/mypyc/irbuild/generator.py +++ b/mypyc/irbuild/generator.py @@ -157,9 +157,8 @@ def add_helper_to_generator_class(builder: IRBuilder, def add_iter_to_generator_class(builder: IRBuilder, fn_info: FuncInfo) -> None: """Generates the '__iter__' method for a generator class.""" - builder.enter_method(fn_info.generator_class.ir, '__iter__', object_rprimitive, fn_info) - builder.add(Return(builder.self())) - builder.leave_method() + with builder.enter_method(fn_info.generator_class.ir, '__iter__', object_rprimitive, fn_info): + builder.add(Return(builder.self())) def add_next_to_generator_class(builder: IRBuilder, @@ -167,14 +166,14 @@ def add_next_to_generator_class(builder: IRBuilder, fn_decl: FuncDecl, sig: FuncSignature) -> None: """Generates the '__next__' method for a generator class.""" - builder.enter_method(fn_info.generator_class.ir, '__next__', object_rprimitive, fn_info) - none_reg = builder.none_object() - # Call the helper function with error flags set to Py_None, and return that result. - result = builder.add(Call(fn_decl, - [builder.self(), none_reg, none_reg, none_reg, none_reg], - fn_info.fitem.line)) - builder.add(Return(result)) - builder.leave_method() + with builder.enter_method(fn_info.generator_class.ir, '__next__', + object_rprimitive, fn_info): + none_reg = builder.none_object() + # Call the helper function with error flags set to Py_None, and return that result. + result = builder.add(Call(fn_decl, + [builder.self(), none_reg, none_reg, none_reg, none_reg], + fn_info.fitem.line)) + builder.add(Return(result)) def add_send_to_generator_class(builder: IRBuilder, @@ -182,15 +181,15 @@ def add_send_to_generator_class(builder: IRBuilder, fn_decl: FuncDecl, sig: FuncSignature) -> None: """Generates the 'send' method for a generator class.""" - builder.enter_method(fn_info.generator_class.ir, 'send', object_rprimitive, fn_info) - arg = builder.add_argument('arg', object_rprimitive) - none_reg = builder.none_object() - # Call the helper function with error flags set to Py_None, and return that result. - result = builder.add(Call(fn_decl, - [builder.self(), none_reg, none_reg, none_reg, builder.read(arg)], - fn_info.fitem.line)) - builder.add(Return(result)) - builder.leave_method() + with builder.enter_method(fn_info.generator_class.ir, 'send', object_rprimitive, fn_info): + arg = builder.add_argument('arg', object_rprimitive) + none_reg = builder.none_object() + # Call the helper function with error flags set to Py_None, and return that result. + result = builder.add(Call( + fn_decl, + [builder.self(), none_reg, none_reg, none_reg, builder.read(arg)], + fn_info.fitem.line)) + builder.add(Return(result)) def add_throw_to_generator_class(builder: IRBuilder, @@ -198,47 +197,42 @@ def add_throw_to_generator_class(builder: IRBuilder, fn_decl: FuncDecl, sig: FuncSignature) -> None: """Generates the 'throw' method for a generator class.""" - builder.enter_method(fn_info.generator_class.ir, 'throw', object_rprimitive, fn_info) - typ = builder.add_argument('type', object_rprimitive) - val = builder.add_argument('value', object_rprimitive, ARG_OPT) - tb = builder.add_argument('traceback', object_rprimitive, ARG_OPT) - - # Because the value and traceback arguments are optional and hence - # can be NULL if not passed in, we have to assign them Py_None if - # they are not passed in. - none_reg = builder.none_object() - builder.assign_if_null(val, lambda: none_reg, builder.fn_info.fitem.line) - builder.assign_if_null(tb, lambda: none_reg, builder.fn_info.fitem.line) - - # Call the helper function using the arguments passed in, and return that result. - result = builder.add( - Call( + with builder.enter_method(fn_info.generator_class.ir, 'throw', + object_rprimitive, fn_info): + typ = builder.add_argument('type', object_rprimitive) + val = builder.add_argument('value', object_rprimitive, ARG_OPT) + tb = builder.add_argument('traceback', object_rprimitive, ARG_OPT) + + # Because the value and traceback arguments are optional and hence + # can be NULL if not passed in, we have to assign them Py_None if + # they are not passed in. + none_reg = builder.none_object() + builder.assign_if_null(val, lambda: none_reg, builder.fn_info.fitem.line) + builder.assign_if_null(tb, lambda: none_reg, builder.fn_info.fitem.line) + + # Call the helper function using the arguments passed in, and return that result. + result = builder.add(Call( fn_decl, [builder.self(), builder.read(typ), builder.read(val), builder.read(tb), none_reg], - fn_info.fitem.line - ) - ) - builder.add(Return(result)) - builder.leave_method() + fn_info.fitem.line)) + builder.add(Return(result)) def add_close_to_generator_class(builder: IRBuilder, fn_info: FuncInfo) -> None: """Generates the '__close__' method for a generator class.""" # TODO: Currently this method just triggers a runtime error. # We should fill this out (https://github.com/mypyc/mypyc/issues/790). - builder.enter_method(fn_info.generator_class.ir, 'close', object_rprimitive, fn_info) - builder.add(RaiseStandardError(RaiseStandardError.RUNTIME_ERROR, - 'close method on generator classes unimplemented', - fn_info.fitem.line)) - builder.add(Unreachable()) - builder.leave_method() + with builder.enter_method(fn_info.generator_class.ir, 'close', object_rprimitive, fn_info): + builder.add(RaiseStandardError(RaiseStandardError.RUNTIME_ERROR, + 'close method on generator classes unimplemented', + fn_info.fitem.line)) + builder.add(Unreachable()) def add_await_to_generator_class(builder: IRBuilder, fn_info: FuncInfo) -> None: """Generates the '__await__' method for a generator class.""" - builder.enter_method(fn_info.generator_class.ir, '__await__', object_rprimitive, fn_info) - builder.add(Return(builder.self())) - builder.leave_method() + with builder.enter_method(fn_info.generator_class.ir, '__await__', object_rprimitive, fn_info): + builder.add(Return(builder.self())) def setup_env_for_generator_class(builder: IRBuilder) -> None: diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index ef2e482e45c2..27419fcc7385 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -9,12 +9,13 @@ """ from typing import ( - Callable, List, Tuple, Optional, Union, Sequence, cast + Callable, List, Tuple, Optional, Sequence ) from typing_extensions import Final -from mypy.nodes import ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, op_methods +from mypy.nodes import ArgKind, ARG_POS, ARG_STAR, ARG_STAR2 +from mypy.operators import op_methods from mypy.types import AnyType, TypeOfAny from mypy.checkexpr import map_actuals_to_formals @@ -23,7 +24,7 @@ GetAttr, LoadStatic, MethodCall, CallC, Truncate, LoadLiteral, AssignMulti, RaiseStandardError, Unreachable, LoadErrorValue, NAMESPACE_TYPE, NAMESPACE_MODULE, NAMESPACE_STATIC, IntOp, GetElementPtr, - LoadMem, ComparisonOp, LoadAddress, TupleGet, SetMem, KeepAlive, ERR_NEVER, ERR_FALSE + LoadMem, ComparisonOp, LoadAddress, TupleGet, KeepAlive, ERR_NEVER, ERR_FALSE, SetMem ) from mypyc.ir.rtypes import ( RType, RUnion, RInstance, RArray, optional_value_type, int_rprimitive, float_rprimitive, @@ -32,26 +33,28 @@ is_list_rprimitive, is_tuple_rprimitive, is_dict_rprimitive, is_set_rprimitive, PySetObject, none_rprimitive, RTuple, is_bool_rprimitive, is_str_rprimitive, c_int_rprimitive, pointer_rprimitive, PyObject, PyListObject, bit_rprimitive, is_bit_rprimitive, - object_pointer_rprimitive, c_size_t_rprimitive, dict_rprimitive + object_pointer_rprimitive, c_size_t_rprimitive, dict_rprimitive, bytes_rprimitive, + is_bytes_rprimitive ) from mypyc.ir.func_ir import FuncDecl, FuncSignature from mypyc.ir.class_ir import ClassIR, all_concrete_classes from mypyc.common import ( - FAST_ISINSTANCE_MAX_SUBCLASSES, MAX_LITERAL_SHORT_INT, PLATFORM_SIZE, use_vectorcall, - use_method_vectorcall + FAST_ISINSTANCE_MAX_SUBCLASSES, MAX_LITERAL_SHORT_INT, MIN_LITERAL_SHORT_INT, PLATFORM_SIZE, + use_vectorcall, use_method_vectorcall ) from mypyc.primitives.registry import ( - method_call_ops, CFunctionDescription, function_ops, + method_call_ops, CFunctionDescription, binary_ops, unary_ops, ERR_NEG_INT ) +from mypyc.primitives.bytes_ops import bytes_compare from mypyc.primitives.list_ops import ( - list_extend_op, new_list_op + list_extend_op, new_list_op, list_build_op ) from mypyc.primitives.tuple_ops import ( list_tuple_op, new_tuple_op, new_tuple_with_length_op ) from mypyc.primitives.dict_ops import ( - dict_update_in_display_op, dict_new_op, dict_build_op, dict_size_op + dict_update_in_display_op, dict_new_op, dict_build_op, dict_ssize_t_size_op ) from mypyc.primitives.generic_ops import ( py_getattr_op, py_call_op, py_call_with_kwargs_op, py_method_call_op, @@ -63,20 +66,29 @@ ) from mypyc.primitives.int_ops import int_comparison_op_mapping from mypyc.primitives.exc_ops import err_occurred_op, keep_propagating_op -from mypyc.primitives.str_ops import unicode_compare, str_check_if_true +from mypyc.primitives.str_ops import ( + unicode_compare, str_check_if_true, str_ssize_t_size_op +) from mypyc.primitives.set_ops import new_set_op from mypyc.rt_subtype import is_runtime_subtype from mypyc.subtype import is_subtype from mypyc.sametype import is_same_type from mypyc.irbuild.mapper import Mapper from mypyc.options import CompilerOptions +from mypyc.irbuild.util import concrete_arg_kind DictEntry = Tuple[Optional[Value], Value] +# If the number of items is less than the threshold when initializing +# a list, we would inline the generate IR using SetMem and expanded +# for-loop. Otherwise, we would call `list_build_op` for larger lists. +# TODO: The threshold is a randomly chosen number which needs further +# study on real-world projects for a better balance. +LIST_BUILDING_EXPANSION_THRESHOLD = 10 # From CPython -PY_VECTORCALL_ARGUMENTS_OFFSET = 1 << (PLATFORM_SIZE * 8 - 1) # type: Final +PY_VECTORCALL_ARGUMENTS_OFFSET: Final = 1 << (PLATFORM_SIZE * 8 - 1) class LowLevelIRBuilder: @@ -89,10 +101,10 @@ def __init__( self.current_module = current_module self.mapper = mapper self.options = options - self.args = [] # type: List[Register] - self.blocks = [] # type: List[BasicBlock] + self.args: List[Register] = [] + self.blocks: List[BasicBlock] = [] # Stack of except handler entry blocks - self.error_handlers = [None] # type: List[Optional[BasicBlock]] + self.error_handlers: List[Optional[BasicBlock]] = [None] # Basic operations @@ -175,6 +187,34 @@ def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) return tmp return src + def coerce_nullable(self, src: Value, target_type: RType, line: int) -> Value: + """Generate a coercion from a potentially null value.""" + if ( + src.type.is_unboxed == target_type.is_unboxed + and ( + (target_type.is_unboxed and is_runtime_subtype(src.type, target_type)) + or (not target_type.is_unboxed and is_subtype(src.type, target_type)) + ) + ): + return src + + target = Register(target_type) + + valid, invalid, out = BasicBlock(), BasicBlock(), BasicBlock() + self.add(Branch(src, invalid, valid, Branch.IS_ERROR)) + + self.activate_block(valid) + coerced = self.coerce(src, target_type, line) + self.add(Assign(target, coerced, line)) + self.goto(out) + + self.activate_block(invalid) + error = self.add(LoadErrorValue(target_type)) + self.add(Assign(target, error, line)) + + self.goto_and_activate(out) + return target + # Attribute access def get_attr(self, obj: Value, attr: str, result_type: RType, line: int) -> Value: @@ -221,11 +261,15 @@ def other() -> Value: ret = self.shortcircuit_helper('or', bool_rprimitive, lambda: ret, other, line) return ret - def type_is_op(self, obj: Value, type_obj: Value, line: int) -> Value: + def get_type_of_obj(self, obj: Value, line: int) -> Value: ob_type_address = self.add(GetElementPtr(obj, PyObject, 'ob_type', line)) ob_type = self.add(LoadMem(object_rprimitive, ob_type_address)) self.add(KeepAlive([obj])) - return self.add(ComparisonOp(ob_type, type_obj, ComparisonOp.EQ, line)) + return ob_type + + def type_is_op(self, obj: Value, type_obj: Value, line: int) -> Value: + typ = self.get_type_of_obj(obj, line) + return self.add(ComparisonOp(typ, type_obj, ComparisonOp.EQ, line)) def isinstance_native(self, obj: Value, class_ir: ClassIR, line: int) -> Value: """Fast isinstance() check for a native class. @@ -252,11 +296,202 @@ def other() -> Value: # Calls + def _construct_varargs(self, + args: Sequence[Tuple[Value, ArgKind, Optional[str]]], + line: int, + *, + has_star: bool, + has_star2: bool) -> Tuple[Optional[Value], Optional[Value]]: + """Construct *args and **kwargs from a collection of arguments + + This is pretty complicated, and almost all of the complication here stems from + one of two things (but mostly the second): + * The handling of ARG_STAR/ARG_STAR2. We want to create as much of the args/kwargs + values in one go as we can, so we collect values until our hand is forced, and + then we emit creation of the list/tuple, and expand it from there if needed. + + * Support potentially nullable argument values. This has very narrow applicability, + as this will never be done by our compiled Python code, but is critically used + by gen_glue_method when generating glue methods to mediate between the function + signature of a parent class and its subclasses. + + For named-only arguments, this is quite simple: if it is + null, don't put it in the dict. + + For positional-or-named arguments, things are much more complicated. + * First, anything that was passed as a positional arg + must be forwarded along as a positional arg. It *must + not* be converted to a named arg. This is because mypy + does not enforce that positional-or-named arguments + have the same name in subclasses, and it is not + uncommon for code to have different names in + subclasses (a bunch of mypy's visitors do this, for + example!). This is arguably a bug in both mypy and code doing + this, and they ought to be using positional-only arguments, but + positional-only arguments are new and ugly. + + * On the flip side, we're willing to accept the + infelicity of sometimes turning an argument that was + passed by keyword into a positional argument. It's wrong, + but it's very marginal, and avoiding it would require passing + a bitmask of which arguments were named with every function call, + or something similar. + (See some discussion of this in testComplicatedArgs) + + Thus, our strategy for positional-or-named arguments is to + always pass them as positional, except in the one + situation where we can not, and where we can be absolutely + sure they were passed by name: when an *earlier* + positional argument was missing its value. + + This means that if we have a method `f(self, x: int=..., y: object=...)`: + * x and y present: args=(x, y), kwargs={} + * x present, y missing: args=(x,), kwargs={} + * x missing, y present: args=(), kwargs={'y': y} + + To implement this, when we have multiple optional + positional arguments, we maintain a flag in a register + that tracks whether an argument has been missing, and for + each such optional argument (except the first), we check + the flag to determine whether to append the argument to + the *args list or add it to the **kwargs dict. What a + mess! + + This is what really makes everything here such a tangle; + otherwise the *args and **kwargs code could be separated. + + The arguments has_star and has_star2 indicate whether the target function + takes an ARG_STAR and ARG_STAR2 argument, respectively. + (These will always be true when making a pycall, and be based + on the actual target signature for a native call.) + """ + + star_result: Optional[Value] = None + star2_result: Optional[Value] = None + # We aggregate values that need to go into *args and **kwargs + # in these lists. Once all arguments are processed (in the + # happiest case), or we encounter an ARG_STAR/ARG_STAR2 or a + # nullable arg, then we create the list and/or dict. + star_values: List[Value] = [] + star2_keys: List[Value] = [] + star2_values: List[Value] = [] + + seen_empty_reg: Optional[Register] = None + + for value, kind, name in args: + if kind == ARG_STAR: + if star_result is None: + star_result = self.new_list_op(star_values, line) + self.call_c(list_extend_op, [star_result, value], line) + elif kind == ARG_STAR2: + if star2_result is None: + star2_result = self._create_dict(star2_keys, star2_values, line) + + self.call_c( + dict_update_in_display_op, + [star2_result, value], + line=line + ) + else: + nullable = kind.is_optional() + maybe_pos = kind.is_positional() and has_star + maybe_named = kind.is_named() or (kind.is_optional() and name and has_star2) + + # If the argument is nullable, we need to create the + # relevant args/kwargs objects so that we can + # conditionally modify them. + if nullable: + if maybe_pos and star_result is None: + star_result = self.new_list_op(star_values, line) + if maybe_named and star2_result is None: + star2_result = self._create_dict(star2_keys, star2_values, line) + + # Easy cases: just collect the argument. + if maybe_pos and star_result is None: + star_values.append(value) + continue + + if maybe_named and star2_result is None: + assert name is not None + key = self.load_str(name) + star2_keys.append(key) + star2_values.append(value) + continue + + # OK, anything that is nullable or *after* a nullable arg needs to be here + # TODO: We could try harder to avoid creating basic blocks in the common case + new_seen_empty_reg = seen_empty_reg + + out = BasicBlock() + if nullable: + # If this is the first nullable positional arg we've seen, create + # a register to track whether anything has been null. + # (We won't *check* the register until the next argument, though.) + if maybe_pos and not seen_empty_reg: + new_seen_empty_reg = Register(bool_rprimitive) + self.add(Assign(new_seen_empty_reg, self.false(), line)) + + skip = BasicBlock() if maybe_pos else out + keep = BasicBlock() + self.add(Branch(value, skip, keep, Branch.IS_ERROR)) + self.activate_block(keep) + + # If this could be positional or named and we /might/ have seen a missing + # positional arg, then we need to compile *both* a positional and named + # version! What a pain! + if maybe_pos and maybe_named and seen_empty_reg: + pos_block, named_block = BasicBlock(), BasicBlock() + self.add(Branch(seen_empty_reg, named_block, pos_block, Branch.BOOL)) + else: + pos_block = named_block = BasicBlock() + self.goto(pos_block) + + if maybe_pos: + self.activate_block(pos_block) + assert star_result + self.translate_special_method_call( + star_result, 'append', [value], result_type=None, line=line) + self.goto(out) + + if maybe_named and (not maybe_pos or seen_empty_reg): + self.activate_block(named_block) + assert name is not None + key = self.load_str(name) + assert star2_result + self.translate_special_method_call( + star2_result, '__setitem__', [key, value], result_type=None, line=line) + self.goto(out) + + if nullable and maybe_pos and new_seen_empty_reg: + assert skip is not out + self.activate_block(skip) + self.add(Assign(new_seen_empty_reg, self.true(), line)) + self.goto(out) + + self.activate_block(out) + + seen_empty_reg = new_seen_empty_reg + + assert not (star_result or star_values) or has_star + assert not (star2_result or star2_values) or has_star2 + if has_star: + # If we managed to make it this far without creating a + # *args list, then we can directly create a + # tuple. Otherwise create the tuple from the list. + if star_result is None: + star_result = self.new_tuple(star_values, line) + else: + star_result = self.call_c(list_tuple_op, [star_result], line) + if has_star2 and star2_result is None: + star2_result = self._create_dict(star2_keys, star2_values, line) + + return star_result, star2_result + def py_call(self, function: Value, arg_values: List[Value], line: int, - arg_kinds: Optional[List[int]] = None, + arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[Sequence[Optional[str]]] = None) -> Value: """Call a Python function (non-native and slow). @@ -275,37 +510,10 @@ def py_call(self, # Otherwise fallback to py_call_with_kwargs_op. assert arg_names is not None - pos_arg_values = [] - kw_arg_key_value_pairs = [] # type: List[DictEntry] - star_arg_values = [] - for value, kind, name in zip(arg_values, arg_kinds, arg_names): - if kind == ARG_POS: - pos_arg_values.append(value) - elif kind == ARG_NAMED: - assert name is not None - key = self.load_str(name) - kw_arg_key_value_pairs.append((key, value)) - elif kind == ARG_STAR: - star_arg_values.append(value) - elif kind == ARG_STAR2: - # NOTE: mypy currently only supports a single ** arg, but python supports multiple. - # This code supports multiple primarily to make the logic easier to follow. - kw_arg_key_value_pairs.append((None, value)) - else: - assert False, ("Argument kind should not be possible:", kind) - - if len(star_arg_values) == 0: - # We can directly construct a tuple if there are no star args. - pos_args_tuple = self.new_tuple(pos_arg_values, line) - else: - # Otherwise we construct a list and call extend it with the star args, since tuples - # don't have an extend method. - pos_args_list = self.new_list_op(pos_arg_values, line) - for star_arg_value in star_arg_values: - self.call_c(list_extend_op, [pos_args_list, star_arg_value], line) - pos_args_tuple = self.call_c(list_tuple_op, [pos_args_list], line) - - kw_args_dict = self.make_dict(kw_arg_key_value_pairs, line) + pos_args_tuple, kw_args_dict = self._construct_varargs( + list(zip(arg_values, arg_kinds, arg_names)), line, has_star=True, has_star2=True + ) + assert pos_args_tuple and kw_args_dict return self.call_c( py_call_with_kwargs_op, [function, pos_args_tuple, kw_args_dict], line) @@ -314,15 +522,16 @@ def _py_vector_call(self, function: Value, arg_values: List[Value], line: int, - arg_kinds: Optional[List[int]] = None, + arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[Sequence[Optional[str]]] = None) -> Optional[Value]: """Call function using the vectorcall API if possible. Return the return value if successful. Return None if a non-vectorcall API should be used instead. """ - # We can do this if all args are positional or named (no *args or **kwargs). - if arg_kinds is None or all(kind in (ARG_POS, ARG_NAMED) for kind in arg_kinds): + # We can do this if all args are positional or named (no *args or **kwargs, not optional). + if arg_kinds is None or all(not kind.is_star() and not kind.is_optional() + for kind in arg_kinds): if arg_values: # Create a C array containing all arguments as boxed values. array = Register(RArray(object_rprimitive, len(arg_values))) @@ -362,7 +571,7 @@ def py_method_call(self, method_name: str, arg_values: List[Value], line: int, - arg_kinds: Optional[List[int]], + arg_kinds: Optional[List[ArgKind]], arg_names: Optional[Sequence[Optional[str]]]) -> Value: """Call a Python method (non-native and slow).""" if use_method_vectorcall(self.options.capi_version): @@ -386,14 +595,15 @@ def _py_vector_method_call(self, method_name: str, arg_values: List[Value], line: int, - arg_kinds: Optional[List[int]], + arg_kinds: Optional[List[ArgKind]], arg_names: Optional[Sequence[Optional[str]]]) -> Optional[Value]: """Call method using the vectorcall API if possible. Return the return value if successful. Return None if a non-vectorcall API should be used instead. """ - if arg_kinds is None or all(kind in (ARG_POS, ARG_NAMED) for kind in arg_kinds): + if arg_kinds is None or all(not kind.is_star() and not kind.is_optional() + for kind in arg_kinds): method_name_reg = self.load_str(method_name) array = Register(RArray(object_rprimitive, len(arg_values) + 1)) self_arg = self.coerce(obj, object_rprimitive, line) @@ -420,7 +630,7 @@ def _py_vector_method_call(self, def call(self, decl: FuncDecl, args: Sequence[Value], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Sequence[Optional[str]], line: int) -> Value: """Call a native function.""" @@ -431,7 +641,7 @@ def call(self, def native_args_to_positional(self, args: Sequence[Value], - arg_kinds: List[int], + arg_kinds: List[ArgKind], arg_names: Sequence[Optional[str]], sig: FuncSignature, line: int) -> List[Value]: @@ -446,30 +656,48 @@ def native_args_to_positional(self, sig_arg_kinds = [arg.kind for arg in sig.args] sig_arg_names = [arg.name for arg in sig.args] - formal_to_actual = map_actuals_to_formals(arg_kinds, + concrete_kinds = [concrete_arg_kind(arg_kind) for arg_kind in arg_kinds] + formal_to_actual = map_actuals_to_formals(concrete_kinds, arg_names, sig_arg_kinds, sig_arg_names, lambda n: AnyType(TypeOfAny.special_form)) + # First scan for */** and construct those + has_star = has_star2 = False + star_arg_entries = [] + for lst, arg in zip(formal_to_actual, sig.args): + if arg.kind.is_star(): + star_arg_entries.extend([(args[i], arg_kinds[i], arg_names[i]) for i in lst]) + has_star = has_star or arg.kind == ARG_STAR + has_star2 = has_star2 or arg.kind == ARG_STAR2 + + star_arg, star2_arg = self._construct_varargs( + star_arg_entries, line, has_star=has_star, has_star2=has_star2 + ) + # Flatten out the arguments, loading error values for default # arguments, constructing tuples/dicts for star args, and # coercing everything to the expected type. output_args = [] for lst, arg in zip(formal_to_actual, sig.args): - output_arg = None if arg.kind == ARG_STAR: - items = [args[i] for i in lst] - output_arg = self.new_tuple(items, line) + assert star_arg + output_arg = star_arg elif arg.kind == ARG_STAR2: - dict_entries = [(self.load_str(cast(str, arg_names[i])), args[i]) - for i in lst] - output_arg = self.make_dict(dict_entries, line) + assert star2_arg + output_arg = star2_arg elif not lst: output_arg = self.add(LoadErrorValue(arg.type, is_borrowed=True)) else: - output_arg = args[lst[0]] - output_args.append(self.coerce(output_arg, arg.type, line)) + base_arg = args[lst[0]] + + if arg_kinds[lst[0]].is_optional(): + output_arg = self.coerce_nullable(base_arg, arg.type, line) + else: + output_arg = self.coerce(base_arg, arg.type, line) + + output_args.append(output_arg) return output_args @@ -479,13 +707,11 @@ def gen_method_call(self, arg_values: List[Value], result_type: Optional[RType], line: int, - arg_kinds: Optional[List[int]] = None, + arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[List[Optional[str]]] = None) -> Value: """Generate either a native or Python method call.""" - # If arg_kinds contains values other than arg_pos and arg_named, then fallback to - # Python method call. - if (arg_kinds is not None - and not all(kind in (ARG_POS, ARG_NAMED) for kind in arg_kinds)): + # If we have *args, then fallback to Python method call. + if arg_kinds is not None and any(kind.is_star() for kind in arg_kinds): return self.py_method_call(base, name, arg_values, base.line, arg_kinds, arg_names) # If the base type is one of ours, do a MethodCall @@ -530,7 +756,7 @@ def union_method_call(self, arg_values: List[Value], return_rtype: Optional[RType], line: int, - arg_kinds: Optional[List[int]], + arg_kinds: Optional[List[ArgKind]], arg_names: Optional[List[Optional[str]]]) -> Value: """Generate a method call with a union type for the object.""" # Union method call needs a return_rtype for the type of the output register. @@ -551,7 +777,7 @@ def none(self) -> Value: def true(self) -> Value: """Load unboxed True value (type: bool_rprimitive).""" - return Integer(1, bool_rprimitive) + return Integer(1, bool_rprimitive) def false(self) -> Value: """Load unboxed False value (type: bool_rprimitive).""" @@ -563,7 +789,7 @@ def none_object(self) -> Value: def load_int(self, value: int) -> Value: """Load a tagged (Python) integer literal value.""" - if abs(value) > MAX_LITERAL_SHORT_INT: + if value > MAX_LITERAL_SHORT_INT or value < MIN_LITERAL_SHORT_INT: return self.add(LoadLiteral(value, int_rprimitive)) else: return Integer(value) @@ -582,7 +808,7 @@ def load_str(self, value: str) -> Value: def load_bytes(self, value: bytes) -> Value: """Load a bytes literal value.""" - return self.add(LoadLiteral(value, object_rprimitive)) + return self.add(LoadLiteral(value, bytes_rprimitive)) def load_complex(self, value: complex) -> Value: """Load a complex literal value.""" @@ -618,11 +844,7 @@ def load_native_type_object(self, fullname: str) -> Value: return self.add(LoadStatic(object_rprimitive, name, module, NAMESPACE_TYPE)) # Other primitive operations - def binary_op(self, - lreg: Value, - rreg: Value, - op: str, - line: int) -> Value: + def binary_op(self, lreg: Value, rreg: Value, op: str, line: int) -> Value: ltype = lreg.type rtype = rreg.type @@ -639,8 +861,12 @@ def binary_op(self, # Special case various ops if op in ('is', 'is not'): return self.translate_is_op(lreg, rreg, op, line) + # TODO: modify 'str' to use same interface as 'compare_bytes' as it avoids + # call to PyErr_Occurred() if is_str_rprimitive(ltype) and is_str_rprimitive(rtype) and op in ('==', '!='): return self.compare_strings(lreg, rreg, op, line) + if is_bytes_rprimitive(ltype) and is_bytes_rprimitive(rtype) and op in ('==', '!='): + return self.compare_bytes(lreg, rreg, op, line) if is_tagged(ltype) and is_tagged(rtype) and op in int_comparison_op_mapping: return self.compare_tagged(lreg, rreg, op, line) if is_bool_rprimitive(ltype) and is_bool_rprimitive(rtype) and op in ( @@ -781,6 +1007,12 @@ def compare_strings(self, lhs: Value, rhs: Value, op: str, line: int) -> Value: return self.add(ComparisonOp(compare_result, Integer(0, c_int_rprimitive), op_type, line)) + def compare_bytes(self, lhs: Value, rhs: Value, op: str, line: int) -> Value: + compare_result = self.call_c(bytes_compare, [lhs, rhs], line) + op_type = ComparisonOp.EQ if op == '==' else ComparisonOp.NEQ + return self.add(ComparisonOp(compare_result, + Integer(1, c_int_rprimitive), op_type, line)) + def compare_tuples(self, lhs: Value, rhs: Value, @@ -797,7 +1029,7 @@ def compare_tuples(self, return result length = len(lhs.type.types) false_assign, true_assign, out = BasicBlock(), BasicBlock(), BasicBlock() - check_blocks = [BasicBlock() for i in range(length)] + check_blocks = [BasicBlock() for _ in range(length)] lhs_items = [self.add(TupleGet(lhs, i, line)) for i in range(length)] rhs_items = [self.add(TupleGet(rhs, i, line)) for i in range(length)] @@ -857,20 +1089,30 @@ def unary_not(self, return self.int_op(value.type, value, mask, IntOp.XOR, line) def unary_op(self, - lreg: Value, + value: Value, expr_op: str, line: int) -> Value: - if (is_bool_rprimitive(lreg.type) or is_bit_rprimitive(lreg.type)) and expr_op == 'not': - return self.unary_not(lreg, line) + typ = value.type + if (is_bool_rprimitive(typ) or is_bit_rprimitive(typ)) and expr_op == 'not': + return self.unary_not(value, line) + if isinstance(typ, RInstance): + if expr_op == '-': + method = '__neg__' + elif expr_op == '~': + method = '__invert__' + else: + method = '' + if method and typ.class_ir.has_method(method): + return self.gen_method_call(value, method, [], None, line) call_c_ops_candidates = unary_ops.get(expr_op, []) - target = self.matching_call_c(call_c_ops_candidates, [lreg], line) + target = self.matching_call_c(call_c_ops_candidates, [value], line) assert target, 'Unsupported unary operation: %s' % expr_op return target def make_dict(self, key_value_pairs: Sequence[DictEntry], line: int) -> Value: - result = None # type: Union[Value, None] - keys = [] # type: List[Value] - values = [] # type: List[Value] + result: Optional[Value] = None + keys: List[Value] = [] + values: List[Value] = [] for key, value in key_value_pairs: if key is not None: # key:value @@ -916,8 +1158,15 @@ def new_list_op_with_length(self, length: Value, line: int) -> Value: return self.call_c(new_list_op, [length], line) def new_list_op(self, values: List[Value], line: int) -> Value: - length = Integer(len(values), c_pyssize_t_rprimitive, line) - result_list = self.call_c(new_list_op, [length], line) + length: List[Value] = [Integer(len(values), c_pyssize_t_rprimitive, line)] + if len(values) >= LIST_BUILDING_EXPANSION_THRESHOLD: + return self.call_c(list_build_op, length + values, line) + + # If the length of the list is less than the threshold, + # LIST_BUILDING_EXPANSION_THRESHOLD, we directly expand the + # for-loop and inline the SetMem operation, which is faster + # than list_build_op, however generates more code. + result_list = self.call_c(new_list_op, length, line) if len(values) == 0: return result_list args = [self.coerce(item, object_rprimitive, line) for item in values] @@ -937,15 +1186,6 @@ def new_list_op(self, values: List[Value], line: int) -> Value: def new_set_op(self, values: List[Value], line: int) -> Value: return self.call_c(new_set_op, values, line) - def builtin_call(self, - args: List[Value], - fn_op: str, - line: int) -> Value: - call_c_ops_candidates = function_ops.get(fn_op, []) - target = self.matching_call_c(call_c_ops_candidates, args, line) - assert target, 'Unsupported builtin function: %s' % fn_op - return target - def shortcircuit_helper(self, op: str, expr_type: RType, left: Callable[[], Value], @@ -953,7 +1193,7 @@ def shortcircuit_helper(self, op: str, # Having actual Phi nodes would be really nice here! target = Register(expr_type) # left_body takes the value of the left side, right_body the right - left_body, right_body, next = BasicBlock(), BasicBlock(), BasicBlock() + left_body, right_body, next_block = BasicBlock(), BasicBlock(), BasicBlock() # true_body is taken if the left is true, false_body if it is false. # For 'and' the value is the right side if the left is true, and for 'or' # it is the right side if the left is false. @@ -966,15 +1206,15 @@ def shortcircuit_helper(self, op: str, self.activate_block(left_body) left_coerced = self.coerce(left_value, expr_type, line) self.add(Assign(target, left_coerced)) - self.goto(next) + self.goto(next_block) self.activate_block(right_body) right_value = right() right_coerced = self.coerce(right_value, expr_type, line) self.add(Assign(target, right_coerced)) - self.goto(next) + self.goto(next_block) - self.activate_block(next) + self.activate_block(next_block) return target def add_bool_branch(self, value: Value, true: BasicBlock, false: BasicBlock) -> None: @@ -1083,9 +1323,7 @@ def matching_call_c(self, args: List[Value], line: int, result_type: Optional[RType] = None) -> Optional[Value]: - # TODO: this function is very similar to matching_primitive_op - # we should remove the old one or refactor both them into only as we move forward - matching = None # type: Optional[CFunctionDescription] + matching: Optional[CFunctionDescription] = None for desc in candidates: if len(desc.arg_types) != len(args): continue @@ -1116,32 +1354,29 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val Return c_pyssize_t if use_pyssize_t is true (unshifted). """ typ = val.type - if is_list_rprimitive(typ) or is_tuple_rprimitive(typ): + size_value = None + if (is_list_rprimitive(typ) or is_tuple_rprimitive(typ) + or is_bytes_rprimitive(typ)): elem_address = self.add(GetElementPtr(val, PyVarObject, 'ob_size')) size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address)) self.add(KeepAlive([val])) - if use_pyssize_t: - return size_value - offset = Integer(1, c_pyssize_t_rprimitive, line) - return self.int_op(short_int_rprimitive, size_value, offset, - IntOp.LEFT_SHIFT, line) - elif is_dict_rprimitive(typ): - size_value = self.call_c(dict_size_op, [val], line) - if use_pyssize_t: - return size_value - offset = Integer(1, c_pyssize_t_rprimitive, line) - return self.int_op(short_int_rprimitive, size_value, offset, - IntOp.LEFT_SHIFT, line) elif is_set_rprimitive(typ): elem_address = self.add(GetElementPtr(val, PySetObject, 'used')) size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address)) self.add(KeepAlive([val])) + elif is_dict_rprimitive(typ): + size_value = self.call_c(dict_ssize_t_size_op, [val], line) + elif is_str_rprimitive(typ): + size_value = self.call_c(str_ssize_t_size_op, [val], line) + + if size_value is not None: if use_pyssize_t: return size_value offset = Integer(1, c_pyssize_t_rprimitive, line) return self.int_op(short_int_rprimitive, size_value, offset, IntOp.LEFT_SHIFT, line) - elif isinstance(typ, RInstance): + + if isinstance(typ, RInstance): # TODO: Support use_pyssize_t assert not use_pyssize_t length = self.gen_method_call(val, '__len__', [], int_rprimitive, line) @@ -1155,15 +1390,15 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val self.add(Unreachable()) self.activate_block(ok) return length + + # generic case + if use_pyssize_t: + return self.call_c(generic_ssize_t_len_op, [val], line) else: - # generic case - if use_pyssize_t: - return self.call_c(generic_ssize_t_len_op, [val], line) - else: - return self.call_c(generic_len_op, [val], line) + return self.call_c(generic_len_op, [val], line) def new_tuple(self, items: List[Value], line: int) -> Value: - size = Integer(len(items), c_pyssize_t_rprimitive) # type: Value + size: Value = Integer(len(items), c_pyssize_t_rprimitive) return self.call_c(new_tuple_op, [size] + items, line) def new_tuple_with_length(self, length: Value, line: int) -> Value: @@ -1329,7 +1564,7 @@ def _create_dict(self, # keys and values should have the same number of items size = len(keys) if size > 0: - size_value = Integer(size, c_pyssize_t_rprimitive) # type: Value + size_value: Value = Integer(size, c_pyssize_t_rprimitive) # merge keys and values items = [i for t in list(zip(keys, values)) for i in t] return self.call_c(dict_build_op, [size_value] + items, line) @@ -1337,7 +1572,7 @@ def _create_dict(self, return self.call_c(dict_new_op, [], line) -def num_positional_args(arg_values: List[Value], arg_kinds: Optional[List[int]]) -> int: +def num_positional_args(arg_values: List[Value], arg_kinds: Optional[List[ArgKind]]) -> int: if arg_kinds is None: return len(arg_values) num_pos = 0 diff --git a/mypyc/irbuild/main.py b/mypyc/irbuild/main.py index 457b535cdbfe..b86b6f2dd3c1 100644 --- a/mypyc/irbuild/main.py +++ b/mypyc/irbuild/main.py @@ -20,7 +20,7 @@ def f(x: int) -> int: below, mypyc.irbuild.builder, and mypyc.irbuild.visitor. """ -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from typing import List, Dict, Callable, Any, TypeVar, cast from mypy.nodes import MypyFile, Expression, ClassDef @@ -36,7 +36,7 @@ def f(x: int) -> int: from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature from mypyc.irbuild.prebuildvisitor import PreBuildVisitor from mypyc.irbuild.vtable import compute_vtable -from mypyc.irbuild.prepare import build_type_map +from mypyc.irbuild.prepare import build_type_map, find_singledispatch_register_impls from mypyc.irbuild.builder import IRBuilder from mypyc.irbuild.visitor import IRBuilderVisitor from mypyc.irbuild.mapper import Mapper @@ -58,21 +58,23 @@ def build_ir(modules: List[MypyFile], """Build IR for a set of modules that have been type-checked by mypy.""" build_type_map(mapper, modules, graph, types, options, errors) + singledispatch_info = find_singledispatch_register_impls(modules, errors) - result = OrderedDict() # type: ModuleIRs + result: ModuleIRs = OrderedDict() # Generate IR for all modules. class_irs = [] for module in modules: # First pass to determine free symbols. - pbv = PreBuildVisitor() + pbv = PreBuildVisitor(errors, module, singledispatch_info.decorators_to_remove) module.accept(pbv) # Construct and configure builder objects (cyclic runtime dependency). visitor = IRBuilderVisitor() builder = IRBuilder( - module.fullname, types, graph, errors, mapper, pbv, visitor, options + module.fullname, types, graph, errors, mapper, pbv, visitor, options, + singledispatch_info.singledispatch_impls, ) visitor.builder = builder @@ -121,6 +123,7 @@ def transform_mypy_file(builder: IRBuilder, mypyfile: MypyFile) -> None: # Generate ops. for node in mypyfile.defs: builder.accept(node) + builder.maybe_add_implicit_return() # Generate special function representing module top level. diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 5b2521d2e76c..901ea49fc2fa 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -2,7 +2,7 @@ from typing import Dict, Optional -from mypy.nodes import FuncDef, TypeInfo, SymbolNode, ARG_STAR, ARG_STAR2 +from mypy.nodes import FuncDef, TypeInfo, SymbolNode, ArgKind, ARG_STAR, ARG_STAR2 from mypy.types import ( Instance, Type, CallableType, LiteralType, TypedDictType, UnboundType, PartialType, UninhabitedType, Overloaded, UnionType, TypeType, AnyType, NoneTyp, TupleType, TypeVarType, @@ -12,7 +12,7 @@ from mypyc.ir.rtypes import ( RType, RUnion, RTuple, RInstance, object_rprimitive, dict_rprimitive, tuple_rprimitive, none_rprimitive, int_rprimitive, float_rprimitive, str_rprimitive, bool_rprimitive, - list_rprimitive, set_rprimitive + list_rprimitive, set_rprimitive, range_rprimitive, bytes_rprimitive ) from mypyc.ir.func_ir import FuncSignature, FuncDecl, RuntimeArg from mypyc.ir.class_ir import ClassIR @@ -30,8 +30,8 @@ class Mapper: def __init__(self, group_map: Dict[str, Optional[str]]) -> None: self.group_map = group_map - self.type_to_ir = {} # type: Dict[TypeInfo, ClassIR] - self.func_to_decl = {} # type: Dict[SymbolNode, FuncDecl] + self.type_to_ir: Dict[TypeInfo, ClassIR] = {} + self.func_to_decl: Dict[SymbolNode, FuncDecl] = {} def type_to_rtype(self, typ: Optional[Type]) -> RType: if typ is None: @@ -43,10 +43,12 @@ def type_to_rtype(self, typ: Optional[Type]) -> RType: return int_rprimitive elif typ.type.fullname == 'builtins.float': return float_rprimitive - elif typ.type.fullname == 'builtins.str': - return str_rprimitive elif typ.type.fullname == 'builtins.bool': return bool_rprimitive + elif typ.type.fullname == 'builtins.str': + return str_rprimitive + elif typ.type.fullname == 'builtins.bytes': + return bytes_rprimitive elif typ.type.fullname == 'builtins.list': return list_rprimitive # Dict subclasses are at least somewhat common and we @@ -58,6 +60,8 @@ def type_to_rtype(self, typ: Optional[Type]) -> RType: return set_rprimitive elif typ.type.fullname == 'builtins.tuple': return tuple_rprimitive # Varying-length tuple + elif typ.type.fullname == 'builtins.range': + return range_rprimitive elif typ.type in self.type_to_ir: inst = RInstance(self.type_to_ir[typ.type]) # Treat protocols as Union[protocol, object], so that we can do fast @@ -108,7 +112,7 @@ def type_to_rtype(self, typ: Optional[Type]) -> RType: # actually show up, so anything else is a bug somewhere. assert False, 'unexpected type %s' % type(typ) - def get_arg_rtype(self, typ: Type, kind: int) -> RType: + def get_arg_rtype(self, typ: Type, kind: ArgKind) -> RType: if kind == ARG_STAR: return tuple_rprimitive elif kind == ARG_STAR2: @@ -120,10 +124,12 @@ def fdef_to_sig(self, fdef: FuncDef) -> FuncSignature: if isinstance(fdef.type, CallableType): arg_types = [self.get_arg_rtype(typ, kind) for typ, kind in zip(fdef.type.arg_types, fdef.type.arg_kinds)] + arg_pos_onlys = [name is None for name in fdef.type.arg_names] ret = self.type_to_rtype(fdef.type.ret_type) else: # Handle unannotated functions arg_types = [object_rprimitive for arg in fdef.arguments] + arg_pos_onlys = [arg.pos_only for arg in fdef.arguments] # We at least know the return type for __init__ methods will be None. is_init_method = fdef.name == '__init__' and bool(fdef.info) if is_init_method: @@ -131,8 +137,22 @@ def fdef_to_sig(self, fdef: FuncDef) -> FuncSignature: else: ret = object_rprimitive - args = [RuntimeArg(arg_name, arg_type, arg_kind) - for arg_name, arg_kind, arg_type in zip(fdef.arg_names, fdef.arg_kinds, arg_types)] + # mypyc FuncSignatures (unlike mypy types) want to have a name + # present even when the argument is position only, since it is + # the sole way that FuncDecl arguments are tracked. This is + # generally fine except in some cases (like for computing + # init_sig) we need to produce FuncSignatures from a + # deserialized FuncDef that lacks arguments. We won't ever + # need to use those inside of a FuncIR, so we just make up + # some crap. + if hasattr(fdef, 'arguments'): + arg_names = [arg.variable.name for arg in fdef.arguments] + else: + arg_names = [name or '' for name in fdef.arg_names] + + args = [RuntimeArg(arg_name, arg_type, arg_kind, arg_pos_only) + for arg_name, arg_kind, arg_type, arg_pos_only + in zip(arg_names, fdef.arg_kinds, arg_types, arg_pos_onlys)] # We force certain dunder methods to return objects to support letting them # return NotImplemented. It also avoids some pointless boxing and unboxing, diff --git a/mypyc/irbuild/nonlocalcontrol.py b/mypyc/irbuild/nonlocalcontrol.py index 27ec7e36eb6d..e2dcbec8fbc3 100644 --- a/mypyc/irbuild/nonlocalcontrol.py +++ b/mypyc/irbuild/nonlocalcontrol.py @@ -132,7 +132,7 @@ class TryFinallyNonlocalControl(NonlocalControl): def __init__(self, target: BasicBlock) -> None: self.target = target - self.ret_reg = None # type: Optional[Register] + self.ret_reg: Optional[Register] = None def gen_break(self, builder: 'IRBuilder', line: int) -> None: builder.error("break inside try/finally block is unimplemented", line) @@ -176,14 +176,6 @@ def __init__(self, outer: NonlocalControl, ret_reg: Optional[Value], saved: Valu self.saved = saved def gen_cleanup(self, builder: 'IRBuilder', line: int) -> None: - # Do an error branch on the return value register, which - # may be undefined. This will allow it to be properly - # decrefed if it is not null. This is kind of a hack. - if self.ret_reg: - target = BasicBlock() - builder.add(Branch(self.ret_reg, target, target, Branch.IS_ERROR)) - builder.activate_block(target) - # Restore the old exc_info target, cleanup = BasicBlock(), BasicBlock() builder.add(Branch(self.saved, target, cleanup, Branch.IS_ERROR)) diff --git a/mypyc/irbuild/prebuildvisitor.py b/mypyc/irbuild/prebuildvisitor.py index 9050920813b2..55928a57b839 100644 --- a/mypyc/irbuild/prebuildvisitor.py +++ b/mypyc/irbuild/prebuildvisitor.py @@ -1,7 +1,9 @@ +from mypyc.errors import Errors from typing import Dict, List, Set from mypy.nodes import ( - Decorator, Expression, FuncDef, FuncItem, LambdaExpr, NameExpr, SymbolNode, Var, MemberExpr + Decorator, Expression, FuncDef, FuncItem, LambdaExpr, NameExpr, SymbolNode, Var, MemberExpr, + MypyFile ) from mypy.traverser import TraverserVisitor @@ -20,35 +22,47 @@ class PreBuildVisitor(TraverserVisitor): The main IR build pass uses this information. """ - def __init__(self) -> None: + def __init__( + self, + errors: Errors, + current_file: MypyFile, + decorators_to_remove: Dict[FuncDef, List[int]], + ) -> None: super().__init__() # Dict from a function to symbols defined directly in the # function that are used as non-local (free) variables within a # nested function. - self.free_variables = {} # type: Dict[FuncItem, Set[SymbolNode]] + self.free_variables: Dict[FuncItem, Set[SymbolNode]] = {} # Intermediate data structure used to find the function where # a SymbolNode is declared. Initially this may point to a # function nested inside the function with the declaration, # but we'll eventually update this to refer to the function # with the declaration. - self.symbols_to_funcs = {} # type: Dict[SymbolNode, FuncItem] + self.symbols_to_funcs: Dict[SymbolNode, FuncItem] = {} # Stack representing current function nesting. - self.funcs = [] # type: List[FuncItem] + self.funcs: List[FuncItem] = [] # All property setters encountered so far. - self.prop_setters = set() # type: Set[FuncDef] + self.prop_setters: Set[FuncDef] = set() # A map from any function that contains nested functions to # a set of all the functions that are nested within it. - self.encapsulating_funcs = {} # type: Dict[FuncItem, List[FuncItem]] + self.encapsulating_funcs: Dict[FuncItem, List[FuncItem]] = {} # Map nested function to its parent/encapsulating function. - self.nested_funcs = {} # type: Dict[FuncItem, FuncItem] + self.nested_funcs: Dict[FuncItem, FuncItem] = {} # Map function to its non-special decorators. - self.funcs_to_decorators = {} # type: Dict[FuncDef, List[Expression]] + self.funcs_to_decorators: Dict[FuncDef, List[Expression]] = {} + + # Map function to indices of decorators to remove + self.decorators_to_remove: Dict[FuncDef, List[int]] = decorators_to_remove + + self.errors: Errors = errors + + self.current_file: MypyFile = current_file def visit_decorator(self, dec: Decorator) -> None: if dec.decorators: @@ -63,7 +77,18 @@ def visit_decorator(self, dec: Decorator) -> None: # Property setters are not treated as decorated methods. self.prop_setters.add(dec.func) else: - self.funcs_to_decorators[dec.func] = dec.decorators + decorators_to_store = dec.decorators.copy() + if dec.func in self.decorators_to_remove: + to_remove = self.decorators_to_remove[dec.func] + + for i in reversed(to_remove): + del decorators_to_store[i] + # if all of the decorators are removed, we shouldn't treat this as a decorated + # function because there aren't any decorators to apply + if not decorators_to_store: + return + + self.funcs_to_decorators[dec.func] = decorators_to_store super().visit_decorator(dec) def visit_func_def(self, fdef: FuncItem) -> None: diff --git a/mypyc/irbuild/prepare.py b/mypyc/irbuild/prepare.py index 4ac752f22f5f..3f028d900943 100644 --- a/mypyc/irbuild/prepare.py +++ b/mypyc/irbuild/prepare.py @@ -11,13 +11,14 @@ Also build a mapping from mypy TypeInfos to ClassIR objects. """ -from typing import List, Dict, Iterable, Optional, Union +from typing import List, Dict, Iterable, Optional, Union, DefaultDict, NamedTuple, Tuple from mypy.nodes import ( - MypyFile, TypeInfo, FuncDef, ClassDef, Decorator, OverloadedFuncDef, MemberExpr, Var, - Expression, SymbolNode, ARG_STAR, ARG_STAR2 + ClassDef, OverloadedFuncDef, Var, + SymbolNode, ARG_STAR, ARG_STAR2, CallExpr, Decorator, Expression, FuncDef, + MemberExpr, MypyFile, NameExpr, RefExpr, TypeInfo ) -from mypy.types import Type +from mypy.types import Type, Instance, get_proper_type from mypy.build import Graph from mypyc.ir.ops import DeserMaps @@ -26,7 +27,7 @@ FuncDecl, FuncSignature, RuntimeArg, FUNC_NORMAL, FUNC_STATICMETHOD, FUNC_CLASSMETHOD ) from mypyc.ir.class_ir import ClassIR -from mypyc.common import PROPSET_PREFIX +from mypyc.common import PROPSET_PREFIX, get_id_from_name from mypyc.irbuild.mapper import Mapper from mypyc.irbuild.util import ( get_func_def, is_dataclass, is_trait, is_extension_class, get_mypyc_attrs @@ -34,6 +35,9 @@ from mypyc.errors import Errors from mypyc.options import CompilerOptions from mypyc.crash import catch_errors +from collections import defaultdict +from mypy.traverser import TraverserVisitor +from mypy.semanal import refers_to_fullname def build_type_map(mapper: Mapper, @@ -54,6 +58,8 @@ def build_type_map(mapper: Mapper, class_ir = ClassIR(cdef.name, module.fullname, is_trait(cdef), is_abstract=cdef.info.is_abstract) class_ir.is_ext_class = is_extension_class(cdef) + if class_ir.is_ext_class: + class_ir.deletable = cdef.info.deletable_attributes[:] # If global optimizations are disabled, turn of tracking of class children if not options.global_opts: class_ir.children = None @@ -93,7 +99,8 @@ def load_type_map(mapper: 'Mapper', for module in modules: for func in get_module_func_defs(module): - mapper.func_to_decl[func] = deser_ctx.functions[func.fullname].decl + func_id = get_id_from_name(func.name, func.fullname, func.line) + mapper.func_to_decl[func] = deser_ctx.functions[func_id].decl def get_module_func_defs(module: MypyFile) -> Iterable[FuncDef]: @@ -157,8 +164,8 @@ def can_subclass_builtin(builtin_base: str) -> bool: # BaseException and dict are special cased. return builtin_base in ( ('builtins.Exception', 'builtins.LookupError', 'builtins.IndexError', - 'builtins.Warning', 'builtins.UserWarning', 'builtins.ValueError', - 'builtins.object', )) + 'builtins.Warning', 'builtins.UserWarning', 'builtins.ValueError', + 'builtins.object', )) def prepare_class_def(path: str, module_name: str, cdef: ClassDef, @@ -179,7 +186,7 @@ def prepare_class_def(path: str, module_name: str, cdef: ClassDef, if isinstance(node.node, Var): assert node.node.type, "Class member %s missing type" % name - if not node.node.is_classvar and name != '__slots__': + if not node.node.is_classvar and name not in ('__slots__', '__deletable__'): ir.attributes[name] = mapper.type_to_rtype(node.node.type) elif isinstance(node.node, (FuncDef, Decorator)): prepare_method_def(ir, module_name, cdef, mapper, node.node) @@ -300,3 +307,119 @@ def prepare_non_ext_class_def(path: str, module_name: str, cdef: ClassDef, ): errors.error( "Non-extension classes may not inherit from extension classes", path, cdef.line) + + +RegisterImplInfo = Tuple[TypeInfo, FuncDef] + + +class SingledispatchInfo(NamedTuple): + singledispatch_impls: Dict[FuncDef, List[RegisterImplInfo]] + decorators_to_remove: Dict[FuncDef, List[int]] + + +def find_singledispatch_register_impls( + modules: List[MypyFile], + errors: Errors, +) -> SingledispatchInfo: + visitor = SingledispatchVisitor(errors) + for module in modules: + visitor.current_path = module.path + module.accept(visitor) + return SingledispatchInfo(visitor.singledispatch_impls, visitor.decorators_to_remove) + + +class SingledispatchVisitor(TraverserVisitor): + current_path: str + + def __init__(self, errors: Errors) -> None: + super().__init__() + + # Map of main singledispatch function to list of registered implementations + self.singledispatch_impls: DefaultDict[FuncDef, List[RegisterImplInfo]] = defaultdict(list) + + # Map of decorated function to the indices of any decorators to remove + self.decorators_to_remove: Dict[FuncDef, List[int]] = {} + + self.errors: Errors = errors + + def visit_decorator(self, dec: Decorator) -> None: + if dec.decorators: + decorators_to_store = dec.decorators.copy() + decorators_to_remove: List[int] = [] + # the index of the last non-register decorator before finding a register decorator + # when going through decorators from top to bottom + last_non_register: Optional[int] = None + for i, d in enumerate(decorators_to_store): + impl = get_singledispatch_register_call_info(d, dec.func) + if impl is not None: + self.singledispatch_impls[impl.singledispatch_func].append( + (impl.dispatch_type, dec.func)) + decorators_to_remove.append(i) + if last_non_register is not None: + # found a register decorator after a non-register decorator, which we + # don't support because we'd have to make a copy of the function before + # calling the decorator so that we can call it later, which complicates + # the implementation for something that is probably not commonly used + self.errors.error( + "Calling decorator after registering function not supported", + self.current_path, + decorators_to_store[last_non_register].line, + ) + else: + if refers_to_fullname(d, 'functools.singledispatch'): + decorators_to_remove.append(i) + # make sure that we still treat the function as a singledispatch function + # even if we don't find any registered implementations (which might happen + # if all registered implementations are registered dynamically) + self.singledispatch_impls.setdefault(dec.func, []) + last_non_register = i + + if decorators_to_remove: + # calling register on a function that tries to dispatch based on type annotations + # raises a TypeError because compiled functions don't have an __annotations__ + # attribute + self.decorators_to_remove[dec.func] = decorators_to_remove + + super().visit_decorator(dec) + + +class RegisteredImpl(NamedTuple): + singledispatch_func: FuncDef + dispatch_type: TypeInfo + + +def get_singledispatch_register_call_info(decorator: Expression, func: FuncDef + ) -> Optional[RegisteredImpl]: + # @fun.register(complex) + # def g(arg): ... + if (isinstance(decorator, CallExpr) and len(decorator.args) == 1 + and isinstance(decorator.args[0], RefExpr)): + callee = decorator.callee + dispatch_type = decorator.args[0].node + if not isinstance(dispatch_type, TypeInfo): + return None + + if isinstance(callee, MemberExpr): + return registered_impl_from_possible_register_call(callee, dispatch_type) + # @fun.register + # def g(arg: int): ... + elif isinstance(decorator, MemberExpr): + # we don't know if this is a register call yet, so we can't be sure that the function + # actually has arguments + if not func.arguments: + return None + arg_type = get_proper_type(func.arguments[0].variable.type) + if not isinstance(arg_type, Instance): + return None + info = arg_type.type + return registered_impl_from_possible_register_call(decorator, info) + return None + + +def registered_impl_from_possible_register_call(expr: MemberExpr, dispatch_type: TypeInfo + ) -> Optional[RegisteredImpl]: + if expr.name == 'register' and isinstance(expr.expr, NameExpr): + node = expr.expr.node + if isinstance(node, Decorator): + return RegisteredImpl(node.func, dispatch_type) + return None diff --git a/mypyc/irbuild/specialize.py b/mypyc/irbuild/specialize.py index ef2986cda0b1..d35039ecc0bc 100644 --- a/mypyc/irbuild/specialize.py +++ b/mypyc/irbuild/specialize.py @@ -14,7 +14,10 @@ from typing import Callable, Optional, Dict, Tuple, List -from mypy.nodes import CallExpr, RefExpr, MemberExpr, TupleExpr, GeneratorExpr, ARG_POS +from mypy.nodes import ( + CallExpr, RefExpr, MemberExpr, NameExpr, TupleExpr, GeneratorExpr, + ListExpr, DictExpr, StrExpr, IntExpr, ARG_POS, ARG_NAMED, Expression +) from mypy.types import AnyType, TypeOfAny from mypyc.ir.ops import ( @@ -22,9 +25,14 @@ ) from mypyc.ir.rtypes import ( RType, RTuple, str_rprimitive, list_rprimitive, dict_rprimitive, set_rprimitive, - bool_rprimitive, is_dict_rprimitive + bool_rprimitive, c_int_rprimitive, is_dict_rprimitive +) +from mypyc.irbuild.format_str_tokenizer import ( + tokenizer_format_call, join_formatted_strings, convert_format_expr_to_str, FormatOp +) +from mypyc.primitives.dict_ops import ( + dict_keys_op, dict_values_op, dict_items_op, dict_setdefault_spec_init_op ) -from mypyc.primitives.dict_ops import dict_keys_op, dict_values_op, dict_items_op from mypyc.primitives.list_ops import new_list_set_item_op from mypyc.primitives.tuple_ops import new_tuple_set_item_op from mypyc.irbuild.builder import IRBuilder @@ -33,7 +41,6 @@ comprehension_helper, sequence_from_generator_preallocate_helper ) - # Specializers are attempted before compiling the arguments to the # function. Specializers can return None to indicate that they failed # and the call should be compiled normally. Otherwise they should emit @@ -47,25 +54,55 @@ # # Specializers can operate on methods as well, and are keyed on the # name and RType in that case. -specializers = {} # type: Dict[Tuple[str, Optional[RType]], List[Specializer]] +specializers: Dict[Tuple[str, Optional[RType]], List[Specializer]] = {} + + +def _apply_specialization(builder: 'IRBuilder', expr: CallExpr, callee: RefExpr, + name: Optional[str], typ: Optional[RType] = None) -> Optional[Value]: + # TODO: Allow special cases to have default args or named args. Currently they don't since + # they check that everything in arg_kinds is ARG_POS. + + # If there is a specializer for this function, try calling it. + # Return the first successful one. + if name and (name, typ) in specializers: + for specializer in specializers[name, typ]: + val = specializer(builder, expr, callee) + if val is not None: + return val + return None + + +def apply_function_specialization(builder: 'IRBuilder', expr: CallExpr, + callee: RefExpr) -> Optional[Value]: + """Invoke the Specializer callback for a function if one has been registered""" + return _apply_specialization(builder, expr, callee, callee.fullname) + + +def apply_method_specialization(builder: 'IRBuilder', expr: CallExpr, callee: MemberExpr, + typ: Optional[RType] = None) -> Optional[Value]: + """Invoke the Specializer callback for a method if one has been registered""" + name = callee.fullname if typ is None else callee.name + return _apply_specialization(builder, expr, callee, name, typ) def specialize_function( name: str, typ: Optional[RType] = None) -> Callable[[Specializer], Specializer]: """Decorator to register a function as being a specializer. - There may exist multiple specializers for one function. When translating method - calls, the earlier appended specializer has higher priority. + There may exist multiple specializers for one function. When + translating method calls, the earlier appended specializer has + higher priority. """ + def wrapper(f: Specializer) -> Specializer: specializers.setdefault((name, typ), []).append(f) return f + return wrapper @specialize_function('builtins.globals') def translate_globals(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case builtins.globals if len(expr.args) == 0: return builder.load_globals_dict() return None @@ -74,13 +111,12 @@ def translate_globals(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Op @specialize_function('builtins.len') def translate_len( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case builtins.len if (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]): expr_rtype = builder.node_type(expr.args[0]) if isinstance(expr_rtype, RTuple): - # len() of fixed-length tuple can be trivially determined statically, - # though we still need to evaluate it. + # len() of fixed-length tuple can be trivially determined + # statically, though we still need to evaluate it. builder.accept(expr.args[0]) return Integer(len(expr_rtype.types)) else: @@ -92,8 +128,12 @@ def translate_len( @specialize_function('builtins.list') def dict_methods_fast_path( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Specialize a common case when list() is called on a dictionary view - # method call, for example foo = list(bar.keys()). + """Specialize a common case when list() is called on a dictionary + view method call. + + For example: + foo = list(bar.keys()) + """ if not (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]): return None arg = expr.args[0] @@ -107,8 +147,9 @@ def dict_methods_fast_path( return None obj = builder.accept(base) - # Note that it is not safe to use fast methods on dict subclasses, so - # the corresponding helpers in CPy.h fallback to (inlined) generic logic. + # Note that it is not safe to use fast methods on dict subclasses, + # so the corresponding helpers in CPy.h fallback to (inlined) + # generic logic. if attr == 'keys': return builder.call_c(dict_keys_op, [obj], expr.line) elif attr == 'values': @@ -120,9 +161,13 @@ def dict_methods_fast_path( @specialize_function('builtins.list') def translate_list_from_generator_call( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case for simplest list comprehension, for example - # list(f(x) for x in other_list/other_tuple) - # translate_list_comprehension() would take care of other cases if this fails. + """Special case for simplest list comprehension. + + For example: + list(f(x) for x in some_list/some_tuple/some_str) + 'translate_list_comprehension()' would take care of other cases + if this fails. + """ if (len(expr.args) == 1 and expr.arg_kinds[0] == ARG_POS and isinstance(expr.args[0], GeneratorExpr)): @@ -136,9 +181,13 @@ def translate_list_from_generator_call( @specialize_function('builtins.tuple') def translate_tuple_from_generator_call( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case for simplest tuple creation from a generator, for example - # tuple(f(x) for x in other_list/other_tuple) - # translate_safe_generator_call() would take care of other cases if this fails. + """Special case for simplest tuple creation from a generator. + + For example: + tuple(f(x) for x in some_list/some_tuple/some_str) + 'translate_safe_generator_call()' would take care of other cases + if this fails. + """ if (len(expr.args) == 1 and expr.arg_kinds[0] == ARG_POS and isinstance(expr.args[0], GeneratorExpr)): @@ -152,8 +201,11 @@ def translate_tuple_from_generator_call( @specialize_function('builtins.set') def translate_set_from_generator_call( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case for set creation from a generator: - # set(f(...) for ... in iterator/nested_generators...) + """Special case for set creation from a generator. + + For example: + set(f(...) for ... in iterator/nested_generators...) + """ if (len(expr.args) == 1 and expr.arg_kinds[0] == ARG_POS and isinstance(expr.args[0], GeneratorExpr)): @@ -161,10 +213,37 @@ def translate_set_from_generator_call( return None +@specialize_function('builtins.min') +@specialize_function('builtins.max') +def faster_min_max(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + if expr.arg_kinds == [ARG_POS, ARG_POS]: + x, y = builder.accept(expr.args[0]), builder.accept(expr.args[1]) + result = Register(builder.node_type(expr)) + # CPython evaluates arguments reversely when calling min(...) or max(...) + if callee.fullname == 'builtins.min': + comparison = builder.binary_op(y, x, '<', expr.line) + else: + comparison = builder.binary_op(y, x, '>', expr.line) + + true_block, false_block, next_block = BasicBlock(), BasicBlock(), BasicBlock() + builder.add_bool_branch(comparison, true_block, false_block) + + builder.activate_block(true_block) + builder.assign(result, builder.coerce(y, result.type, expr.line), expr.line) + builder.goto(next_block) + + builder.activate_block(false_block) + builder.assign(result, builder.coerce(x, result.type, expr.line), expr.line) + builder.goto(next_block) + + builder.activate_block(next_block) + return result + return None + + @specialize_function('builtins.tuple') @specialize_function('builtins.frozenset') @specialize_function('builtins.dict') -@specialize_function('builtins.sum') @specialize_function('builtins.min') @specialize_function('builtins.max') @specialize_function('builtins.sorted') @@ -175,8 +254,9 @@ def translate_set_from_generator_call( @specialize_function('update', set_rprimitive) def translate_safe_generator_call( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special cases for things that consume iterators where we know we - # can safely compile a generator into a list. + """Special cases for things that consume iterators where we know we + can safely compile a generator into a list. + """ if (len(expr.args) > 0 and expr.arg_kinds[0] == ARG_POS and isinstance(expr.args[0], GeneratorExpr)): @@ -184,13 +264,13 @@ def translate_safe_generator_call( return builder.gen_method_call( builder.accept(callee.expr), callee.name, ([translate_list_comprehension(builder, expr.args[0])] - + [builder.accept(arg) for arg in expr.args[1:]]), + + [builder.accept(arg) for arg in expr.args[1:]]), builder.node_type(expr), expr.line, expr.arg_kinds, expr.arg_names) else: return builder.call_refexpr_with_args( expr, callee, ([translate_list_comprehension(builder, expr.args[0])] - + [builder.accept(arg) for arg in expr.args[1:]])) + + [builder.accept(arg) for arg in expr.args[1:]])) return None @@ -241,38 +321,74 @@ def gen_inner_stmts() -> None: return retval +@specialize_function('builtins.sum') +def translate_sum_call(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + # specialized implementation is used if: + # - only one or two arguments given (if not, sum() has been given invalid arguments) + # - first argument is a Generator (there is no benefit to optimizing the performance of eg. + # sum([1, 2, 3]), so non-Generator Iterables are not handled) + if not (len(expr.args) in (1, 2) + and expr.arg_kinds[0] == ARG_POS + and isinstance(expr.args[0], GeneratorExpr)): + return None + + # handle 'start' argument, if given + if len(expr.args) == 2: + # ensure call to sum() was properly constructed + if not expr.arg_kinds[1] in (ARG_POS, ARG_NAMED): + return None + start_expr = expr.args[1] + else: + start_expr = IntExpr(0) + + gen_expr = expr.args[0] + target_type = builder.node_type(expr) + retval = Register(target_type) + builder.assign(retval, builder.coerce(builder.accept(start_expr), target_type, -1), -1) + + def gen_inner_stmts() -> None: + call_expr = builder.accept(gen_expr.left_expr) + builder.assign(retval, builder.binary_op(retval, call_expr, '+', -1), -1) + + loop_params = list(zip(gen_expr.indices, gen_expr.sequences, gen_expr.condlists)) + comprehension_helper(builder, loop_params, gen_inner_stmts, gen_expr.line) + + return retval + + @specialize_function('dataclasses.field') +@specialize_function('attr.ib') +@specialize_function('attr.attrib') @specialize_function('attr.Factory') def translate_dataclasses_field_call( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case for 'dataclasses.field' and 'attr.Factory' function calls - # because the results of such calls are typechecked by mypy using the types - # of the arguments to their respective functions, resulting in attempted - # coercions by mypyc that throw a runtime error. + """Special case for 'dataclasses.field', 'attr.attrib', and 'attr.Factory' + function calls because the results of such calls are type-checked + by mypy using the types of the arguments to their respective + functions, resulting in attempted coercions by mypyc that throw a + runtime error. + """ builder.types[expr] = AnyType(TypeOfAny.from_error) return None @specialize_function('builtins.next') def translate_next_call(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: - # Special case for calling next() on a generator expression, an - # idiom that shows up some in mypy. - # - # For example, next(x for x in l if x.id == 12, None) will - # generate code that searches l for an element where x.id == 12 - # and produce the first such object, or None if no such element - # exists. + """Special case for calling next() on a generator expression, an + idiom that shows up some in mypy. + + For example, next(x for x in l if x.id == 12, None) will + generate code that searches l for an element where x.id == 12 + and produce the first such object, or None if no such element + exists. + """ if not (expr.arg_kinds in ([ARG_POS], [ARG_POS, ARG_POS]) and isinstance(expr.args[0], GeneratorExpr)): return None gen = expr.args[0] - retval = Register(builder.node_type(expr)) - default_val = None - if len(expr.args) > 1: - default_val = builder.accept(expr.args[1]) - + default_val = builder.accept(expr.args[1]) if len(expr.args) > 1 else None exit_block = BasicBlock() def gen_inner_stmts() -> None: @@ -300,16 +416,125 @@ def gen_inner_stmts() -> None: @specialize_function('builtins.isinstance') def translate_isinstance(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + """Special case for builtins.isinstance. + + Prevent coercions on the thing we are checking the instance of - + there is no need to coerce something to a new type before checking + what type it is, and the coercion could lead to bugs. + """ if (len(expr.args) == 2 and expr.arg_kinds == [ARG_POS, ARG_POS] and isinstance(expr.args[1], (RefExpr, TupleExpr))): - # Special case for builtins.isinstance - # Prevent coercions on the thing we are checking the instance of - there is no need to - # coerce something to a new type before checking what type it is, and the coercion could - # lead to bugs. builder.types[expr.args[0]] = AnyType(TypeOfAny.from_error) irs = builder.flatten_classes(expr.args[1]) if irs is not None: return builder.builder.isinstance_helper(builder.accept(expr.args[0]), irs, expr.line) return None + + +@specialize_function('setdefault', dict_rprimitive) +def translate_dict_setdefault( + builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + """Special case for 'dict.setdefault' which would only construct + default empty collection when needed. + + The dict_setdefault_spec_init_op checks whether the dict contains + the key and would construct the empty collection only once. + + For example, this specializer works for the following cases: + d.setdefault(key, set()).add(value) + d.setdefault(key, []).append(value) + d.setdefault(key, {})[inner_key] = inner_val + """ + if (len(expr.args) == 2 + and expr.arg_kinds == [ARG_POS, ARG_POS] + and isinstance(callee, MemberExpr)): + arg = expr.args[1] + if isinstance(arg, ListExpr): + if len(arg.items): + return None + data_type = Integer(1, c_int_rprimitive, expr.line) + elif isinstance(arg, DictExpr): + if len(arg.items): + return None + data_type = Integer(2, c_int_rprimitive, expr.line) + elif (isinstance(arg, CallExpr) and isinstance(arg.callee, NameExpr) + and arg.callee.fullname == 'builtins.set'): + if len(arg.args): + return None + data_type = Integer(3, c_int_rprimitive, expr.line) + else: + return None + + callee_dict = builder.accept(callee.expr) + key_val = builder.accept(expr.args[0]) + return builder.call_c(dict_setdefault_spec_init_op, + [callee_dict, key_val, data_type], + expr.line) + return None + + +@specialize_function('format', str_rprimitive) +def translate_str_format( + builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + if (isinstance(callee, MemberExpr) and isinstance(callee.expr, StrExpr) + and expr.arg_kinds.count(ARG_POS) == len(expr.arg_kinds)): + format_str = callee.expr.value + tokens = tokenizer_format_call(format_str) + if tokens is None: + return None + literals, format_ops = tokens + # Convert variables to strings + substitutions = convert_format_expr_to_str(builder, format_ops, expr.args, expr.line) + if substitutions is None: + return None + return join_formatted_strings(builder, literals, substitutions, expr.line) + return None + + +@specialize_function('join', str_rprimitive) +def translate_fstring( + builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: + """Special case for f-string, which is translated into str.join() + in mypy AST. + + This specializer optimizes simplest f-strings which don't contain + any format operation. + """ + if (isinstance(callee, MemberExpr) + and isinstance(callee.expr, StrExpr) and callee.expr.value == '' + and expr.arg_kinds == [ARG_POS] and isinstance(expr.args[0], ListExpr)): + for item in expr.args[0].items: + if isinstance(item, StrExpr): + continue + elif isinstance(item, CallExpr): + if (not isinstance(item.callee, MemberExpr) + or item.callee.name != 'format'): + return None + elif (not isinstance(item.callee.expr, StrExpr) + or item.callee.expr.value != '{:{}}'): + return None + + if not isinstance(item.args[1], StrExpr) or item.args[1].value != '': + return None + else: + return None + + format_ops = [] + exprs: List[Expression] = [] + + for item in expr.args[0].items: + if isinstance(item, StrExpr) and item.value != '': + format_ops.append(FormatOp.STR) + exprs.append(item) + elif isinstance(item, CallExpr): + format_ops.append(FormatOp.STR) + exprs.append(item.args[0]) + + substitutions = convert_format_expr_to_str(builder, format_ops, exprs, expr.line) + if substitutions is None: + return None + + return join_formatted_strings(builder, None, substitutions, expr.line) + return None diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index d6e85c61007b..6a744781ee50 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -20,9 +20,9 @@ Assign, Unreachable, RaiseStandardError, LoadErrorValue, BasicBlock, TupleGet, Value, Register, Branch, NO_TRACEBACK_LINE_NO ) -from mypyc.ir.rtypes import exc_rtuple +from mypyc.ir.rtypes import RInstance, exc_rtuple from mypyc.primitives.generic_ops import py_delattr_op -from mypyc.primitives.misc_ops import type_op +from mypyc.primitives.misc_ops import type_op, import_from_op from mypyc.primitives.exc_ops import ( raise_exception_op, reraise_exception_op, error_catch_op, exc_matches_op, restore_exc_info_op, get_exc_value_op, keep_propagating_op, get_exc_info_op @@ -165,28 +165,27 @@ def transform_import_from(builder: IRBuilder, node: ImportFrom) -> None: module_state = builder.graph[builder.module_name] if module_state.ancestors is not None and module_state.ancestors: module_package = module_state.ancestors[0] + elif builder.module_path.endswith("__init__.py"): + module_package = builder.module_name else: module_package = '' id = importlib.util.resolve_name('.' * node.relative + node.id, module_package) - builder.gen_import(id, node.line) - module = builder.load_module(id) + globals = builder.load_globals_dict() + imported_names = [name for name, _ in node.names] + module = builder.gen_import_from(id, globals, imported_names, node.line) # Copy everything into our module's dict. # Note that we miscompile import from inside of functions here, # since that case *shouldn't* load it into the globals dict. # This probably doesn't matter much and the code runs basically right. - globals = builder.load_globals_dict() for name, maybe_as_name in node.names: - # If one of the things we are importing is a module, - # import it as a module also. - fullname = id + '.' + name - if fullname in builder.graph or fullname in module_state.suppressed: - builder.gen_import(fullname, node.line) - as_name = maybe_as_name or name - obj = builder.py_get_attr(module, name, node.line) + obj = builder.call_c(import_from_op, + [module, builder.load_str(id), + builder.load_str(name), builder.load_str(as_name)], + node.line) builder.gen_method_call( globals, '__setitem__', [builder.load_str(as_name), obj], result_type=None, line=node.line) @@ -242,6 +241,9 @@ def transform_while_stmt(builder: IRBuilder, s: WhileStmt) -> None: def transform_for_stmt(builder: IRBuilder, s: ForStmt) -> None: + if s.is_async: + builder.error('async for is unimplemented', s.line) + def body() -> None: builder.accept(s.body) @@ -610,6 +612,9 @@ def finally_body() -> None: def transform_with_stmt(builder: IRBuilder, o: WithStmt) -> None: + if o.is_async: + builder.error('async with is unimplemented', o.line) + # Generate separate logic for each expr in it, left to right def generate(i: int) -> None: if i >= len(o.expr): @@ -658,6 +663,13 @@ def transform_del_item(builder: IRBuilder, target: AssignmentTarget, line: int) line=line ) elif isinstance(target, AssignmentTargetAttr): + if isinstance(target.obj_type, RInstance): + cl = target.obj_type.class_ir + if not cl.is_deletable(target.attr): + builder.error('"{}" cannot be deleted'.format(target.attr), line) + builder.note( + 'Using "__deletable__ = ' + + '[\'\']" in the class body enables "del obj."', line) key = builder.load_str(target.attr) builder.call_c(py_delattr_op, [target.obj, key], line) elif isinstance(target, AssignmentTargetRegister): diff --git a/mypyc/irbuild/targets.py b/mypyc/irbuild/targets.py index 67369126af9d..f6346d4fa7e7 100644 --- a/mypyc/irbuild/targets.py +++ b/mypyc/irbuild/targets.py @@ -7,7 +7,7 @@ class AssignmentTarget: """Abstract base class for assignment targets during IR building.""" - type = object_rprimitive # type: RType + type: RType = object_rprimitive class AssignmentTargetRegister(AssignmentTarget): @@ -40,7 +40,7 @@ def __init__(self, obj: Value, attr: str) -> None: self.attr = attr if isinstance(obj.type, RInstance) and obj.type.class_ir.has_attr(attr): # Native attribute reference - self.obj_type = obj.type # type: RType + self.obj_type: RType = obj.type self.type = obj.type.attr_type(attr) else: # Python attribute reference diff --git a/mypyc/irbuild/util.py b/mypyc/irbuild/util.py index 93bc4e5d3f00..7a7b95245d4c 100644 --- a/mypyc/irbuild/util.py +++ b/mypyc/irbuild/util.py @@ -4,11 +4,18 @@ from mypy.nodes import ( ClassDef, FuncDef, Decorator, OverloadedFuncDef, StrExpr, CallExpr, RefExpr, Expression, - IntExpr, FloatExpr, Var, TupleExpr, UnaryExpr, BytesExpr, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, - ARG_OPT, GDEF + IntExpr, FloatExpr, Var, NameExpr, TupleExpr, UnaryExpr, BytesExpr, + ArgKind, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, ARG_OPT, GDEF, ) +DATACLASS_DECORATORS = { + 'dataclasses.dataclass', + 'attr.s', + 'attr.attrs', +} + + def is_trait_decorator(d: Expression) -> bool: return isinstance(d, RefExpr) and d.fullname == 'mypy_extensions.trait' @@ -17,21 +24,40 @@ def is_trait(cdef: ClassDef) -> bool: return any(is_trait_decorator(d) for d in cdef.decorators) or cdef.info.is_protocol -def is_dataclass_decorator(d: Expression) -> bool: - return ( - (isinstance(d, RefExpr) and d.fullname == 'dataclasses.dataclass') - or ( - isinstance(d, CallExpr) +def dataclass_decorator_type(d: Expression) -> Optional[str]: + if isinstance(d, RefExpr) and d.fullname in DATACLASS_DECORATORS: + return d.fullname.split('.')[0] + elif (isinstance(d, CallExpr) and isinstance(d.callee, RefExpr) - and d.callee.fullname == 'dataclasses.dataclass' - ) - ) + and d.callee.fullname in DATACLASS_DECORATORS): + name = d.callee.fullname.split('.')[0] + if name == 'attr' and 'auto_attribs' in d.arg_names: + # Note: the mypy attrs plugin checks that the value of auto_attribs is + # not computed at runtime, so we don't need to perform that check here + auto = d.args[d.arg_names.index('auto_attribs')] + if isinstance(auto, NameExpr) and auto.name == 'True': + return 'attr-auto' + return name + else: + return None + + +def is_dataclass_decorator(d: Expression) -> bool: + return dataclass_decorator_type(d) is not None def is_dataclass(cdef: ClassDef) -> bool: return any(is_dataclass_decorator(d) for d in cdef.decorators) +def dataclass_type(cdef: ClassDef) -> Optional[str]: + for d in cdef.decorators: + typ = dataclass_decorator_type(d) + if typ is not None: + return typ + return None + + def get_mypyc_attr_literal(e: Expression) -> Any: """Convert an expression from a mypyc_attr decorator to a value. @@ -60,7 +86,7 @@ def get_mypyc_attr_call(d: Expression) -> Optional[CallExpr]: def get_mypyc_attrs(stmt: Union[ClassDef, Decorator]) -> Dict[str, Any]: """Collect all the mypyc_attr attributes on a class definition or a function.""" - attrs = {} # type: Dict[str, Any] + attrs: Dict[str, Any] = {} for dec in stmt.decorators: d = get_mypyc_attr_call(dec) if d: @@ -101,7 +127,7 @@ def get_func_def(op: Union[FuncDef, Decorator, OverloadedFuncDef]) -> FuncDef: return op -def concrete_arg_kind(kind: int) -> int: +def concrete_arg_kind(kind: ArgKind) -> ArgKind: """Find the concrete version of an arg kind that is being passed.""" if kind == ARG_OPT: return ARG_POS diff --git a/mypyc/irbuild/visitor.py b/mypyc/irbuild/visitor.py index 67b8f04a7dc2..1a6a84809707 100644 --- a/mypyc/irbuild/visitor.py +++ b/mypyc/irbuild/visitor.py @@ -95,7 +95,7 @@ class IRBuilderVisitor(IRVisitor): # This gets passed to all the implementations and contains all the # state and many helpers. The attribute is initialized outside # this class since this class and IRBuilder form a reference loop. - builder = None # type: IRBuilder + builder: IRBuilder def visit_mypy_file(self, mypyfile: MypyFile) -> None: assert False, "use transform_mypy_file instead" diff --git a/mypyc/irbuild/vtable.py b/mypyc/irbuild/vtable.py index e6763c2d77d0..ce2c2d3b2222 100644 --- a/mypyc/irbuild/vtable.py +++ b/mypyc/irbuild/vtable.py @@ -8,7 +8,8 @@ def compute_vtable(cls: ClassIR) -> None: """Compute the vtable structure for a class.""" - if cls.vtable is not None: return + if cls.vtable is not None: + return if not cls.is_generated: cls.has_dict = any(x.inherits_python for x in cls.mro) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index d43c79590636..987819154abf 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -158,6 +158,24 @@ static inline int CPyTagged_CheckShort(CPyTagged x) { return !CPyTagged_CheckLong(x); } +static inline void CPyTagged_INCREF(CPyTagged x) { + if (unlikely(CPyTagged_CheckLong(x))) { + CPyTagged_IncRef(x); + } +} + +static inline void CPyTagged_DECREF(CPyTagged x) { + if (unlikely(CPyTagged_CheckLong(x))) { + CPyTagged_DecRef(x); + } +} + +static inline void CPyTagged_XDECREF(CPyTagged x) { + if (unlikely(CPyTagged_CheckLong(x))) { + CPyTagged_XDecRef(x); + } +} + static inline Py_ssize_t CPyTagged_ShortAsSsize_t(CPyTagged x) { // NOTE: Assume that we sign extend. return (Py_ssize_t)x >> 1; @@ -253,11 +271,10 @@ static inline bool CPyTagged_IsLe(CPyTagged left, CPyTagged right) { // Generic operations (that work with arbitrary types) -/* We use intentionally non-inlined decrefs since it pretty - * substantially speeds up compile time while only causing a ~1% - * performance degradation. We have our own copies both to avoid the - * null check in Py_DecRef and to avoid making an indirect PIC - * call. */ +/* We use intentionally non-inlined decrefs in rarely executed code + * paths since it pretty substantially speeds up compile time. We have + * our own copies both to avoid the null check in Py_DecRef and to avoid + * making an indirect PIC call. */ CPy_NOINLINE static void CPy_DecRef(PyObject *p) { CPy_DECREF(p); @@ -285,7 +302,7 @@ static inline CPyTagged CPyObject_Size(PyObject *obj) { static void CPy_LogGetAttr(const char *method, PyObject *obj, PyObject *attr) { PyObject *module = PyImport_ImportModule("getattr_hook"); if (module) { - PyObject *res = PyObject_CallMethod(module, method, "OO", obj, attr); + PyObject *res = PyObject_CallMethodObjArgs(module, method, obj, attr, NULL); Py_XDECREF(res); Py_DECREF(module); } @@ -318,6 +335,7 @@ PyObject *CPyObject_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); // List operations +PyObject *CPyList_Build(Py_ssize_t len, ...); PyObject *CPyList_GetItem(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index); @@ -344,6 +362,7 @@ PyObject *CPyDict_Get(PyObject *dict, PyObject *key, PyObject *fallback); PyObject *CPyDict_GetWithNone(PyObject *dict, PyObject *key); PyObject *CPyDict_SetDefault(PyObject *dict, PyObject *key, PyObject *value); PyObject *CPyDict_SetDefaultWithNone(PyObject *dict, PyObject *key); +PyObject *CPyDict_SetDefaultWithEmptyDatatype(PyObject *dict, PyObject *key, int data_type); PyObject *CPyDict_Build(Py_ssize_t size, ...); int CPyDict_Update(PyObject *dict, PyObject *stuff); int CPyDict_UpdateInDisplay(PyObject *dict, PyObject *stuff); @@ -383,6 +402,7 @@ static inline char CPyDict_CheckSize(PyObject *dict, CPyTagged size) { // Str operations +PyObject *CPyStr_Build(Py_ssize_t len, ...); PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index); PyObject *CPyStr_Split(PyObject *str, PyObject *sep, CPyTagged max_split); PyObject *CPyStr_Replace(PyObject *str, PyObject *old_substr, PyObject *new_substr, CPyTagged max_replace); @@ -391,6 +411,23 @@ PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); bool CPyStr_Startswith(PyObject *self, PyObject *subobj); bool CPyStr_Endswith(PyObject *self, PyObject *subobj); bool CPyStr_IsTrue(PyObject *obj); +Py_ssize_t CPyStr_Size_size_t(PyObject *str); +PyObject *CPy_Decode(PyObject *obj, PyObject *encoding, PyObject *errors); +PyObject *CPy_Encode(PyObject *obj, PyObject *encoding, PyObject *errors); + + +// Bytes operations + + +PyObject *CPyBytes_Build(Py_ssize_t len, ...); +PyObject *CPyBytes_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); +CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index); +PyObject *CPyBytes_Concat(PyObject *a, PyObject *b); +PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter); + + +int CPyBytes_Compare(PyObject *left, PyObject *right); + // Set operations @@ -541,7 +578,14 @@ int CPyStatics_Initialize(PyObject **statics, const double *complex_numbers, const int *tuples); PyObject *CPy_Super(PyObject *builtins, PyObject *self); +PyObject *CPy_CallReverseOpMethod(PyObject *left, PyObject *right, const char *op, + _Py_Identifier *method); + +PyObject *CPyImport_ImportFrom(PyObject *module, PyObject *package_name, + PyObject *import_name, PyObject *as_name); +PyObject *CPySingledispatch_RegisterFunction(PyObject *singledispatch_func, PyObject *cls, + PyObject *func); #ifdef __cplusplus } #endif diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c new file mode 100644 index 000000000000..bece7c13c957 --- /dev/null +++ b/mypyc/lib-rt/bytes_ops.c @@ -0,0 +1,143 @@ +// Bytes primitive operations +// +// These are registered in mypyc.primitives.bytes_ops. + +#include +#include "CPy.h" + +// Returns -1 on error, 0 on inequality, 1 on equality. +// +// Falls back to PyObject_RichCompareBool. +int CPyBytes_Compare(PyObject *left, PyObject *right) { + if (PyBytes_CheckExact(left) && PyBytes_CheckExact(right)) { + if (left == right) { + return 1; + } + + // Adapted from cpython internal implementation of bytes_compare. + Py_ssize_t len = Py_SIZE(left); + if (Py_SIZE(right) != len) { + return 0; + } + PyBytesObject *left_b = (PyBytesObject *)left; + PyBytesObject *right_b = (PyBytesObject *)right; + if (left_b->ob_sval[0] != right_b->ob_sval[0]) { + return 0; + } + + return memcmp(left_b->ob_sval, right_b->ob_sval, len) == 0; + } + return PyObject_RichCompareBool(left, right, Py_EQ); +} + +CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index) { + if (CPyTagged_CheckShort(index)) { + Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); + Py_ssize_t size = ((PyVarObject *)o)->ob_size; + if (n < 0) + n += size; + if (n < 0 || n >= size) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return CPY_INT_TAG; + } + unsigned char num = PyBytes_Check(o) ? ((PyBytesObject *)o)->ob_sval[n] + : ((PyByteArrayObject *)o)->ob_bytes[n]; + return num << 1; + } else { + PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); + return CPY_INT_TAG; + } +} + +PyObject *CPyBytes_Concat(PyObject *a, PyObject *b) { + if (PyBytes_Check(a) && PyBytes_Check(b)) { + Py_ssize_t a_len = ((PyVarObject *)a)->ob_size; + Py_ssize_t b_len = ((PyVarObject *)b)->ob_size; + PyBytesObject *ret = (PyBytesObject *)PyBytes_FromStringAndSize(NULL, a_len + b_len); + if (ret != NULL) { + memcpy(ret->ob_sval, ((PyBytesObject *)a)->ob_sval, a_len); + memcpy(ret->ob_sval + a_len, ((PyBytesObject *)b)->ob_sval, b_len); + } + return (PyObject *)ret; + } else if (PyByteArray_Check(a)) { + return PyByteArray_Concat(a, b); + } else { + PyBytes_Concat(&a, b); + return a; + } +} + +static inline Py_ssize_t Clamp(Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) { + return a < b ? b : (a >= c ? c : a); +} + +PyObject *CPyBytes_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { + if ((PyBytes_Check(obj) || PyByteArray_Check(obj)) + && CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end)) { + Py_ssize_t startn = CPyTagged_ShortAsSsize_t(start); + Py_ssize_t endn = CPyTagged_ShortAsSsize_t(end); + Py_ssize_t len = ((PyVarObject *)obj)->ob_size; + if (startn < 0) { + startn += len; + } + if (endn < 0) { + endn += len; + } + startn = Clamp(startn, 0, len); + endn = Clamp(endn, 0, len); + Py_ssize_t slice_len = endn - startn; + if (PyBytes_Check(obj)) { + return PyBytes_FromStringAndSize(PyBytes_AS_STRING(obj) + startn, slice_len); + } else { + return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING(obj) + startn, slice_len); + } + } + return CPyObject_GetSlice(obj, start, end); +} + +// Like _PyBytes_Join but fallback to dynamic call if 'sep' is not bytes +// (mostly commonly, for bytearrays) +PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter) { + if (PyBytes_CheckExact(sep)) { + return _PyBytes_Join(sep, iter); + } else { + _Py_IDENTIFIER(join); + return _PyObject_CallMethodIdOneArg(sep, &PyId_join, iter); + } +} + +PyObject *CPyBytes_Build(Py_ssize_t len, ...) { + Py_ssize_t i; + Py_ssize_t sz = 0; + + va_list args; + va_start(args, len); + for (i = 0; i < len; i++) { + PyObject *item = va_arg(args, PyObject *); + size_t add_sz = ((PyVarObject *)item)->ob_size; + // Using size_t to avoid overflow during arithmetic calculation + if (add_sz > (size_t)(PY_SSIZE_T_MAX - sz)) { + PyErr_SetString(PyExc_OverflowError, + "join() result is too long for a Python bytes"); + return NULL; + } + sz += add_sz; + } + va_end(args); + + PyBytesObject *ret = (PyBytesObject *)PyBytes_FromStringAndSize(NULL, sz); + if (ret != NULL) { + char *res_data = ret->ob_sval; + va_start(args, len); + for (i = 0; i < len; i++) { + PyObject *item = va_arg(args, PyObject *); + Py_ssize_t item_sz = ((PyVarObject *)item)->ob_size; + memcpy(res_data, ((PyBytesObject *)item)->ob_sval, item_sz); + res_data += item_sz; + } + va_end(args); + assert(res_data == ret->ob_sval + ((PyVarObject *)ret)->ob_size); + } + + return (PyObject *)ret; +} diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index 2de5f4a9e7a4..21a9035021ea 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -68,18 +68,48 @@ PyObject *CPyDict_GetWithNone(PyObject *dict, PyObject *key) { } PyObject *CPyDict_SetDefault(PyObject *dict, PyObject *key, PyObject *value) { - if (PyDict_CheckExact(dict)){ + if (PyDict_CheckExact(dict)) { PyObject* ret = PyDict_SetDefault(dict, key, value); Py_XINCREF(ret); return ret; } - return PyObject_CallMethod(dict, "setdefault", "(OO)", key, value); + _Py_IDENTIFIER(setdefault); + return _PyObject_CallMethodIdObjArgs(dict, &PyId_setdefault, key, value, NULL); } PyObject *CPyDict_SetDefaultWithNone(PyObject *dict, PyObject *key) { return CPyDict_SetDefault(dict, key, Py_None); } +PyObject *CPyDict_SetDefaultWithEmptyDatatype(PyObject *dict, PyObject *key, + int data_type) { + PyObject *res = CPyDict_GetItem(dict, key); + if (!res) { + // CPyDict_GetItem() would generates an PyExc_KeyError + // when key is not found. + PyErr_Clear(); + + PyObject *new_obj; + if (data_type == 1) { + new_obj = PyList_New(0); + } else if (data_type == 2) { + new_obj = PyDict_New(); + } else if (data_type == 3) { + new_obj = PySet_New(NULL); + } else { + return NULL; + } + + if (CPyDict_SetItem(dict, key, new_obj) == -1) { + return NULL; + } else { + return new_obj; + } + } else { + return res; + } +} + int CPyDict_SetItem(PyObject *dict, PyObject *key, PyObject *value) { if (PyDict_CheckExact(dict)) { return PyDict_SetItem(dict, key, value); @@ -99,7 +129,7 @@ static inline int CPy_ObjectToStatus(PyObject *obj) { static int CPyDict_UpdateGeneral(PyObject *dict, PyObject *stuff) { _Py_IDENTIFIER(update); - PyObject *res = _PyObject_CallMethodIdObjArgs(dict, &PyId_update, stuff, NULL); + PyObject *res = _PyObject_CallMethodIdOneArg(dict, &PyId_update, stuff); return CPy_ObjectToStatus(res); } @@ -165,21 +195,24 @@ PyObject *CPyDict_KeysView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictKeys_Type); } - return PyObject_CallMethod(dict, "keys", NULL); + _Py_IDENTIFIER(keys); + return _PyObject_CallMethodIdNoArgs(dict, &PyId_keys); } PyObject *CPyDict_ValuesView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictValues_Type); } - return PyObject_CallMethod(dict, "values", NULL); + _Py_IDENTIFIER(values); + return _PyObject_CallMethodIdNoArgs(dict, &PyId_values); } PyObject *CPyDict_ItemsView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictItems_Type); } - return PyObject_CallMethod(dict, "items", NULL); + _Py_IDENTIFIER(items); + return _PyObject_CallMethodIdNoArgs(dict, &PyId_items); } PyObject *CPyDict_Keys(PyObject *dict) { @@ -188,7 +221,8 @@ PyObject *CPyDict_Keys(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - PyObject *view = PyObject_CallMethod(dict, "keys", NULL); + _Py_IDENTIFIER(keys); + PyObject *view = _PyObject_CallMethodIdNoArgs(dict, &PyId_keys); if (view == NULL) { return NULL; } @@ -207,7 +241,8 @@ PyObject *CPyDict_Values(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - PyObject *view = PyObject_CallMethod(dict, "values", NULL); + _Py_IDENTIFIER(values); + PyObject *view = _PyObject_CallMethodIdNoArgs(dict, &PyId_values); if (view == NULL) { return NULL; } @@ -226,7 +261,8 @@ PyObject *CPyDict_Items(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - PyObject *view = PyObject_CallMethod(dict, "items", NULL); + _Py_IDENTIFIER(items); + PyObject *view = _PyObject_CallMethodIdNoArgs(dict, &PyId_items); if (view == NULL) { return NULL; } @@ -243,7 +279,8 @@ char CPyDict_Clear(PyObject *dict) { if (PyDict_CheckExact(dict)) { PyDict_Clear(dict); } else { - PyObject *res = PyObject_CallMethod(dict, "clear", NULL); + _Py_IDENTIFIER(clear); + PyObject *res = _PyObject_CallMethodIdNoArgs(dict, &PyId_clear); if (res == NULL) { return 0; } @@ -255,7 +292,8 @@ PyObject *CPyDict_Copy(PyObject *dict) { if (PyDict_CheckExact(dict)) { return PyDict_Copy(dict); } - return PyObject_CallMethod(dict, "copy", NULL); + _Py_IDENTIFIER(copy); + return _PyObject_CallMethodIdNoArgs(dict, &PyId_copy); } PyObject *CPyDict_GetKeysIter(PyObject *dict) { @@ -273,7 +311,8 @@ PyObject *CPyDict_GetItemsIter(PyObject *dict) { Py_INCREF(dict); return dict; } - PyObject *view = PyObject_CallMethod(dict, "items", NULL); + _Py_IDENTIFIER(items); + PyObject *view = _PyObject_CallMethodIdNoArgs(dict, &PyId_items); if (view == NULL) { return NULL; } @@ -288,7 +327,8 @@ PyObject *CPyDict_GetValuesIter(PyObject *dict) { Py_INCREF(dict); return dict; } - PyObject *view = PyObject_CallMethod(dict, "values", NULL); + _Py_IDENTIFIER(values); + PyObject *view = _PyObject_CallMethodIdNoArgs(dict, &PyId_values); if (view == NULL) { return NULL; } diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index 50f01f2e4e7e..b87d5471a411 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -189,38 +189,9 @@ void CPy_TypeError(const char *expected, PyObject *value) { } } -// These functions are basically exactly PyCode_NewEmpty and -// _PyTraceback_Add which are available in all the versions we support. -// We're continuing to use them because we'll probably optimize them later. -static PyCodeObject *CPy_CreateCodeObject(const char *filename, const char *funcname, int line) { - PyObject *filename_obj = PyUnicode_FromString(filename); - PyObject *funcname_obj = PyUnicode_FromString(funcname); - PyObject *empty_bytes = PyBytes_FromStringAndSize("", 0); - PyObject *empty_tuple = PyTuple_New(0); - PyCodeObject *code_obj = NULL; - if (filename_obj == NULL || funcname_obj == NULL || empty_bytes == NULL - || empty_tuple == NULL) { - goto Error; - } - code_obj = PyCode_New(0, 0, 0, 0, 0, - empty_bytes, - empty_tuple, - empty_tuple, - empty_tuple, - empty_tuple, - empty_tuple, - filename_obj, - funcname_obj, - line, - empty_bytes); - Error: - Py_XDECREF(empty_bytes); - Py_XDECREF(empty_tuple); - Py_XDECREF(filename_obj); - Py_XDECREF(funcname_obj); - return code_obj; -} - +// This function is basically exactly the same with _PyTraceback_Add +// which is available in all the versions we support. +// We're continuing to use this because we'll probably optimize this later. void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyObject *globals) { PyObject *exc, *val, *tb; PyThreadState *thread_state = PyThreadState_GET(); @@ -233,7 +204,7 @@ void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyOb // FS encoding, which could have a decoder in Python. We don't do // that so *that* doesn't apply to us.) PyErr_Fetch(&exc, &val, &tb); - PyCodeObject *code_obj = CPy_CreateCodeObject(filename, funcname, line); + PyCodeObject *code_obj = PyCode_NewEmpty(filename, funcname, line); if (code_obj == NULL) { goto error; } diff --git a/mypyc/lib-rt/getargsfast.c b/mypyc/lib-rt/getargsfast.c index affd8621884d..afb161e643c7 100644 --- a/mypyc/lib-rt/getargsfast.c +++ b/mypyc/lib-rt/getargsfast.c @@ -21,6 +21,8 @@ /* None of this is supported on Python 3.6 or earlier */ #if PY_VERSION_HEX >= 0x03070000 +#define PARSER_INITED(parser) ((parser)->kwtuple != NULL) + /* Forward */ static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, @@ -93,7 +95,8 @@ CPyArg_ParseStackAndKeywordsSimple(PyObject *const *args, Py_ssize_t nargs, PyOb va_list va; va_start(va, parser); - if (kwnames == NULL && nargs >= parser->min && nargs <= parser->max) { + if (kwnames == NULL && PARSER_INITED(parser) && + nargs >= parser->min && nargs <= parser->max) { // Fast path: correct number of positional arguments only PyObject **p; Py_ssize_t i; @@ -124,7 +127,7 @@ parser_init(CPyArg_Parser *parser) PyObject *kwtuple; assert(parser->keywords != NULL); - if (parser->kwtuple != NULL) { + if (PARSER_INITED(parser)) { return 1; } diff --git a/mypyc/lib-rt/int_ops.c b/mypyc/lib-rt/int_ops.c index 0ac9b6fe490b..1275f2c10577 100644 --- a/mypyc/lib-rt/int_ops.c +++ b/mypyc/lib-rt/int_ops.c @@ -190,16 +190,17 @@ CPyTagged CPyTagged_Multiply(CPyTagged left, CPyTagged right) { } CPyTagged CPyTagged_FloorDivide(CPyTagged left, CPyTagged right) { - if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right) + if (CPyTagged_CheckShort(left) + && CPyTagged_CheckShort(right) && !CPyTagged_MaybeFloorDivideFault(left, right)) { - Py_ssize_t result = ((Py_ssize_t)left / CPyTagged_ShortAsSsize_t(right)) & ~1; + Py_ssize_t result = CPyTagged_ShortAsSsize_t(left) / CPyTagged_ShortAsSsize_t(right); if (((Py_ssize_t)left < 0) != (((Py_ssize_t)right) < 0)) { - if (result / 2 * right != left) { + if (result * right != left) { // Round down - result -= 2; + result--; } } - return result; + return result << 1; } PyObject *left_obj = CPyTagged_AsObject(left); PyObject *right_obj = CPyTagged_AsObject(right); diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index ccc8390966a0..28547cfd7b60 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -5,6 +5,26 @@ #include #include "CPy.h" +PyObject *CPyList_Build(Py_ssize_t len, ...) { + Py_ssize_t i; + + PyObject *res = PyList_New(len); + if (res == NULL) { + return NULL; + } + + va_list args; + va_start(args, len); + for (i = 0; i < len; i++) { + // Steals the reference + PyObject *value = va_arg(args, PyObject *); + PyList_SET_ITEM(res, i, value); + } + va_end(args); + + return res; +} + PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); PyObject *result = PyList_GET_ITEM(list, n); diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index 923ea22629a8..6b5685ab1f1a 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -3,6 +3,7 @@ // These are registered in mypyc.primitives.misc_ops. #include +#include "pythoncapi_compat.h" #include "CPy.h" PyObject *CPy_GetCoro(PyObject *obj) @@ -27,7 +28,7 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val) if (val == Py_None) { return CPyIter_Next(iter); } else { - return _PyObject_CallMethodIdObjArgs(iter, &PyId_send, val, NULL); + return _PyObject_CallMethodIdOneArg(iter, &PyId_send, val); } } @@ -148,7 +149,7 @@ PyObject *CPyType_FromTemplate(PyObject *template, // to being type. (This allows us to avoid needing to initialize // it explicitly on windows.) if (!Py_TYPE(template_)) { - Py_TYPE(template_) = &PyType_Type; + Py_SET_TYPE(template_, &PyType_Type); } PyTypeObject *metaclass = Py_TYPE(template_); @@ -249,7 +250,7 @@ PyObject *CPyType_FromTemplate(PyObject *template, // the mro. It was needed for mypy.stats. I need to investigate // what is actually going on here. Py_INCREF(metaclass); - Py_TYPE(t) = metaclass; + Py_SET_TYPE(t, metaclass); if (dummy_class) { if (PyDict_Merge(t->ht_type.tp_dict, dummy_class->tp_dict, 0) != 0) @@ -512,7 +513,7 @@ int CPySequence_CheckUnpackCount(PyObject *sequence, Py_ssize_t expected) { // Parse an integer (size_t) encoded as a variable-length binary sequence. static const char *parse_int(const char *s, size_t *len) { - ssize_t n = 0; + Py_ssize_t n = 0; while ((unsigned char)*s >= 0x80) { n = (n << 7) + (*s & 0x7f); s++; @@ -643,3 +644,143 @@ CPy_Super(PyObject *builtins, PyObject *self) { Py_DECREF(super_type); return result; } + +// This helper function is a simplification of cpython/ceval.c/import_from() +PyObject *CPyImport_ImportFrom(PyObject *module, PyObject *package_name, + PyObject *import_name, PyObject *as_name) { + // check if the imported module has an attribute by that name + PyObject *x = PyObject_GetAttr(module, import_name); + if (x == NULL) { + // if not, attempt to import a submodule with that name + PyObject *fullmodname = PyUnicode_FromFormat("%U.%U", package_name, import_name); + if (fullmodname == NULL) { + goto fail; + } + + // The following code is a simplification of cpython/import.c/PyImport_GetModule() + x = PyObject_GetItem(module, fullmodname); + Py_DECREF(fullmodname); + if (x == NULL) { + goto fail; + } + } + return x; + +fail: + PyErr_Clear(); + PyObject *package_path = PyModule_GetFilenameObject(module); + PyObject *errmsg = PyUnicode_FromFormat("cannot import name %R from %R (%S)", + import_name, package_name, package_path); + // NULL checks for errmsg and package_name done by PyErr_SetImportError. + PyErr_SetImportError(errmsg, package_name, package_path); + Py_DECREF(package_path); + Py_DECREF(errmsg); + return NULL; +} + +// From CPython +static PyObject * +CPy_BinopTypeError(PyObject *left, PyObject *right, const char *op) { + PyErr_Format(PyExc_TypeError, + "unsupported operand type(s) for %.100s: " + "'%.100s' and '%.100s'", + op, + Py_TYPE(left)->tp_name, + Py_TYPE(right)->tp_name); + return NULL; +} + +PyObject * +CPy_CallReverseOpMethod(PyObject *left, + PyObject *right, + const char *op, + _Py_Identifier *method) { + // Look up reverse method + PyObject *m = _PyObject_GetAttrId(right, method); + if (m == NULL) { + // If reverse method not defined, generate TypeError instead AttributeError + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + CPy_BinopTypeError(left, right, op); + } + return NULL; + } + // Call reverse method + PyObject *result = PyObject_CallOneArg(m, left); + Py_DECREF(m); + return result; +} + +PyObject *CPySingledispatch_RegisterFunction(PyObject *singledispatch_func, + PyObject *cls, + PyObject *func) { + PyObject *registry = PyObject_GetAttrString(singledispatch_func, "registry"); + PyObject *register_func = NULL; + PyObject *typing = NULL; + PyObject *get_type_hints = NULL; + PyObject *type_hints = NULL; + + if (registry == NULL) goto fail; + if (func == NULL) { + // one argument case + if (PyType_Check(cls)) { + // passed a class + // bind cls to the first argument so that register gets called again with both the + // class and the function + register_func = PyObject_GetAttrString(singledispatch_func, "register"); + if (register_func == NULL) goto fail; + return PyMethod_New(register_func, cls); + } + // passed a function + PyObject *annotations = PyFunction_GetAnnotations(cls); + const char *invalid_first_arg_msg = + "Invalid first argument to `register()`: %R. " + "Use either `@register(some_class)` or plain `@register` " + "on an annotated function."; + + if (annotations == NULL) { + PyErr_Format(PyExc_TypeError, invalid_first_arg_msg, cls); + goto fail; + } + + Py_INCREF(annotations); + + func = cls; + typing = PyImport_ImportModule("typing"); + if (typing == NULL) goto fail; + get_type_hints = PyObject_GetAttrString(typing, "get_type_hints"); + + type_hints = PyObject_CallOneArg(get_type_hints, func); + PyObject *argname; + Py_ssize_t pos = 0; + if (!PyDict_Next(type_hints, &pos, &argname, &cls)) { + // the functools implementation raises the same type error if annotations is an empty dict + PyErr_Format(PyExc_TypeError, invalid_first_arg_msg, cls); + goto fail; + } + if (!PyType_Check(cls)) { + const char *invalid_annotation_msg = "Invalid annotation for %R. %R is not a class."; + PyErr_Format(PyExc_TypeError, invalid_annotation_msg, argname, cls); + goto fail; + } + } + if (PyDict_SetItem(registry, cls, func) == -1) { + goto fail; + } + + // clear the cache so we consider the newly added function when dispatching + PyObject *dispatch_cache = PyObject_GetAttrString(singledispatch_func, "dispatch_cache"); + if (dispatch_cache == NULL) goto fail; + PyDict_Clear(dispatch_cache); + + Py_INCREF(func); + return func; + +fail: + Py_XDECREF(registry); + Py_XDECREF(register_func); + Py_XDECREF(typing); + Py_XDECREF(get_type_hints); + Py_XDECREF(type_hints); + return NULL; + +} diff --git a/mypyc/lib-rt/pythoncapi_compat.h b/mypyc/lib-rt/pythoncapi_compat.h new file mode 100644 index 000000000000..b4011d20a19a --- /dev/null +++ b/mypyc/lib-rt/pythoncapi_compat.h @@ -0,0 +1,393 @@ +// Header file providing new functions of the Python C API to old Python +// versions. +// +// File distributed under the MIT license. +// Copyright Contributors to the pythoncapi_compat project. +// +// Homepage: +// https://github.com/pythoncapi/pythoncapi_compat +// +// Latest version: +// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h +// +// SPDX-License-Identifier: MIT + +#ifndef PYTHONCAPI_COMPAT +#define PYTHONCAPI_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "frameobject.h" // PyFrameObject, PyFrame_GetBack() + + +// Compatibility with Visual Studio 2013 and older which don't support +// the inline keyword in C (only in C++): use __inline instead. +#if (defined(_MSC_VER) && _MSC_VER < 1900 \ + && !defined(__cplusplus) && !defined(inline)) +# define inline __inline +# define PYTHONCAPI_COMPAT_MSC_INLINE + // These two macros are undefined at the end of this file +#endif + + +// Cast argument to PyObject* type. +#ifndef _PyObject_CAST +# define _PyObject_CAST(op) ((PyObject*)(op)) +#endif +#ifndef _PyObject_CAST_CONST +# define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) +#endif + + +// bpo-42262 added Py_NewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) +static inline PyObject* _Py_NewRef(PyObject *obj) +{ + Py_INCREF(obj); + return obj; +} +#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) +#endif + + +// bpo-42262 added Py_XNewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) +static inline PyObject* _Py_XNewRef(PyObject *obj) +{ + Py_XINCREF(obj); + return obj; +} +#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) +#endif + + +// See https://bugs.python.org/issue42522 +#if !defined(_Py_StealRef) +static inline PyObject* __Py_StealRef(PyObject *obj) +{ + Py_DECREF(obj); + return obj; +} +#define _Py_StealRef(obj) __Py_StealRef(_PyObject_CAST(obj)) +#endif + + +// See https://bugs.python.org/issue42522 +#if !defined(_Py_XStealRef) +static inline PyObject* __Py_XStealRef(PyObject *obj) +{ + Py_XDECREF(obj); + return obj; +} +#define _Py_XStealRef(obj) __Py_XStealRef(_PyObject_CAST(obj)) +#endif + + +// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) +static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) +{ + ob->ob_refcnt = refcnt; +} +#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +#endif + + +// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2. +// It is excluded from the limited C API. +#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API) +#define Py_SETREF(op, op2) \ + do { \ + PyObject *_py_tmp = _PyObject_CAST(op); \ + (op) = (op2); \ + Py_DECREF(_py_tmp); \ + } while (0) + +#define Py_XSETREF(op, op2) \ + do { \ + PyObject *_py_tmp = _PyObject_CAST(op); \ + (op) = (op2); \ + Py_XDECREF(_py_tmp); \ + } while (0) +#endif + + +// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse() +// to Python 3.10.0b1. +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is) +# define Py_Is(x, y) ((x) == (y)) +#endif +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone) +# define Py_IsNone(x) Py_Is(x, Py_None) +#endif +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsTrue) +# define Py_IsTrue(x) Py_Is(x, Py_True) +#endif +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsFalse) +# define Py_IsFalse(x) Py_Is(x, Py_False) +#endif + + +// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) +static inline void +_Py_SET_TYPE(PyObject *ob, PyTypeObject *type) +{ + ob->ob_type = type; +} +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) +static inline void +_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) +{ + ob->ob_size = size; +} +#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) +#endif + + +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 +static inline PyCodeObject* +PyFrame_GetCode(PyFrameObject *frame) +{ + assert(frame != NULL); + assert(frame->f_code != NULL); + return (PyCodeObject*)Py_NewRef(frame->f_code); +} +#endif + +static inline PyCodeObject* +_PyFrame_GetCodeBorrow(PyFrameObject *frame) +{ + return (PyCodeObject *)_Py_StealRef(PyFrame_GetCode(frame)); +} + + +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* +PyFrame_GetBack(PyFrameObject *frame) +{ + assert(frame != NULL); + return (PyFrameObject*)Py_XNewRef(frame->f_back); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* +_PyFrame_GetBackBorrow(PyFrameObject *frame) +{ + return (PyFrameObject *)_Py_XStealRef(PyFrame_GetBack(frame)); +} +#endif + + +// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 +static inline PyInterpreterState * +PyThreadState_GetInterpreter(PyThreadState *tstate) +{ + assert(tstate != NULL); + return tstate->interp; +} +#endif + + +// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* +PyThreadState_GetFrame(PyThreadState *tstate) +{ + assert(tstate != NULL); + return (PyFrameObject *)Py_XNewRef(tstate->frame); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* +_PyThreadState_GetFrameBorrow(PyThreadState *tstate) +{ + return (PyFrameObject *)_Py_XStealRef(PyThreadState_GetFrame(tstate)); +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 +static inline PyInterpreterState * +PyInterpreterState_Get(void) +{ + PyThreadState *tstate; + PyInterpreterState *interp; + + tstate = PyThreadState_GET(); + if (tstate == NULL) { + Py_FatalError("GIL released (tstate is NULL)"); + } + interp = tstate->interp; + if (interp == NULL) { + Py_FatalError("no current interpreter"); + } + return interp; +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 +#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline uint64_t +PyThreadState_GetID(PyThreadState *tstate) +{ + assert(tstate != NULL); + return tstate->id; +} +#endif + +// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_EnterTracing(PyThreadState *tstate) +{ + tstate->tracing++; +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = 0; +#else + tstate->use_tracing = 0; +#endif +} +#endif + +// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) +{ + tstate->tracing--; + int use_tracing = (tstate->c_tracefunc != NULL + || tstate->c_profilefunc != NULL); +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = use_tracing; +#else + tstate->use_tracing = use_tracing; +#endif +} +#endif + + +// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 +#if PY_VERSION_HEX < 0x030900A1 +static inline PyObject* +PyObject_CallNoArgs(PyObject *func) +{ + return PyObject_CallFunctionObjArgs(func, NULL); +} +#endif + + +// bpo-39245 made PyObject_CallOneArg() public (previously called +// _PyObject_CallOneArg) in Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 +static inline PyObject* +PyObject_CallOneArg(PyObject *func, PyObject *arg) +{ + return PyObject_CallFunctionObjArgs(func, arg, NULL); +} +#endif + + +// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 +static inline int +PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) +{ + int res; + Py_XINCREF(value); + res = PyModule_AddObject(module, name, value); + if (res < 0) { + Py_XDECREF(value); + } + return res; +} +#endif + + +// bpo-40024 added PyModule_AddType() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 +static inline int +PyModule_AddType(PyObject *module, PyTypeObject *type) +{ + const char *name, *dot; + + if (PyType_Ready(type) < 0) { + return -1; + } + + // inline _PyType_Name() + name = type->tp_name; + assert(name != NULL); + dot = strrchr(name, '.'); + if (dot != NULL) { + name = dot + 1; + } + + return PyModule_AddObjectRef(module, name, (PyObject *)type); +} +#endif + + +// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. +// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. +#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline int +PyObject_GC_IsTracked(PyObject* obj) +{ + return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); +} +#endif + +// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. +// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. +#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) +static inline int +PyObject_GC_IsFinalized(PyObject *obj) +{ + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1)); +} +#endif + + +// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) +static inline int +_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { + return ob->ob_type == type; +} +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) +#endif + + +// Py_UNUSED() was added to Python 3.4.0b2. +#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED) +# if defined(__GNUC__) || defined(__clang__) +# define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) +# else +# define Py_UNUSED(name) _unused_ ## name +# endif +#endif + + +#ifdef PYTHONCAPI_COMPAT_MSC_INLINE +# undef inline +# undef PYTHONCAPI_COMPAT_MSC_INLINE +#endif + +#ifdef __cplusplus +} +#endif +#endif // PYTHONCAPI_COMPAT diff --git a/mypyc/lib-rt/pythonsupport.h b/mypyc/lib-rt/pythonsupport.h index a8b00e168bb7..c4091dada7fd 100644 --- a/mypyc/lib-rt/pythonsupport.h +++ b/mypyc/lib-rt/pythonsupport.h @@ -8,6 +8,7 @@ #include #include +#include "pythoncapi_compat.h" #include #include #include "mypyc_util.h" @@ -220,7 +221,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize) */ if (allocated >= newsize && newsize >= (allocated >> 1)) { assert(self->ob_item != NULL || newsize == 0); - Py_SIZE(self) = newsize; + Py_SET_SIZE(self, newsize); return 0; } @@ -248,7 +249,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize) return -1; } self->ob_item = items; - Py_SIZE(self) = newsize; + Py_SET_SIZE(self, newsize); self->allocated = new_allocated; return 0; } @@ -322,7 +323,7 @@ _PyDict_GetItemStringWithError(PyObject *v, const char *key) #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION < 6 /* _PyUnicode_EqualToASCIIString got added in 3.5.3 (argh!) so we can't actually know - * whether it will be precent at runtime, so we just assume we don't have it in 3.5. */ + * whether it will be present at runtime, so we just assume we don't have it in 3.5. */ #define CPyUnicode_EqualToASCIIString(x, y) (PyUnicode_CompareWithASCIIString((x), (y)) == 0) #elif PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 6 #define CPyUnicode_EqualToASCIIString(x, y) _PyUnicode_EqualToASCIIString(x, y) @@ -403,4 +404,16 @@ _CPyObject_HasAttrId(PyObject *v, _Py_Identifier *name) { #define _CPyObject_HasAttrId _PyObject_HasAttrId #endif +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION < 9 +// OneArgs and NoArgs functions got added in 3.9 +#define _PyObject_CallMethodIdNoArgs(self, name) \ + _PyObject_CallMethodIdObjArgs((self), (name), NULL) +#define _PyObject_CallMethodIdOneArg(self, name, arg) \ + _PyObject_CallMethodIdObjArgs((self), (name), (arg), NULL) +#define PyObject_CallNoArgs(callable) \ + PyObject_CallFunctionObjArgs((callable), NULL) +#define PyObject_CallOneArg(callable, arg) \ + PyObject_CallFunctionObjArgs((callable), (arg), NULL) +#endif + #endif diff --git a/mypyc/lib-rt/str_ops.c b/mypyc/lib-rt/str_ops.c index 7208a9b7e206..3c0d275fbe39 100644 --- a/mypyc/lib-rt/str_ops.c +++ b/mypyc/lib-rt/str_ops.c @@ -10,12 +10,12 @@ PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); Py_ssize_t size = PyUnicode_GET_LENGTH(str); - if ((n >= 0 && n >= size) || (n < 0 && n + size < 0)) { + if (n < 0) + n += size; + if (n < 0 || n >= size) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return NULL; } - if (n < 0) - n += size; enum PyUnicode_Kind kind = (enum PyUnicode_Kind)PyUnicode_KIND(str); void *data = PyUnicode_DATA(str); Py_UCS4 ch = PyUnicode_READ(kind, data, n); @@ -25,8 +25,7 @@ PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index) { if (PyUnicode_KIND(unicode) == PyUnicode_1BYTE_KIND) { PyUnicode_1BYTE_DATA(unicode)[0] = (Py_UCS1)ch; - } - else if (PyUnicode_KIND(unicode) == PyUnicode_2BYTE_KIND) { + } else if (PyUnicode_KIND(unicode) == PyUnicode_2BYTE_KIND) { PyUnicode_2BYTE_DATA(unicode)[0] = (Py_UCS2)ch; } else { assert(PyUnicode_KIND(unicode) == PyUnicode_4BYTE_KIND); @@ -43,22 +42,108 @@ PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index) { } } -PyObject *CPyStr_Split(PyObject *str, PyObject *sep, CPyTagged max_split) -{ +// A simplification of _PyUnicode_JoinArray() from CPython 3.9.6 +PyObject *CPyStr_Build(Py_ssize_t len, ...) { + Py_ssize_t i; + va_list args; + + // Calculate the total amount of space and check + // whether all components have the same kind. + Py_ssize_t sz = 0; + Py_UCS4 maxchar = 0; + int use_memcpy = 1; // Use memcpy by default + PyObject *last_obj = NULL; + + va_start(args, len); + for (i = 0; i < len; i++) { + PyObject *item = va_arg(args, PyObject *); + if (!PyUnicode_Check(item)) { + PyErr_Format(PyExc_TypeError, + "sequence item %zd: expected str instance," + " %.80s found", + i, Py_TYPE(item)->tp_name); + return NULL; + } + if (PyUnicode_READY(item) == -1) + return NULL; + + size_t add_sz = PyUnicode_GET_LENGTH(item); + Py_UCS4 item_maxchar = PyUnicode_MAX_CHAR_VALUE(item); + maxchar = Py_MAX(maxchar, item_maxchar); + + // Using size_t to avoid overflow during arithmetic calculation + if (add_sz > (size_t)(PY_SSIZE_T_MAX - sz)) { + PyErr_SetString(PyExc_OverflowError, + "join() result is too long for a Python string"); + return NULL; + } + sz += add_sz; + + // If these strings have different kind, we would call + // _PyUnicode_FastCopyCharacters() in the following part. + if (use_memcpy && last_obj != NULL) { + if (PyUnicode_KIND(last_obj) != PyUnicode_KIND(item)) + use_memcpy = 0; + } + last_obj = item; + } + va_end(args); + + // Construct the string + PyObject *res = PyUnicode_New(sz, maxchar); + if (res == NULL) + return NULL; + + if (use_memcpy) { + unsigned char *res_data = PyUnicode_1BYTE_DATA(res); + unsigned int kind = PyUnicode_KIND(res); + + va_start(args, len); + for (i = 0; i < len; ++i) { + PyObject *item = va_arg(args, PyObject *); + Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item); + if (itemlen != 0) { + memcpy(res_data, PyUnicode_DATA(item), kind * itemlen); + res_data += kind * itemlen; + } + } + va_end(args); + assert(res_data == PyUnicode_1BYTE_DATA(res) + kind * PyUnicode_GET_LENGTH(res)); + } else { + Py_ssize_t res_offset = 0; + + va_start(args, len); + for (i = 0; i < len; ++i) { + PyObject *item = va_arg(args, PyObject *); + Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item); + if (itemlen != 0) { + _PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen); + res_offset += itemlen; + } + } + va_end(args); + assert(res_offset == PyUnicode_GET_LENGTH(res)); + } + + assert(_PyUnicode_CheckConsistency(res, 1)); + return res; +} + +PyObject *CPyStr_Split(PyObject *str, PyObject *sep, CPyTagged max_split) { Py_ssize_t temp_max_split = CPyTagged_AsSsize_t(max_split); if (temp_max_split == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); - return NULL; + return NULL; } return PyUnicode_Split(str, sep, temp_max_split); } -PyObject *CPyStr_Replace(PyObject *str, PyObject *old_substr, PyObject *new_substr, CPyTagged max_replace) -{ +PyObject *CPyStr_Replace(PyObject *str, PyObject *old_substr, + PyObject *new_substr, CPyTagged max_replace) { Py_ssize_t temp_max_replace = CPyTagged_AsSsize_t(max_replace); if (temp_max_replace == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); - return NULL; + return NULL; } return PyUnicode_Replace(str, old_substr, new_substr, temp_max_replace); } @@ -102,8 +187,55 @@ PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { } return CPyObject_GetSlice(obj, start, end); } + /* Check if the given string is true (i.e. it's length isn't zero) */ bool CPyStr_IsTrue(PyObject *obj) { Py_ssize_t length = PyUnicode_GET_LENGTH(obj); return length != 0; } + +Py_ssize_t CPyStr_Size_size_t(PyObject *str) { + if (PyUnicode_READY(str) != -1) { + return PyUnicode_GET_LENGTH(str); + } + return -1; +} + +PyObject *CPy_Decode(PyObject *obj, PyObject *encoding, PyObject *errors) { + const char *enc = NULL; + const char *err = NULL; + if (encoding) { + enc = PyUnicode_AsUTF8AndSize(encoding, NULL); + if (!enc) return NULL; + } + if (errors) { + err = PyUnicode_AsUTF8AndSize(errors, NULL); + if (!err) return NULL; + } + if (PyBytes_Check(obj)) { + return PyUnicode_Decode(((PyBytesObject *)obj)->ob_sval, + ((PyVarObject *)obj)->ob_size, + enc, err); + } else { + return PyUnicode_FromEncodedObject(obj, enc, err); + } +} + +PyObject *CPy_Encode(PyObject *obj, PyObject *encoding, PyObject *errors) { + const char *enc = NULL; + const char *err = NULL; + if (encoding) { + enc = PyUnicode_AsUTF8AndSize(encoding, NULL); + if (!enc) return NULL; + } + if (errors) { + err = PyUnicode_AsUTF8AndSize(errors, NULL); + if (!err) return NULL; + } + if (PyUnicode_Check(obj)) { + return PyUnicode_AsEncodedString(obj, enc, err); + } else { + PyErr_BadArgument(); + return NULL; + } +} diff --git a/mypyc/namegen.py b/mypyc/namegen.py index a6c0c24dd85c..acf901caf93c 100644 --- a/mypyc/namegen.py +++ b/mypyc/namegen.py @@ -43,11 +43,11 @@ def __init__(self, groups: Iterable[List[str]]) -> None: names are supported for generated names, but uncompiled modules will use long names. """ - self.module_map = {} # type: Dict[str, str] + self.module_map: Dict[str, str] = {} for names in groups: self.module_map.update(make_module_translation_map(names)) - self.translations = {} # type: Dict[Tuple[str, str], str] - self.used_names = set() # type: Set[str] + self.translations: Dict[Tuple[str, str], str] = {} + self.used_names: Set[str] = set() def private_name(self, module: str, partial_name: Optional[str] = None) -> str: """Return a C name usable for a static definition. @@ -90,7 +90,7 @@ def exported_name(fullname: str) -> str: def make_module_translation_map(names: List[str]) -> Dict[str, str]: - num_instances = {} # type: Dict[str, int] + num_instances: Dict[str, int] = {} for name in names: for suffix in candidate_suffixes(name): num_instances[suffix] = num_instances.get(suffix, 0) + 1 diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py new file mode 100644 index 000000000000..6ddb5e38111c --- /dev/null +++ b/mypyc/primitives/bytes_ops.py @@ -0,0 +1,84 @@ +"""Primitive bytes ops.""" + +from mypyc.ir.ops import ERR_MAGIC +from mypyc.ir.rtypes import ( + object_rprimitive, bytes_rprimitive, list_rprimitive, dict_rprimitive, + str_rprimitive, c_int_rprimitive, RUnion, c_pyssize_t_rprimitive, + int_rprimitive, +) +from mypyc.primitives.registry import ( + load_address_op, function_op, method_op, binary_op, custom_op, ERR_NEG_INT +) + +# Get the 'bytes' type object. +load_address_op( + name='builtins.bytes', + type=object_rprimitive, + src='PyBytes_Type') + +# bytes(obj) +function_op( + name='builtins.bytes', + arg_types=[RUnion([list_rprimitive, dict_rprimitive, str_rprimitive])], + return_type=bytes_rprimitive, + c_function_name='PyBytes_FromObject', + error_kind=ERR_MAGIC) + +# bytearray(obj) +function_op( + name='builtins.bytearray', + arg_types=[object_rprimitive], + return_type=bytes_rprimitive, + c_function_name='PyByteArray_FromObject', + error_kind=ERR_MAGIC) + +# bytes ==/!= (return -1/0/1) +bytes_compare = custom_op( + arg_types=[bytes_rprimitive, bytes_rprimitive], + return_type=c_int_rprimitive, + c_function_name='CPyBytes_Compare', + error_kind=ERR_NEG_INT) + +# bytes + bytes +# bytearray + bytearray +binary_op( + name='+', + arg_types=[bytes_rprimitive, bytes_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPyBytes_Concat', + error_kind=ERR_MAGIC, + steals=[True, False]) + +# bytes[begin:end] +bytes_slice_op = custom_op( + arg_types=[bytes_rprimitive, int_rprimitive, int_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPyBytes_GetSlice', + error_kind=ERR_MAGIC) + +# bytes[index] +# bytearray[index] +method_op( + name='__getitem__', + arg_types=[bytes_rprimitive, int_rprimitive], + return_type=int_rprimitive, + c_function_name='CPyBytes_GetItem', + error_kind=ERR_MAGIC) + +# bytes.join(obj) +method_op( + name='join', + arg_types=[bytes_rprimitive, object_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPyBytes_Join', + error_kind=ERR_MAGIC) + +# Join bytes objects and return a new bytes. +# The first argument is the total number of the following bytes. +bytes_build_op = custom_op( + arg_types=[c_pyssize_t_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPyBytes_Build', + error_kind=ERR_MAGIC, + var_arg_type=bytes_rprimitive +) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index e176ffcac316..4fe8693c66c5 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -17,6 +17,14 @@ type=object_rprimitive, src='PyDict_Type') +# Construct an empty dictionary via dict(). +function_op( + name='builtins.dict', + arg_types=[], + return_type=dict_rprimitive, + c_function_name='PyDict_New', + error_kind=ERR_MAGIC) + # Construct an empty dictionary. dict_new_op = custom_op( arg_types=[], @@ -111,7 +119,7 @@ error_kind=ERR_MAGIC) # dict.get(key) -method_op( +dict_get_method_with_none = method_op( name='get', arg_types=[dict_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -119,7 +127,7 @@ error_kind=ERR_MAGIC) # dict.setdefault(key, default) -method_op( +dict_setdefault_op = method_op( name='setdefault', arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -135,6 +143,16 @@ is_borrowed=True, error_kind=ERR_MAGIC) +# dict.setdefault(key, empty tuple/list/set) +# The third argument marks the data type of the second argument. +# 1: list 2: dict 3: set +# Other number would lead to an error. +dict_setdefault_spec_init_op = custom_op( + arg_types=[dict_rprimitive, object_rprimitive, c_int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyDict_SetDefaultWithEmptyDatatype', + error_kind=ERR_MAGIC) + # dict.keys() method_op( name='keys', @@ -240,7 +258,7 @@ c_function_name='CPyDict_CheckSize', error_kind=ERR_FALSE) -dict_size_op = custom_op( +dict_ssize_t_size_op = custom_op( arg_types=[dict_rprimitive], return_type=c_pyssize_t_rprimitive, c_function_name='PyDict_Size', diff --git a/mypyc/primitives/generic_ops.py b/mypyc/primitives/generic_ops.py index 5c93426c5eb7..402de4524b88 100644 --- a/mypyc/primitives/generic_ops.py +++ b/mypyc/primitives/generic_ops.py @@ -15,7 +15,7 @@ object_pointer_rprimitive, c_size_t_rprimitive, c_pyssize_t_rprimitive ) from mypyc.primitives.registry import ( - binary_op, c_unary_op, method_op, function_op, custom_op, ERR_NEG_INT + binary_op, unary_op, method_op, function_op, custom_op, ERR_NEG_INT ) @@ -46,7 +46,8 @@ ('>>', 'PyNumber_Rshift'), ('&', 'PyNumber_And'), ('^', 'PyNumber_Xor'), - ('|', 'PyNumber_Or')]: + ('|', 'PyNumber_Or'), + ('@', 'PyNumber_MatrixMultiply')]: binary_op(name=op, arg_types=[object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -96,14 +97,14 @@ for op, funcname in [('-', 'PyNumber_Negative'), ('+', 'PyNumber_Positive'), ('~', 'PyNumber_Invert')]: - c_unary_op(name=op, - arg_type=object_rprimitive, - return_type=object_rprimitive, - c_function_name=funcname, - error_kind=ERR_MAGIC, - priority=0) + unary_op(name=op, + arg_type=object_rprimitive, + return_type=object_rprimitive, + c_function_name=funcname, + error_kind=ERR_MAGIC, + priority=0) -c_unary_op( +unary_op( name='not', arg_type=object_rprimitive, return_type=c_int_rprimitive, diff --git a/mypyc/primitives/int_ops.py b/mypyc/primitives/int_ops.py index ce10b8b9c66e..f4a2ce8c66e3 100644 --- a/mypyc/primitives/int_ops.py +++ b/mypyc/primitives/int_ops.py @@ -15,7 +15,7 @@ str_rprimitive, bit_rprimitive, RType ) from mypyc.primitives.registry import ( - load_address_op, c_unary_op, CFunctionDescription, function_op, binary_op, custom_op + load_address_op, unary_op, CFunctionDescription, function_op, binary_op, custom_op ) # These int constructors produce object_rprimitives that then need to be unboxed @@ -28,7 +28,7 @@ type=object_rprimitive, src='PyLong_Type') -# Convert from a float to int. We could do a bit better directly. +# int(float). We could do a bit better directly. function_op( name='builtins.int', arg_types=[float_rprimitive], @@ -52,8 +52,8 @@ c_function_name='CPyLong_FromStrWithBase', error_kind=ERR_MAGIC) -# str(n) on ints -function_op( +# str(int) +int_to_str_op = function_op( name='builtins.str', arg_types=[int_rprimitive], return_type=str_rprimitive, @@ -114,11 +114,11 @@ def int_binary_op(name: str, c_function_name: str, def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription: - return c_unary_op(name=name, - arg_type=int_rprimitive, - return_type=int_rprimitive, - c_function_name=c_function_name, - error_kind=ERR_NEVER) + return unary_op(name=name, + arg_type=int_rprimitive, + return_type=int_rprimitive, + c_function_name=c_function_name, + error_kind=ERR_NEVER) int_neg_op = int_unary_op('-', 'CPyTagged_Negate') @@ -155,11 +155,11 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription: # Provide mapping from textual op to short int's op variant and boxed int's description. # Note that these are not complete implementations and require extra IR. -int_comparison_op_mapping = { +int_comparison_op_mapping: Dict[str, IntComparisonOpDescription] = { '==': IntComparisonOpDescription(ComparisonOp.EQ, int_equal_, False, False), '!=': IntComparisonOpDescription(ComparisonOp.NEQ, int_equal_, True, False), '<': IntComparisonOpDescription(ComparisonOp.SLT, int_less_than_, False, False), '<=': IntComparisonOpDescription(ComparisonOp.SLE, int_less_than_, True, True), '>': IntComparisonOpDescription(ComparisonOp.SGT, int_less_than_, False, True), '>=': IntComparisonOpDescription(ComparisonOp.SGE, int_less_than_, True, False), -} # type: Dict[str, IntComparisonOpDescription] +} diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index 9abb0a46f4a8..3988511c9772 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -22,8 +22,16 @@ arg_types=[object_rprimitive], return_type=list_rprimitive, c_function_name='PySequence_List', + error_kind=ERR_MAGIC) + +# Construct an empty list via list(). +function_op( + name='builtins.list', + arg_types=[], + return_type=list_rprimitive, + c_function_name='PyList_New', error_kind=ERR_MAGIC, -) + extra_int_constants=[(0, int_rprimitive)]) new_list_op = custom_op( arg_types=[c_pyssize_t_rprimitive], @@ -31,6 +39,14 @@ c_function_name='PyList_New', error_kind=ERR_MAGIC) +list_build_op = custom_op( + arg_types=[c_pyssize_t_rprimitive], + return_type=list_rprimitive, + c_function_name='CPyList_Build', + error_kind=ERR_MAGIC, + var_arg_type=object_rprimitive, + steals=True) + # list[index] (for an integer index) list_get_item_op = method_op( name='__getitem__', @@ -163,11 +179,12 @@ error_kind=ERR_MAGIC) # int * list -binary_op(name='*', - arg_types=[int_rprimitive, list_rprimitive], - return_type=list_rprimitive, - c_function_name='CPySequence_RMultiply', - error_kind=ERR_MAGIC) +binary_op( + name='*', + arg_types=[int_rprimitive, list_rprimitive], + return_type=list_rprimitive, + c_function_name='CPySequence_RMultiply', + error_kind=ERR_MAGIC) # list[begin:end] list_slice_op = custom_op( diff --git a/mypyc/primitives/misc_ops.py b/mypyc/primitives/misc_ops.py index 4f3a49c14a9f..cfdbb8a0f78d 100644 --- a/mypyc/primitives/misc_ops.py +++ b/mypyc/primitives/misc_ops.py @@ -3,7 +3,8 @@ from mypyc.ir.ops import ERR_NEVER, ERR_MAGIC, ERR_FALSE from mypyc.ir.rtypes import ( bool_rprimitive, object_rprimitive, str_rprimitive, object_pointer_rprimitive, - int_rprimitive, dict_rprimitive, c_int_rprimitive, bit_rprimitive, c_pyssize_t_rprimitive + int_rprimitive, dict_rprimitive, c_int_rprimitive, bit_rprimitive, c_pyssize_t_rprimitive, + list_rprimitive, ) from mypyc.primitives.registry import ( function_op, custom_op, load_address_op, ERR_NEG_INT @@ -15,6 +16,12 @@ type=object_rprimitive, src='PyBool_Type') +# Get the 'range' type object. +load_address_op( + name='builtins.range', + type=object_rprimitive, + src='PyRange_Type') + # Get the boxed Python 'None' object none_object_op = load_address_op( name='Py_None', @@ -107,6 +114,24 @@ c_function_name='PyImport_Import', error_kind=ERR_MAGIC) +# Import with extra arguments (used in from import handling) +import_extra_args_op = custom_op( + arg_types=[str_rprimitive, dict_rprimitive, dict_rprimitive, + list_rprimitive, c_int_rprimitive], + return_type=object_rprimitive, + c_function_name='PyImport_ImportModuleLevelObject', + error_kind=ERR_MAGIC +) + +# Import-from helper op +import_from_op = custom_op( + arg_types=[object_rprimitive, str_rprimitive, + str_rprimitive, str_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyImport_ImportFrom', + error_kind=ERR_MAGIC +) + # Get the sys.modules dictionary get_module_dict_op = custom_op( arg_types=[], @@ -116,7 +141,7 @@ is_borrowed=True) # isinstance(obj, cls) -function_op( +slow_isinstance_op = function_op( name='builtins.isinstance', arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -189,3 +214,12 @@ return_type=c_int_rprimitive, c_function_name='CPySequence_CheckUnpackCount', error_kind=ERR_NEG_INT) + + +# register an implementation for a singledispatch function +register_function = custom_op( + arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], + return_type=object_rprimitive, + c_function_name='CPySingledispatch_RegisterFunction', + error_kind=ERR_MAGIC, +) diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index cefbda71cfdf..5ed910549f5a 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -43,7 +43,7 @@ # Error kind for functions that return negative integer on exception. This # is only used for primitives. We translate it away during IR building. -ERR_NEG_INT = 10 # type: Final +ERR_NEG_INT: Final = 10 CFunctionDescription = NamedTuple( @@ -68,18 +68,18 @@ # CallC op for method call(such as 'str.join') -method_call_ops = {} # type: Dict[str, List[CFunctionDescription]] +method_call_ops: Dict[str, List[CFunctionDescription]] = {} # CallC op for top level function call(such as 'builtins.list') -function_ops = {} # type: Dict[str, List[CFunctionDescription]] +function_ops: Dict[str, List[CFunctionDescription]] = {} # CallC op for binary ops -binary_ops = {} # type: Dict[str, List[CFunctionDescription]] +binary_ops: Dict[str, List[CFunctionDescription]] = {} # CallC op for unary ops -unary_ops = {} # type: Dict[str, List[CFunctionDescription]] +unary_ops: Dict[str, List[CFunctionDescription]] = {} -builtin_names = {} # type: Dict[str, Tuple[RType, str]] +builtin_names: Dict[str, Tuple[RType, str]] = {} def method_op(name: str, @@ -202,17 +202,17 @@ def custom_op(arg_types: List[RType], extra_int_constants, 0) -def c_unary_op(name: str, - arg_type: RType, - return_type: RType, - c_function_name: str, - error_kind: int, - truncated_type: Optional[RType] = None, - ordering: Optional[List[int]] = None, - extra_int_constants: List[Tuple[int, RType]] = [], - steals: StealsDescription = False, - is_borrowed: bool = False, - priority: int = 1) -> CFunctionDescription: +def unary_op(name: str, + arg_type: RType, + return_type: RType, + c_function_name: str, + error_kind: int, + truncated_type: Optional[RType] = None, + ordering: Optional[List[int]] = None, + extra_int_constants: List[Tuple[int, RType]] = [], + steals: StealsDescription = False, + is_borrowed: bool = False, + priority: int = 1) -> CFunctionDescription: """Define a c function call op for an unary operation. This will be automatically generated by matching against the AST. @@ -239,6 +239,7 @@ def load_address_op(name: str, # Import various modules that set up global state. import mypyc.primitives.int_ops # noqa import mypyc.primitives.str_ops # noqa +import mypyc.primitives.bytes_ops # noqa import mypyc.primitives.list_ops # noqa import mypyc.primitives.dict_ops # noqa import mypyc.primitives.tuple_ops # noqa diff --git a/mypyc/primitives/str_ops.py b/mypyc/primitives/str_ops.py index 4e56d885528b..e7db008f4218 100644 --- a/mypyc/primitives/str_ops.py +++ b/mypyc/primitives/str_ops.py @@ -5,11 +5,12 @@ from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import ( RType, object_rprimitive, str_rprimitive, int_rprimitive, list_rprimitive, - c_int_rprimitive, pointer_rprimitive, bool_rprimitive, bit_rprimitive + c_int_rprimitive, pointer_rprimitive, bool_rprimitive, bit_rprimitive, + c_pyssize_t_rprimitive, bytes_rprimitive ) from mypyc.primitives.registry import ( method_op, binary_op, function_op, - load_address_op, custom_op + load_address_op, custom_op, ERR_NEG_INT ) @@ -20,7 +21,7 @@ src='PyUnicode_Type') # str(obj) -function_op( +str_op = function_op( name='builtins.str', arg_types=[object_rprimitive], return_type=str_rprimitive, @@ -28,11 +29,46 @@ error_kind=ERR_MAGIC) # str1 + str2 -binary_op(name='+', - arg_types=[str_rprimitive, str_rprimitive], - return_type=str_rprimitive, - c_function_name='PyUnicode_Concat', - error_kind=ERR_MAGIC) +binary_op( + name='+', + arg_types=[str_rprimitive, str_rprimitive], + return_type=str_rprimitive, + c_function_name='PyUnicode_Concat', + error_kind=ERR_MAGIC) + +# str1 += str2 +# +# PyUnicode_Append makes an effort to reuse the LHS when the refcount +# is 1. This is super dodgy but oh well, the interpreter does it. +binary_op( + name='+=', + arg_types=[str_rprimitive, str_rprimitive], + return_type=str_rprimitive, + c_function_name='CPyStr_Append', + error_kind=ERR_MAGIC, + steals=[True, False]) + +unicode_compare = custom_op( + arg_types=[str_rprimitive, str_rprimitive], + return_type=c_int_rprimitive, + c_function_name='PyUnicode_Compare', + error_kind=ERR_NEVER) + +# str[index] (for an int index) +method_op( + name='__getitem__', + arg_types=[str_rprimitive, int_rprimitive], + return_type=str_rprimitive, + c_function_name='CPyStr_GetItem', + error_kind=ERR_MAGIC +) + +# str[begin:end] +str_slice_op = custom_op( + arg_types=[str_rprimitive, int_rprimitive, int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyStr_GetSlice', + error_kind=ERR_MAGIC) # str.join(obj) method_op( @@ -43,6 +79,14 @@ error_kind=ERR_MAGIC ) +str_build_op = custom_op( + arg_types=[c_pyssize_t_rprimitive], + return_type=str_rprimitive, + c_function_name='CPyStr_Build', + error_kind=ERR_MAGIC, + var_arg_type=str_rprimitive +) + # str.startswith(str) method_op( name='startswith', @@ -61,22 +105,14 @@ error_kind=ERR_NEVER ) -# str[index] (for an int index) -method_op( - name='__getitem__', - arg_types=[str_rprimitive, int_rprimitive], - return_type=str_rprimitive, - c_function_name='CPyStr_GetItem', - error_kind=ERR_MAGIC -) - # str.split(...) -str_split_types = [str_rprimitive, str_rprimitive, int_rprimitive] # type: List[RType] -str_split_functions = ['PyUnicode_Split', 'PyUnicode_Split', 'CPyStr_Split'] -str_split_constants = [[(0, pointer_rprimitive), (-1, c_int_rprimitive)], - [(-1, c_int_rprimitive)], - []] \ - # type: List[List[Tuple[int, RType]]] +str_split_types: List[RType] = [str_rprimitive, str_rprimitive, int_rprimitive] +str_split_functions = ["PyUnicode_Split", "PyUnicode_Split", "CPyStr_Split"] +str_split_constants: List[List[Tuple[int, RType]]] = [ + [(0, pointer_rprimitive), (-1, c_int_rprimitive)], + [(-1, c_int_rprimitive)], + [], +] for i in range(len(str_split_types)): method_op( name='split', @@ -86,36 +122,12 @@ extra_int_constants=str_split_constants[i], error_kind=ERR_MAGIC) -# str1 += str2 -# -# PyUnicodeAppend makes an effort to reuse the LHS when the refcount -# is 1. This is super dodgy but oh well, the interpreter does it. -binary_op(name='+=', - arg_types=[str_rprimitive, str_rprimitive], - return_type=str_rprimitive, - c_function_name='CPyStr_Append', - error_kind=ERR_MAGIC, - steals=[True, False]) - -unicode_compare = custom_op( - arg_types=[str_rprimitive, str_rprimitive], - return_type=c_int_rprimitive, - c_function_name='PyUnicode_Compare', - error_kind=ERR_NEVER) - -# str[begin:end] -str_slice_op = custom_op( - arg_types=[str_rprimitive, int_rprimitive, int_rprimitive], - return_type=object_rprimitive, - c_function_name='CPyStr_GetSlice', - error_kind=ERR_MAGIC) - # str.replace(old, new) method_op( name='replace', arg_types=[str_rprimitive, str_rprimitive, str_rprimitive], return_type=str_rprimitive, - c_function_name="PyUnicode_Replace", + c_function_name='PyUnicode_Replace', error_kind=ERR_MAGIC, extra_int_constants=[(-1, c_int_rprimitive)]) @@ -124,13 +136,70 @@ name='replace', arg_types=[str_rprimitive, str_rprimitive, str_rprimitive, int_rprimitive], return_type=str_rprimitive, - c_function_name="CPyStr_Replace", + c_function_name='CPyStr_Replace', error_kind=ERR_MAGIC) # check if a string is true (isn't an empty string) str_check_if_true = custom_op( arg_types=[str_rprimitive], return_type=bit_rprimitive, - c_function_name="CPyStr_IsTrue", - error_kind=ERR_NEVER, -) + c_function_name='CPyStr_IsTrue', + error_kind=ERR_NEVER) + +str_ssize_t_size_op = custom_op( + arg_types=[str_rprimitive], + return_type=c_pyssize_t_rprimitive, + c_function_name='CPyStr_Size_size_t', + error_kind=ERR_NEG_INT) + +# obj.decode() +method_op( + name='decode', + arg_types=[bytes_rprimitive], + return_type=str_rprimitive, + c_function_name='CPy_Decode', + error_kind=ERR_MAGIC, + extra_int_constants=[(0, pointer_rprimitive), (0, pointer_rprimitive)]) + +# obj.decode(encoding) +method_op( + name='decode', + arg_types=[bytes_rprimitive, str_rprimitive], + return_type=str_rprimitive, + c_function_name='CPy_Decode', + error_kind=ERR_MAGIC, + extra_int_constants=[(0, pointer_rprimitive)]) + +# obj.decode(encoding, errors) +method_op( + name='decode', + arg_types=[bytes_rprimitive, str_rprimitive, str_rprimitive], + return_type=str_rprimitive, + c_function_name='CPy_Decode', + error_kind=ERR_MAGIC) + +# str.encode() +method_op( + name='encode', + arg_types=[str_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPy_Encode', + error_kind=ERR_MAGIC, + extra_int_constants=[(0, pointer_rprimitive), (0, pointer_rprimitive)]) + +# str.encode(encoding) +method_op( + name='encode', + arg_types=[str_rprimitive, str_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPy_Encode', + error_kind=ERR_MAGIC, + extra_int_constants=[(0, pointer_rprimitive)]) + +# str.encode(encoding, errors) +method_op( + name='encode', + arg_types=[str_rprimitive, str_rprimitive, str_rprimitive], + return_type=bytes_rprimitive, + c_function_name='CPy_Encode', + error_kind=ERR_MAGIC) diff --git a/mypyc/test-data/analysis.test b/mypyc/test-data/analysis.test index 48105d5607bd..efd219cc222a 100644 --- a/mypyc/test-data/analysis.test +++ b/mypyc/test-data/analysis.test @@ -536,10 +536,8 @@ def lol(x): r2 :: object r3 :: str r4 :: object - r5 :: bit - r6 :: int - r7 :: bit - r8, r9 :: int + r5, r6 :: bit + r7, r8 :: int L0: L1: r0 = CPyTagged_Id(x) @@ -555,9 +553,8 @@ L3: r5 = CPy_ExceptionMatches(r4) if r5 goto L4 else goto L5 :: bool L4: - r6 = CPyTagged_Negate(2) CPy_RestoreExcInfo(r1) - return r6 + return -2 L5: CPy_Reraise() if not 0 goto L8 else goto L6 :: bool @@ -568,16 +565,16 @@ L7: goto L10 L8: CPy_RestoreExcInfo(r1) - r7 = CPy_KeepPropagating() - if not r7 goto L11 else goto L9 :: bool + r6 = CPy_KeepPropagating() + if not r6 goto L11 else goto L9 :: bool L9: unreachable L10: - r8 = CPyTagged_Add(st, 2) - return r8 + r7 = CPyTagged_Add(st, 2) + return r7 L11: - r9 = :: int - return r9 + r8 = :: int + return r8 (0, 0) {x} {x} (1, 0) {x} {r0} (1, 1) {r0} {st} @@ -589,20 +586,18 @@ L11: (2, 4) {r1, r4} {r1, r4} (3, 0) {r1, r4} {r1, r5} (3, 1) {r1, r5} {r1} -(4, 0) {r1} {r1, r6} -(4, 1) {r1, r6} {r6} -(4, 2) {r6} {} +(4, 0) {r1} {} +(4, 1) {} {} (5, 0) {r1} {r1} (5, 1) {r1} {r1} (6, 0) {} {} (7, 0) {r1, st} {st} (7, 1) {st} {st} (8, 0) {r1} {} -(8, 1) {} {r7} -(8, 2) {r7} {} +(8, 1) {} {r6} +(8, 2) {r6} {} (9, 0) {} {} -(10, 0) {st} {r8} -(10, 1) {r8} {} -(11, 0) {} {r9} -(11, 1) {r9} {} - +(10, 0) {st} {r7} +(10, 1) {r7} {} +(11, 0) {} {r8} +(11, 1) {r8} {} diff --git a/mypyc/test-data/commandline.test b/mypyc/test-data/commandline.test index 8ff21a37089d..971a4c4a254c 100644 --- a/mypyc/test-data/commandline.test +++ b/mypyc/test-data/commandline.test @@ -24,6 +24,7 @@ for x in [a, b, p, p.q]: import b import c from p import s +from typing import NamedTuple print('', ord('A') == 65) # Test full builtins @@ -42,6 +43,11 @@ print('', f(5).x) print('', c.foo()) assert s.bar(10) == 20 +class NT(NamedTuple): + x: int + +print(NT(2)) + [file b.py] import a import p.q @@ -79,6 +85,7 @@ def bar(x: int) -> int: True 5 10 +NT(x=2)
16 -- This test is here so we can turn it on when we get nervous about @@ -98,9 +105,10 @@ def f(x: int) -> int: # cmd: test.py [file test.py] -from typing import List, Any +from typing import List, Any, AsyncIterable from typing_extensions import Final from mypy_extensions import trait, mypyc_attr +from functools import singledispatch def busted(b: bool) -> None: for i in range(1, 10, 0): # E: range() step can't be zero @@ -192,3 +200,43 @@ class AllowInterp1(Concrete1): # E: Base class "test.Concrete1" does not allow @mypyc_attr(allow_interpreted_subclasses=True) class AllowInterp2(PureTrait): # E: Base class "test.PureTrait" does not allow interpreted subclasses pass + +async def async_for(xs: AsyncIterable[int]) -> None: + async for x in xs: # E: async for is unimplemented + print(x) + + [x async for x in xs] # E: async comprehensions are unimplemented + (x async for x in xs) # E: async comprehensions are unimplemented # W: Treating generator comprehension as list + {x async for x in xs} # E: async comprehensions are unimplemented + {x: x async for x in xs} # E: async comprehensions are unimplemented + +class async_ctx: + async def __aenter__(self) -> int: pass + async def __aexit__(self, x, y, z) -> None: pass + +async def async_with() -> None: + async with async_ctx() as x: # E: async with is unimplemented + print(x) + +async def async_generators() -> AsyncIterable[int]: + yield 1 # E: async generators are unimplemented + +@singledispatch +def a(arg) -> None: + pass + +@decorator # E: Calling decorator after registering function not supported +@a.register +def g(arg: int) -> None: + pass + +@a.register +@decorator +def h(arg: str) -> None: + pass + +@decorator +@decorator # E: Calling decorator after registering function not supported +@a.register +def i(arg: Foo) -> None: + pass diff --git a/mypyc/test-data/driver/driver.py b/mypyc/test-data/driver/driver.py index 4db9843358f1..6717f402f72d 100644 --- a/mypyc/test-data/driver/driver.py +++ b/mypyc/test-data/driver/driver.py @@ -26,7 +26,9 @@ def extract_line(tb): formatted = '\n'.join(format_tb(tb)) - m = re.search('File "native.py", line ([0-9]+), in test_', formatted) + m = re.search('File "(native|driver).py", line ([0-9]+), in (test_|)', formatted) + if m is None: + return "0" return m.group(1) # Sort failures by line number of test function. diff --git a/mypyc/test-data/exceptions-freq.test b/mypyc/test-data/exceptions-freq.test new file mode 100644 index 000000000000..26b690a99503 --- /dev/null +++ b/mypyc/test-data/exceptions-freq.test @@ -0,0 +1,124 @@ +-- Test cases for basic block execution frequency analysis. +-- +-- These test cases are using exception transform test machinery for convenience. +-- +-- NOTE: These must all have the _freq suffix + +[case testSimpleError_freq] +from typing import List +def f(x: List[int]) -> int: + return x[0] +[out] +def f(x): + x :: list + r0 :: object + r1, r2 :: int +L0: + r0 = CPyList_GetItemShort(x, 0) + if is_error(r0) goto L3 (error at f:3) else goto L1 +L1: + r1 = unbox(int, r0) + dec_ref r0 + if is_error(r1) goto L3 (error at f:3) else goto L2 +L2: + return r1 +L3: + r2 = :: int + return r2 +hot blocks: [0, 1, 2] + +[case testHotBranch_freq] +from typing import List +def f(x: bool) -> None: + if x: + y = 1 + else: + y = 2 +[out] +def f(x): + x :: bool + y :: int +L0: + if x goto L1 else goto L2 :: bool +L1: + y = 2 + dec_ref y :: int + goto L3 +L2: + y = 4 + dec_ref y :: int +L3: + return 1 +hot blocks: [0, 1, 2, 3] + +[case testGoto_freq] +from typing import List +def f(x: bool) -> int: + if x: + y = 1 + else: + return 2 + return y +[out] +def f(x): + x :: bool + y :: int +L0: + if x goto L1 else goto L2 :: bool +L1: + y = 2 + goto L3 +L2: + return 4 +L3: + return y +hot blocks: [0, 1, 2, 3] + +[case testFalseOnError_freq] +from typing import List +def f(x: List[int]) -> None: + x[0] = 1 +[out] +def f(x): + x :: list + r0 :: object + r1 :: bit + r2 :: None +L0: + r0 = box(short_int, 2) + r1 = CPyList_SetItem(x, 0, r0) + if not r1 goto L2 (error at f:3) else goto L1 :: bool +L1: + return 1 +L2: + r2 = :: None + return r2 +hot blocks: [0, 1] + +[case testRareBranch_freq] +from typing_extensions import Final + +x: Final = str() + +def f() -> str: + return x +[out] +def f(): + r0 :: str + r1 :: bool + r2 :: str +L0: + r0 = __main__.x :: static + if is_error(r0) goto L1 else goto L3 +L1: + r1 = raise NameError('value for final name "x" was not set') + if not r1 goto L4 (error at f:6) else goto L2 :: bool +L2: + unreachable +L3: + inc_ref r0 + return r0 +L4: + r2 = :: str + return r2 +hot blocks: [0, 3] diff --git a/mypyc/test-data/exceptions.test b/mypyc/test-data/exceptions.test index 87bfb6fd9fb7..9d688a4c0651 100644 --- a/mypyc/test-data/exceptions.test +++ b/mypyc/test-data/exceptions.test @@ -259,7 +259,7 @@ L1: L2: r3 = PyObject_CallFunctionObjArgs(r2, 0) dec_ref r2 - if is_error(r3) goto L5 (error at a:3) else goto L20 + if is_error(r3) goto L5 (error at a:3) else goto L19 L3: r4 = 'hi' inc_ref r4 @@ -278,52 +278,52 @@ L6: r11 = builtins :: module r12 = 'print' r13 = CPyObject_GetAttr(r11, r12) - if is_error(r13) goto L13 (error at a:6) else goto L7 + if is_error(r13) goto L20 (error at a:6) else goto L7 L7: r14 = PyObject_CallFunctionObjArgs(r13, r10, 0) dec_ref r13 - if is_error(r14) goto L13 (error at a:6) else goto L21 + if is_error(r14) goto L20 (error at a:6) else goto L21 L8: - if is_error(r7) goto L11 else goto L9 + if is_error(r7) goto L11 else goto L22 L9: CPy_Reraise() - if not 0 goto L13 else goto L22 :: bool + if not 0 goto L13 else goto L23 :: bool L10: unreachable L11: - if is_error(r5) goto L18 else goto L12 + if is_error(r5) goto L17 else goto L12 L12: return r5 L13: - if is_error(r5) goto L14 else goto L23 + if is_error(r7) goto L15 else goto L14 L14: - if is_error(r7) goto L16 else goto L15 -L15: CPy_RestoreExcInfo(r7) - dec_ref r7 -L16: + xdec_ref r7 +L15: r15 = CPy_KeepPropagating() - if not r15 goto L19 else goto L17 :: bool + if not r15 goto L18 else goto L16 :: bool +L16: + unreachable L17: unreachable L18: - unreachable -L19: r16 = :: str return r16 -L20: +L19: dec_ref r3 goto L3 +L20: + xdec_ref r5 + goto L13 L21: dec_ref r14 goto L8 L22: - dec_ref r5 - dec_ref r7 - goto L10 + xdec_ref r5 + goto L9 L23: - dec_ref r5 - goto L14 + xdec_ref r7 + goto L10 [case testDocstring1] def lol() -> None: diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index b13deed90f4a..786f77143e9e 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -36,6 +36,7 @@ def __sub__(self, n: int) -> int: pass def __mul__(self, n: int) -> int: pass def __pow__(self, n: int, modulo: Optional[int] = None) -> int: pass def __floordiv__(self, x: int) -> int: pass + def __truediv__(self, x: float) -> float: pass def __mod__(self, x: int) -> int: pass def __neg__(self) -> int: pass def __pos__(self) -> int: pass @@ -74,10 +75,11 @@ def split(self, sep: Optional[str] = None, max: Optional[int] = None) -> List[st def strip (self, item: str) -> str: pass def join(self, x: Iterable[str]) -> str: pass def format(self, *args: Any, **kwargs: Any) -> str: ... - def upper(self) -> str: pass - def startswith(self, x: str, start: int=..., end: int=...) -> bool: pass - def endswith(self, x: str, start: int=..., end: int=...) -> bool: pass - def replace(self, old: str, new: str, maxcount: Optional[int] = None) -> str: pass + def upper(self) -> str: ... + def startswith(self, x: str, start: int=..., end: int=...) -> bool: ... + def endswith(self, x: str, start: int=..., end: int=...) -> bool: ... + def replace(self, old: str, new: str, maxcount: int=...) -> str: ... + def encode(self, x: str=..., y: str=...) -> bytes: ... class float: def __init__(self, x: object) -> None: pass @@ -96,11 +98,31 @@ def __truediv__(self, n: complex) -> complex: pass def __neg__(self) -> complex: pass class bytes: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, x: object) -> None: ... + def __add__(self, x: bytes) -> bytes: ... + def __eq__(self, x: object) -> bool: ... + def __ne__(self, x: object) -> bool: ... + @overload + def __getitem__(self, i: int) -> int: ... + @overload + def __getitem__(self, i: slice) -> bytes: ... + def join(self, x: Iterable[object]) -> bytes: ... + def decode(self, x: str=..., y: str=...) -> str: ... + +class bytearray: + @overload + def __init__(self) -> None: pass + @overload def __init__(self, x: object) -> None: pass - def __add__(self, x: object) -> bytes: pass - def __eq__(self, x:object) -> bool:pass - def __ne__(self, x: object) -> bool: pass - def join(self, x: Iterable[object]) -> bytes: pass + @overload + def __init__(self, string: str, encoding: str, err: str = ...) -> None: pass + def __add__(self, s: bytes) -> bytearray: ... + def __setitem__(self, i: int, o: int) -> None: ... + def __getitem__(self, i: int) -> int: ... + def decode(self, x: str = ..., y: str = ...) -> str: ... class bool(int): def __init__(self, o: object = ...) -> None: ... @@ -177,7 +199,7 @@ def values(self) -> Iterable[V]: pass def items(self) -> Iterable[Tuple[K, V]]: pass def clear(self) -> None: pass def copy(self) -> Dict[K, V]: pass - def setdefault(self, k: K, v: Optional[V] = None) -> Optional[V]: pass + def setdefault(self, key: K, val: V = ...) -> V: pass class set(Generic[T]): def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass @@ -193,6 +215,12 @@ def __or__(self, s: Set[S]) -> Set[Union[T, S]]: ... class slice: pass +class range(Iterable[int]): + def __init__(self, x: int, y: int = ..., z: int = ...) -> None: pass + def __iter__(self) -> Iterator[int]: pass + def __len__(self) -> int: pass + def __next__(self) -> int: pass + class property: def __init__(self, fget: Optional[Callable[[Any], Any]] = ..., fset: Optional[Callable[[Any, Any], None]] = ..., @@ -223,6 +251,8 @@ class ValueError(Exception): pass class AttributeError(Exception): pass +class ImportError(Exception): pass + class NameError(Exception): pass class LookupError(Exception): pass @@ -233,19 +263,27 @@ class IndexError(LookupError): pass class RuntimeError(Exception): pass +class UnicodeEncodeError(RuntimeError): pass + +class UnicodeDecodeError(RuntimeError): pass + class NotImplementedError(RuntimeError): pass class StopIteration(Exception): value: Any +class ArithmeticError(Exception): pass + +class ZeroDivisionError(Exception): pass + def any(i: Iterable[T]) -> bool: pass def all(i: Iterable[T]) -> bool: pass +def sum(i: Iterable[T]) -> int: pass def reversed(object: Sequence[T]) -> Iterator[T]: ... def id(o: object) -> int: pass # This type is obviously wrong but the test stubs don't have Sized anymore def len(o: object) -> int: pass def print(*object) -> None: pass -def range(x: int, y: int = ..., z: int = ...) -> Iterator[int]: pass def isinstance(x: object, t: object) -> bool: pass def iter(i: Iterable[T]) -> Iterator[T]: pass @overload @@ -254,7 +292,8 @@ def next(i: Iterator[T]) -> T: pass def next(i: Iterator[T], default: T) -> T: pass def hash(o: object) -> int: ... def globals() -> Dict[str, Any]: ... -def setattr(object: Any, name: str, value: Any) -> None: ... +def getattr(obj: object, name: str) -> Any: ... +def setattr(obj: object, name: str, value: Any) -> None: ... def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ... @overload def zip(x: Iterable[T], y: Iterable[S]) -> Iterator[Tuple[T, S]]: ... @@ -263,9 +302,15 @@ def zip(x: Iterable[T], y: Iterable[S], z: Iterable[V]) -> Iterator[Tuple[T, S, def eval(e: str) -> Any: ... def abs(x: float) -> float: ... def exit() -> None: ... +def min(x: T, y: T) -> T: ... +def max(x: T, y: T) -> T: ... +def repr(o: object) -> str: ... +def ascii(o: object) -> str: ... +def ord(o: object) -> int: ... +def chr(i: int) -> str: ... # Dummy definitions. class classmethod: pass class staticmethod: pass -NotImplemented = ... # type: Any +NotImplemented: Any = ... diff --git a/mypyc/test-data/fixtures/testutil.py b/mypyc/test-data/fixtures/testutil.py index ad53e474c8bf..462b02c1946d 100644 --- a/mypyc/test-data/fixtures/testutil.py +++ b/mypyc/test-data/fixtures/testutil.py @@ -1,7 +1,10 @@ # Simple support library for our run tests. from contextlib import contextmanager -from typing import Iterator, TypeVar, Generator, Optional, List, Tuple, Sequence, Union +from typing import ( + Any, Iterator, TypeVar, Generator, Optional, List, Tuple, Sequence, + Union, Callable, +) @contextmanager def assertRaises(typ: type, msg: str = '') -> Iterator[None]: @@ -20,7 +23,7 @@ def assertRaises(typ: type, msg: str = '') -> Iterator[None]: def run_generator(gen: Generator[T, V, U], inputs: Optional[List[V]] = None, p: bool = False) -> Tuple[Sequence[T], Union[U, str]]: - res = [] # type: List[T] + res: List[T] = [] i = -1 while True: try: @@ -37,3 +40,13 @@ def run_generator(gen: Generator[T, V, U], print(val) res.append(val) i += 1 + +F = TypeVar('F', bound=Callable) + + +# Wrap a mypyc-generated function in a real python function, to allow it to be +# stuck into classes and the like. +def make_python_function(f: F) -> F: + def g(*args: Any, **kwargs: Any) -> Any: + return f(*args, **kwargs) + return g # type: ignore diff --git a/mypyc/test-data/fixtures/typing-full.pyi b/mypyc/test-data/fixtures/typing-full.pyi index b2a9c5bccb2b..c36b1001106e 100644 --- a/mypyc/test-data/fixtures/typing-full.pyi +++ b/mypyc/test-data/fixtures/typing-full.pyi @@ -141,6 +141,9 @@ class MutableMapping(Mapping[T, U], metaclass=ABCMeta): class SupportsInt(Protocol): def __int__(self) -> int: pass +class SupportsFloat(Protocol): + def __float__(self) -> float: pass + def runtime_checkable(cls: T) -> T: return cls diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 40fe1f5aa809..2032ea034e71 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -581,12 +581,12 @@ L8: [case testUnaryMinus] def f(n: int) -> int: - return -1 + return -n [out] def f(n): n, r0 :: int L0: - r0 = CPyTagged_Negate(2) + r0 = CPyTagged_Negate(n) return r0 [case testConditionalExpr] @@ -761,7 +761,7 @@ def f() -> bytes: return b'1234' [out] def f(): - r0, x, r1 :: object + r0, x, r1 :: bytes L0: r0 = b'\xf0' x = r0 @@ -1748,10 +1748,10 @@ def g(): r6, r7 :: dict r8 :: str r9 :: object - r10 :: tuple - r11 :: dict - r12 :: int32 - r13 :: bit + r10 :: dict + r11 :: int32 + r12 :: bit + r13 :: tuple r14 :: object r15 :: tuple[int, int, int] L0: @@ -1765,11 +1765,11 @@ L0: r7 = __main__.globals :: static r8 = 'f' r9 = CPyDict_GetItem(r7, r8) - r10 = PyTuple_Pack(0) - r11 = PyDict_New() - r12 = CPyDict_UpdateInDisplay(r11, r6) - r13 = r12 >= 0 :: signed - r14 = PyObject_Call(r9, r10, r11) + r10 = PyDict_New() + r11 = CPyDict_UpdateInDisplay(r10, r6) + r12 = r11 >= 0 :: signed + r13 = PyTuple_Pack(0) + r14 = PyObject_Call(r9, r13, r10) r15 = unbox(tuple[int, int, int], r14) return r15 def h(): @@ -1777,11 +1777,12 @@ def h(): r2, r3 :: object r4, r5 :: dict r6 :: str - r7, r8 :: object - r9 :: tuple - r10 :: dict - r11 :: int32 - r12 :: bit + r7 :: object + r8 :: dict + r9 :: int32 + r10 :: bit + r11 :: object + r12 :: tuple r13 :: object r14 :: tuple[int, int, int] L0: @@ -1793,12 +1794,12 @@ L0: r5 = __main__.globals :: static r6 = 'f' r7 = CPyDict_GetItem(r5, r6) - r8 = box(short_int, 2) - r9 = PyTuple_Pack(1, r8) - r10 = PyDict_New() - r11 = CPyDict_UpdateInDisplay(r10, r4) - r12 = r11 >= 0 :: signed - r13 = PyObject_Call(r7, r9, r10) + r8 = PyDict_New() + r9 = CPyDict_UpdateInDisplay(r8, r4) + r10 = r9 >= 0 :: signed + r11 = box(short_int, 2) + r12 = PyTuple_Pack(1, r11) + r13 = PyObject_Call(r7, r12, r8) r14 = unbox(tuple[int, int, int], r13) return r14 @@ -2491,80 +2492,82 @@ def __top_level__(): r0, r1 :: object r2 :: bit r3 :: str - r4, r5, r6 :: object - r7 :: bit - r8 :: str - r9, r10 :: object - r11 :: dict - r12 :: str - r13 :: object + r4 :: object + r5 :: dict + r6, r7, r8 :: str + r9 :: list + r10, r11, r12, r13 :: ptr r14 :: str - r15 :: int32 - r16 :: bit - r17 :: str - r18 :: object - r19 :: str - r20 :: int32 - r21 :: bit - r22 :: str - r23 :: object - r24 :: str - r25 :: int32 - r26 :: bit - r27, r28 :: str - r29 :: object - r30 :: tuple[str, object] - r31 :: object - r32 :: str + r15 :: object + r16, r17, r18 :: str + r19 :: object + r20 :: str + r21 :: int32 + r22 :: bit + r23, r24, r25 :: str + r26 :: object + r27 :: str + r28 :: int32 + r29 :: bit + r30, r31, r32 :: str r33 :: object - r34 :: tuple[str, object] - r35 :: object - r36 :: tuple[object, object] - r37 :: object - r38 :: dict - r39 :: str - r40, r41 :: object - r42 :: dict - r43 :: str - r44 :: int32 - r45 :: bit - r46 :: str - r47 :: dict - r48 :: str - r49, r50, r51 :: object - r52 :: tuple - r53 :: dict - r54 :: str - r55 :: int32 - r56 :: bit + r34 :: str + r35 :: int32 + r36 :: bit + r37, r38 :: str + r39 :: object + r40 :: tuple[str, object] + r41 :: object + r42 :: str + r43 :: object + r44 :: tuple[str, object] + r45 :: object + r46 :: tuple[object, object] + r47 :: object + r48 :: dict + r49 :: str + r50, r51 :: object + r52 :: dict + r53 :: str + r54 :: int32 + r55 :: bit + r56 :: str r57 :: dict r58 :: str r59, r60, r61 :: object - r62 :: dict - r63 :: str - r64 :: int32 - r65 :: bit - r66 :: str + r62 :: tuple + r63 :: dict + r64 :: str + r65 :: int32 + r66 :: bit r67 :: dict r68 :: str - r69 :: object - r70 :: dict - r71 :: str - r72, r73 :: object - r74 :: dict - r75 :: str - r76 :: int32 - r77 :: bit - r78 :: list - r79, r80, r81 :: object - r82, r83, r84, r85 :: ptr - r86 :: dict - r87 :: str - r88, r89 :: object - r90 :: dict - r91 :: str - r92 :: int32 - r93 :: bit + r69, r70, r71 :: object + r72 :: dict + r73 :: str + r74 :: int32 + r75 :: bit + r76 :: str + r77 :: dict + r78 :: str + r79 :: object + r80 :: dict + r81 :: str + r82, r83 :: object + r84 :: dict + r85 :: str + r86 :: int32 + r87 :: bit + r88 :: list + r89, r90, r91 :: object + r92, r93, r94, r95 :: ptr + r96 :: dict + r97 :: str + r98, r99 :: object + r100 :: dict + r101 :: str + r102 :: int32 + r103 :: bit L0: r0 = builtins :: module r1 = load_address _Py_NoneStruct @@ -2575,103 +2578,114 @@ L1: r4 = PyImport_Import(r3) builtins = r4 :: module L2: - r5 = typing :: module - r6 = load_address _Py_NoneStruct - r7 = r5 != r6 - if r7 goto L4 else goto L3 :: bool -L3: - r8 = 'typing' - r9 = PyImport_Import(r8) - typing = r9 :: module -L4: - r10 = typing :: module - r11 = __main__.globals :: static - r12 = 'List' - r13 = CPyObject_GetAttr(r10, r12) - r14 = 'List' - r15 = CPyDict_SetItem(r11, r14, r13) - r16 = r15 >= 0 :: signed - r17 = 'NewType' - r18 = CPyObject_GetAttr(r10, r17) - r19 = 'NewType' - r20 = CPyDict_SetItem(r11, r19, r18) - r21 = r20 >= 0 :: signed - r22 = 'NamedTuple' - r23 = CPyObject_GetAttr(r10, r22) - r24 = 'NamedTuple' - r25 = CPyDict_SetItem(r11, r24, r23) - r26 = r25 >= 0 :: signed - r27 = 'Lol' - r28 = 'a' - r29 = load_address PyLong_Type - r30 = (r28, r29) - r31 = box(tuple[str, object], r30) - r32 = 'b' - r33 = load_address PyUnicode_Type - r34 = (r32, r33) - r35 = box(tuple[str, object], r34) - r36 = (r31, r35) - r37 = box(tuple[object, object], r36) - r38 = __main__.globals :: static - r39 = 'NamedTuple' - r40 = CPyDict_GetItem(r38, r39) - r41 = PyObject_CallFunctionObjArgs(r40, r27, r37, 0) - r42 = __main__.globals :: static - r43 = 'Lol' - r44 = CPyDict_SetItem(r42, r43, r41) - r45 = r44 >= 0 :: signed - r46 = '' - r47 = __main__.globals :: static - r48 = 'Lol' - r49 = CPyDict_GetItem(r47, r48) - r50 = box(short_int, 2) - r51 = PyObject_CallFunctionObjArgs(r49, r50, r46, 0) - r52 = cast(tuple, r51) - r53 = __main__.globals :: static - r54 = 'x' - r55 = CPyDict_SetItem(r53, r54, r52) - r56 = r55 >= 0 :: signed + r5 = __main__.globals :: static + r6 = 'List' + r7 = 'NewType' + r8 = 'NamedTuple' + r9 = PyList_New(3) + r10 = get_element_ptr r9 ob_item :: PyListObject + r11 = load_mem r10 :: ptr* + set_mem r11, r6 :: builtins.object* + r12 = r11 + WORD_SIZE*1 + set_mem r12, r7 :: builtins.object* + r13 = r11 + WORD_SIZE*2 + set_mem r13, r8 :: builtins.object* + keep_alive r9 + r14 = 'typing' + r15 = PyImport_ImportModuleLevelObject(r14, r5, 0, r9, 0) + typing = r15 :: module + r16 = 'typing' + r17 = 'List' + r18 = 'List' + r19 = CPyImport_ImportFrom(r15, r16, r17, r18) + r20 = 'List' + r21 = CPyDict_SetItem(r5, r20, r19) + r22 = r21 >= 0 :: signed + r23 = 'typing' + r24 = 'NewType' + r25 = 'NewType' + r26 = CPyImport_ImportFrom(r15, r23, r24, r25) + r27 = 'NewType' + r28 = CPyDict_SetItem(r5, r27, r26) + r29 = r28 >= 0 :: signed + r30 = 'typing' + r31 = 'NamedTuple' + r32 = 'NamedTuple' + r33 = CPyImport_ImportFrom(r15, r30, r31, r32) + r34 = 'NamedTuple' + r35 = CPyDict_SetItem(r5, r34, r33) + r36 = r35 >= 0 :: signed + r37 = 'Lol' + r38 = 'a' + r39 = load_address PyLong_Type + r40 = (r38, r39) + r41 = box(tuple[str, object], r40) + r42 = 'b' + r43 = load_address PyUnicode_Type + r44 = (r42, r43) + r45 = box(tuple[str, object], r44) + r46 = (r41, r45) + r47 = box(tuple[object, object], r46) + r48 = __main__.globals :: static + r49 = 'NamedTuple' + r50 = CPyDict_GetItem(r48, r49) + r51 = PyObject_CallFunctionObjArgs(r50, r37, r47, 0) + r52 = __main__.globals :: static + r53 = 'Lol' + r54 = CPyDict_SetItem(r52, r53, r51) + r55 = r54 >= 0 :: signed + r56 = '' r57 = __main__.globals :: static - r58 = 'List' + r58 = 'Lol' r59 = CPyDict_GetItem(r57, r58) - r60 = load_address PyLong_Type - r61 = PyObject_GetItem(r59, r60) - r62 = __main__.globals :: static - r63 = 'Foo' - r64 = CPyDict_SetItem(r62, r63, r61) - r65 = r64 >= 0 :: signed - r66 = 'Bar' + r60 = box(short_int, 2) + r61 = PyObject_CallFunctionObjArgs(r59, r60, r56, 0) + r62 = cast(tuple, r61) + r63 = __main__.globals :: static + r64 = 'x' + r65 = CPyDict_SetItem(r63, r64, r62) + r66 = r65 >= 0 :: signed r67 = __main__.globals :: static - r68 = 'Foo' + r68 = 'List' r69 = CPyDict_GetItem(r67, r68) - r70 = __main__.globals :: static - r71 = 'NewType' - r72 = CPyDict_GetItem(r70, r71) - r73 = PyObject_CallFunctionObjArgs(r72, r66, r69, 0) - r74 = __main__.globals :: static - r75 = 'Bar' - r76 = CPyDict_SetItem(r74, r75, r73) - r77 = r76 >= 0 :: signed - r78 = PyList_New(3) - r79 = box(short_int, 2) - r80 = box(short_int, 4) - r81 = box(short_int, 6) - r82 = get_element_ptr r78 ob_item :: PyListObject - r83 = load_mem r82 :: ptr* - set_mem r83, r79 :: builtins.object* - r84 = r83 + WORD_SIZE*1 - set_mem r84, r80 :: builtins.object* - r85 = r83 + WORD_SIZE*2 - set_mem r85, r81 :: builtins.object* - keep_alive r78 - r86 = __main__.globals :: static - r87 = 'Bar' - r88 = CPyDict_GetItem(r86, r87) - r89 = PyObject_CallFunctionObjArgs(r88, r78, 0) - r90 = __main__.globals :: static - r91 = 'y' - r92 = CPyDict_SetItem(r90, r91, r89) - r93 = r92 >= 0 :: signed + r70 = load_address PyLong_Type + r71 = PyObject_GetItem(r69, r70) + r72 = __main__.globals :: static + r73 = 'Foo' + r74 = CPyDict_SetItem(r72, r73, r71) + r75 = r74 >= 0 :: signed + r76 = 'Bar' + r77 = __main__.globals :: static + r78 = 'Foo' + r79 = CPyDict_GetItem(r77, r78) + r80 = __main__.globals :: static + r81 = 'NewType' + r82 = CPyDict_GetItem(r80, r81) + r83 = PyObject_CallFunctionObjArgs(r82, r76, r79, 0) + r84 = __main__.globals :: static + r85 = 'Bar' + r86 = CPyDict_SetItem(r84, r85, r83) + r87 = r86 >= 0 :: signed + r88 = PyList_New(3) + r89 = box(short_int, 2) + r90 = box(short_int, 4) + r91 = box(short_int, 6) + r92 = get_element_ptr r88 ob_item :: PyListObject + r93 = load_mem r92 :: ptr* + set_mem r93, r89 :: builtins.object* + r94 = r93 + WORD_SIZE*1 + set_mem r94, r90 :: builtins.object* + r95 = r93 + WORD_SIZE*2 + set_mem r95, r91 :: builtins.object* + keep_alive r88 + r96 = __main__.globals :: static + r97 = 'Bar' + r98 = CPyDict_GetItem(r96, r97) + r99 = PyObject_CallFunctionObjArgs(r98, r88, 0) + r100 = __main__.globals :: static + r101 = 'y' + r102 = CPyDict_SetItem(r100, r101, r99) + r103 = r102 >= 0 :: signed return 1 [case testChainedConditional] @@ -2916,7 +2930,7 @@ L0: r0.g = r2; r4 = is_error r5 = r0.g return r5 -def __mypyc_d_decorator_helper_____mypyc_c_decorator_helper___obj.__get__(__mypyc_self__, instance, owner): +def d_c_obj.__get__(__mypyc_self__, instance, owner): __mypyc_self__, instance, owner, r0 :: object r1 :: bit r2 :: object @@ -2929,9 +2943,9 @@ L1: L2: r2 = PyMethod_New(__mypyc_self__, instance) return r2 -def __mypyc_d_decorator_helper_____mypyc_c_decorator_helper___obj.__call__(__mypyc_self__): - __mypyc_self__ :: __main__.__mypyc_d_decorator_helper_____mypyc_c_decorator_helper___obj - r0 :: __main__.__mypyc_c_decorator_helper___env +def d_c_obj.__call__(__mypyc_self__): + __mypyc_self__ :: __main__.d_c_obj + r0 :: __main__.c_env r1, d :: object r2 :: str r3 :: object @@ -2947,9 +2961,9 @@ L0: r5 = CPyObject_GetAttr(r3, r4) r6 = PyObject_CallFunctionObjArgs(r5, r2, 0) return 1 -def __mypyc_c_decorator_helper__(): - r0 :: __main__.__mypyc_c_decorator_helper___env - r1 :: __main__.__mypyc_d_decorator_helper_____mypyc_c_decorator_helper___obj +def c(): + r0 :: __main__.c_env + r1 :: __main__.d_c_obj r2 :: bool r3 :: dict r4 :: str @@ -2958,13 +2972,17 @@ def __mypyc_c_decorator_helper__(): r8 :: str r9, r10 :: object r11 :: bool - r12 :: str - r13 :: object - r14 :: str - r15, r16, r17, r18 :: object + r12 :: dict + r13 :: str + r14 :: int32 + r15 :: bit + r16 :: str + r17 :: object + r18 :: str + r19, r20, r21, r22 :: object L0: - r0 = __mypyc_c_decorator_helper___env() - r1 = __mypyc_d_decorator_helper_____mypyc_c_decorator_helper___obj() + r0 = c_env() + r1 = d_c_obj() r1.__mypyc_env__ = r0; r2 = is_error r3 = __main__.globals :: static r4 = 'b' @@ -2975,41 +2993,47 @@ L0: r9 = CPyDict_GetItem(r7, r8) r10 = PyObject_CallFunctionObjArgs(r9, r6, 0) r0.d = r10; r11 = is_error - r12 = 'c' - r13 = builtins :: module - r14 = 'print' - r15 = CPyObject_GetAttr(r13, r14) - r16 = PyObject_CallFunctionObjArgs(r15, r12, 0) - r17 = r0.d - r18 = PyObject_CallFunctionObjArgs(r17, 0) + r12 = __main__.globals :: static + r13 = 'd' + r14 = CPyDict_SetItem(r12, r13, r10) + r15 = r14 >= 0 :: signed + r16 = 'c' + r17 = builtins :: module + r18 = 'print' + r19 = CPyObject_GetAttr(r17, r18) + r20 = PyObject_CallFunctionObjArgs(r19, r16, 0) + r21 = r0.d + r22 = PyObject_CallFunctionObjArgs(r21, 0) return 1 def __top_level__(): r0, r1 :: object r2 :: bit r3 :: str - r4, r5, r6 :: object - r7 :: bit - r8 :: str - r9, r10 :: object - r11 :: dict - r12 :: str - r13 :: object - r14 :: str - r15 :: int32 - r16 :: bit - r17 :: dict - r18 :: str - r19 :: object - r20 :: dict - r21 :: str - r22, r23 :: object - r24 :: dict - r25 :: str - r26, r27 :: object - r28 :: dict - r29 :: str - r30 :: int32 - r31 :: bit + r4 :: object + r5 :: dict + r6 :: str + r7 :: list + r8, r9 :: ptr + r10 :: str + r11 :: object + r12, r13, r14 :: str + r15 :: object + r16 :: str + r17 :: int32 + r18 :: bit + r19 :: dict + r20 :: str + r21 :: object + r22 :: dict + r23 :: str + r24, r25 :: object + r26 :: dict + r27 :: str + r28, r29 :: object + r30 :: dict + r31 :: str + r32 :: int32 + r33 :: bit L0: r0 = builtins :: module r1 = load_address _Py_NoneStruct @@ -3020,37 +3044,38 @@ L1: r4 = PyImport_Import(r3) builtins = r4 :: module L2: - r5 = typing :: module - r6 = load_address _Py_NoneStruct - r7 = r5 != r6 - if r7 goto L4 else goto L3 :: bool -L3: - r8 = 'typing' - r9 = PyImport_Import(r8) - typing = r9 :: module -L4: - r10 = typing :: module - r11 = __main__.globals :: static - r12 = 'Callable' - r13 = CPyObject_GetAttr(r10, r12) + r5 = __main__.globals :: static + r6 = 'Callable' + r7 = PyList_New(1) + r8 = get_element_ptr r7 ob_item :: PyListObject + r9 = load_mem r8 :: ptr* + set_mem r9, r6 :: builtins.object* + keep_alive r7 + r10 = 'typing' + r11 = PyImport_ImportModuleLevelObject(r10, r5, 0, r7, 0) + typing = r11 :: module + r12 = 'typing' + r13 = 'Callable' r14 = 'Callable' - r15 = CPyDict_SetItem(r11, r14, r13) - r16 = r15 >= 0 :: signed - r17 = __main__.globals :: static - r18 = '__mypyc_c_decorator_helper__' - r19 = CPyDict_GetItem(r17, r18) - r20 = __main__.globals :: static - r21 = 'b' - r22 = CPyDict_GetItem(r20, r21) - r23 = PyObject_CallFunctionObjArgs(r22, r19, 0) - r24 = __main__.globals :: static - r25 = 'a' - r26 = CPyDict_GetItem(r24, r25) - r27 = PyObject_CallFunctionObjArgs(r26, r23, 0) - r28 = __main__.globals :: static - r29 = 'c' - r30 = CPyDict_SetItem(r28, r29, r27) - r31 = r30 >= 0 :: signed + r15 = CPyImport_ImportFrom(r11, r12, r13, r14) + r16 = 'Callable' + r17 = CPyDict_SetItem(r5, r16, r15) + r18 = r17 >= 0 :: signed + r19 = __main__.globals :: static + r20 = 'c' + r21 = CPyDict_GetItem(r19, r20) + r22 = __main__.globals :: static + r23 = 'b' + r24 = CPyDict_GetItem(r22, r23) + r25 = PyObject_CallFunctionObjArgs(r24, r21, 0) + r26 = __main__.globals :: static + r27 = 'a' + r28 = CPyDict_GetItem(r26, r27) + r29 = PyObject_CallFunctionObjArgs(r28, r25, 0) + r30 = __main__.globals :: static + r31 = 'c' + r32 = CPyDict_SetItem(r30, r31, r29) + r33 = r32 >= 0 :: signed return 1 [case testDecoratorsSimple_toplevel] @@ -3125,16 +3150,18 @@ def __top_level__(): r0, r1 :: object r2 :: bit r3 :: str - r4, r5, r6 :: object - r7 :: bit - r8 :: str - r9, r10 :: object - r11 :: dict - r12 :: str - r13 :: object - r14 :: str - r15 :: int32 - r16 :: bit + r4 :: object + r5 :: dict + r6 :: str + r7 :: list + r8, r9 :: ptr + r10 :: str + r11 :: object + r12, r13, r14 :: str + r15 :: object + r16 :: str + r17 :: int32 + r18 :: bit L0: r0 = builtins :: module r1 = load_address _Py_NoneStruct @@ -3145,22 +3172,23 @@ L1: r4 = PyImport_Import(r3) builtins = r4 :: module L2: - r5 = typing :: module - r6 = load_address _Py_NoneStruct - r7 = r5 != r6 - if r7 goto L4 else goto L3 :: bool -L3: - r8 = 'typing' - r9 = PyImport_Import(r8) - typing = r9 :: module -L4: - r10 = typing :: module - r11 = __main__.globals :: static - r12 = 'Callable' - r13 = CPyObject_GetAttr(r10, r12) + r5 = __main__.globals :: static + r6 = 'Callable' + r7 = PyList_New(1) + r8 = get_element_ptr r7 ob_item :: PyListObject + r9 = load_mem r8 :: ptr* + set_mem r9, r6 :: builtins.object* + keep_alive r7 + r10 = 'typing' + r11 = PyImport_ImportModuleLevelObject(r10, r5, 0, r7, 0) + typing = r11 :: module + r12 = 'typing' + r13 = 'Callable' r14 = 'Callable' - r15 = CPyDict_SetItem(r11, r14, r13) - r16 = r15 >= 0 :: signed + r15 = CPyImport_ImportFrom(r11, r12, r13, r14) + r16 = 'Callable' + r17 = CPyDict_SetItem(r5, r16, r15) + r18 = r17 >= 0 :: signed return 1 [case testAnyAllG] @@ -3259,6 +3287,46 @@ L10: L11: return r0 +[case testSum] +from typing import Callable, Iterable + +def call_sum(l: Iterable[int], comparison: Callable[[int], bool]) -> int: + return sum(comparison(x) for x in l) + +[out] +def call_sum(l, comparison): + l, comparison :: object + r0 :: int + r1, r2 :: object + r3, x :: int + r4, r5 :: object + r6 :: bool + r7 :: object + r8, r9 :: int + r10 :: bit +L0: + r0 = 0 + r1 = PyObject_GetIter(l) +L1: + r2 = PyIter_Next(r1) + if is_error(r2) goto L4 else goto L2 +L2: + r3 = unbox(int, r2) + x = r3 + r4 = box(int, x) + r5 = PyObject_CallFunctionObjArgs(comparison, r4, 0) + r6 = unbox(bool, r5) + r7 = box(bool, r6) + r8 = unbox(int, r7) + r9 = CPyTagged_Add(r0, r8) + r0 = r9 +L3: + goto L1 +L4: + r10 = CPy_NoErrOccured() +L5: + return r0 + [case testSetAttr1] from typing import Any, Dict, List def lol(x: Any): @@ -3649,3 +3717,95 @@ L0: r2 = r1 >= 0 :: signed r3 = truncate r1: int32 to builtins.bool return r3 + +[case testRangeObject] +def range_object() -> None: + r = range(4, 12, 2) + sum = 0 + for i in r: + sum += i + +def range_in_loop() -> None: + sum = 0 + for i in range(4, 12, 2): + sum += i +[out] +def range_object(): + r0, r1, r2, r3, r4 :: object + r5, r :: range + sum :: int + r6, r7 :: object + r8, i, r9 :: int + r10 :: bit +L0: + r0 = load_address PyRange_Type + r1 = box(short_int, 8) + r2 = box(short_int, 24) + r3 = box(short_int, 4) + r4 = PyObject_CallFunctionObjArgs(r0, r1, r2, r3, 0) + r5 = cast(range, r4) + r = r5 + sum = 0 + r6 = PyObject_GetIter(r) +L1: + r7 = PyIter_Next(r6) + if is_error(r7) goto L4 else goto L2 +L2: + r8 = unbox(int, r7) + i = r8 + r9 = CPyTagged_Add(sum, i) + sum = r9 +L3: + goto L1 +L4: + r10 = CPy_NoErrOccured() +L5: + return 1 +def range_in_loop(): + sum :: int + r0 :: short_int + i :: int + r1 :: bit + r2 :: int + r3 :: short_int +L0: + sum = 0 + r0 = 8 + i = r0 +L1: + r1 = r0 < 24 :: signed + if r1 goto L2 else goto L4 :: bool +L2: + r2 = CPyTagged_Add(sum, i) + sum = r2 +L3: + r3 = r0 + 4 + r0 = r3 + i = r3 + goto L1 +L4: + return 1 +[case testLocalRedefinition] +# mypy: allow-redefinition +def f() -> None: + i = 0 + i += 1 + i = "foo" + i += i + i = 0.0 +[out] +def f(): + i, r0 :: int + r1, i__redef__, r2 :: str + r3, i__redef____redef__ :: float +L0: + i = 0 + r0 = CPyTagged_Add(i, 2) + i = r0 + r1 = 'foo' + i__redef__ = r1 + r2 = CPyStr_Append(i__redef__, i__redef__) + i__redef__ = r2 + r3 = 0.0 + i__redef____redef__ = r3 + return 1 diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test new file mode 100644 index 000000000000..f13a1a956580 --- /dev/null +++ b/mypyc/test-data/irbuild-bytes.test @@ -0,0 +1,184 @@ +[case testBytesBasics] +def f(num: int, l: list, d: dict, s: str) -> None: + b1 = bytes() + b2 = bytes(num) + b3 = bytes(l) + b4 = bytes(d) + b5 = bytes(s) +[out] +def f(num, l, d, s): + num :: int + l :: list + d :: dict + s :: str + r0, r1 :: object + r2, b1 :: bytes + r3, r4, r5 :: object + r6, b2, r7, b3, r8, b4, r9, b5 :: bytes +L0: + r0 = load_address PyBytes_Type + r1 = PyObject_CallFunctionObjArgs(r0, 0) + r2 = cast(bytes, r1) + b1 = r2 + r3 = load_address PyBytes_Type + r4 = box(int, num) + r5 = PyObject_CallFunctionObjArgs(r3, r4, 0) + r6 = cast(bytes, r5) + b2 = r6 + r7 = PyBytes_FromObject(l) + b3 = r7 + r8 = PyBytes_FromObject(d) + b4 = r8 + r9 = PyBytes_FromObject(s) + b5 = r9 + return 1 + +[case testBytearrayBasics] +def f(s: str, num: int) -> None: + a = bytearray() + b = bytearray(s) + c = bytearray(num) +[out] +def f(s, num): + s :: str + num :: int + r0 :: object + r1 :: str + r2, r3, a :: object + r4 :: bytes + b, r5 :: object + r6 :: bytes + c :: object +L0: + r0 = builtins :: module + r1 = 'bytearray' + r2 = CPyObject_GetAttr(r0, r1) + r3 = PyObject_CallFunctionObjArgs(r2, 0) + a = r3 + r4 = PyByteArray_FromObject(s) + b = r4 + r5 = box(int, num) + r6 = PyByteArray_FromObject(r5) + c = r6 + return 1 + +[case testBytesEquality] +def eq(x: bytes, y: bytes) -> bool: + return x == y + +def neq(x: bytes, y: bytes) -> bool: + return x != y +[out] +def eq(x, y): + x, y :: bytes + r0 :: int32 + r1, r2 :: bit +L0: + r0 = CPyBytes_Compare(x, y) + r1 = r0 >= 0 :: signed + r2 = r0 == 1 + return r2 +def neq(x, y): + x, y :: bytes + r0 :: int32 + r1, r2 :: bit +L0: + r0 = CPyBytes_Compare(x, y) + r1 = r0 >= 0 :: signed + r2 = r0 != 1 + return r2 + +[case testBytesSlicing] +def f(a: bytes, start: int, end: int) -> bytes: + return a[start:end] +[out] +def f(a, start, end): + a :: bytes + start, end :: int + r0 :: bytes +L0: + r0 = CPyBytes_GetSlice(a, start, end) + return r0 + +[case testBytesIndex] +def f(a: bytes, i: int) -> int: + return a[i] +[out] +def f(a, i): + a :: bytes + i, r0 :: int +L0: + r0 = CPyBytes_GetItem(a, i) + return r0 + +[case testBytesConcat] +def f(a: bytes, b: bytes) -> bytes: + return a + b +[out] +def f(a, b): + a, b, r0 :: bytes +L0: + r0 = CPyBytes_Concat(a, b) + return r0 + +[case testBytesJoin] +from typing import List +def f(b: List[bytes]) -> bytes: + return b" ".join(b) +[out] +def f(b): + b :: list + r0, r1 :: bytes +L0: + r0 = b' ' + r1 = CPyBytes_Join(r0, b) + return r1 + +[case testBytesLen] +def f(b: bytes) -> int: + return len(b) +[out] +def f(b): + b :: bytes + r0 :: ptr + r1 :: native_int + r2 :: short_int +L0: + r0 = get_element_ptr b ob_size :: PyVarObject + r1 = load_mem r0 :: native_int* + keep_alive b + r2 = r1 << 1 + return r2 + +[case testBytesFormatting] +def f(var: bytes, num: int) -> None: + b1 = b'aaaa%bbbbb%s' % (var, var) + b2 = b'aaaa%bbbbb%s%d' % (var, var, num) + b3 = b'%b' % var + b4 = b'%ssss' % var +[typing fixtures/typing-full.pyi] +[out] +def f(var, num): + var :: bytes + num :: int + r0, r1, r2, b1, r3 :: bytes + r4 :: tuple[bytes, bytes, int] + r5, r6 :: object + r7, b2, r8, b3, r9, r10, b4 :: bytes +L0: + r0 = b'aaaa' + r1 = b'bbbb' + r2 = CPyBytes_Build(4, r0, var, r1, var) + b1 = r2 + r3 = b'aaaa%bbbbb%s%d' + r4 = (var, var, num) + r5 = box(tuple[bytes, bytes, int], r4) + r6 = PyNumber_Remainder(r3, r5) + r7 = cast(bytes, r6) + b2 = r7 + r8 = CPyBytes_Build(1, var) + b3 = r8 + r9 = b'sss' + r10 = CPyBytes_Build(2, var, r9) + b4 = r10 + return 1 diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index 1d09ab84ef86..8f9b768df47c 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -290,81 +290,84 @@ def __top_level__(): r0, r1 :: object r2 :: bit r3 :: str - r4, r5, r6 :: object - r7 :: bit - r8 :: str - r9, r10 :: object - r11 :: dict + r4 :: object + r5 :: dict + r6, r7 :: str + r8 :: list + r9, r10, r11 :: ptr r12 :: str r13 :: object - r14 :: str - r15 :: int32 - r16 :: bit - r17 :: str - r18 :: object - r19 :: str - r20 :: int32 - r21 :: bit - r22, r23 :: object - r24 :: bit + r14, r15, r16 :: str + r17 :: object + r18 :: str + r19 :: int32 + r20 :: bit + r21, r22, r23 :: str + r24 :: object r25 :: str - r26, r27 :: object + r26 :: int32 + r27 :: bit r28 :: dict r29 :: str - r30 :: object - r31 :: str - r32 :: int32 - r33 :: bit - r34 :: str - r35 :: dict - r36 :: str - r37, r38 :: object - r39 :: dict - r40 :: str - r41 :: int32 - r42 :: bit - r43 :: object + r30 :: list + r31, r32 :: ptr + r33 :: str + r34 :: object + r35, r36, r37 :: str + r38 :: object + r39 :: str + r40 :: int32 + r41 :: bit + r42 :: str + r43 :: dict r44 :: str r45, r46 :: object - r47 :: bool + r47 :: dict r48 :: str - r49 :: tuple - r50 :: int32 - r51 :: bit - r52 :: dict - r53 :: str - r54 :: int32 - r55 :: bit - r56 :: object - r57 :: str - r58, r59 :: object - r60 :: str - r61 :: tuple + r49 :: int32 + r50 :: bit + r51 :: object + r52 :: str + r53, r54 :: object + r55 :: bool + r56 :: str + r57 :: tuple + r58 :: int32 + r59 :: bit + r60 :: dict + r61 :: str r62 :: int32 r63 :: bit - r64 :: dict + r64 :: object r65 :: str - r66 :: int32 - r67 :: bit - r68, r69 :: object - r70 :: dict - r71 :: str - r72 :: object - r73 :: dict - r74 :: str - r75, r76 :: object - r77 :: tuple - r78 :: str - r79, r80 :: object - r81 :: bool - r82, r83 :: str - r84 :: tuple - r85 :: int32 - r86 :: bit - r87 :: dict - r88 :: str - r89 :: int32 - r90 :: bit + r66, r67 :: object + r68 :: str + r69 :: tuple + r70 :: int32 + r71 :: bit + r72 :: dict + r73 :: str + r74 :: int32 + r75 :: bit + r76, r77 :: object + r78 :: dict + r79 :: str + r80 :: object + r81 :: dict + r82 :: str + r83, r84 :: object + r85 :: tuple + r86 :: str + r87, r88 :: object + r89 :: bool + r90, r91 :: str + r92 :: tuple + r93 :: int32 + r94 :: bit + r95 :: dict + r96 :: str + r97 :: int32 + r98 :: bit L0: r0 = builtins :: module r1 = load_address _Py_NoneStruct @@ -375,103 +378,110 @@ L1: r4 = PyImport_Import(r3) builtins = r4 :: module L2: - r5 = typing :: module - r6 = load_address _Py_NoneStruct - r7 = r5 != r6 - if r7 goto L4 else goto L3 :: bool -L3: - r8 = 'typing' - r9 = PyImport_Import(r8) - typing = r9 :: module -L4: - r10 = typing :: module - r11 = __main__.globals :: static - r12 = 'TypeVar' - r13 = CPyObject_GetAttr(r10, r12) - r14 = 'TypeVar' - r15 = CPyDict_SetItem(r11, r14, r13) - r16 = r15 >= 0 :: signed - r17 = 'Generic' - r18 = CPyObject_GetAttr(r10, r17) - r19 = 'Generic' - r20 = CPyDict_SetItem(r11, r19, r18) - r21 = r20 >= 0 :: signed - r22 = mypy_extensions :: module - r23 = load_address _Py_NoneStruct - r24 = r22 != r23 - if r24 goto L6 else goto L5 :: bool -L5: - r25 = 'mypy_extensions' - r26 = PyImport_Import(r25) - mypy_extensions = r26 :: module -L6: - r27 = mypy_extensions :: module + r5 = __main__.globals :: static + r6 = 'TypeVar' + r7 = 'Generic' + r8 = PyList_New(2) + r9 = get_element_ptr r8 ob_item :: PyListObject + r10 = load_mem r9 :: ptr* + set_mem r10, r6 :: builtins.object* + r11 = r10 + WORD_SIZE*1 + set_mem r11, r7 :: builtins.object* + keep_alive r8 + r12 = 'typing' + r13 = PyImport_ImportModuleLevelObject(r12, r5, 0, r8, 0) + typing = r13 :: module + r14 = 'typing' + r15 = 'TypeVar' + r16 = 'TypeVar' + r17 = CPyImport_ImportFrom(r13, r14, r15, r16) + r18 = 'TypeVar' + r19 = CPyDict_SetItem(r5, r18, r17) + r20 = r19 >= 0 :: signed + r21 = 'typing' + r22 = 'Generic' + r23 = 'Generic' + r24 = CPyImport_ImportFrom(r13, r21, r22, r23) + r25 = 'Generic' + r26 = CPyDict_SetItem(r5, r25, r24) + r27 = r26 >= 0 :: signed r28 = __main__.globals :: static r29 = 'trait' - r30 = CPyObject_GetAttr(r27, r29) - r31 = 'trait' - r32 = CPyDict_SetItem(r28, r31, r30) - r33 = r32 >= 0 :: signed - r34 = 'T' - r35 = __main__.globals :: static - r36 = 'TypeVar' - r37 = CPyDict_GetItem(r35, r36) - r38 = PyObject_CallFunctionObjArgs(r37, r34, 0) - r39 = __main__.globals :: static - r40 = 'T' - r41 = CPyDict_SetItem(r39, r40, r38) - r42 = r41 >= 0 :: signed - r43 = :: object - r44 = '__main__' - r45 = __main__.C_template :: type - r46 = CPyType_FromTemplate(r45, r43, r44) - r47 = C_trait_vtable_setup() - r48 = '__mypyc_attrs__' - r49 = PyTuple_Pack(0) - r50 = PyObject_SetAttr(r46, r48, r49) - r51 = r50 >= 0 :: signed - __main__.C = r46 :: type - r52 = __main__.globals :: static - r53 = 'C' - r54 = CPyDict_SetItem(r52, r53, r46) - r55 = r54 >= 0 :: signed - r56 = :: object - r57 = '__main__' - r58 = __main__.S_template :: type - r59 = CPyType_FromTemplate(r58, r56, r57) - r60 = '__mypyc_attrs__' - r61 = PyTuple_Pack(0) - r62 = PyObject_SetAttr(r59, r60, r61) + r30 = PyList_New(1) + r31 = get_element_ptr r30 ob_item :: PyListObject + r32 = load_mem r31 :: ptr* + set_mem r32, r29 :: builtins.object* + keep_alive r30 + r33 = 'mypy_extensions' + r34 = PyImport_ImportModuleLevelObject(r33, r28, 0, r30, 0) + mypy_extensions = r34 :: module + r35 = 'mypy_extensions' + r36 = 'trait' + r37 = 'trait' + r38 = CPyImport_ImportFrom(r34, r35, r36, r37) + r39 = 'trait' + r40 = CPyDict_SetItem(r28, r39, r38) + r41 = r40 >= 0 :: signed + r42 = 'T' + r43 = __main__.globals :: static + r44 = 'TypeVar' + r45 = CPyDict_GetItem(r43, r44) + r46 = PyObject_CallFunctionObjArgs(r45, r42, 0) + r47 = __main__.globals :: static + r48 = 'T' + r49 = CPyDict_SetItem(r47, r48, r46) + r50 = r49 >= 0 :: signed + r51 = :: object + r52 = '__main__' + r53 = __main__.C_template :: type + r54 = CPyType_FromTemplate(r53, r51, r52) + r55 = C_trait_vtable_setup() + r56 = '__mypyc_attrs__' + r57 = PyTuple_Pack(0) + r58 = PyObject_SetAttr(r54, r56, r57) + r59 = r58 >= 0 :: signed + __main__.C = r54 :: type + r60 = __main__.globals :: static + r61 = 'C' + r62 = CPyDict_SetItem(r60, r61, r54) r63 = r62 >= 0 :: signed - __main__.S = r59 :: type - r64 = __main__.globals :: static - r65 = 'S' - r66 = CPyDict_SetItem(r64, r65, r59) - r67 = r66 >= 0 :: signed - r68 = __main__.C :: type - r69 = __main__.S :: type - r70 = __main__.globals :: static - r71 = 'Generic' - r72 = CPyDict_GetItem(r70, r71) - r73 = __main__.globals :: static - r74 = 'T' - r75 = CPyDict_GetItem(r73, r74) - r76 = PyObject_GetItem(r72, r75) - r77 = PyTuple_Pack(3, r68, r69, r76) - r78 = '__main__' - r79 = __main__.D_template :: type - r80 = CPyType_FromTemplate(r79, r77, r78) - r81 = D_trait_vtable_setup() - r82 = '__mypyc_attrs__' - r83 = '__dict__' - r84 = PyTuple_Pack(1, r83) - r85 = PyObject_SetAttr(r80, r82, r84) - r86 = r85 >= 0 :: signed - __main__.D = r80 :: type - r87 = __main__.globals :: static - r88 = 'D' - r89 = CPyDict_SetItem(r87, r88, r80) - r90 = r89 >= 0 :: signed + r64 = :: object + r65 = '__main__' + r66 = __main__.S_template :: type + r67 = CPyType_FromTemplate(r66, r64, r65) + r68 = '__mypyc_attrs__' + r69 = PyTuple_Pack(0) + r70 = PyObject_SetAttr(r67, r68, r69) + r71 = r70 >= 0 :: signed + __main__.S = r67 :: type + r72 = __main__.globals :: static + r73 = 'S' + r74 = CPyDict_SetItem(r72, r73, r67) + r75 = r74 >= 0 :: signed + r76 = __main__.C :: type + r77 = __main__.S :: type + r78 = __main__.globals :: static + r79 = 'Generic' + r80 = CPyDict_GetItem(r78, r79) + r81 = __main__.globals :: static + r82 = 'T' + r83 = CPyDict_GetItem(r81, r82) + r84 = PyObject_GetItem(r80, r83) + r85 = PyTuple_Pack(3, r76, r77, r84) + r86 = '__main__' + r87 = __main__.D_template :: type + r88 = CPyType_FromTemplate(r87, r85, r86) + r89 = D_trait_vtable_setup() + r90 = '__mypyc_attrs__' + r91 = '__dict__' + r92 = PyTuple_Pack(1, r91) + r93 = PyObject_SetAttr(r88, r90, r92) + r94 = r93 >= 0 :: signed + __main__.D = r88 :: type + r95 = __main__.globals :: static + r96 = 'D' + r97 = CPyDict_SetItem(r95, r96, r88) + r98 = r97 >= 0 :: signed return 1 [case testIsInstance] @@ -1069,3 +1079,106 @@ class A(B): pass class B(C): pass class C: pass [out] + +[case testDeletableSemanticAnalysis] +class Err1: + __deletable__ = 'x' # E: "__deletable__" must be initialized with a list or tuple expression +class Err2: + __deletable__ = [ + 1 # E: Invalid "__deletable__" item; string literal expected + ] +class Err3: + __deletable__ = ['x', ['y'], 'z'] # E: Invalid "__deletable__" item; string literal expected +class Err4: + __deletable__ = (1,) # E: Invalid "__deletable__" item; string literal expected +a = ['x'] +class Err5: + __deletable__ = a # E: "__deletable__" must be initialized with a list or tuple expression + +class Ok1: + __deletable__ = ('x',) + x: int +class Ok2: + __deletable__ = ['x'] + x: int + +[case testInvalidDeletableAttribute] +class NotDeletable: + __deletable__ = ['x'] + x: int + y: int + +def g(o: NotDeletable) -> None: + del o.x + del o.y # E: "y" cannot be deleted \ + # N: Using "__deletable__ = ['']" in the class body enables "del obj." + +class Base: + x: int + +class Deriv(Base): + __deletable__ = ['x'] # E: Attribute "x" not defined in "Deriv" (defined in "Base") + +class UndefinedDeletable: + __deletable__ = ['x'] # E: Attribute "x" not defined + +class DeletableProperty: + __deletable__ = ['prop'] # E: Cannot make property "prop" deletable + + @property + def prop(self) -> int: + return 5 + +[case testFinalDeletable] +from typing import Final + +class DeletableFinal1: + x: Final[int] # E: Deletable attribute cannot be final + + __deletable__ = ['x'] + + def __init__(self, x: int) -> None: + self.x = x + +class DeletableFinal2: + X: Final = 0 # E: Deletable attribute cannot be final + + __deletable__ = ['X'] + +[case testNeedAnnotateClassVar] +from typing import Final, ClassVar, Type + +class C: + a = 'A' + b: str = 'B' + f: Final = 'F' + c: ClassVar = 'C' + +class D(C): + pass + +def f() -> None: + C.a # E: Cannot access instance attribute "a" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + C.b # E: Cannot access instance attribute "b" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + C.f + C.c + + D.a # E: Cannot access instance attribute "a" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + D.b # E: Cannot access instance attribute "b" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + D.f + D.c + +def g(c: Type[C], d: Type[D]) -> None: + c.a # E: Cannot access instance attribute "a" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + c.f + c.c + + d.a # E: Cannot access instance attribute "a" through class object \ + # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) + d.f + d.c diff --git a/mypyc/test-data/irbuild-constant-fold.test b/mypyc/test-data/irbuild-constant-fold.test new file mode 100644 index 000000000000..7c09021c27ec --- /dev/null +++ b/mypyc/test-data/irbuild-constant-fold.test @@ -0,0 +1,263 @@ +[case testIntConstantFolding] +def bin_ops() -> None: + add = 15 + 47 + add_mul = (2 + 3) * 5 + sub = 7 - 11 + bit_and = 6 & 10 + bit_or = 6 | 10 + bit_xor = 6 ^ 10 + lshift = 5 << 2 + rshift = 13 >> 2 + lshift0 = 5 << 0 + rshift0 = 13 >> 0 +def unary_ops() -> None: + neg1 = -5 + neg2 = --1 + neg3 = -0 + pos = +5 + inverted1 = ~0 + inverted2 = ~5 + inverted3 = ~3 +def pow() -> None: + p0 = 3**0 + p1 = 3**5 + p2 = (-5)**3 + p3 = 0**0 +[out] +def bin_ops(): + add, add_mul, sub, bit_and, bit_or, bit_xor, lshift, rshift, lshift0, rshift0 :: int +L0: + add = 124 + add_mul = 50 + sub = -8 + bit_and = 4 + bit_or = 28 + bit_xor = 24 + lshift = 40 + rshift = 6 + lshift0 = 10 + rshift0 = 26 + return 1 +def unary_ops(): + neg1, neg2, neg3, pos, inverted1, inverted2, inverted3 :: int +L0: + neg1 = -10 + neg2 = 2 + neg3 = 0 + pos = 10 + inverted1 = -2 + inverted2 = -12 + inverted3 = -8 + return 1 +def pow(): + p0, p1, p2, p3 :: int +L0: + p0 = 2 + p1 = 486 + p2 = -250 + p3 = 2 + return 1 + +[case testIntConstantFoldingDivMod] +def div() -> None: + div1 = 25 // 5 + div2 = 24 // 5 + div3 = 29 // 5 + div4 = 30 // 5 + div_zero = 0 // 5 + neg1 = -1 // 3 + neg2 = -2 // 3 + neg3 = -3 // 3 + neg4 = -4 // 3 + neg_neg = -765467 // -234 + pos_neg = 983745 // -7864 +def mod() -> None: + mod1 = 25 % 5 + mod2 = 24 % 5 + mod3 = 29 % 5 + mod4 = 30 % 5 + mod_zero = 0 % 5 + neg1 = -4 % 3 + neg2 = -5 % 3 + neg3 = -6 % 3 + neg4 = -7 % 3 + neg_neg = -765467 % -234 + pos_neg = 983745 % -7864 +[out] +def div(): + div1, div2, div3, div4, div_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int +L0: + div1 = 10 + div2 = 8 + div3 = 10 + div4 = 12 + div_zero = 0 + neg1 = -2 + neg2 = -2 + neg3 = -2 + neg4 = -4 + neg_neg = 6542 + pos_neg = -252 + return 1 +def mod(): + mod1, mod2, mod3, mod4, mod_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int +L0: + mod1 = 0 + mod2 = 8 + mod3 = 8 + mod4 = 0 + mod_zero = 0 + neg1 = 4 + neg2 = 2 + neg3 = 0 + neg4 = 4 + neg_neg = -106 + pos_neg = -14238 + return 1 + +[case testIntConstantFoldingUnsupportedCases] +def error_cases() -> None: + div_by_zero = 5 // 0 + mod_by_zero = 5 % 0 + lshift_neg = 6 << -1 + rshift_neg = 7 >> -1 +def unsupported_div() -> None: + x = 4 / 6 + y = 10 / 5 +def unsupported_pow() -> None: + p = 3 ** (-1) +[out] +def error_cases(): + r0, div_by_zero, r1, mod_by_zero, r2, lshift_neg, r3, rshift_neg :: int +L0: + r0 = CPyTagged_FloorDivide(10, 0) + div_by_zero = r0 + r1 = CPyTagged_Remainder(10, 0) + mod_by_zero = r1 + r2 = CPyTagged_Lshift(12, -2) + lshift_neg = r2 + r3 = CPyTagged_Rshift(14, -2) + rshift_neg = r3 + return 1 +def unsupported_div(): + r0, r1, r2 :: object + r3, x :: float + r4, r5, r6 :: object + r7, y :: float +L0: + r0 = box(short_int, 8) + r1 = box(short_int, 12) + r2 = PyNumber_TrueDivide(r0, r1) + r3 = cast(float, r2) + x = r3 + r4 = box(short_int, 20) + r5 = box(short_int, 10) + r6 = PyNumber_TrueDivide(r4, r5) + r7 = cast(float, r6) + y = r7 + return 1 +def unsupported_pow(): + r0, r1, r2 :: object + r3, p :: float +L0: + r0 = box(short_int, 6) + r1 = box(short_int, -2) + r2 = CPyNumber_Power(r0, r1) + r3 = cast(float, r2) + p = r3 + return 1 + +[case testIntConstantFoldingBigIntResult_64bit] +def long_and_short() -> None: + # The smallest and largest representable short integers + short1 = 0x3ffffffffffffff0 + 0xf # (1 << 62) - 1 + short2 = -0x3fffffffffffffff - 1 # -(1 << 62) + short3 = -0x4000000000000000 + # Smallest big integers by absolute value + big1 = 1 << 62 + big2 = 0x4000000000000000 # 1 << 62 + big3 = -(1 << 62) - 1 + big4 = -0x4000000000000001 # -(1 << 62) - 1 + big5 = 123**41 +[out] +def long_and_short(): + short1, short2, short3, r0, big1, r1, big2, r2, big3, r3, big4, r4, big5 :: int +L0: + short1 = 9223372036854775806 + short2 = -9223372036854775808 + short3 = -9223372036854775808 + r0 = object 4611686018427387904 + big1 = r0 + r1 = object 4611686018427387904 + big2 = r1 + r2 = object -4611686018427387905 + big3 = r2 + r3 = object -4611686018427387905 + big4 = r3 + r4 = object 48541095000524544750127162673405880068636916264012200797813591925035550682238127143323 + big5 = r4 + return 1 + +[case testIntConstantFoldingFinal] +from typing_extensions import Final +X: Final = 5 +Y: Final = 2 + 4 + +def f() -> None: + a = X + 1 + # TODO: Constant fold this as well + a = Y + 1 +[out] +def f(): + a, r0 :: int + r1 :: bool + r2 :: int +L0: + a = 12 + r0 = __main__.Y :: static + if is_error(r0) goto L1 else goto L2 +L1: + r1 = raise NameError('value for final name "Y" was not set') + unreachable +L2: + r2 = CPyTagged_Add(r0, 2) + a = r2 + return 1 + +[case testIntConstantFoldingClassFinal] +from typing_extensions import Final +class C: + X: Final = 5 + +def f() -> None: + a = C.X + 1 +[out] +def C.__mypyc_defaults_setup(__mypyc_self__): + __mypyc_self__ :: __main__.C + r0 :: bool +L0: + __mypyc_self__.X = 10; r0 = is_error + return 1 +def f(): + a :: int +L0: + a = 12 + return 1 + +[case testStrConstantFolding] +from typing_extensions import Final + +S: Final = 'z' + +def f() -> None: + x = 'foo' + 'bar' + y = 'x' + 'y' + S +[out] +def f(): + r0, x, r1, y :: str +L0: + r0 = 'foobar' + x = r0 + r1 = 'xyz' + y = r1 + return 1 diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index da08ed79d5bd..69dd42f01dd3 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -42,6 +42,19 @@ L0: d = r0 return 1 +[case testNewEmptyDictViaFunc] +from typing import Dict +def f() -> None: + d: Dict[bool, int] = dict() + +[out] +def f(): + r0, d :: dict +L0: + r0 = PyDict_New() + d = r0 + return 1 + [case testNewDictWithValues] def f(x: object) -> None: d = {1: 2, '': x} @@ -141,8 +154,8 @@ def increment(d): r1 :: native_int r2 :: short_int r3 :: object - r4 :: tuple[bool, int, object] - r5 :: int + r4 :: tuple[bool, short_int, object] + r5 :: short_int r6 :: bool r7 :: object r8, k :: str @@ -219,8 +232,8 @@ def print_dict_methods(d1, d2): r1 :: native_int r2 :: short_int r3 :: object - r4 :: tuple[bool, int, object] - r5 :: int + r4 :: tuple[bool, short_int, object] + r5 :: short_int r6 :: bool r7 :: object r8, v :: int @@ -233,8 +246,8 @@ def print_dict_methods(d1, d2): r16 :: native_int r17 :: short_int r18 :: object - r19 :: tuple[bool, int, object, object] - r20 :: int + r19 :: tuple[bool, short_int, object, object] + r20 :: short_int r21 :: bool r22, r23 :: object r24, r25, k :: int @@ -340,6 +353,24 @@ L0: from typing import Dict def f(d: Dict[object, object]) -> object: return d.setdefault('a', 'b') + +def f2(d: Dict[object, object], flag: bool) -> object: + if flag: + return d.setdefault('a', set()) + else: + return d.setdefault('a', set('b')) + +def f3(d: Dict[object, object], flag: bool) -> object: + if flag: + return d.setdefault('a', []) + else: + return d.setdefault('a', [1]) + +def f4(d: Dict[object, object], flag: bool) -> object: + if flag: + return d.setdefault('a', {}) + else: + return d.setdefault('a', {'c': 1}) [out] def f(d): d :: dict @@ -350,3 +381,81 @@ L0: r1 = 'b' r2 = CPyDict_SetDefault(d, r0, r1) return r2 +def f2(d, flag): + d :: dict + flag :: bool + r0 :: str + r1 :: object + r2, r3 :: str + r4 :: set + r5, r6 :: object +L0: + if flag goto L1 else goto L2 :: bool +L1: + r0 = 'a' + r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 3) + return r1 +L2: + r2 = 'a' + r3 = 'b' + r4 = PySet_New(r3) + r5 = CPyDict_SetDefault(d, r2, r4) + return r5 +L3: + r6 = box(None, 1) + return r6 +def f3(d, flag): + d :: dict + flag :: bool + r0 :: str + r1 :: object + r2 :: str + r3 :: list + r4 :: object + r5, r6 :: ptr + r7, r8 :: object +L0: + if flag goto L1 else goto L2 :: bool +L1: + r0 = 'a' + r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 1) + return r1 +L2: + r2 = 'a' + r3 = PyList_New(1) + r4 = box(short_int, 2) + r5 = get_element_ptr r3 ob_item :: PyListObject + r6 = load_mem r5 :: ptr* + set_mem r6, r4 :: builtins.object* + keep_alive r3 + r7 = CPyDict_SetDefault(d, r2, r3) + return r7 +L3: + r8 = box(None, 1) + return r8 +def f4(d, flag): + d :: dict + flag :: bool + r0 :: str + r1 :: object + r2, r3 :: str + r4 :: object + r5 :: dict + r6, r7 :: object +L0: + if flag goto L1 else goto L2 :: bool +L1: + r0 = 'a' + r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 2) + return r1 +L2: + r2 = 'a' + r3 = 'c' + r4 = box(short_int, 2) + r5 = CPyDict_Build(1, r3, r4) + r6 = CPyDict_SetDefault(d, r2, r5) + return r6 +L3: + r7 = box(None, 1) + return r7 + diff --git a/mypyc/test-data/irbuild-dunders.test b/mypyc/test-data/irbuild-dunders.test index d36ce549fd17..808617e43889 100644 --- a/mypyc/test-data/irbuild-dunders.test +++ b/mypyc/test-data/irbuild-dunders.test @@ -133,3 +133,58 @@ def f(c): L0: r0 = c.__delitem__(10) return 1 + +[case testDundersUnary] +class C: + def __neg__(self) -> int: + return 1 + + def __invert__(self) -> int: + return 2 + + def __int__(self) -> int: + return 3 + + def __float__(self) -> float: + return 4.0 + +def f(c: C) -> None: + -c + ~c + int(c) + float(c) +[out] +def C.__neg__(self): + self :: __main__.C +L0: + return 2 +def C.__invert__(self): + self :: __main__.C +L0: + return 4 +def C.__int__(self): + self :: __main__.C +L0: + return 6 +def C.__float__(self): + self :: __main__.C + r0 :: float +L0: + r0 = 4.0 + return r0 +def f(c): + c :: __main__.C + r0, r1 :: int + r2, r3, r4 :: object + r5 :: str + r6, r7 :: object +L0: + r0 = c.__neg__() + r1 = c.__invert__() + r2 = load_address PyLong_Type + r3 = PyObject_CallFunctionObjArgs(r2, c, 0) + r4 = builtins :: module + r5 = 'float' + r6 = CPyObject_GetAttr(r4, r5) + r7 = PyObject_CallFunctionObjArgs(r6, c, 0) + return 1 diff --git a/mypyc/test-data/irbuild-generics.test b/mypyc/test-data/irbuild-generics.test index 6abd1105bbad..6ec8eb58fe7d 100644 --- a/mypyc/test-data/irbuild-generics.test +++ b/mypyc/test-data/irbuild-generics.test @@ -122,3 +122,29 @@ L0: r6 = C(r5) x = r6 return 1 + +[case testMax] +from typing import TypeVar +T = TypeVar('T') +def f(x: T, y: T) -> T: + return max(x, y) +[out] +def f(x, y): + x, y, r0 :: object + r1 :: int32 + r2 :: bit + r3 :: bool + r4 :: object +L0: + r0 = PyObject_RichCompare(y, x, 4) + r1 = PyObject_IsTrue(r0) + r2 = r1 >= 0 :: signed + r3 = truncate r1: int32 to builtins.bool + if r3 goto L1 else goto L2 :: bool +L1: + r4 = y + goto L3 +L2: + r4 = x +L3: + return r4 diff --git a/mypyc/test-data/irbuild-int.test b/mypyc/test-data/irbuild-int.test index b1b8d191bd05..ea943eef2c69 100644 --- a/mypyc/test-data/irbuild-int.test +++ b/mypyc/test-data/irbuild-int.test @@ -80,3 +80,40 @@ L14: L15: L16: return 12 + +[case testIntMin] +def f(x: int, y: int) -> int: + return min(x, y) +[out] +def f(x, y): + x, y :: int + r0 :: native_int + r1 :: bit + r2 :: native_int + r3, r4, r5 :: bit + r6 :: bool + r7 :: bit + r8 :: int +L0: + r0 = y & 1 + r1 = r0 == 0 + r2 = x & 1 + r3 = r2 == 0 + r4 = r1 & r3 + if r4 goto L1 else goto L2 :: bool +L1: + r5 = y < x :: signed + r6 = r5 + goto L3 +L2: + r7 = CPyTagged_IsLt_(y, x) + r6 = r7 +L3: + if r6 goto L4 else goto L5 :: bool +L4: + r8 = y + goto L6 +L5: + r8 = x +L6: + return r8 diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index e08b8d500c14..0d29f256cc59 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -70,6 +70,19 @@ L0: x = r0 return 1 +[case testNewListEmptyViaFunc] +from typing import List +def f() -> None: + x: List[int] = list() + +[out] +def f(): + r0, x :: list +L0: + r0 = PyList_New(0) + x = r0 + return 1 + [case testNewListTwoItems] from typing import List def f() -> None: @@ -93,6 +106,30 @@ L0: x = r0 return 1 +[case testNewListTenItems] +from typing import List +def f() -> None: + x: List[str] = ['a', 'b', 'c', 'd', 'e', + 'f', 'g', 'h', 'i', 'j'] +[out] +def f(): + r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 :: str + r10, x :: list +L0: + r0 = 'a' + r1 = 'b' + r2 = 'c' + r3 = 'd' + r4 = 'e' + r5 = 'f' + r6 = 'g' + r7 = 'h' + r8 = 'i' + r9 = 'j' + r10 = CPyList_Build(10, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) + x = r10 + return 1 + [case testListMultiply] from typing import List def f(a: List[int]) -> None: @@ -344,3 +381,49 @@ L7: L8: b = r16 return 1 +[case testGeneratorNext] +from typing import List, Optional + +def test(x: List[int]) -> None: + res = next((i for i in x), None) +[out] +def test(x): + x :: list + r0 :: short_int + r1 :: ptr + r2 :: native_int + r3 :: short_int + r4 :: bit + r5 :: object + r6, i :: int + r7 :: object + r8 :: union[int, None] + r9 :: short_int + r10 :: object + res :: union[int, None] +L0: + r0 = 0 +L1: + r1 = get_element_ptr x ob_size :: PyVarObject + r2 = load_mem r1 :: native_int* + keep_alive x + r3 = r2 << 1 + r4 = r0 < r3 :: signed + if r4 goto L2 else goto L4 :: bool +L2: + r5 = CPyList_GetItemUnsafe(x, r0) + r6 = unbox(int, r5) + i = r6 + r7 = box(int, i) + r8 = r7 + goto L5 +L3: + r9 = r0 + 2 + r0 = r9 + goto L1 +L4: + r10 = box(None, 1) + r8 = r10 +L5: + res = r8 + return 1 diff --git a/mypyc/test-data/irbuild-set.test b/mypyc/test-data/irbuild-set.test index aab70ecd0e76..f620039b7655 100644 --- a/mypyc/test-data/irbuild-set.test +++ b/mypyc/test-data/irbuild-set.test @@ -173,8 +173,8 @@ def test3(): r9 :: native_int r10 :: short_int r11 :: object - r12 :: tuple[bool, int, object] - r13 :: int + r12 :: tuple[bool, short_int, object] + r13 :: short_int r14 :: bool r15 :: object r16, x, r17 :: int diff --git a/mypyc/test-data/irbuild-singledispatch.test b/mypyc/test-data/irbuild-singledispatch.test new file mode 100644 index 000000000000..8b2e2abd507a --- /dev/null +++ b/mypyc/test-data/irbuild-singledispatch.test @@ -0,0 +1,262 @@ +[case testNativeCallsUsedInDispatchFunction] +from functools import singledispatch +@singledispatch +def f(arg) -> bool: + return False + +@f.register +def g(arg: int) -> bool: + return True +[out] +def __mypyc_singledispatch_main_function_f__(arg): + arg :: object +L0: + return 0 +def f_obj.__init__(__mypyc_self__): + __mypyc_self__ :: __main__.f_obj + r0 :: dict + r1 :: bool + r2 :: dict + r3 :: str + r4 :: int32 + r5 :: bit +L0: + r0 = PyDict_New() + __mypyc_self__.registry = r0; r1 = is_error + r2 = PyDict_New() + r3 = 'dispatch_cache' + r4 = PyObject_SetAttr(__mypyc_self__, r3, r2) + r5 = r4 >= 0 :: signed + return 1 +def f_obj.__call__(__mypyc_self__, arg): + __mypyc_self__ :: __main__.f_obj + arg :: object + r0 :: ptr + r1 :: object + r2 :: dict + r3, r4 :: object + r5 :: bit + r6, r7 :: object + r8 :: str + r9 :: object + r10 :: dict + r11 :: object + r12 :: int32 + r13 :: bit + r14 :: object + r15 :: ptr + r16 :: object + r17 :: bit + r18 :: int + r19 :: bit + r20 :: int + r21 :: bool + r22 :: object + r23 :: bool +L0: + r0 = get_element_ptr arg ob_type :: PyObject + r1 = load_mem r0 :: builtins.object* + keep_alive arg + r2 = __mypyc_self__.dispatch_cache + r3 = CPyDict_GetWithNone(r2, r1) + r4 = load_address _Py_NoneStruct + r5 = r3 != r4 + if r5 goto L1 else goto L2 :: bool +L1: + r6 = r3 + goto L3 +L2: + r7 = functools :: module + r8 = '_find_impl' + r9 = CPyObject_GetAttr(r7, r8) + r10 = __mypyc_self__.registry + r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0) + r12 = CPyDict_SetItem(r2, r1, r11) + r13 = r12 >= 0 :: signed + r6 = r11 +L3: + r14 = load_address PyLong_Type + r15 = get_element_ptr r6 ob_type :: PyObject + r16 = load_mem r15 :: builtins.object* + keep_alive r6 + r17 = r16 == r14 + if r17 goto L4 else goto L7 :: bool +L4: + r18 = unbox(int, r6) + r19 = r18 == 0 + if r19 goto L5 else goto L6 :: bool +L5: + r20 = unbox(int, arg) + r21 = g(r20) + return r21 +L6: + unreachable +L7: + r22 = PyObject_CallFunctionObjArgs(r6, arg, 0) + r23 = unbox(bool, r22) + return r23 +def f_obj.__get__(__mypyc_self__, instance, owner): + __mypyc_self__, instance, owner, r0 :: object + r1 :: bit + r2 :: object +L0: + r0 = load_address _Py_NoneStruct + r1 = instance == r0 + if r1 goto L1 else goto L2 :: bool +L1: + return __mypyc_self__ +L2: + r2 = PyMethod_New(__mypyc_self__, instance) + return r2 +def f_obj.register(__mypyc_self__, cls, func): + __mypyc_self__ :: __main__.f_obj + cls, func, r0 :: object +L0: + r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func) + return r0 +def f(arg): + arg :: object + r0 :: dict + r1 :: str + r2 :: object + r3 :: bool +L0: + r0 = __main__.globals :: static + r1 = 'f' + r2 = CPyDict_GetItem(r0, r1) + r3 = f_obj.__call__(r2, arg) + return r3 +def g(arg): + arg :: int +L0: + return 1 + + +[case testCallsToSingledispatchFunctionsAreNative] +from functools import singledispatch + +@singledispatch +def f(x: object) -> None: + pass + +def test(): + f('a') +[out] +def __mypyc_singledispatch_main_function_f__(x): + x :: object +L0: + return 1 +def f_obj.__init__(__mypyc_self__): + __mypyc_self__ :: __main__.f_obj + r0 :: dict + r1 :: bool + r2 :: dict + r3 :: str + r4 :: int32 + r5 :: bit +L0: + r0 = PyDict_New() + __mypyc_self__.registry = r0; r1 = is_error + r2 = PyDict_New() + r3 = 'dispatch_cache' + r4 = PyObject_SetAttr(__mypyc_self__, r3, r2) + r5 = r4 >= 0 :: signed + return 1 +def f_obj.__call__(__mypyc_self__, x): + __mypyc_self__ :: __main__.f_obj + x :: object + r0 :: ptr + r1 :: object + r2 :: dict + r3, r4 :: object + r5 :: bit + r6, r7 :: object + r8 :: str + r9 :: object + r10 :: dict + r11 :: object + r12 :: int32 + r13 :: bit + r14 :: object + r15 :: ptr + r16 :: object + r17 :: bit + r18 :: int + r19 :: object + r20 :: None +L0: + r0 = get_element_ptr x ob_type :: PyObject + r1 = load_mem r0 :: builtins.object* + keep_alive x + r2 = __mypyc_self__.dispatch_cache + r3 = CPyDict_GetWithNone(r2, r1) + r4 = load_address _Py_NoneStruct + r5 = r3 != r4 + if r5 goto L1 else goto L2 :: bool +L1: + r6 = r3 + goto L3 +L2: + r7 = functools :: module + r8 = '_find_impl' + r9 = CPyObject_GetAttr(r7, r8) + r10 = __mypyc_self__.registry + r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0) + r12 = CPyDict_SetItem(r2, r1, r11) + r13 = r12 >= 0 :: signed + r6 = r11 +L3: + r14 = load_address PyLong_Type + r15 = get_element_ptr r6 ob_type :: PyObject + r16 = load_mem r15 :: builtins.object* + keep_alive r6 + r17 = r16 == r14 + if r17 goto L4 else goto L5 :: bool +L4: + r18 = unbox(int, r6) + unreachable +L5: + r19 = PyObject_CallFunctionObjArgs(r6, x, 0) + r20 = unbox(None, r19) + return r20 +def f_obj.__get__(__mypyc_self__, instance, owner): + __mypyc_self__, instance, owner, r0 :: object + r1 :: bit + r2 :: object +L0: + r0 = load_address _Py_NoneStruct + r1 = instance == r0 + if r1 goto L1 else goto L2 :: bool +L1: + return __mypyc_self__ +L2: + r2 = PyMethod_New(__mypyc_self__, instance) + return r2 +def f_obj.register(__mypyc_self__, cls, func): + __mypyc_self__ :: __main__.f_obj + cls, func, r0 :: object +L0: + r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func) + return r0 +def f(x): + x :: object + r0 :: dict + r1 :: str + r2 :: object + r3 :: None +L0: + r0 = __main__.globals :: static + r1 = 'f' + r2 = CPyDict_GetItem(r0, r1) + r3 = f_obj.__call__(r2, x) + return r3 +def test(): + r0 :: str + r1 :: None + r2 :: object +L0: + r0 = 'a' + r1 = f(r0) + r2 = box(None, 1) + return r2 + diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index e5e47c05877a..8b85e494b07d 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -342,8 +342,8 @@ def f(d): r1 :: native_int r2 :: short_int r3 :: object - r4 :: tuple[bool, int, object] - r5 :: int + r4 :: tuple[bool, short_int, object] + r5 :: short_int r6 :: bool r7 :: object r8, key :: int @@ -394,8 +394,8 @@ def sum_over_even_values(d): r1 :: native_int r2 :: short_int r3 :: object - r4 :: tuple[bool, int, object] - r5 :: int + r4 :: tuple[bool, short_int, object] + r5 :: short_int r6 :: bool r7 :: object r8, key :: int @@ -880,6 +880,7 @@ L0: [case testDelAttribute] class Dummy(): + __deletable__ = ('x', 'y') def __init__(self, x: int, y: int) -> None: self.x = x self.y = y diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index 3de91be40ea2..bb296c53d224 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -159,3 +159,159 @@ L2: L3: unreachable +[case testStringFormatMethod] +def f(s: str, num: int) -> None: + s1 = "Hi! I'm {}, and I'm {} years old.".format(s, num) + s2 = ''.format() + s3 = 'abc'.format() + s4 = '}}{}{{{}}}{{{}'.format(num, num, num) +[out] +def f(s, num): + s :: str + num :: int + r0, r1, r2, r3, r4, s1, r5, s2, r6, s3, r7, r8, r9, r10, r11, r12, r13, s4 :: str +L0: + r0 = CPyTagged_Str(num) + r1 = "Hi! I'm " + r2 = ", and I'm " + r3 = ' years old.' + r4 = CPyStr_Build(5, r1, s, r2, r0, r3) + s1 = r4 + r5 = '' + s2 = r5 + r6 = 'abc' + s3 = r6 + r7 = CPyTagged_Str(num) + r8 = CPyTagged_Str(num) + r9 = CPyTagged_Str(num) + r10 = '}' + r11 = '{' + r12 = '}{' + r13 = CPyStr_Build(6, r10, r7, r11, r8, r12, r9) + s4 = r13 + return 1 + +[case testFStrings] +def f(var: str, num: int) -> None: + s1 = f"Hi! I'm {var}. I am {num} years old." + s2 = f'Hello {var:>{num}}' + s3 = f'' + s4 = f'abc' +[out] +def f(var, num): + var :: str + num :: int + r0, r1, r2, r3, r4, s1, r5, r6, r7, r8, r9, r10, r11 :: str + r12 :: object + r13 :: str + r14 :: list + r15, r16, r17 :: ptr + r18, s2, r19, s3, r20, s4 :: str +L0: + r0 = "Hi! I'm " + r1 = '. I am ' + r2 = CPyTagged_Str(num) + r3 = ' years old.' + r4 = CPyStr_Build(5, r0, var, r1, r2, r3) + s1 = r4 + r5 = '' + r6 = 'Hello ' + r7 = '{:{}}' + r8 = '>' + r9 = CPyTagged_Str(num) + r10 = CPyStr_Build(2, r8, r9) + r11 = 'format' + r12 = CPyObject_CallMethodObjArgs(r7, r11, var, r10, 0) + r13 = cast(str, r12) + r14 = PyList_New(2) + r15 = get_element_ptr r14 ob_item :: PyListObject + r16 = load_mem r15 :: ptr* + set_mem r16, r6 :: builtins.object* + r17 = r16 + WORD_SIZE*1 + set_mem r17, r13 :: builtins.object* + keep_alive r14 + r18 = PyUnicode_Join(r5, r14) + s2 = r18 + r19 = '' + s3 = r19 + r20 = 'abc' + s4 = r20 + return 1 + +[case testStringFormattingCStyle] +def f(var: str, num: int) -> None: + s1 = "Hi! I'm %s." % var + s2 = "I am %d years old." % num + s3 = "Hi! I'm %s. I am %d years old." % (var, num) + s4 = "Float: %f" % num +[typing fixtures/typing-full.pyi] +[out] +def f(var, num): + var :: str + num :: int + r0, r1, r2, s1, r3, r4, r5, r6, s2, r7, r8, r9, r10, r11, s3, r12 :: str + r13, r14 :: object + r15, s4 :: str +L0: + r0 = "Hi! I'm " + r1 = '.' + r2 = CPyStr_Build(3, r0, var, r1) + s1 = r2 + r3 = CPyTagged_Str(num) + r4 = 'I am ' + r5 = ' years old.' + r6 = CPyStr_Build(3, r4, r3, r5) + s2 = r6 + r7 = CPyTagged_Str(num) + r8 = "Hi! I'm " + r9 = '. I am ' + r10 = ' years old.' + r11 = CPyStr_Build(5, r8, var, r9, r7, r10) + s3 = r11 + r12 = 'Float: %f' + r13 = box(int, num) + r14 = PyNumber_Remainder(r12, r13) + r15 = cast(str, r14) + s4 = r15 + return 1 + +[case testDecode] +def f(b: bytes) -> None: + b.decode() + b.decode('utf-8') + b.decode('utf-8', 'backslashreplace') +[out] +def f(b): + b :: bytes + r0, r1, r2, r3, r4, r5 :: str +L0: + r0 = CPy_Decode(b, 0, 0) + r1 = 'utf-8' + r2 = CPy_Decode(b, r1, 0) + r3 = 'utf-8' + r4 = 'backslashreplace' + r5 = CPy_Decode(b, r3, r4) + return 1 + +[case testEncode] +def f(s: str) -> None: + s.encode() + s.encode('utf-8') + s.encode('ascii', 'backslashreplace') +[out] +def f(s): + s :: str + r0 :: bytes + r1 :: str + r2 :: bytes + r3, r4 :: str + r5 :: bytes +L0: + r0 = CPy_Encode(s, 0, 0) + r1 = 'utf-8' + r2 = CPy_Encode(s, r1, 0) + r3 = 'ascii' + r4 = 'backslashreplace' + r5 = CPy_Encode(s, r3, r4) + return 1 + diff --git a/mypyc/test-data/irbuild-strip-asserts.test b/mypyc/test-data/irbuild-strip-asserts.test index 1ab6b4107b4d..5772fc8911fe 100644 --- a/mypyc/test-data/irbuild-strip-asserts.test +++ b/mypyc/test-data/irbuild-strip-asserts.test @@ -5,11 +5,8 @@ def g(): return x [out] def g(): - r0 :: int - r1, x :: object + r0, x :: object L0: - r0 = CPyTagged_Add(2, 4) - r1 = box(int, r0) - x = r1 + r0 = box(short_int, 6) + x = r0 return x - diff --git a/mypyc/test-data/irbuild-tuple.test b/mypyc/test-data/irbuild-tuple.test index 20590645d5d3..564a4bf74d50 100644 --- a/mypyc/test-data/irbuild-tuple.test +++ b/mypyc/test-data/irbuild-tuple.test @@ -350,14 +350,13 @@ L4: return 1 -[case testTupleBuiltFromList2] +[case testTupleBuiltFromStr] def f2(val: str) -> str: return val + "f2" def test() -> None: - source = ["a", "b", "c"] + source = "abc" a = tuple(f2(x) for x in source) - print(a) [out] def f2(val): val, r0, r1 :: str @@ -366,71 +365,45 @@ L0: r1 = PyUnicode_Concat(val, r0) return r1 def test(): - r0, r1, r2 :: str - r3 :: list - r4, r5, r6, r7 :: ptr - source :: list - r8 :: ptr - r9 :: native_int - r10 :: tuple - r11 :: short_int - r12 :: ptr - r13 :: native_int - r14 :: short_int - r15 :: bit - r16 :: object - r17, x, r18 :: str - r19 :: bit - r20 :: short_int + r0, source :: str + r1 :: native_int + r2 :: bit + r3 :: tuple + r4 :: short_int + r5 :: native_int + r6 :: bit + r7 :: short_int + r8 :: bit + r9, x, r10 :: str + r11 :: bit + r12 :: short_int a :: tuple - r21 :: object - r22 :: str - r23, r24 :: object L0: - r0 = 'a' - r1 = 'b' - r2 = 'c' - r3 = PyList_New(3) - r4 = get_element_ptr r3 ob_item :: PyListObject - r5 = load_mem r4 :: ptr* - set_mem r5, r0 :: builtins.object* - r6 = r5 + WORD_SIZE*1 - set_mem r6, r1 :: builtins.object* - r7 = r5 + WORD_SIZE*2 - set_mem r7, r2 :: builtins.object* - keep_alive r3 - source = r3 - r8 = get_element_ptr source ob_size :: PyVarObject - r9 = load_mem r8 :: native_int* - keep_alive source - r10 = PyTuple_New(r9) - r11 = 0 + r0 = 'abc' + source = r0 + r1 = CPyStr_Size_size_t(source) + r2 = r1 >= 0 :: signed + r3 = PyTuple_New(r1) + r4 = 0 L1: - r12 = get_element_ptr source ob_size :: PyVarObject - r13 = load_mem r12 :: native_int* - keep_alive source - r14 = r13 << 1 - r15 = r11 < r14 :: signed - if r15 goto L2 else goto L4 :: bool + r5 = CPyStr_Size_size_t(source) + r6 = r5 >= 0 :: signed + r7 = r5 << 1 + r8 = r4 < r7 :: signed + if r8 goto L2 else goto L4 :: bool L2: - r16 = CPyList_GetItemUnsafe(source, r11) - r17 = cast(str, r16) - x = r17 - r18 = f2(x) - r19 = CPySequenceTuple_SetItemUnsafe(r10, r11, r18) + r9 = CPyStr_GetItem(source, r4) + x = r9 + r10 = f2(x) + r11 = CPySequenceTuple_SetItemUnsafe(r3, r4, r10) L3: - r20 = r11 + 2 - r11 = r20 + r12 = r4 + 2 + r4 = r12 goto L1 L4: - a = r10 - r21 = builtins :: module - r22 = 'print' - r23 = CPyObject_GetAttr(r21, r22) - r24 = PyObject_CallFunctionObjArgs(r23, a, 0) + a = r3 return 1 - [case testTupleBuiltFromVariableLengthTuple] from typing import Tuple diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index 64b38f33a26b..c48ae1acce09 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -724,8 +724,8 @@ def f(d): r1 :: native_int r2 :: short_int r3 :: object - r4 :: tuple[bool, int, object] - r5 :: int + r4 :: tuple[bool, short_int, object] + r5 :: short_int r6 :: bool r7 :: object r8, key :: int diff --git a/mypyc/test-data/run-attrs.test b/mypyc/test-data/run-attrs.test new file mode 100644 index 000000000000..9c402a3eea7c --- /dev/null +++ b/mypyc/test-data/run-attrs.test @@ -0,0 +1,318 @@ +-- Test cases for dataclasses based on the attrs library, where auto_attribs=True + +[case testRunAttrsclass] +import attr +from typing import Set, List, Callable, Any + +@attr.s(auto_attribs=True) +class Person1: + age : int + name : str + + def __bool__(self) -> bool: + return self.name == 'robot' + +def testBool(p: Person1) -> bool: + if p: + return True + else: + return False + +@attr.s(auto_attribs=True) +class Person1b(Person1): + id: str = '000' + +@attr.s(auto_attribs=True) +class Person2: + age : int + name : str = attr.ib(default='robot') + +@attr.s(auto_attribs=True, order=True) +class Person3: + age : int = attr.ib(default = 6) + friendIDs : List[int] = attr.ib(factory = list) + + def get_age(self) -> int: + return (self.age) + + def set_age(self, new_age : int) -> None: + self.age = new_age + + def add_friendID(self, fid : int) -> None: + self.friendIDs.append(fid) + + def get_friendIDs(self) -> List[int]: + return self.friendIDs + +def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]: + def f(a: Any) -> int: + return g(a) + 1 + return f + +@attr.s(auto_attribs=True) +class Person4: + age : int + _name : str = 'Bot' + + @get_next_age + def get_age(self) -> int: + return self.age + + @property + def name(self) -> str: + return self._name + +@attr.s(auto_attribs=True) +class Point: + x : int = attr.ib(converter=int) + y : int = attr.ib(init=False) + + def __attrs_post_init__(self): + self.y = self.x + 1 + + +[file other.py] +from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point +i1 = Person1(age = 5, name = 'robot') +assert i1.age == 5 +assert i1.name == 'robot' +assert testBool(i1) == True +assert testBool(Person1(age = 5, name = 'robo')) == False +i1b = Person1b(age = 5, name = 'robot') +assert i1b.age == 5 +assert i1b.name == 'robot' +assert i1b.id == '000' +assert testBool(i1b) == True +assert testBool(Person1b(age = 5, name = 'robo')) == False +i1c = Person1b(age = 20, name = 'robot', id = 'test') +assert i1c.age == 20 +assert i1c.id == 'test' + +i2 = Person2(age = 5) +assert i2.age == 5 +assert i2.name == 'robot' +i3 = Person2(age = 5, name = 'new_robot') +assert i3.age == 5 +assert i3.name == 'new_robot' +i4 = Person3() +assert i4.age == 6 +assert i4.friendIDs == [] +i5 = Person3(age = 5) +assert i5.age == 5 +assert i5.friendIDs == [] +i6 = Person3(age = 5, friendIDs = [1,2,3]) +assert i6.age == 5 +assert i6.friendIDs == [1,2,3] +assert i6.get_age() == 5 +i6.set_age(10) +assert i6.get_age() == 10 +i6.add_friendID(4) +assert i6.get_friendIDs() == [1,2,3,4] +i7 = Person4(age = 5) +assert i7.get_age() == 6 +i7.age += 3 +assert i7.age == 8 +assert i7.name == 'Bot' +i8 = Person3(age = 1, friendIDs = [1,2]) +i9 = Person3(age = 1, friendIDs = [1,2]) +assert i8 == i9 +i8.age = 2 +assert i8 > i9 + +assert Person1.__annotations__ == {'age': int, 'name': str} +assert Person2.__annotations__ == {'age': int, 'name': str} + +p1 = Point(2) +assert p1.x == 2 +assert p1.y == 3 +p2 = Point('2') +assert p2.x == 2 +assert p2.y == 3 + +assert Point.__annotations__ == {'x': int, 'y': int} + +[file driver.py] +import sys + +# PEP 526 introduced in 3.6 +version = sys.version_info[:2] +if version[0] < 3 or version[1] < 6: + exit() + +# Run the tests in both interpreted and compiled mode +import other +import other_interpreted + +# Test for an exceptional cases +from testutil import assertRaises +from native import Person1, Person1b, Person3 +from types import BuiltinMethodType + +with assertRaises(TypeError, "missing 1 required positional argument"): + Person1(0) + +with assertRaises(TypeError, "missing 2 required positional arguments"): + Person1b() + +with assertRaises(TypeError, "int object expected; got str"): + Person1('nope', 'test') + +p = Person1(0, 'test') +with assertRaises(TypeError, "int object expected; got str"): + p.age = 'nope' + +assert isinstance(Person3().get_age, BuiltinMethodType) + + +[case testRunAttrsclassNonAuto] +import attr +from typing import Set, List, Callable, Any + +@attr.s +class Person1: + age = attr.ib(type=int) + name = attr.ib(type=str) + + def __bool__(self) -> bool: + return self.name == 'robot' + +def testBool(p: Person1) -> bool: + if p: + return True + else: + return False + +@attr.s +class Person1b(Person1): + id = attr.ib(type=str, default='000') + +@attr.s +class Person2: + age = attr.ib(type=int) + name = attr.ib(type=str, default='robot') + +@attr.s(order=True) +class Person3: + age = attr.ib(type=int, default=6) + friendIDs = attr.ib(factory=list, type=List[int]) + + def get_age(self) -> int: + return (self.age) + + def set_age(self, new_age : int) -> None: + self.age = new_age + + def add_friendID(self, fid : int) -> None: + self.friendIDs.append(fid) + + def get_friendIDs(self) -> List[int]: + return self.friendIDs + +def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]: + def f(a: Any) -> int: + return g(a) + 1 + return f + +@attr.s +class Person4: + age = attr.ib(type=int) + _name = attr.ib(type=str, default='Bot') + + @get_next_age + def get_age(self) -> int: + return self.age + + @property + def name(self) -> str: + return self._name + +@attr.s +class Point: + x = attr.ib(type=int, converter=int) + y = attr.ib(type=int, init=False) + + def __attrs_post_init__(self): + self.y = self.x + 1 + + +[file other.py] +from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point +i1 = Person1(age = 5, name = 'robot') +assert i1.age == 5 +assert i1.name == 'robot' +assert testBool(i1) == True +assert testBool(Person1(age = 5, name = 'robo')) == False +i1b = Person1b(age = 5, name = 'robot') +assert i1b.age == 5 +assert i1b.name == 'robot' +assert i1b.id == '000' +assert testBool(i1b) == True +assert testBool(Person1b(age = 5, name = 'robo')) == False +i1c = Person1b(age = 20, name = 'robot', id = 'test') +assert i1c.age == 20 +assert i1c.id == 'test' + +i2 = Person2(age = 5) +assert i2.age == 5 +assert i2.name == 'robot' +i3 = Person2(age = 5, name = 'new_robot') +assert i3.age == 5 +assert i3.name == 'new_robot' +i4 = Person3() +assert i4.age == 6 +assert i4.friendIDs == [] +i5 = Person3(age = 5) +assert i5.age == 5 +assert i5.friendIDs == [] +i6 = Person3(age = 5, friendIDs = [1,2,3]) +assert i6.age == 5 +assert i6.friendIDs == [1,2,3] +assert i6.get_age() == 5 +i6.set_age(10) +assert i6.get_age() == 10 +i6.add_friendID(4) +assert i6.get_friendIDs() == [1,2,3,4] +i7 = Person4(age = 5) +assert i7.get_age() == 6 +i7.age += 3 +assert i7.age == 8 +assert i7.name == 'Bot' +i8 = Person3(age = 1, friendIDs = [1,2]) +i9 = Person3(age = 1, friendIDs = [1,2]) +assert i8 == i9 +i8.age = 2 +assert i8 > i9 + +p1 = Point(2) +assert p1.x == 2 +assert p1.y == 3 +p2 = Point('2') +assert p2.x == 2 +assert p2.y == 3 + +[file driver.py] +import sys + +# Run the tests in both interpreted and compiled mode +import other +import other_interpreted + +# Test for an exceptional cases +from testutil import assertRaises +from native import Person1, Person1b, Person3 +from types import BuiltinMethodType + +with assertRaises(TypeError, "missing 1 required positional argument"): + Person1(0) + +with assertRaises(TypeError, "missing 2 required positional arguments"): + Person1b() + +with assertRaises(TypeError, "int object expected; got str"): + Person1('nope', 'test') + +p = Person1(0, 'test') +with assertRaises(TypeError, "int object expected; got str"): + p.age = 'nope' + +assert isinstance(Person3().get_age, BuiltinMethodType) diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test new file mode 100644 index 000000000000..aaf541194ac6 --- /dev/null +++ b/mypyc/test-data/run-bytes.test @@ -0,0 +1,302 @@ +# Bytes test cases (compile and run) + +[case testBytesBasics] +# Note: Add tests for additional operations to testBytesOps or in a new test case + +def f(x: bytes) -> bytes: + return x + +def eq(a: bytes, b: bytes) -> bool: + return a == b + +def neq(a: bytes, b: bytes) -> bool: + return a != b +[file driver.py] +from native import f, eq, neq +assert f(b'123') == b'123' +assert f(b'\x07 \x0b " \t \x7f \xf0') == b'\x07 \x0b " \t \x7f \xf0' +assert eq(b'123', b'123') +assert not eq(b'123', b'1234') +assert not eq(b'123', b'124') +assert not eq(b'123', b'223') +assert neq(b'123', b'1234') +try: + f('x') + assert False +except TypeError: + pass + +[case testBytesInit] +def test_bytes_init() -> None: + b1 = bytes([5]) + assert b1 == b'\x05' + b2 = bytes([5, 10, 12]) + assert b2 == b'\x05\n\x0c' + b3 = bytes(bytearray(b'foo')) + assert b3 == b'foo' + b4 = bytes(b'aaa') + assert b4 == b'aaa' + b5 = bytes(5) + assert b5 == b'\x00\x00\x00\x00\x00' + try: + bytes('x') + assert False + except TypeError: + pass + +[case testBytesOps] +from testutil import assertRaises + +def test_indexing() -> None: + # Use bytes() to avoid constant folding + b = b'asdf' + bytes() + assert b[0] == 97 + assert b[1] == 115 + assert b[3] == 102 + assert b[-1] == 102 + b = b'\xae\x80\xfe\x15' + bytes() + assert b[0] == 174 + assert b[1] == 128 + assert b[2] == 254 + assert b[3] == 21 + assert b[-4] == 174 + with assertRaises(IndexError, "index out of range"): + b[4] + with assertRaises(IndexError, "index out of range"): + b[-5] + with assertRaises(IndexError, "index out of range"): + b[2**26] + +def test_concat() -> None: + b1 = b'123' + bytes() + b2 = b'456' + bytes() + assert b1 + b2 == b'123456' + b3 = b1 + b2 + b3 = b3 + b1 + assert b3 == b'123456123' + assert b1 == b'123' + assert b2 == b'456' + assert type(b1) == bytes + assert type(b2) == bytes + assert type(b3) == bytes + brr1: bytes = bytearray(3) + brr2: bytes = bytearray(range(5)) + b4 = b1 + brr1 + assert b4 == b'123\x00\x00\x00' + assert type(brr1) == bytearray + assert type(b4) == bytes + brr3 = brr1 + brr2 + assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04') + assert len(brr3) == 8 + assert type(brr3) == bytearray + brr3 = brr3 + bytearray([10]) + assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04\n') + b5 = brr2 + b2 + assert b5 == bytearray(b'\x00\x01\x02\x03\x04456') + assert type(b5) == bytearray + b5 = b2 + brr2 + assert b5 == b'456\x00\x01\x02\x03\x04' + assert type(b5) == bytes + +def test_join() -> None: + seq = (b'1', b'"', b'\xf0') + assert b'\x07'.join(seq) == b'1\x07"\x07\xf0' + assert b', '.join(()) == b'' + assert b', '.join([bytes() + b'ab']) == b'ab' + assert b', '.join([bytes() + b'ab', b'cd']) == b'ab, cd' + +def test_len() -> None: + # Use bytes() to avoid constant folding + b = b'foo' + bytes() + assert len(b) == 3 + assert len(bytes()) == 0 + +[case testBytesSlicing] +def test_bytes_slicing() -> None: + b = b'abcdefg' + zero = int() + ten = 10 + zero + two = 2 + zero + five = 5 + zero + seven = 7 + zero + assert b[:ten] == b'abcdefg' + assert b[0:seven] == b'abcdefg' + assert b[0:(len(b)+1)] == b'abcdefg' + assert b[two:five] == b'cde' + assert b[two:two] == b'' + assert b[-two:-two] == b'' + assert b[-ten:(-ten+1)] == b'' + assert b[:-two] == b'abcde' + assert b[:two] == b'ab' + assert b[:] == b'abcdefg' + assert b[-two:] == b'fg' + assert b[zero:] == b'abcdefg' + assert b[:zero] == b'' + assert b[-ten:] == b'abcdefg' + assert b[-ten:ten] == b'abcdefg' + big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63] + for big_int in big_ints: + assert b[1:big_int] == b'bcdefg' + assert b[big_int:] == b'' + assert b[-big_int:-1] == b'abcdef' + assert b[-big_int:big_int] == b'abcdefg' + assert type(b[-big_int:-1]) == bytes + assert type(b[-ten:]) == bytes + assert type(b[:]) == bytes + +[case testBytearrayBasics] +from typing import Any + +def test_basics() -> None: + brr1: bytes = bytearray(3) + assert brr1 == bytearray(b'\x00\x00\x00') + assert brr1 == b'\x00\x00\x00' + l = [10, 20, 30, 40] + brr2: bytes = bytearray(l) + assert brr2 == bytearray(b'\n\x14\x1e(') + assert brr2 == b'\n\x14\x1e(' + brr3: bytes = bytearray(range(5)) + assert brr3 == bytearray(b'\x00\x01\x02\x03\x04') + assert brr3 == b'\x00\x01\x02\x03\x04' + brr4: bytes = bytearray('string', 'utf-8') + assert brr4 == bytearray(b'string') + assert brr4 == b'string' + assert len(brr1) == 3 + assert len(brr2) == 4 + +def f(b: bytes) -> bool: + return True + +def test_bytearray_passed_into_bytes() -> None: + assert f(bytearray(3)) + brr1: Any = bytearray() + assert f(brr1) + +[case testBytearraySlicing] +def test_bytearray_slicing() -> None: + b: bytes = bytearray(b'abcdefg') + zero = int() + ten = 10 + zero + two = 2 + zero + five = 5 + zero + seven = 7 + zero + assert b[:ten] == b'abcdefg' + assert b[0:seven] == b'abcdefg' + assert b[two:five] == b'cde' + assert b[two:two] == b'' + assert b[-two:-two] == b'' + assert b[-ten:(-ten+1)] == b'' + assert b[:-two] == b'abcde' + assert b[:two] == b'ab' + assert b[:] == b'abcdefg' + assert b[-two:] == b'fg' + assert b[zero:] == b'abcdefg' + assert b[:zero] == b'' + assert b[-ten:] == b'abcdefg' + assert b[-ten:ten] == b'abcdefg' + big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63] + for big_int in big_ints: + assert b[1:big_int] == b'bcdefg' + assert b[big_int:] == b'' + assert b[-big_int:-1] == b'abcdef' + assert b[-big_int:big_int] == b'abcdefg' + assert type(b[-big_int:-1]) == bytearray + assert type(b[-ten:]) == bytearray + assert type(b[:]) == bytearray + +[case testBytearrayIndexing] +from testutil import assertRaises + +def test_bytearray_indexing() -> None: + b: bytes = bytearray(b'\xae\x80\xfe\x15') + assert b[0] == 174 + assert b[1] == 128 + assert b[2] == 254 + assert b[3] == 21 + assert b[-4] == 174 + with assertRaises(IndexError, "index out of range"): + b[4] + with assertRaises(IndexError, "index out of range"): + b[-5] + b2 = bytearray([175, 255, 128, 22]) + assert b2[0] == 175 + assert b2[1] == 255 + assert b2[-1] == 22 + assert b2[2] == 128 + with assertRaises(ValueError, "byte must be in range(0, 256)"): + b2[0] = -1 + with assertRaises(ValueError, "byte must be in range(0, 256)"): + b2[0] = 256 + +[case testBytesJoin] +from typing import Any +from testutil import assertRaises +from a import bytes_subclass + +def test_bytes_join() -> None: + assert b' '.join([b'a', b'b']) == b'a b' + assert b' '.join([]) == b'' + + x: bytes = bytearray(b' ') + assert x.join([b'a', b'b']) == b'a b' + assert type(x.join([b'a', b'b'])) == bytearray + + y: bytes = bytes_subclass() + assert y.join([]) == b'spook' + + n: Any = 5 + with assertRaises(TypeError, "can only join an iterable"): + assert b' '.join(n) + +[file a.py] +class bytes_subclass(bytes): + def join(self, iter): + return b'spook' + +[case testBytesFormatting] +[typing fixtures/typing-full.pyi] +from testutil import assertRaises + +# https://www.python.org/dev/peps/pep-0461/ +def test_bytes_formatting() -> None: + val = 10 + assert b"%x" % val == b'a' + assert b'%4x' % val == b' a' + assert b'%#4x' % val == b' 0xa' + assert b'%04X' % val == b'000A' + + assert b'%c' % 48 == b'0' + assert b'%c' % b'a' == b'a' + assert b'%c%c' % (48, b'a') == b'0a' + + assert b'%b' % b'abc' == b'abc' + assert b'%b' % 'some string'.encode('utf8') == b'some string' + + assert b'%a' % 3.14 == b'3.14' + assert b'%a' % b'abc' == b"b'abc'" + assert b'%a' % 'def' == b"'def'" + +def test_bytes_formatting_2() -> None: + var = b'bb' + num = 10 + assert b'aaa%bbbb%s' % (var, var) == b'aaabbbbbbb' + assert b'aaa%dbbb%b' % (num, var) == b'aaa10bbbbb' + assert b'%s%b' % (var, var) == b'bbbb' + assert b'%b' % bytes() == b'' + assert b'%b' % b'' == b'' + + assert b'\xff%s' % b'\xff' == b'\xff\xff' + assert b'\xff%b' % '你好'.encode() == b'\xff\xe4\xbd\xa0\xe5\xa5\xbd' + + aa = b'\xe4\xbd\xa0\xe5\xa5\xbd%b' % b'\xe4\xbd\xa0\xe5\xa5\xbd' + assert aa == b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd' + assert aa.decode() == '你好你好' + + +class A: + def __bytes__(self): + return b'aaa' + +def test_bytes_dunder() -> None: + assert b'%b' % A() == b'aaa' + assert b'%s' % A() == b'aaa' diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index 0c794a4bf9fc..e2beca1bafc6 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -27,6 +27,7 @@ class D: pass [file driver.py] from native import C +from testutil import assertRaises c = C() assert not hasattr(c, 'x') @@ -42,11 +43,13 @@ print(c.x) assert hasattr(c, 'x') assert hasattr(c, 'y') assert not hasattr(c, 'z') -del c.x -assert not hasattr(c, 'x') +with assertRaises(AttributeError, "'C' object attribute 'x' cannot be deleted"): + del c.x +assert hasattr(c, 'x') +assert hasattr(c, 'y') +with assertRaises(AttributeError, "'C' object attribute 'y' cannot be deleted"): + del c.y assert hasattr(c, 'y') -del c.y -assert not hasattr(c, 'y') c.x = 10**30+2 print(c.x) assert hasattr(c, 'x') @@ -57,6 +60,121 @@ assert hasattr(c, 'x') 1000000000000000000000000000001 1000000000000000000000000000002 +[case testClassWithDeletableAttributes] +from typing import Any, cast +from testutil import assertRaises + +class C: + __deletable__ = ['x', 'y'] + x: int + y: int + z: int + +def test_delete() -> None: + c = C() + c.x = 1 + c.y = 2 + c.z = 3 + del c.x + del c.y + assert c.z == 3 + with assertRaises(AttributeError): + c.x + with assertRaises(AttributeError): + c.y + +def test_delete_any() -> None: + c: Any = C() + c.x = 1 + c.y = 2 + c.z = 3 + del c.x + del c.y + with assertRaises(AttributeError, "'C' object attribute 'z' cannot be deleted"): + del c.z + assert c.z == 3 + with assertRaises(AttributeError): + c.x + with assertRaises(AttributeError): + c.y + +class Base: + __deletable__ = ['a'] + a: int + b: int + +class Deriv(Base): + __deletable__ = ('c',) + c: str + d: str + +def test_delete_with_inheritance() -> None: + d = Deriv() + d.a = 0 + d.b = 1 + d.c = 'X' + d.d = 'Y' + del d.a + with assertRaises(AttributeError): + d.a + del d.c + with assertRaises(AttributeError): + d.c + assert d.b == 1 + assert d.d == 'Y' + +def test_delete_with_inheritance_any() -> None: + d: Any = Deriv() + d.a = 0 + d.b = 1 + d.c = 'X' + d.d = 'Y' + del d.a + with assertRaises(AttributeError): + d.a + del d.c + with assertRaises(AttributeError): + d.c + with assertRaises(AttributeError): + del d.b + assert d.b == 1 + with assertRaises(AttributeError): + del d.d + assert d.d == 'Y' + +def decorator(cls): + return cls + +@decorator +class NonExt: + x: int + y: int + + # No effect in a non-native class + __deletable__ = ['x'] + +def test_non_ext() -> None: + n = NonExt() + n.x = 2 + n.y = 3 + del n.x + del n.y + with assertRaises(AttributeError): + n.x + with assertRaises(AttributeError): + n.y + +def test_non_ext_any() -> None: + n: Any = NonExt() + n.x = 2 + n.y = 3 + del n.x + del n.y + with assertRaises(AttributeError): + n.x + with assertRaises(AttributeError): + n.y + [case testNonExtMisc] from typing import Any, overload @@ -107,8 +225,15 @@ class Overload: def get(c: Overload, s: str) -> str: return c.get(s) +@decorator +class Var: + x = 'xy' + +def get_class_var() -> str: + return Var.x + [file driver.py] -from native import A, Overload, get +from native import A, Overload, get, get_class_var a = A() assert a.a == 1 assert a.b == 2 @@ -122,6 +247,8 @@ o = Overload() assert get(o, "test") == "test" assert o.get(20) == 20 +assert get_class_var() == 'xy' + [case testEnum] from enum import Enum @@ -870,11 +997,11 @@ b(B()) [case testMethodOverrideDefault2] class A: - def foo(self, *, x: int = 0) -> None: + def foo(self, *, x: int = -1) -> None: pass - def bar(self, *, x: int = 0, y: int = 0) -> None: + def bar(self, *, x: int = -1, y: int = -1) -> None: pass - def baz(self, x: int = 0) -> None: + def baz(self, x: int = -1) -> None: pass class B(A): def foo(self, *, y: int = 0, x: int = 0) -> None: @@ -953,6 +1080,152 @@ B 1 0 10 +[case testMethodOverrideDefault4] +class Foo: + def f(self, x: int=20, *, z: int=10) -> None: + pass + +class Bar(Foo): + def f(self, *args: int, **kwargs: int) -> None: + print("stuff", args, kwargs) + +z: Foo = Bar() +z.f(1, z=50) +z.f() + +[out] +stuff (1,) {'z': 50} +stuff () {} + +[case testMethodOverrideDefault5] +from testutil import make_python_function +from mypy_extensions import mypyc_attr +from typing import TypeVar, Any + +@mypyc_attr(allow_interpreted_subclasses=True) +class Foo: + def f(self, x: int=20, *, z: int=10) -> None: + print("Foo", x, z) + +@make_python_function +def baz_f(self: Any, *args: int, **kwargs: int) -> None: + print("Baz", args, kwargs) + +# Make an "interpreted" subtype of Foo +type2: Any = type +Bar = type2('Bar', (Foo,), {}) +Baz = type2('Baz', (Foo,), {'f': baz_f}) + +y: Foo = Bar() +y.f(1, z=2) +y.f() + +z: Foo = Baz() +z.f(1, z=2) +z.f() + +[out] +Foo 1 2 +Foo 20 10 +Baz (1,) {'z': 2} +Baz () {} + +[case testMethodOverrideDefault6] +from typing import Optional + +class Foo: + def f(self, x: int=20) -> None: + pass + +class Bar(Foo): + def f(self, x: Optional[int]=None) -> None: + print(x) + +z: Foo = Bar() +z.f(1) +z.f() + +[out] +1 +None + +[case testMethodOverrideDefault7] +from typing import TypeVar, Any + +class Foo: + def f(self, x: int, *args: int, **kwargs: int) -> None: + print("Foo", x, args, kwargs) + +class Bar(Foo): + def f(self, *args: int, **kwargs: int) -> None: + print("Bar", args, kwargs) + +z: Foo = Bar() +z.f(1, z=2) +z.f(1, 2, 3) +# z.f(x=5) # Not tested because we (knowingly) do the wrong thing and pass it as positional + +[out] +Bar (1,) {'z': 2} +Bar (1, 2, 3) {} +--Bar () {'x': 5} + +[case testMethodOverrideDefault8] +from typing import TypeVar, Any + +class Foo: + def f(self, *args: int, **kwargs: int) -> None: + print("Foo", args, kwargs) + +class Bar(Foo): + def f(self, x: int = 10, *args: int, **kwargs: int) -> None: + print("Bar", x, args, kwargs) + +z: Foo = Bar() +z.f(1, z=2) +z.f(1, 2, 3) +z.f() + +[out] +Bar 1 () {'z': 2} +Bar 1 (2, 3) {} +Bar 10 () {} + +[case testMethodOverrideDefault9] +from testutil import make_python_function +from mypy_extensions import mypyc_attr +from typing import TypeVar, Any + +@mypyc_attr(allow_interpreted_subclasses=True) +class Foo: + def f(self, x: int=20, y: int=40) -> None: + print("Foo", x, y) + +# This sort of argument renaming is dodgy and not really sound but we +# shouldn't break it when they aren't actually used by name... +# (They *ought* to be positional only!) +@make_python_function +def baz_f(self, a: int=30, y: int=50) -> None: + print("Baz", a, y) + +# Make an "interpreted" subtype of Foo +type2: Any = type +Baz = type2('Baz', (Foo,), {'f': baz_f}) + +z: Foo = Baz() +z.f() +z.f(y=1) +z.f(1, 2) +# Not tested because we don't (and probably won't) match cpython here +# from testutil import assertRaises +# with assertRaises(TypeError): +# z.f(x=7) + +[out] +Baz 30 50 +Baz 30 1 +Baz 1 2 + [case testOverride] class A: def f(self) -> int: @@ -1318,13 +1591,13 @@ from mypy_extensions import trait class Temperature: @property def celsius(self) -> float: - return 5.0 * (self.farenheit - 32.0) / 9.0 + return 5.0 * (self.fahrenheit - 32.0) / 9.0 - def __init__(self, farenheit: float) -> None: - self.farenheit = farenheit + def __init__(self, fahrenheit: float) -> None: + self.fahrenheit = fahrenheit def print_temp(self) -> None: - print("F:", self.farenheit, "C:", self.celsius) + print("F:", self.fahrenheit, "C:", self.celsius) @property def rankine(self) -> float: diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index 49deb0854483..41675e7fcc91 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -1,4 +1,4 @@ -# Dict test cases (compile and run) +# Test cases for dicts (compile and run) [case testDictStuff] from typing import Dict, Any, List, Set, Tuple @@ -196,7 +196,7 @@ else: [case testDictMethods] from collections import defaultdict -from typing import Dict, Optional +from typing import Dict, Optional, List, Set def test_dict_clear() -> None: d = {'a': 1, 'b': 2} @@ -232,7 +232,7 @@ class MyDict(dict): return super().setdefault(k, v) + 10 def test_dict_setdefault() -> None: - d: Dict[str, int] = {'a': 1, 'b': 2} + d: Dict[str, Optional[int]] = {'a': 1, 'b': 2} assert d.setdefault('a', 2) == 1 assert d.setdefault('b', 2) == 2 assert d.setdefault('c', 3) == 3 @@ -254,6 +254,32 @@ def test_dict_subclass_setdefault() -> None: assert d.setdefault('e') == None assert d.setdefault('e', 100) == 110 +def test_dict_empty_collection_setdefault() -> None: + d1: Dict[str, List[int]] = {'a': [1, 2, 3]} + assert d1.setdefault('a', []) == [1, 2, 3] + assert d1.setdefault('b', []) == [] + assert 'b' in d1 + d1.setdefault('b', []).append(3) + assert d1['b'] == [3] + assert d1.setdefault('c', [1]) == [1] + + d2: Dict[str, Dict[str, int]] = {'a': {'a': 1}} + assert d2.setdefault('a', {}) == {'a': 1} + assert d2.setdefault('b', {}) == {} + assert 'b' in d2 + d2.setdefault('b', {})['aa'] = 2 + d2.setdefault('b', {})['bb'] = 3 + assert d2['b'] == {'aa': 2, 'bb': 3} + assert d2.setdefault('c', {'cc': 1}) == {'cc': 1} + + d3: Dict[str, Set[str]] = {'a': set('a')} + assert d3.setdefault('a', set()) == {'a'} + assert d3.setdefault('b', set()) == set() + d3.setdefault('b', set()).add('b') + d3.setdefault('b', set()).add('c') + assert d3['b'] == {'b', 'c'} + assert d3.setdefault('c', set('d')) == {'d'} + [case testDictToBool] from typing import Dict, List diff --git a/mypyc/test-data/run-dunders.test b/mypyc/test-data/run-dunders.test index 261ffb9d5af6..aee2a956c47f 100644 --- a/mypyc/test-data/run-dunders.test +++ b/mypyc/test-data/run-dunders.test @@ -312,3 +312,487 @@ def test_native_del_item_override() -> None: assert a.key == 10 and a.value == 12 del a[16] assert a.key == 18 + +[case testDundersNumber] +from typing import Any + +class C: + def __init__(self, x: int) -> None: + self.x = x + + def __neg__(self) -> int: + return self.x + 1 + + def __invert__(self) -> int: + return self.x + 2 + + def __int__(self) -> int: + return self.x + 3 + + def __float__(self) -> float: + return float(self.x + 4) + +def test_unary_dunders_generic() -> None: + a: Any = C(10) + + assert -a == 11 + assert ~a == 12 + assert int(a) == 13 + assert float(a) == 14.0 + +def test_unary_dunders_native() -> None: + c = C(10) + + assert -c == 11 + assert ~c == 12 + assert int(c) == 13 + assert float(c) == 14.0 + +[case testDundersBinarySimple] +from typing import Any + +class C: + def __init__(self) -> None: + self.x = 5 + + def __add__(self, y: int) -> int: + return self.x + y + + def __sub__(self, y: int) -> int: + return self.x - y + + def __mul__(self, y: int) -> int: + return self.x * y + + def __mod__(self, y: int) -> int: + return self.x % y + + def __lshift__(self, y: int) -> int: + return self.x << y + + def __rshift__(self, y: int) -> int: + return self.x >> y + + def __and__(self, y: int) -> int: + return self.x & y + + def __or__(self, y: int) -> int: + return self.x | y + + def __xor__(self, y: int) -> int: + return self.x ^ y + + def __matmul__(self, y: int) -> int: + return self.x + y + 10 + + def __truediv__(self, y: int) -> int: + return self.x + y + 20 + + def __floordiv__(self, y: int) -> int: + return self.x + y + 30 + +def test_generic() -> None: + a: Any = C() + assert a + 3 == 8 + assert a - 3 == 2 + assert a * 5 == 25 + assert a % 2 == 1 + assert a << 4 == 80 + assert a >> 0 == 5 + assert a >> 1 == 2 + assert a & 1 == 1 + assert a | 3 == 7 + assert a ^ 3 == 6 + assert a @ 3 == 18 + assert a / 2 == 27 + assert a // 2 == 37 + +def test_native() -> None: + c = C() + assert c + 3 == 8 + assert c - 3 == 2 + +def test_error() -> None: + a: Any = C() + try: + a + 'x' + except TypeError as e: + assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'" + else: + assert False + try: + a - 'x' + except TypeError as e: + assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'" + else: + assert False + +[case testDundersBinaryReverse] +from typing import Any + +class C: + def __init__(self) -> None: + self.x = 5 + + def __add__(self, y: int) -> int: + return self.x + y + + def __radd__(self, y: int) -> int: + return self.x + y + 1 + + def __sub__(self, y: int) -> int: + return self.x - y + + def __rsub__(self, y: int) -> int: + return self.x - y - 1 + +def test_generic() -> None: + a: Any = C() + assert a + 3 == 8 + assert 4 + a == 10 + assert a - 3 == 2 + assert 4 - a == 0 + +def test_native() -> None: + c = C() + assert c + 3 == 8 + assert 4 + c == 10 + assert c - 3 == 2 + assert 4 - c == 0 + +def test_errors() -> None: + a: Any = C() + try: + a + 'x' + except TypeError as e: + assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'" + else: + assert False + try: + a - 'x' + except TypeError as e: + assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'" + else: + assert False + try: + 'x' + a + except TypeError as e: + assert str(e) in ('can only concatenate str (not "C") to str', + 'must be str, not C') + else: + assert False + +class F: + def __add__(self, x: int) -> int: + return 5 + +class G: + def __add__(self, x: int) -> int: + return 33 + + def __radd__(self, x: F) -> int: + return 6 + +def test_type_mismatch_fall_back_to_reverse() -> None: + assert F() + G() == 6 + +[case testDundersBinaryNotImplemented] +from typing import Any, Union +from testutil import assertRaises + +class C: + def __init__(self, v: int) -> None: + self.v = v + + def __add__(self, y: int) -> Union[int, Any]: + if y == 1: + return self.v + return NotImplemented + +def test_any_add() -> None: + a: Any = C(4) + assert a + 1 == 4 + try: + a + 2 + except TypeError: + pass + else: + assert False + +class D: + def __init__(self, x: int) -> None: + self.x = x + + def __add__(self, e: E) -> Union[int, Any]: + if e.x == 1: + return 2 + return NotImplemented + +class E: + def __init__(self, x: int) -> None: + self.x = x + + def __radd__(self, d: D) -> Union[int, Any]: + if d.x == 3: + return 4 + return NotImplemented + +def test_any_radd() -> None: + d1: Any = D(1) + d3: Any = D(3) + e1: Any = E(1) + e3: Any = E(3) + assert d1 + e1 == 2 + assert d3 + e1 == 2 + assert d3 + e3 == 4 + +class F: + def __init__(self, v): + self.v = v + + def __add__(self, x): + if isinstance(x, int): + return self.v + x + return NotImplemented + +class G: + def __radd__(self, x): + if isinstance(x, F): + return x.v + 1 + if isinstance(x, str): + return 'a' + return NotImplemented + +def test_unannotated_add() -> None: + o = F(4) + assert o + 5 == 9 + with assertRaises(TypeError, "unsupported operand type(s) for +: 'F' and 'str'"): + o + 'x' + +def test_unannotated_add_and_radd_1() -> None: + o = F(4) + assert o + G() == 5 + +def test_unannotated_radd() -> None: + assert 'x' + G() == 'a' + with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'G'"): + 1 + G() + +class H: + def __add__(self, x): + if isinstance(x, int): + return x + 1 + return NotImplemented + + def __radd__(self, x): + if isinstance(x, str): + return 22 + return NotImplemented + +def test_unannotated_add_and_radd_2() -> None: + h = H() + assert h + 5 == 6 + assert 'x' + h == 22 + with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'H'"): + 1 + h + +# TODO: Inheritance + +[case testDifferentReverseDunders] +class C: + # __radd__ and __rsub__ are tested elsewhere + + def __rmul__(self, x): + return 1 + + def __rtruediv__(self, x): + return 2 + + def __rmod__(self, x): + return 3 + + def __rfloordiv__(self, x): + return 4 + + def __rlshift__(self, x): + return 5 + + def __rrshift__(self, x): + return 6 + + def __rand__(self, x): + return 7 + + def __ror__(self, x): + return 8 + + def __rxor__(self, x): + return 9 + + def __rmatmul__(self, x): + return 10 + +def test_reverse_dunders() -> None: + x = 0 + c = C() + assert x * c == 1 + assert x / c == 2 + assert x % c == 3 + assert x // c == 4 + assert x << c == 5 + assert x >> c == 6 + assert x & c == 7 + assert x | c == 8 + assert x ^ c == 9 + assert x @ c == 10 + +[case testDundersInplace] +from typing import Any +from testutil import assertRaises + +class C: + def __init__(self) -> None: + self.x = 5 + + def __iadd__(self, y: int) -> C: + self.x += y + return self + + def __isub__(self, y: int) -> C: + self.x -= y + return self + + def __imul__(self, y: int) -> C: + self.x *= y + return self + + def __imod__(self, y: int) -> C: + self.x %= y + return self + + def __itruediv__(self, y: int) -> C: + self.x += y + 10 + return self + + def __ifloordiv__(self, y: int) -> C: + self.x += y + 20 + return self + + def __ilshift__(self, y: int) -> C: + self.x <<= y + return self + + def __irshift__(self, y: int) -> C: + self.x >>= y + return self + + def __iand__(self, y: int) -> C: + self.x &= y + return self + + def __ior__(self, y: int) -> C: + self.x |= y + return self + + def __ixor__(self, y: int) -> C: + self.x ^= y + return self + + def __imatmul__(self, y: int) -> C: + self.x += y + 5 + return self + +def test_generic_1() -> None: + c: Any = C() + c += 3 + assert c.x == 8 + c -= 5 + assert c.x == 3 + c *= 3 + assert c.x == 9 + c %= 4 + assert c.x == 1 + c /= 5 + assert c.x == 16 + c //= 4 + assert c.x == 40 + +def test_generic_2() -> None: + c: Any = C() + c <<= 4 + assert c.x == 80 + c >>= 3 + assert c.x == 10 + c &= 3 + assert c.x == 2 + c |= 6 + assert c.x == 6 + c ^= 12 + assert c.x == 10 + c @= 3 + assert c.x == 18 + +def test_native() -> None: + c = C() + c += 3 + assert c.x == 8 + c -= 5 + assert c.x == 3 + c *= 3 + assert c.x == 9 + +def test_error() -> None: + c: Any = C() + with assertRaises(TypeError, "int object expected; got str"): + c += 'x' + +class BadInplaceAdd: + def __init__(self): + self.x = 0 + + def __iadd__(self, x): + self.x += x + +def test_in_place_operator_returns_none() -> None: + o = BadInplaceAdd() + with assertRaises(TypeError, "native.BadInplaceAdd object expected; got None"): + o += 5 + +[case testDunderMinMax] +class SomeItem: + def __init__(self, val: int) -> None: + self.val = val + + def __lt__(self, x: 'SomeItem') -> bool: + return self.val < x.val + + def __gt__(self, x: 'SomeItem') -> bool: + return self.val > x.val + +class AnotherItem: + def __init__(self, val: str) -> None: + self.val = val + + def __lt__(self, x: 'AnotherItem') -> bool: + return True + + def __gt__(self, x: 'AnotherItem') -> bool: + return True + +def test_dunder_min() -> None: + x = SomeItem(5) + y = SomeItem(10) + z = SomeItem(15) + assert min(x, y).val == 5 + assert min(y, z).val == 10 + assert max(x, y).val == 10 + assert max(y, z).val == 15 + x2 = AnotherItem('xxx') + y2 = AnotherItem('yyy') + z2 = AnotherItem('zzz') + assert min(x2, y2).val == 'yyy' + assert min(y2, x2).val == 'xxx' + assert max(x2, y2).val == 'yyy' + assert max(y2, x2).val == 'xxx' + assert min(y2, z2).val == 'zzz' + assert max(x2, z2).val == 'zzz' diff --git a/mypyc/test-data/run-floats.test b/mypyc/test-data/run-floats.test index e716949d69c4..1b67a1190cd8 100644 --- a/mypyc/test-data/run-floats.test +++ b/mypyc/test-data/run-floats.test @@ -1,3 +1,5 @@ +# Test cases for floats (compile and run) + [case testStrToFloat] def str_to_float(x: str) -> float: return float(x) @@ -11,10 +13,18 @@ assert str_to_float("44324") == 44324.0 assert str_to_float("23.4") == 23.4 assert str_to_float("-43.44e-4") == -43.44e-4 -[case testFloatAbs] +[case testFloatArithmetic] def test_abs() -> None: assert abs(0.0) == 0.0 assert abs(-1.234567) == 1.234567 assert abs(44324.732) == 44324.732 assert abs(-23.4) == 23.4 assert abs(-43.44e-4) == 43.44e-4 + +def test_float_min_max() -> None: + x: float = 20.0 + y: float = 30.0 + assert min(x, y) == 20.0 + assert min(y, x) == 20.0 + assert max(x, y) == 30.0 + assert max(y, x) == 30.0 diff --git a/mypyc/test-data/run-functions.test b/mypyc/test-data/run-functions.test index 481d8d6425bc..66b56503f329 100644 --- a/mypyc/test-data/run-functions.test +++ b/mypyc/test-data/run-functions.test @@ -21,7 +21,6 @@ def fib(n: int) -> int: return 1 else: return fib(n - 1) + fib(n - 2) - return 0 # TODO: This should be unnecessary [file driver.py] from native import fib print(fib(0)) @@ -969,6 +968,10 @@ assert onearg(*t) == 2 d = {'x': 5} assert onearg(**d) == 6 +# Test a bogus call to twoargs before any correct calls are made +with assertRaises(TypeError, "twoargs() missing required argument 'x' (pos 1)"): + twoargs() + assert twoargs(5, 'foo') == 8 assert twoargs(4, y='foo') == 7 assert twoargs(y='foo', x=7) == 10 @@ -1003,6 +1006,8 @@ with assertRaises(TypeError, "onearg() missing required argument 'x' (pos 1)"): with assertRaises(TypeError, "onearg() takes at most 1 argument (2 given)"): onearg(1, y=1) +with assertRaises(TypeError, "twoargs() missing required argument 'x' (pos 1)"): + twoargs() with assertRaises(TypeError, "twoargs() missing required argument 'y' (pos 2)"): twoargs(1) with assertRaises(TypeError, 'twoargs() takes at most 2 arguments (3 given)'): @@ -1093,6 +1098,7 @@ assert kwonly4(y=2, x=1) == (1, 2) # varargs tests assert varargs1() == () assert varargs1(1, 2, 3) == (1, 2, 3) +assert varargs1(1, *[2, 3, 4], 5, *[6, 7, 8], 9) == (1, 2, 3, 4, 5, 6, 7, 8, 9) assert varargs2(1, 2, 3) == ((1, 2, 3), {}) assert varargs2(1, 2, 3, x=4) == ((1, 2, 3), {'x': 4}) assert varargs2(x=4) == ((), {'x': 4}) @@ -1177,3 +1183,12 @@ with assertRaises(TypeError, "varargs4() missing required keyword-only argument varargs4(1, 2, 3) with assertRaises(TypeError, "varargs4() missing required argument 'a' (pos 1)"): varargs4(y=20) + +[case testDecoratorName] +def dec(f): return f + +@dec +def foo(): pass + +def test_decorator_name(): + assert foo.__name__ == "foo" diff --git a/mypyc/test-data/run-imports.test b/mypyc/test-data/run-imports.test index 78b167861ae8..0957d1b2b87f 100644 --- a/mypyc/test-data/run-imports.test +++ b/mypyc/test-data/run-imports.test @@ -86,6 +86,76 @@ def g(x: int) -> int: from native import f assert f(1) == 2 +[case testFromImportWithUntypedModule] + +# avoid including an __init__.py and use type: ignore to test what happens +# if mypy can't tell if mod isn't a module +from pkg import mod # type: ignore + +def test_import() -> None: + assert mod.h(8) == 24 + +[file pkg/mod.py] +def h(x): + return x * 3 + +[case testFromImportWithKnownModule] +from pkg import mod1 +from pkg import mod2 as modmod +from pkg.mod2 import g as gg +from pkg.mod3 import h as h2, g as g2 + +def test_import() -> None: + assert mod1.h(8) == 24 + assert modmod.g(1) == 1 + assert gg(2) == 2 + assert h2(10) == 12 + assert g2(10) == 13 + +[file pkg/__init__.py] +[file pkg/mod1.py] +def h(x: int) -> int: + return x * 3 + +[file pkg/mod2.py] +def g(x: int) -> int: + return x + +[file pkg/mod3.py] +def h(x: int) -> int: + return x + 2 + +def g(x: int) -> int: + return x + 3 + +[case testFromImportWithUnKnownModule] +def test_import() -> None: + try: + from pkg import a # type: ignore + except ImportError: + pass + +[file pkg/__init__.py] + +[case testMultipleFromImportsWithSamePackageButDifferentModules] +from pkg import a +from pkg import b + +def test_import() -> None: + assert a.g() == 4 + assert b.h() == 39 + +[file pkg/__init__.py] +[file pkg/a.py] + +def g() -> int: + return 4 + +[file pkg/b.py] + +def h() -> int: + return 39 + [case testReexport] # Test that we properly handle accessing values that have been reexported import a diff --git a/mypyc/test-data/run-integers.test b/mypyc/test-data/run-integers.test index 59e61931439b..b9668d6dec9f 100644 --- a/mypyc/test-data/run-integers.test +++ b/mypyc/test-data/run-integers.test @@ -87,15 +87,36 @@ def big_int() -> None: max_63_bit = 9223372036854775807 d_64_bit = 9223372036854775808 max_32_bit = 2147483647 + max_32_bit_plus1 = 2147483648 max_31_bit = 1073741823 + max_31_bit_plus1 = 1073741824 + neg = -1234567 + min_signed_63_bit = -4611686018427387904 + underflow = -4611686018427387905 + min_signed_64_bit = -9223372036854775808 + min_signed_31_bit = -1073741824 + min_signed_31_bit_plus1 = -1073741823 + min_signed_31_bit_minus1 = -1073741825 + min_signed_32_bit = -2147483648 print(a_62_bit) print(max_62_bit) print(b_63_bit) print(c_63_bit) print(max_63_bit) print(d_64_bit) + print('==') print(max_32_bit) + print(max_32_bit_plus1) print(max_31_bit) + print(max_31_bit_plus1) + print(neg) + print(min_signed_63_bit) + print(underflow) + print(min_signed_64_bit) + print(min_signed_31_bit) + print(min_signed_31_bit_plus1) + print(min_signed_31_bit_minus1) + print(min_signed_32_bit) [file driver.py] from native import big_int big_int() @@ -106,8 +127,19 @@ big_int() 9223372036854775806 9223372036854775807 9223372036854775808 +== 2147483647 +2147483648 1073741823 +1073741824 +-1234567 +-4611686018427387904 +-4611686018427387905 +-9223372036854775808 +-1073741824 +-1073741823 +-1073741825 +-2147483648 [case testNeg] def neg(x: int) -> int: @@ -131,6 +163,14 @@ assert neg(-9223372036854775807) == 9223372036854775807 assert neg(9223372036854775808) == -9223372036854775808 assert neg(-9223372036854775808) == 9223372036854775808 +[case testIsinstanceIntAndNotBool] +def test_isinstance_int_and_not_bool(value: object) -> bool: + return isinstance(value, int) and not isinstance(value, bool) +[file driver.py] +from native import test_isinstance_int_and_not_bool +assert test_isinstance_int_and_not_bool(True) == False +assert test_isinstance_int_and_not_bool(1) == True + [case testIntOps] def check_and(x: int, y: int) -> None: # eval() can be trusted to calculate expected result @@ -157,15 +197,6 @@ def check_bitwise(x: int, y: int) -> None: check_or(ll, rr) check_xor(ll, rr) -[case testIsinstanceIntAndNotBool] -def test_isinstance_int_and_not_bool(value: object) -> bool: - return isinstance(value, int) and not isinstance(value, bool) -[file driver.py] -from native import test_isinstance_int_and_not_bool -assert test_isinstance_int_and_not_bool(True) == False -assert test_isinstance_int_and_not_bool(1) == True - - SHIFT = 30 DIGIT0a = 615729753 DIGIT0b = 832796681 @@ -198,6 +229,10 @@ def test_and_or_xor() -> None: check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a) check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50) + for x in range(-25, 25): + for y in range(-25, 25): + check_bitwise(x, y) + def test_bitwise_inplace() -> None: # Basic sanity checks; these should use the same code as the non-in-place variants for x, y in (DIGIT0a, DIGIT1a), (DIGIT2a, DIGIT0a + DIGIT2b): @@ -328,3 +363,116 @@ def test_int_as_bool() -> None: for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101): assert is_true(x) assert not is_false(x) + +def test_divide() -> None: + for x in range(-100, 100): + for y in range(-100, 100): + if y != 0: + assert x // y == getattr(x, "__floordiv__")(y) + +def test_mod() -> None: + for x in range(-100, 100): + for y in range(-100, 100): + if y != 0: + assert x % y == getattr(x, "__mod__")(y) + +def test_constant_fold() -> None: + assert str(-5 + 3) == "-2" + assert str(15 - 3) == "12" + assert str(1000 * 1000) == "1000000" + assert str(12325 // 12 ) == "1027" + assert str(87645 % 321) == "12" + assert str(674253 | 76544) == "748493" + assert str(765 ^ 82) == "687" + assert str(6546 << 3) == "52368" + assert str(6546 >> 7) == "51" + assert str(3**5) == "243" + assert str(~76) == "-77" + try: + 2 / 0 + except ZeroDivisionError: + pass + else: + assert False, "no exception raised" + + x = int() + y = int() - 1 + assert x == -1 or y != -3 + assert -1 <= x + assert -1 == y + + # Use int() to avoid constant propagation + i30 = (1 << 30) + int() + assert i30 == 1 << 30 + i31 = (1 << 31) + int() + assert i31 == 1 << 31 + i32 = (1 << 32) + int() + assert i32 == 1 << 32 + i62 = (1 << 62) + int() + assert i62 == 1 << 62 + i63 = (1 << 63) + int() + assert i63 == 1 << 63 + i64 = (1 << 64) + int() + assert i64 == 1 << 64 + + n30 = -(1 << 30) + int() + assert n30 == -(1 << 30) + n31 = -(1 << 31) + int() + assert n31 == -(1 << 31) + n32 = -(1 << 32) + int() + assert n32 == -(1 << 32) + n62 = -(1 << 62) + int() + assert n62 == -(1 << 62) + n63 = -(1 << 63) + int() + assert n63 == -(1 << 63) + n64 = -(1 << 64) + int() + assert n64 == -(1 << 64) + +[case testIntMinMax] +def test_int_min_max() -> None: + x: int = 200 + y: int = 30 + assert min(x, y) == 30 + assert max(x, y) == 200 + assert min(y, x) == 30 + assert max(y, x) == 200 + +def test_int_hybrid_min_max() -> None: + from typing import Any + + x: object = 30 + y: Any = 20.0 + assert min(x, y) == 20.0 + assert max(x, y) == 30 + + u: object = 20 + v: float = 30.0 + assert min(u, v) == 20 + assert max(u, v) == 30.0 + +def test_int_incompatible_min_max() -> None: + x: int = 2 + y: str = 'aaa' + try: + print(min(x, y)) + except TypeError as e: + assert str(e) == "'<' not supported between instances of 'str' and 'int'" + try: + print(max(x, y)) + except TypeError as e: + assert str(e) == "'>' not supported between instances of 'str' and 'int'" + +def test_int_bool_min_max() -> None: + x: int = 2 + y: bool = False + z: bool = True + assert min(x, y) == False + assert min(x, z) == True + assert max(x, y) == 2 + assert max(x, z) == 2 + + u: int = -10 + assert min(u, y) == -10 + assert min(u, z) == -10 + assert max(u, y) == False + assert max(u, z) == True diff --git a/mypyc/test-data/run-lists.test b/mypyc/test-data/run-lists.test index a78b2d65de4b..c98ab9171123 100644 --- a/mypyc/test-data/run-lists.test +++ b/mypyc/test-data/run-lists.test @@ -75,6 +75,25 @@ print(primes(13)) \[0, 0, 1, 1] \[0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1] +[case testListBuild] +def test_list_build() -> None: + # Currently LIST_BUILDING_EXPANSION_THRESHOLD equals to 10 + # long list built by list_build_op + l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + l1.pop() + l1.append(100) + assert l1 == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100] + # short list built by Setmem + l2 = [1, 2] + l2.append(3) + l2.pop() + l2.pop() + assert l2 == [1] + # empty list + l3 = [] + l3.append('a') + assert l3 == ['a'] + [case testListPrims] from typing import List @@ -357,3 +376,11 @@ def test() -> None: source_e = [0, 1, 2] e = list((x ** 2) for x in (y + 2 for y in source_e)) assert e == [4, 9, 16] + source_str = "abcd" + f = list("str:" + x for x in source_str) + assert f == ["str:a", "str:b", "str:c", "str:d"] +[case testNextBug] +from typing import List, Optional + +def test(x: List[int]) -> None: + res = next((i for i in x), None) diff --git a/mypyc/test-data/run-loops.test b/mypyc/test-data/run-loops.test index b83853bc6d16..994b30b42347 100644 --- a/mypyc/test-data/run-loops.test +++ b/mypyc/test-data/run-loops.test @@ -1,4 +1,4 @@ -# Test cases for "for" and "while" loops (compile and run) +# Test cases for "range" objects, "for" and "while" loops (compile and run) [case testFor] from typing import List, Tuple @@ -452,3 +452,34 @@ def bar(x: Optional[str]) -> None: [file driver.py] from native import bar bar(None) + +[case testRangeObject] +from typing import Any + +def f(x: range) -> int: + sum = 0 + for i in x: + sum += i + return sum + +def test_range_object() -> None: + r1 = range(4, 12, 2) + tmp_list = [x for x in r1] + assert tmp_list == [4, 6, 8, 10] + assert f(r1) == 28 + r2: Any = range(10) + assert f(r2) == 45 + r3: Any = 'x' + try: + f(r3) + except TypeError as e: + assert "range object expected; got str" in str(e) + try: + ff: Any = f + ff(r3) + except TypeError as e: + assert "range object expected; got str" in str(e) + try: + r4 = range(4, 12, 0) + except ValueError as e: + assert "range() arg 3 must not be zero" in str(e) diff --git a/mypyc/test-data/run-misc.test b/mypyc/test-data/run-misc.test index 46fa8d0e176f..736169f95b82 100644 --- a/mypyc/test-data/run-misc.test +++ b/mypyc/test-data/run-misc.test @@ -2,6 +2,7 @@ [case testAsync] import asyncio +import sys async def h() -> int: return 1 @@ -13,8 +14,13 @@ async def g() -> int: async def f() -> int: return await g() -loop = asyncio.get_event_loop() -result = loop.run_until_complete(f()) +# sys.version_info >= (3, 7) fails with +# error: Unsupported left operand type for >= ("Tuple[int, int, int, str, int]") +if sys.version_info[0] >= 3 and sys.version_info[1] >= 7: + result = asyncio.run(f()) +else: + loop = asyncio.get_event_loop() + result = loop.run_until_complete(f()) assert result == 1 [typing fixtures/typing-full.pyi] @@ -22,8 +28,13 @@ assert result == 1 [file driver.py] from native import f import asyncio -loop = asyncio.get_event_loop() -result = loop.run_until_complete(f()) +import sys + +if sys.version_info >= (3, 7): + result = asyncio.run(f()) +else: + loop = asyncio.get_event_loop() + result = loop.run_until_complete(f()) assert result == 1 [case testMaybeUninitVar] @@ -485,6 +496,8 @@ print(native.x) 77 [case testComprehensions] +from typing import List + # A list comprehension l = [str(x) + " " + str(y) + " " + str(x*y) for x in range(10) if x != 6 if x != 5 for y in range(x) if y*x != 8] @@ -498,6 +511,17 @@ def pred(x: int) -> bool: # eventually and will raise an exception. l2 = [x for x in range(10) if x <= 6 if pred(x)] +src = ['x'] + +def f() -> List[str]: + global src + res = src + src = [] + return res + +l3 = [s for s in f()] +l4 = [s for s in f()] + # A dictionary comprehension d = {k: k*k for k in range(10) if k != 5 if k != 6} @@ -506,10 +530,12 @@ s = {str(x) + " " + str(y) + " " + str(x*y) for x in range(10) if x != 6 if x != 5 for y in range(x) if y*x != 8} [file driver.py] -from native import l, l2, d, s +from native import l, l2, l3, l4, d, s for a in l: print(a) print(tuple(l2)) +assert l3 == ['x'] +assert l4 == [] for k in sorted(d): print(k, d[k]) for a in sorted(s): @@ -805,6 +831,51 @@ assert call_all(mixed_110) == 1 assert call_any_nested([[1, 1, 1], [1, 1], []]) == 1 assert call_any_nested([[1, 1, 1], [0, 1], []]) == 0 +[case testSum] +[typing fixtures/typing-full.pyi] +from typing import Any, List + +def test_sum_of_numbers() -> None: + assert sum(x for x in [1, 2, 3]) == 6 + assert sum(x for x in [0.0, 1.2, 2]) == 6.2 + assert sum(x for x in [1, 1j]) == 1 + 1j + +def test_sum_callables() -> None: + assert sum((lambda x: x == 0)(x) for x in []) == 0 + assert sum((lambda x: x == 0)(x) for x in [0]) == 1 + assert sum((lambda x: x == 0)(x) for x in [0, 0, 0]) == 3 + assert sum((lambda x: x == 0)(x) for x in [0, 1, 0]) == 2 + assert sum((lambda x: x % 2 == 0)(x) for x in range(2**10)) == 2**9 + +def test_sum_comparisons() -> None: + assert sum(x == 0 for x in []) == 0 + assert sum(x == 0 for x in [0]) == 1 + assert sum(x == 0 for x in [0, 0, 0]) == 3 + assert sum(x == 0 for x in [0, 1, 0]) == 2 + assert sum(x % 2 == 0 for x in range(2**10)) == 2**9 + +def test_sum_multi() -> None: + assert sum(i + j == 0 for i, j in zip([0, 0, 0], [0, 1, 0])) == 2 + +def test_sum_misc() -> None: + # misc cases we do optimize (note, according to sum's helptext, we don't need to support + # non-numeric cases, but CPython and mypyc both do anyway) + assert sum(c == 'd' for c in 'abcdd') == 2 + # misc cases we do not optimize + assert sum([0, 1]) == 1 + assert sum([0, 1], 1) == 2 + +def test_sum_start_given() -> None: + a = 1 + assert sum((x == 0 for x in [0, 1]), a) == 2 + assert sum(((lambda x: x == 0)(x) for x in []), 1) == 1 + assert sum(((lambda x: x == 0)(x) for x in [0]), 1) == 2 + assert sum(((lambda x: x == 0)(x) for x in [0, 0, 0]), 1) == 4 + assert sum(((lambda x: x == 0)(x) for x in [0, 1, 0]), 1) == 3 + assert sum(((lambda x: x % 2 == 0)(x) for x in range(2**10)), 1) == 2**9 + 1 + assert sum((x for x in [1, 1j]), 2j) == 1 + 3j + assert sum((c == 'd' for c in 'abcdd'), 1) == 3 + [case testNoneStuff] from typing import Optional class A: @@ -819,7 +890,6 @@ def none() -> None: def arg(x: Optional[A]) -> bool: return x is None - [file driver.py] import native native.lol(native.A()) @@ -1037,3 +1107,51 @@ C = sys.platform == 'x' and (lambda x: y + x) assert not A assert not B assert not C + +[case testDoesntSegfaultWhenTopLevelFails] +# make the initial import fail +assert False + +class C: + def __init__(self): + self.x = 1 + self.y = 2 +def test() -> None: + a = C() +[file driver.py] +# load native, cause PyInit to be run, create the module but don't finish initializing the globals +try: + import native +except: + pass +try: + # try accessing those globals that were never properly initialized + import native + native.test() +# should fail with AssertionError due to `assert False` in other function +except AssertionError: + pass + +[case testRepeatedUnderscoreFunctions] +def _(arg): pass +def _(arg): pass + +[case testUnderscoreFunctionsInMethods] + +class A: + def _(arg): pass + def _(arg): pass +class B(A): + def _(arg): pass + def _(arg): pass + +[case testGlobalRedefinition_toplevel] +# mypy: allow-redefinition +i = 0 +i += 1 +i = "foo" +i += i +i = b"foo" + +def test_redefinition() -> None: + assert i == b"foo" diff --git a/mypyc/test-data/run-multimodule.test b/mypyc/test-data/run-multimodule.test index 352611ce0cc4..1444254b7595 100644 --- a/mypyc/test-data/run-multimodule.test +++ b/mypyc/test-data/run-multimodule.test @@ -780,6 +780,7 @@ assert other_a.foo() == 10 [file other_a.py] def foo() -> int: return 10 +[file build/__native_other_a.c] [delete build/__native_other_a.c.2] diff --git a/mypyc/test-data/run-primitives.test b/mypyc/test-data/run-primitives.test index 0ed12c7f04a6..b95f742977be 100644 --- a/mypyc/test-data/run-primitives.test +++ b/mypyc/test-data/run-primitives.test @@ -255,32 +255,6 @@ assert str(to_int(3.14)) == '3' assert str(to_int(3)) == '3' assert get_complex() == 3.5 + 6.2j -[case testBytes] -def f(x: bytes) -> bytes: - return x - -def concat(a: bytes, b: bytes) -> bytes: - return a + b - -def eq(a: bytes, b: bytes) -> bool: - return a == b - -def neq(a: bytes, b: bytes) -> bool: - return a != b - -def join() -> bytes: - seq = (b'1', b'"', b'\xf0') - return b'\x07'.join(seq) -[file driver.py] -from native import f, concat, eq, neq, join -assert f(b'123') == b'123' -assert f(b'\x07 \x0b " \t \x7f \xf0') == b'\x07 \x0b " \t \x7f \xf0' -assert concat(b'123', b'456') == b'123456' -assert eq(b'123', b'123') -assert not eq(b'123', b'1234') -assert neq(b'123', b'1234') -assert join() == b'1\x07"\x07\xf0' - [case testDel] from typing import List from testutil import assertRaises @@ -317,6 +291,8 @@ def delDictMultiple() -> None: printDict(d) class Dummy(): + __deletable__ = ('x', 'y') + def __init__(self, x: int, y: int) -> None: self.x = x self.y = y diff --git a/mypyc/test-data/run-python37.test b/mypyc/test-data/run-python37.test index 3660ba13a6c8..734e116c1335 100644 --- a/mypyc/test-data/run-python37.test +++ b/mypyc/test-data/run-python37.test @@ -1,6 +1,7 @@ -- Test cases for Python 3.7 features [case testRunDataclass] +import dataclasses from dataclasses import dataclass, field from typing import Set, List, Callable, Any @@ -27,6 +28,11 @@ class Person2: age : int name : str = field(default='robot') +@dataclasses.dataclass +class Person2b: + age : int + name : str = dataclasses.field(default='robot') + @dataclass(order = True) class Person3: age : int = field(default = 6) @@ -109,6 +115,8 @@ assert i8 == i9 i8.age = 2 assert i8 > i9 +assert Person1.__annotations__ == {'age': int, 'name': str} +assert Person2.__annotations__ == {'age': int, 'name': str} [file driver.py] import sys diff --git a/mypyc/test-data/run-python38.test b/mypyc/test-data/run-python38.test index 9b620ddb8dae..7de43907cb86 100644 --- a/mypyc/test-data/run-python38.test +++ b/mypyc/test-data/run-python38.test @@ -50,3 +50,39 @@ from native import Node, make, pairs assert pairs(make([1,2,3])) == [(1,2), (2,3)] assert pairs(make([1])) == [] assert pairs(make([])) == [] + +[case testFStrings] +from datetime import datetime + +def test_fstring_equal_sign() -> None: + today = datetime(year=2017, month=1, day=27) + assert f"{today=:%B %d, %Y}" == 'today=January 27, 2017' # using date format specifier and debugging + + foo = "bar" + assert f"{ foo = }" == " foo = 'bar'" # preserves whitespace + + line = "The mill's closed" + assert f"{line = }" == 'line = "The mill\'s closed"' + assert f"{line = :20}" == "line = The mill's closed " + assert f"{line = !r:20}" == 'line = "The mill\'s closed" ' + +[case testMethodOverrideDefaultPosOnly1] +class Foo: + def f(self, x: int=20, /, *, z: int=10) -> None: + pass + +class Bar(Foo): + def f(self, *args: int, **kwargs: int) -> None: + print("stuff", args, kwargs) + +z: Foo = Bar() +z.f(1, z=50) +z.f() +z.f(1) +z.f(z=50) + +[out] +stuff (1,) {'z': 50} +stuff () {} +stuff (1,) {} +stuff () {'z': 50} diff --git a/mypyc/test-data/run-singledispatch.test b/mypyc/test-data/run-singledispatch.test new file mode 100644 index 000000000000..61e4897c96d6 --- /dev/null +++ b/mypyc/test-data/run-singledispatch.test @@ -0,0 +1,698 @@ +# Test cases related to the functools.singledispatch decorator +# Most of these tests are marked as xfails because mypyc doesn't support singledispatch yet +# (These tests will be re-enabled when mypyc supports singledispatch) + +[case testSpecializedImplementationUsed] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register +def fun_specialized(arg: str) -> bool: + return True + +def test_specialize() -> None: + assert fun('a') + assert not fun(3) + +[case testSubclassesOfExpectedTypeUseSpecialized] +from functools import singledispatch +class A: pass +class B(A): pass + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register +def fun_specialized(arg: A) -> bool: + return True + +def test_specialize() -> None: + assert fun(B()) + assert fun(A()) + +[case testSuperclassImplementationNotUsedWhenSubclassHasImplementation] +from functools import singledispatch +class A: pass +class B(A): pass + +@singledispatch +def fun(arg) -> bool: + # shouldn't be using this + assert False + +@fun.register +def fun_specialized(arg: A) -> bool: + return False + +@fun.register +def fun_specialized2(arg: B) -> bool: + return True + +def test_specialize() -> None: + assert fun(B()) + assert not fun(A()) + +[case testMultipleUnderscoreFunctionsIsntError] +from functools import singledispatch + +@singledispatch +def fun(arg) -> str: + return 'default' + +@fun.register +def _(arg: str) -> str: + return 'str' + +@fun.register +def _(arg: int) -> str: + return 'int' + +# extra function to make sure all 3 underscore functions aren't treated as one OverloadedFuncDef +def a(b): pass + +@fun.register +def _(arg: list) -> str: + return 'list' + +def test_singledispatch() -> None: + assert fun(0) == 'int' + assert fun('a') == 'str' + assert fun([1, 2]) == 'list' + assert fun({'a': 'b'}) == 'default' + +[case testCanRegisterCompiledClasses] +from functools import singledispatch +class A: pass + +@singledispatch +def fun(arg) -> bool: + return False +@fun.register +def fun_specialized(arg: A) -> bool: + return True + +def test_singledispatch() -> None: + assert fun(A()) + assert not fun(1) + +[case testTypeUsedAsArgumentToRegister] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register(int) +def fun_specialized(arg) -> bool: + return True + +def test_singledispatch() -> None: + assert fun(1) + assert not fun('a') + +[case testUseRegisterAsAFunction] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +def fun_specialized_impl(arg) -> bool: + return True + +fun.register(int, fun_specialized_impl) + +def test_singledispatch() -> None: + assert fun(0) + assert not fun('a') + +[case testRegisterDoesntChangeFunction] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register(int) +def fun_specialized(arg) -> bool: + return True + +def test_singledispatch() -> None: + assert fun_specialized('a') + +# TODO: turn this into a mypy error +[case testNoneIsntATypeWhenUsedAsArgumentToRegister] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +try: + @fun.register + def fun_specialized(arg: None) -> bool: + return True +except TypeError: + pass + +[case testRegisteringTheSameFunctionSeveralTimes] +from functools import singledispatch + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register(int) +@fun.register(str) +def fun_specialized(arg) -> bool: + return True + +def test_singledispatch() -> None: + assert fun(0) + assert fun('a') + assert not fun([1, 2]) + +[case testTypeIsAnABC] +from functools import singledispatch +from collections.abc import Mapping + +@singledispatch +def fun(arg) -> bool: + return False + +@fun.register +def fun_specialized(arg: Mapping) -> bool: + return True + +def test_singledispatch() -> None: + assert not fun(1) + assert fun({'a': 'b'}) + +[case testSingleDispatchMethod-xfail] +from functools import singledispatchmethod +class A: + @singledispatchmethod + def fun(self, arg) -> str: + return 'default' + + @fun.register + def fun_int(self, arg: int) -> str: + return 'int' + + @fun.register + def fun_str(self, arg: str) -> str: + return 'str' + +def test_singledispatchmethod() -> None: + x = A() + assert x.fun(5) == 'int' + assert x.fun('a') == 'str' + assert x.fun([1, 2]) == 'default' + +[case testSingleDispatchMethodWithOtherDecorator-xfail] +from functools import singledispatchmethod +class A: + @singledispatchmethod + @staticmethod + def fun(arg) -> str: + return 'default' + + @fun.register + @staticmethod + def fun_int(arg: int) -> str: + return 'int' + + @fun.register + @staticmethod + def fun_str(arg: str) -> str: + return 'str' + +def test_singledispatchmethod() -> None: + x = A() + assert x.fun(5) == 'int' + assert x.fun('a') == 'str' + assert x.fun([1, 2]) == 'default' + +[case testSingledispatchTreeSumAndEqual] +from functools import singledispatch + +class Tree: + pass +class Leaf(Tree): + pass +class Node(Tree): + def __init__(self, value: int, left: Tree, right: Tree) -> None: + self.value = value + self.left = left + self.right = right + +@singledispatch +def calc_sum(x: Tree) -> int: + raise TypeError('invalid type for x') + +@calc_sum.register +def _(x: Leaf) -> int: + return 0 + +@calc_sum.register +def _(x: Node) -> int: + return x.value + calc_sum(x.left) + calc_sum(x.right) + +@singledispatch +def equal(to_compare: Tree, known: Tree) -> bool: + raise TypeError('invalid type for x') + +@equal.register +def _(to_compare: Leaf, known: Tree) -> bool: + return isinstance(known, Leaf) + +@equal.register +def _(to_compare: Node, known: Tree) -> bool: + if isinstance(known, Node): + if to_compare.value != known.value: + return False + else: + return equal(to_compare.left, known.left) and equal(to_compare.right, known.right) + return False + +def build(n: int) -> Tree: + if n == 0: + return Leaf() + return Node(n, build(n - 1), build(n - 1)) + +def test_sum_and_equal(): + tree = build(5) + tree2 = build(5) + tree2.right.right.right.value = 10 + assert calc_sum(tree) == 57 + assert calc_sum(tree2) == 65 + assert equal(tree, tree) + assert not equal(tree, tree2) + tree3 = build(4) + assert not equal(tree, tree3) + +[case testSimulateMypySingledispatch] +from functools import singledispatch +from mypy_extensions import trait +from typing import Iterator, Union, TypeVar, Any, List, Type +# based on use of singledispatch in stubtest.py +class Error: + def __init__(self, msg: str) -> None: + self.msg = msg + +@trait +class Node: pass + +class MypyFile(Node): pass +class TypeInfo(Node): pass + + +@trait +class SymbolNode(Node): pass +@trait +class Expression(Node): pass +class TypeVarLikeExpr(SymbolNode, Expression): pass +class TypeVarExpr(TypeVarLikeExpr): pass +class TypeAlias(SymbolNode): pass + +class Missing: pass +MISSING = Missing() + +T = TypeVar("T") + +MaybeMissing = Union[T, Missing] + +@singledispatch +def verify(stub: Node, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]: + yield Error('unknown node type') + +@verify.register(MypyFile) +def verify_mypyfile(stub: MypyFile, a: MaybeMissing[int], b: List[str]) -> Iterator[Error]: + if isinstance(a, Missing): + yield Error("shouldn't be missing") + return + if not isinstance(a, int): + # this check should be unnecessary because of the type signature and the previous check, + # but stubtest.py has this check + yield Error("should be an int") + return + yield from verify(TypeInfo(), str, ['abc', 'def']) + +@verify.register(TypeInfo) +def verify_typeinfo(stub: TypeInfo, a: MaybeMissing[Type[Any]], b: List[str]) -> Iterator[Error]: + yield Error('in TypeInfo') + yield Error('hello') + +@verify.register(TypeVarExpr) +def verify_typevarexpr(stub: TypeVarExpr, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]: + if False: + yield None + +def verify_list(stub, a, b) -> List[str]: + """Helper function that converts iterator of errors to list of messages""" + return list(err.msg for err in verify(stub, a, b)) + +def test_verify() -> None: + assert verify_list(TypeAlias(), 'a', ['a', 'b']) == ['unknown node type'] + assert verify_list(MypyFile(), MISSING, ['a', 'b']) == ["shouldn't be missing"] + assert verify_list(MypyFile(), 5, ['a', 'b']) == ['in TypeInfo', 'hello'] + assert verify_list(TypeInfo(), str, ['a', 'b']) == ['in TypeInfo', 'hello'] + assert verify_list(TypeVarExpr(), 'a', ['x', 'y']) == [] + + +[case testArgsInRegisteredImplNamedDifferentlyFromMainFunction] +from functools import singledispatch + +@singledispatch +def f(a) -> bool: + return False + +@f.register +def g(b: int) -> bool: + return True + +def test_singledispatch(): + assert f(5) + assert not f('a') + +[case testKeywordArguments] +from functools import singledispatch + +@singledispatch +def f(arg, *, kwarg: int = 0) -> int: + return kwarg + 10 + +@f.register +def g(arg: int, *, kwarg: int = 5) -> int: + return kwarg - 10 + +def test_keywords(): + assert f('a') == 10 + assert f('a', kwarg=3) == 13 + assert f('a', kwarg=7) == 17 + + assert f(1) == -5 + assert f(1, kwarg=4) == -6 + assert f(1, kwarg=6) == -4 + +[case testGeneratorAndMultipleTypesOfIterable] +from functools import singledispatch +from typing import * + +@singledispatch +def f(arg: Any) -> Iterable[int]: + yield 1 + +@f.register +def g(arg: str) -> Iterable[int]: + return [0] + +def test_iterables(): + assert f(1) != [1] + assert list(f(1)) == [1] + assert f('a') == [0] + +[case testRegisterUsedAtSameTimeAsOtherDecorators] +from functools import singledispatch +from typing import TypeVar + +class A: pass +class B: pass + +T = TypeVar('T') + +def decorator(f: T) -> T: + return f + +@singledispatch +def f(arg) -> int: + return 0 + +@f.register +@decorator +def h(arg: str) -> int: + return 2 + +def test_singledispatch(): + assert f(1) == 0 + assert f('a') == 2 + +[case testDecoratorModifiesFunction] +from functools import singledispatch +from typing import Callable, Any + +class A: pass + +def decorator(f: Callable[[Any], int]) -> Callable[[Any], int]: + def wrapper(x) -> int: + return f(x) * 7 + return wrapper + +@singledispatch +def f(arg) -> int: + return 10 + +@f.register +@decorator +def h(arg: str) -> int: + return 5 + + +def test_singledispatch(): + assert f('a') == 35 + assert f(A()) == 10 + +[case testMoreSpecificTypeBeforeLessSpecificType] +from functools import singledispatch +class A: pass +class B(A): pass + +@singledispatch +def f(arg) -> str: + return 'default' + +@f.register +def g(arg: B) -> str: + return 'b' + +@f.register +def h(arg: A) -> str: + return 'a' + +def test_singledispatch(): + assert f(B()) == 'b' + assert f(A()) == 'a' + assert f(5) == 'default' + +[case testMultipleRelatedClassesBeingRegistered] +from functools import singledispatch + +class A: pass +class B(A): pass +class C(B): pass + +@singledispatch +def f(arg) -> str: return 'default' + +@f.register +def _(arg: A) -> str: return 'a' + +@f.register +def _(arg: C) -> str: return 'c' + +@f.register +def _(arg: B) -> str: return 'b' + +def test_singledispatch(): + assert f(A()) == 'a' + assert f(B()) == 'b' + assert f(C()) == 'c' + assert f(1) == 'default' + +[case testRegisteredImplementationsInDifferentFiles] +from other_a import f, A, B, C +@f.register +def a(arg: A) -> int: + return 2 + +@f.register +def _(arg: C) -> int: + return 3 + +def test_singledispatch(): + assert f(B()) == 1 + assert f(A()) == 2 + assert f(C()) == 3 + assert f(1) == 0 + +[file other_a.py] +from functools import singledispatch + +class A: pass +class B(A): pass +class C(B): pass + +@singledispatch +def f(arg) -> int: + return 0 + +@f.register +def g(arg: B) -> int: + return 1 + +[case testOrderCanOnlyBeDeterminedFromMRONotIsinstanceChecks] +from mypy_extensions import trait +from functools import singledispatch + +@trait +class A: pass +@trait +class B: pass +class AB(A, B): pass +class BA(B, A): pass + +@singledispatch +def f(arg) -> str: + return "default" + pass + +@f.register +def fa(arg: A) -> str: + return "a" + +@f.register +def fb(arg: B) -> str: + return "b" + +def test_singledispatch(): + assert f(AB()) == "a" + assert f(BA()) == "b" + +[case testCallingFunctionBeforeAllImplementationsRegistered] +from functools import singledispatch + +class A: pass +class B(A): pass + +@singledispatch +def f(arg) -> str: + return 'default' + +assert f(A()) == 'default' +assert f(B()) == 'default' +assert f(1) == 'default' + +@f.register +def g(arg: A) -> str: + return 'a' + +assert f(A()) == 'a' +assert f(B()) == 'a' +assert f(1) == 'default' + +@f.register +def _(arg: B) -> str: + return 'b' + +assert f(A()) == 'a' +assert f(B()) == 'b' +assert f(1) == 'default' + + +[case testDynamicallyRegisteringFunctionFromInterpretedCode] +from functools import singledispatch + +class A: pass +class B(A): pass +class C(B): pass +class D(C): pass + +@singledispatch +def f(arg) -> str: + return "default" + +@f.register +def _(arg: B) -> str: + return 'b' + +[file register_impl.py] +from native import f, A, B, C + +@f.register(A) +def a(arg) -> str: + return 'a' + +@f.register +def c(arg: C) -> str: + return 'c' + +[file driver.py] +from native import f, A, B, C +from register_impl import a, c +# We need a custom driver here because register_impl has to be run before we test this (so that the +# additional implementations are registered) +assert f(C()) == 'c' +assert f(A()) == 'a' +assert f(B()) == 'b' +assert a(C()) == 'a' +assert c(A()) == 'c' + +[case testMalformedDynamicRegisterCall] +from functools import singledispatch + +@singledispatch +def f(arg) -> None: + pass +[file register.py] +from native import f +from testutil import assertRaises + +with assertRaises(TypeError, 'Invalid first argument to `register()`'): + @f.register + def _(): + pass + +[file driver.py] +import register + +[case testCacheClearedWhenNewFunctionRegistered] +from functools import singledispatch + +@singledispatch +def f(arg) -> str: + return 'default' + +[file register.py] +from native import f +class A: pass +class B: pass +class C: pass + +# annotated function +assert f(A()) == 'default' +@f.register +def _(arg: A) -> str: + return 'a' +assert f(A()) == 'a' + +# type passed as argument +assert f(B()) == 'default' +@f.register(B) +def _(arg: B) -> str: + return 'b' +assert f(B()) == 'b' + +# 2 argument form +assert f(C()) == 'default' +def c(arg) -> str: + return 'c' +f.register(C, c) +assert f(C()) == 'c' + + +[file driver.py] +import register diff --git a/mypyc/test-data/run-strings.test b/mypyc/test-data/run-strings.test index 83186d5b033c..c2b010bdb2bd 100644 --- a/mypyc/test-data/run-strings.test +++ b/mypyc/test-data/run-strings.test @@ -1,6 +1,6 @@ # Test cases for strings (compile and run) -[case testStr] +[case testStrBasics] from typing import Tuple def f() -> str: return 'some string' @@ -47,36 +47,6 @@ assert match('', 'abc') == (False, False) [case testStringOps] from typing import List, Optional -var = 'mypyc' - -num = 20 - -def test_fstring_simple() -> None: - f1 = f'Hello {var}, this is a test' - assert f1 == "Hello mypyc, this is a test" - -def test_fstring_conversion() -> None: - f2 = f'Hello {var!r}' - assert f2 == "Hello 'mypyc'" - f3 = f'Hello {var!a}' - assert f3 == "Hello 'mypyc'" - f4 = f'Hello {var!s}' - assert f4 == "Hello mypyc" - -def test_fstring_align() -> None: - f5 = f'Hello {var:>20}' - assert f5 == "Hello mypyc" - f6 = f'Hello {var!r:>20}' - assert f6 == "Hello 'mypyc'" - f7 = f'Hello {var:>{num}}' - assert f7 == "Hello mypyc" - f8 = f'Hello {var!r:>{num}}' - assert f8 == "Hello 'mypyc'" - -def test_fstring_multi() -> None: - f9 = f'Hello {var}, hello again {var}' - assert f9 == "Hello mypyc, hello again mypyc" - def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]: if sep is not None: if max_split is not None: @@ -178,3 +148,490 @@ def test_str_to_bool() -> None: for x in 'a', 'foo', 'bar', 'some string': assert is_true(x) assert not is_false(x) + +def test_str_min_max() -> None: + x: str = 'aaa' + y: str = 'bbb' + z: str = 'aa' + assert min(x, y) == 'aaa' + assert min(x, z) == 'aa' + assert max(x, y) == 'bbb' + assert max(x, z) == 'aaa' + +[case testStringFormattingCStyle] +[typing fixtures/typing-full.pyi] +from typing import Tuple + +var = 'mypyc' +num = 20 + +def test_basics() -> None: + assert 'Hello %s, this is a test' % var == "Hello mypyc, this is a test" + assert 'Hello %s %d, this is a test' % (var, num) == "Hello mypyc 20, this is a test" + t: Tuple[str, int] = (var, num) + assert 'Hello %s %d, this is a test' % t == "Hello mypyc 20, this is a test" + + large_num = 2**65 + assert 'number: %d' % large_num == 'number: 36893488147419103232' + neg_num = -3 + assert 'negative integer: %d' % neg_num == 'negative integer: -3' + assert 'negative integer: %d' % (-large_num) == 'negative integer: -36893488147419103232' + + bool_var1 = True + bool_var2 = False + assert 'bool: %s, %s' % (bool_var1, bool_var2) == 'bool: True, False' + + float_num = 123.4 + assert '%f' % float_num == '123.400000' + assert '%.2f' % float_num == '123.40' + assert '%.5f' % float_num == '123.40000' + assert '%10.2f' % float_num == ' 123.40' + assert '%10.5f' % float_num == ' 123.40000' + assert '%010.5f' % float_num == '0123.40000' + assert '%015.5f' % float_num == '000000123.40000' + assert '%e' % float_num == '1.234000e+02' + large_float = 1.23e30 + large_float2 = 1234123412341234123400000000000000000 + small_float = 1.23e-20 + assert '%f, %f, %f' % (small_float, large_float, large_float2) == \ + '0.000000, 1229999999999999959718843908096.000000, 1234123412341234169005079998930878464.000000' + assert '%s, %s, %s' % (small_float, large_float, large_float2) == \ + '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' + assert '%d, %d, %d' % (small_float, large_float, large_float2) == \ + '0, 1229999999999999959718843908096, 1234123412341234123400000000000000000' + + nan_num = float('nan') + inf_num = float('inf') + assert '%s, %s' % (nan_num, inf_num) == 'nan, inf' + assert '%f, %f' % (nan_num, inf_num) == 'nan, inf' + +[case testFStrings] +import decimal +from datetime import datetime + +var = 'mypyc' +num = 20 + +def test_fstring_basics() -> None: + assert f'Hello {var}, this is a test' == "Hello mypyc, this is a test" + + large_num = 2**65 + assert f'number: {large_num}' == 'number: 36893488147419103232' + neg_num = -3 + assert f'negative integer: {neg_num}' == 'negative integer: -3' + assert f'negative integer: {-large_num}' == 'negative integer: -36893488147419103232' + + bool_var1 = True + bool_var2 = False + assert f'bool: {bool_var1}, {bool_var2}' == 'bool: True, False' + + x = bytes([1, 2, 3, 4]) + # assert f'bytes: {x}' == "bytes: b'\\x01\\x02\\x03\\x04'" + # error: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; + # use "{!r}" if this is desired behavior behavior + + float_num = 123.4 + assert f'{float_num}' == '123.4' + assert f'{float_num:.2f}' == '123.40' + assert f'{float_num:.5f}' == '123.40000' + assert f'{float_num:>10.2f}' == ' 123.40' + assert f'{float_num:>10.5f}' == ' 123.40000' + assert f'{float_num:>010.5f}' == '0123.40000' + assert f'{float_num:>015.5f}' == '000000123.40000' + assert f'{float_num:e}' == '1.234000e+02' + + large_float = 1.23e30 + large_float2 = 1234123412341234123400000000000000000 + small_float = 1.23e-20 + assert f'{small_float}, {large_float}, {large_float2}' == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' + nan_num = float('nan') + inf_num = float('inf') + assert f'{nan_num}, {inf_num}' == 'nan, inf' + +# F-strings would be translated into ''.join[string literals, format method call, ...] in mypy AST. +# Currently we are using a str.join specializer for f-string speed up. We might not cover all cases +# and the rest ones should fall back to a normal str.join method call. +# TODO: Once we have a new pipeline for f-strings, this test case can be moved to testStringOps. +def test_str_join() -> None: + var = 'mypyc' + num = 10 + assert ''.join(['a', 'b', '{}'.format(var), 'c']) == 'abmypycc' + assert ''.join(['a', 'b', '{:{}}'.format(var, ''), 'c']) == 'abmypycc' + assert ''.join(['a', 'b', '{:{}}'.format(var, '>10'), 'c']) == 'ab mypycc' + assert ''.join(['a', 'b', '{:{}}'.format(var, '>{}'.format(num)), 'c']) == 'ab mypycc' + assert var.join(['a', '{:{}}'.format(var, ''), 'b']) == 'amypycmypycmypycb' + assert ','.join(['a', '{:{}}'.format(var, ''), 'b']) == 'a,mypyc,b' + assert ''.join(['x', var]) == 'xmypyc' + +class A: + def __init__(self, name, age): + self.name = name + self.age = age + + def __repr__(self): + return f'{self.name} is {self.age} years old.' + +def test_fstring_datatype() -> None: + u = A('John Doe', 14) + assert f'{u}' == 'John Doe is 14 years old.' + d = {'name': 'John Doe', 'age': 14} + assert f'{d}' == "{'name': 'John Doe', 'age': 14}" + +def test_fstring_escape() -> None: + assert f"{'inside'}" == 'inside' + assert f'{"inside"}' == 'inside' + assert f"""inside""" == 'inside' + assert f'''inside''' == 'inside' + assert f"\"{'inside'}\"" == '"inside"' + assert f'\'{"inside"}\'' == "'inside'" + + assert f'{{10}}' == '{10}' + assert f'{{10 + 10}}' == '{10 + 10}' + assert f'{{{10 + 10}}}' == '{20}' + assert f'{{{{10 + 10}}}}' == '{{10 + 10}}' + +def test_fstring_conversion() -> None: + assert f'Hello {var!r}' == "Hello 'mypyc'" + # repr() is equivalent to !r + assert f'Hello {repr(var)}' == "Hello 'mypyc'" + + assert f'Hello {var!a}' == "Hello 'mypyc'" + # ascii() is equivalent to !a + assert f'Hello {ascii(var)}' == "Hello 'mypyc'" + + tmp_str = """this + is a new line.""" + assert f'Test: {tmp_str!a}' == "Test: 'this\\n is a new line.'" + + s = 'test: āĀēĒčČ..šŠūŪžŽ' + assert f'{s}' == 'test: āĀēĒčČ..šŠūŪžŽ' + assert f'{s!a}' == "'test: \\u0101\\u0100\\u0113\\u0112\\u010d\\u010c..\\u0161\\u0160\\u016b\\u016a\\u017e\\u017d'" + + assert f'Hello {var!s}' == 'Hello mypyc' + assert f'Hello {num!s}' == 'Hello 20' + +def test_fstring_align() -> None: + assert f'Hello {var:>20}' == "Hello mypyc" + assert f'Hello {var!r:>20}' == "Hello 'mypyc'" + assert f'Hello {var:>{num}}' == "Hello mypyc" + assert f'Hello {var!r:>{num}}' == "Hello 'mypyc'" + +def test_fstring_multi() -> None: + assert f'Hello {var}, hello again {var}' == "Hello mypyc, hello again mypyc" + a = 'py' + s = f'my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}' + assert s == 'mypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypy' + +def test_fstring_python_doc() -> None: + name = 'Fred' + assert f"He said his name is {name!r}." == "He said his name is 'Fred'." + assert f"He said his name is {repr(name)}." == "He said his name is 'Fred'." + + width = 10 + precision = 4 + value = decimal.Decimal('12.34567') + assert f'result: {value:{width}.{precision}}' == 'result: 12.35' # nested field + + today = datetime(year=2017, month=1, day=27) + assert f'{today:%B %d, %Y}' == 'January 27, 2017' # using date format specifier + + number = 1024 + assert f'{number:#0x}' == '0x400' # using integer format specifier + +[case testStringFormatMethod] +from typing import Tuple + +def test_format_method_basics() -> None: + x = str() + assert 'x{}'.format(x) == 'x' + assert 'ā{}'.format(x) == 'ā' + assert '😀{}'.format(x) == '😀' + assert ''.format() == '' + assert 'abc'.format() == 'abc' + assert '{}{}'.format(1, 2) == '12' + + name = 'Eric' + age = 14 + assert "My name is {name}, I'm {age}.".format(name=name, age=age) == "My name is Eric, I'm 14." + assert "My name is {A}, I'm {B}.".format(A=name, B=age) == "My name is Eric, I'm 14." + assert "My name is {}, I'm {B}.".format(name, B=age) == "My name is Eric, I'm 14." + + bool_var1 = True + bool_var2 = False + assert 'bool: {}, {}'.format(bool_var1, bool_var2) == 'bool: True, False' + +def test_format_method_empty_braces() -> None: + name = 'Eric' + age = 14 + + assert 'Hello, {}!'.format(name) == 'Hello, Eric!' + assert '{}'.format(name) == 'Eric' + assert '{}! Hi!'.format(name) == 'Eric! Hi!' + assert '{}, Hi, {}'.format(name, name) == 'Eric, Hi, Eric' + assert 'Hi! {}'.format(name) == 'Hi! Eric' + assert "Hi, I'm {}. I'm {}.".format(name, age) == "Hi, I'm Eric. I'm 14." + + assert '{{}}'.format() == '{}' + assert '{{{{}}}}'.format() == '{{}}' + assert '{{}}{}'.format(name) == '{}Eric' + assert 'Hi! {{{}}}'.format(name) == 'Hi! {Eric}' + assert 'Hi! {{ {}'.format(name) == 'Hi! { Eric' + assert 'Hi! {{ {} }}}}'.format(name) == 'Hi! { Eric }}' + +def test_format_method_numbers() -> None: + s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-233) + assert s == 'int: -233; hex: -e9; oct: -351; bin: -11101001' + num = 2**65 + s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(num) + assert s == 'int: 36893488147419103232; hex: 20000000000000000; oct: 4000000000000000000000; bin: 100000000000000000000000000000000000000000000000000000000000000000' + s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-num) + assert s == 'int: -36893488147419103232; hex: -20000000000000000; oct: -4000000000000000000000; bin: -100000000000000000000000000000000000000000000000000000000000000000' + + large_num = 2**65 + assert 'number: {}'.format(large_num) == 'number: 36893488147419103232' + neg_num = -3 + assert 'negative integer: {}'.format(neg_num) == 'negative integer: -3' + assert 'negative integer: {}'.format(-large_num) == 'negative integer: -36893488147419103232' + + large_float = 1.23e30 + large_float2 = 1234123412341234123400000000000000000 + small_float = 1.23e-20 + assert '{}, {}, {}'.format(small_float, large_float, large_float2) == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' + nan_num = float('nan') + inf_num = float('inf') + assert '{}, {}'.format(nan_num, inf_num) == 'nan, inf' + +def format_args(*args: int) -> str: + return 'x{}y{}'.format(*args) +def format_kwargs(**kwargs: int) -> str: + return 'c{x}d{y}'.format(**kwargs) +def format_args_self(*args: int) -> str: + return '{}'.format(args) +def format_kwargs_self(**kwargs: int) -> str: + return '{}'.format(kwargs) + +def test_format_method_args() -> None: + assert format_args(10, 2) == 'x10y2' + assert format_args_self(10, 2) == '(10, 2)' + assert format_kwargs(x=10, y=2) == 'c10d2' + assert format_kwargs(x=10, y=2, z=1) == 'c10d2' + assert format_kwargs_self(x=10, y=2, z=1) == "{'x': 10, 'y': 2, 'z': 1}" + +def test_format_method_different_kind() -> None: + s1 = "Literal['😀']" + assert 'Revealed type is {}'.format(s1) == "Revealed type is Literal['😀']" + s2 = "Revealed type is" + assert "{} Literal['😀']".format(s2) == "Revealed type is Literal['😀']" + s3 = "测试:" + assert "{}{} {}".format(s3, s2, s1) == "测试:Revealed type is Literal['😀']" + assert "Test: {}{}".format(s3, s1) == "Test: 测试:Literal['😀']" + assert "Test: {}{}".format(s3, s2) == "Test: 测试:Revealed type is" + +def test_format_method_nested() -> None: + var = 'mypyc' + num = 10 + assert '{:{}}'.format(var, '') == 'mypyc' + assert '{:{}}'.format(var, '>10') == ' mypyc' + assert '{:{}}'.format(var, '>{}'.format(num)) == ' mypyc' + +class Point: + def __init__(self, x, y): + self.x, self.y = x, y + def __str__(self): + return 'Point({self.x}, {self.y})'.format(self=self) + +# Format examples from Python doc +# https://docs.python.org/3/library/string.html#formatexamples +def test_format_method_python_doc() -> None: + # Accessing arguments by position: + assert '{0}, {1}, {2}'.format('a', 'b', 'c') == 'a, b, c' + assert '{}, {}, {}'.format('a', 'b', 'c') == 'a, b, c' + assert '{2}, {1}, {0}'.format('a', 'b', 'c') == 'c, b, a' + assert '{2}, {1}, {0}'.format(*'abc') == 'c, b, a' # unpacking argument sequence + # assert '{0}{1}{0}'.format('abra', 'cad') = 'abracadabra' # arguments' indices can be repeated + + # Accessing arguments by name: + s = 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W') + assert s == 'Coordinates: 37.24N, -115.81W' + coord = {'latitude': '37.24N', 'longitude': '-115.81W'} + assert 'Coordinates: {latitude}, {longitude}'.format(**coord) == 'Coordinates: 37.24N, -115.81W' + + # Accessing arguments’ attributes: + assert str(Point(4, 2)) == 'Point(4, 2)' + + # Accessing arguments’ items: + coord2 = (3, 5) + assert 'X: {0[0]}; Y: {0[1]}'.format(coord2) == 'X: 3; Y: 5' + + # Replacing %s and %r: + s = "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2') + assert s == "repr() shows quotes: 'test1'; str() doesn't: test2" + + # Aligning the text and specifying a width: + assert '{:<30}'.format('left aligned') == 'left aligned ' + assert '{:>30}'.format('right aligned') == ' right aligned' + assert '{:^30}'.format('centered') == ' centered ' + assert '{:*^30}'.format('centered') == '***********centered***********' # use '*' as a fill char + + # Replacing %+f, %-f, and % f and specifying a sign: + assert '{:+f}; {:+f}'.format(3.14, -3.14) == '+3.140000; -3.140000' # show it always + assert '{: f}; {: f}'.format(3.14, -3.14) == ' 3.140000; -3.140000' # show a space for positive numbers + assert '{:-f}; {:-f}'.format(3.14, -3.14) == '3.140000; -3.140000' # show only the minus -- same as '{:f}; {:f}' + + # Replacing %x and %o and converting the value to different bases: + s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42) # format also supports binary numbers + assert s == 'int: 42; hex: 2a; oct: 52; bin: 101010' + s = 'int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42) # with 0x, 0o, or 0b as prefix: + assert s == 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010' + + # Using the comma as a thousands separator: + assert '{:,}'.format(1234567890) == '1,234,567,890' + + # Expressing a percentage: + points = 19.0 + total = 22.0 + assert 'Correct answers: {:.2%}'.format(points/total) == 'Correct answers: 86.36%' + + # Using type-specific formatting: + import datetime + d = datetime.datetime(2010, 7, 4, 12, 15, 58) + assert '{:%Y-%m-%d %H:%M:%S}'.format(d) == '2010-07-04 12:15:58' + + # Nesting arguments and more complex examples: + tmp_strs = [] + for align, text in zip('<^>', ['left', 'center', 'right']): + tmp_strs.append('{0:{fill}{align}16}'.format(text, fill=align, align=align)) + assert tmp_strs == ['left<<<<<<<<<<<<', '^^^^^center^^^^^', '>>>>>>>>>>>right'] + + octets = [192, 168, 0, 1] + assert '{:02X}{:02X}{:02X}{:02X}'.format(*octets) == 'C0A80001' + + width = 5 + tmp_strs = [] + for num in range(5,12): + tmp_str = '' + for base in 'dXob': + tmp_str += ('{0:{width}{base}}'.format(num, base=base, width=width)) + tmp_strs.append(tmp_str) + assert tmp_strs == [' 5 5 5 101',\ + ' 6 6 6 110',\ + ' 7 7 7 111',\ + ' 8 8 10 1000',\ + ' 9 9 11 1001',\ + ' 10 A 12 1010',\ + ' 11 B 13 1011'] + +[case testChr] +# Some test cases are from https://docs.python.org/3/howto/unicode.html + +def try_invalid(x: int) -> bool: + try: + chr(x + int()) + return False + except ValueError: + return True + +def test_chr() -> None: + assert chr(57344) == '\ue000' + assert chr(0) == '\x00' + assert chr(65) == 'A' + assert chr(150) == '\x96' + try: + chr(-1) + assert False + except ValueError: + pass + try: + chr(1114112) + assert False + except ValueError: + pass + assert chr(1114111) == '\U0010ffff' + x = 0 + assert chr(x + int()) == '\x00' + x = 100 + assert chr(x + int()) == 'd' + x = 150 + assert chr(x + int()) == '\x96' + x = 257 + assert chr(x + int()) == 'ā' + x = 65537 + assert chr(x + int()) == '𐀁' + assert try_invalid(-1) + assert try_invalid(1114112) + +[case testOrd] +def test_ord() -> None: + assert ord('\ue000') == 57344 + s = "a\xac\u1234\u20ac\U00008000" + # ^^^^ two-digit hex escape + # ^^^^^^ four-digit Unicode escape + # ^^^^^^^^^^ eight-digit Unicode escape + l1 = [ord(c) for c in s] + assert l1 == [97, 172, 4660, 8364, 32768] + u = 'abcdé' + assert ord(u[-1]) == 233 + assert ord(b'a') == 97 + assert ord(b'a' + bytes()) == 97 + u2 = '\U0010ffff' + assert ord(u2) == 1114111 + try: + ord('aa') + assert False + except TypeError: + pass + +[case testDecode] +def test_decode() -> None: + assert "\N{GREEK CAPITAL LETTER DELTA}" == '\u0394' + assert "\u0394" == "\u0394" + assert "\U00000394" == '\u0394' + assert b'\x80abc'.decode('utf-8', 'replace') == '\ufffdabc' + assert b'\x80abc'.decode('utf-8', 'backslashreplace') == '\\x80abc' + assert b'abc'.decode() == 'abc' + assert b'abc'.decode('utf-8') == 'abc' + assert b'\x80abc'.decode('utf-8', 'ignore') == 'abc' + assert b'\x80abc'.decode('UTF-8', 'ignore') == 'abc' + assert b'\x80abc'.decode('Utf-8', 'ignore') == 'abc' + assert b'\x80abc'.decode('utf_8', 'ignore') == 'abc' + assert b'\x80abc'.decode('latin1', 'ignore') == '\x80abc' + assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('gbk', 'ignore') == '一二三' + assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('latin1', 'ignore') == 'Ò»¶þÈý' + assert b'Z\xc3\xbcrich'.decode("utf-8") == 'Zürich' + try: + b'Z\xc3\xbcrich'.decode('ascii') + assert False + except UnicodeDecodeError: + pass + assert bytearray(range(5)).decode() == '\x00\x01\x02\x03\x04' + b = bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd') + assert b.decode() == '你好' + assert b.decode('gbk') == '浣犲ソ' + assert b.decode('latin1') == 'ä½\xa0好' + +[case testEncode] +from testutil import assertRaises + +def test_encode() -> None: + u = chr(40960) + 'abcd' + chr(1972) + assert u.encode() == b'\xea\x80\x80abcd\xde\xb4' + assert u.encode('utf-8') == b'\xea\x80\x80abcd\xde\xb4' + with assertRaises(UnicodeEncodeError): + u.encode('ascii') + with assertRaises(LookupError): + u.encode('aaa') + assert u.encode('utf-8', 'aaaaaa') == b'\xea\x80\x80abcd\xde\xb4' + assert u.encode('ascii', 'ignore') == b'abcd' + assert u.encode('ASCII', 'ignore') == b'abcd' + assert u.encode('ascii', 'replace') == b'?abcd?' + assert u.encode('ascii', 'xmlcharrefreplace') == b'ꀀabcd޴' + assert u.encode('ascii', 'backslashreplace') == b'\\ua000abcd\\u07b4' + assert u.encode('ascii', 'namereplace') == b'\\N{YI SYLLABLE IT}abcd\\u07b4' + assert 'pythön!'.encode() == b'pyth\xc3\xb6n!' + assert '一二三'.encode('gbk') == b'\xd2\xbb\xb6\xfe\xc8\xfd' + assert u.encode('UTF-8', 'ignore') == b'\xea\x80\x80abcd\xde\xb4' + assert u.encode('Utf_8') == b'\xea\x80\x80abcd\xde\xb4' + assert u.encode('UTF_8') == b'\xea\x80\x80abcd\xde\xb4' + assert u'\u00E1'.encode('latin1') == b'\xe1' + with assertRaises(UnicodeEncodeError): + u.encode('latin1') diff --git a/mypyc/test-data/run-tuples.test b/mypyc/test-data/run-tuples.test index c4abfb1d3a36..759177342fa9 100644 --- a/mypyc/test-data/run-tuples.test +++ b/mypyc/test-data/run-tuples.test @@ -196,6 +196,10 @@ def test_sequence_generator() -> None: a = tuple(f8(x) for x in source_fixed_length_tuple) assert a == (False, True, False, True) + source_str = 'abbc' + b = tuple('s:' + x for x in source_str) + assert b == ('s:a', 's:b', 's:b', 's:c') + TUPLE: Final[Tuple[str, ...]] = ('x', 'y') def test_final_boxed_tuple() -> None: diff --git a/mypyc/test/test_analysis.py b/mypyc/test/test_analysis.py index 82317ef34765..b71983705b65 100644 --- a/mypyc/test/test_analysis.py +++ b/mypyc/test/test_analysis.py @@ -45,7 +45,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: exceptions.insert_exception_handling(fn) actual.extend(format_func(fn)) cfg = dataflow.get_cfg(fn.blocks) - args = set(fn.arg_regs) # type: Set[Value] + args: Set[Value] = set(fn.arg_regs) name = testcase.name if name.endswith('_MaybeDefined'): # Forward, maybe diff --git a/mypyc/test/test_commandline.py b/mypyc/test/test_commandline.py index 5dae26d294ab..5c80d0fddb1d 100644 --- a/mypyc/test/test_commandline.py +++ b/mypyc/test/test_commandline.py @@ -47,8 +47,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: out = b'' try: # Compile program - cmd = subprocess.run([sys.executable, - os.path.join(base_path, 'scripts', 'mypyc')] + args, + cmd = subprocess.run([sys.executable, '-m', 'mypyc', *args], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd='tmp') if 'ErrorOutput' in testcase.name or cmd.returncode != 0: out += cmd.stdout diff --git a/mypyc/test/test_emit.py b/mypyc/test/test_emit.py index 45227fd0524e..1721a6876984 100644 --- a/mypyc/test/test_emit.py +++ b/mypyc/test/test_emit.py @@ -17,7 +17,7 @@ def test_label(self) -> None: assert emitter.label(BasicBlock(4)) == 'CPyL4' def test_reg(self) -> None: - names = {self.n: 'n'} # type: Dict[Value, str] + names: Dict[Value, str] = {self.n: "n"} emitter = Emitter(self.context, names) assert emitter.reg(self.n) == 'cpy_r_n' diff --git a/mypyc/test/test_emitclass.py b/mypyc/test/test_emitclass.py new file mode 100644 index 000000000000..195cccbd0312 --- /dev/null +++ b/mypyc/test/test_emitclass.py @@ -0,0 +1,12 @@ +import unittest + +from mypyc.codegen.emitclass import slot_key + + +class TestEmitClass(unittest.TestCase): + def test_slot_key(self) -> None: + attrs = ['__add__', '__radd__', '__rshift__', '__rrshift__', '__setitem__', '__delitem__'] + s = sorted(attrs, key=lambda x: slot_key(x)) + # __delitem__ and reverse methods should come last. + assert s == [ + '__add__', '__rshift__', '__setitem__', '__delitem__', '__radd__', '__rrshift__'] diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 11f46fc46919..a3f55a7facf2 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -2,14 +2,14 @@ from typing import List, Optional -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from mypy.test.helpers import assert_string_arrays_equal from mypyc.ir.ops import ( BasicBlock, Goto, Return, Integer, Assign, AssignMulti, IncRef, DecRef, Branch, Call, Unbox, Box, TupleGet, GetAttr, SetAttr, Op, Value, CallC, IntOp, LoadMem, - GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register + GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register, Unreachable ) from mypyc.ir.rtypes import ( RTuple, RInstance, RType, RArray, int_rprimitive, bool_rprimitive, list_rprimitive, @@ -37,7 +37,7 @@ class TestFunctionEmitterVisitor(unittest.TestCase): """Test generation of fragments of C from individual IR ops.""" def setUp(self) -> None: - self.registers = [] # type: List[Register] + self.registers: List[Register] = [] def add_local(name: str, rtype: RType) -> Register: reg = Register(rtype, name) @@ -202,18 +202,26 @@ def test_call_two_args(self) -> None: "cpy_r_r0 = CPyDef_myfn(cpy_r_m, cpy_r_k);") def test_inc_ref(self) -> None: - self.assert_emit(IncRef(self.m), - "CPyTagged_IncRef(cpy_r_m);") + self.assert_emit(IncRef(self.o), "CPy_INCREF(cpy_r_o);") + self.assert_emit(IncRef(self.o), "CPy_INCREF(cpy_r_o);", rare=True) def test_dec_ref(self) -> None: - self.assert_emit(DecRef(self.m), - "CPyTagged_DecRef(cpy_r_m);") + self.assert_emit(DecRef(self.o), "CPy_DECREF(cpy_r_o);") + self.assert_emit(DecRef(self.o), "CPy_DecRef(cpy_r_o);", rare=True) + + def test_inc_ref_int(self) -> None: + self.assert_emit(IncRef(self.m), "CPyTagged_INCREF(cpy_r_m);") + self.assert_emit(IncRef(self.m), "CPyTagged_IncRef(cpy_r_m);", rare=True) + + def test_dec_ref_int(self) -> None: + self.assert_emit(DecRef(self.m), "CPyTagged_DECREF(cpy_r_m);") + self.assert_emit(DecRef(self.m), "CPyTagged_DecRef(cpy_r_m);", rare=True) def test_dec_ref_tuple(self) -> None: - self.assert_emit(DecRef(self.t), 'CPyTagged_DecRef(cpy_r_t.f0);') + self.assert_emit(DecRef(self.t), 'CPyTagged_DECREF(cpy_r_t.f0);') def test_dec_ref_tuple_nested(self) -> None: - self.assert_emit(DecRef(self.tt), 'CPyTagged_DecRef(cpy_r_tt.f0.f0);') + self.assert_emit(DecRef(self.tt), 'CPyTagged_DECREF(cpy_r_tt.f0.f0);') def test_list_get_item(self) -> None: self.assert_emit(CallC(list_get_item_op.c_function_name, [self.m, self.k], @@ -236,8 +244,7 @@ def test_unbox(self) -> None: """if (likely(PyLong_Check(cpy_r_m))) cpy_r_r0 = CPyTagged_FromObject(cpy_r_m); else { - CPy_TypeError("int", cpy_r_m); - cpy_r_r0 = CPY_INT_TAG; + CPy_TypeError("int", cpy_r_m); cpy_r_r0 = CPY_INT_TAG; } """) @@ -254,7 +261,7 @@ def test_get_attr(self) -> None: if (unlikely(((mod___AObject *)cpy_r_r)->_y == CPY_INT_TAG)) { PyErr_SetString(PyExc_AttributeError, "attribute 'y' of 'A' undefined"); } else { - CPyTagged_IncRef(((mod___AObject *)cpy_r_r)->_y); + CPyTagged_INCREF(((mod___AObject *)cpy_r_r)->_y); } """) @@ -262,7 +269,7 @@ def test_set_attr(self) -> None: self.assert_emit( SetAttr(self.r, 'y', self.m, 1), """if (((mod___AObject *)cpy_r_r)->_y != CPY_INT_TAG) { - CPyTagged_DecRef(((mod___AObject *)cpy_r_r)->_y); + CPyTagged_DECREF(((mod___AObject *)cpy_r_r)->_y); } ((mod___AObject *)cpy_r_r)->_y = cpy_r_m; cpy_r_r0 = 1; @@ -373,11 +380,23 @@ def test_assign_multi(self) -> None: def test_long_unsigned(self) -> None: a = Register(int64_rprimitive, 'a') self.assert_emit(Assign(a, Integer(1 << 31, int64_rprimitive)), - """cpy_r_a = 2147483648U;""") + """cpy_r_a = 2147483648ULL;""") self.assert_emit(Assign(a, Integer((1 << 31) - 1, int64_rprimitive)), """cpy_r_a = 2147483647;""") - def assert_emit(self, op: Op, expected: str, next_block: Optional[BasicBlock] = None) -> None: + def test_long_signed(self) -> None: + a = Register(int64_rprimitive, 'a') + self.assert_emit(Assign(a, Integer(-(1 << 31) + 1, int64_rprimitive)), + """cpy_r_a = -2147483647;""") + self.assert_emit(Assign(a, Integer(-(1 << 31), int64_rprimitive)), + """cpy_r_a = -2147483648LL;""") + + def assert_emit(self, + op: Op, + expected: str, + next_block: Optional[BasicBlock] = None, + *, + rare: bool = False) -> None: block = BasicBlock(0) block.ops.append(op) value_names = generate_names_for_ir(self.registers, [block]) @@ -388,6 +407,7 @@ def assert_emit(self, op: Op, expected: str, next_block: Optional[BasicBlock] = visitor = FunctionEmitterVisitor(emitter, declarations, 'prog.py', 'prog') visitor.next_block = next_block + visitor.rare = rare op.accept(visitor) frags = declarations.fragments + emitter.fragments @@ -452,6 +472,7 @@ def test_register(self) -> None: reg = Register(int_rprimitive) op = Assign(reg, Integer(5)) self.block.ops.append(op) + self.block.ops.append(Unreachable()) fn = FuncIR(FuncDecl('myfunc', None, 'mod', FuncSignature([self.arg], list_rprimitive)), [self.reg], [self.block]) @@ -465,6 +486,7 @@ def test_register(self) -> None: ' CPyTagged cpy_r_r0;\n', 'CPyL0: ;\n', ' cpy_r_r0 = 10;\n', + ' CPy_Unreachable();\n', '}\n', ], result, msg='Generated code invalid') diff --git a/mypyc/test/test_emitwrapper.py b/mypyc/test/test_emitwrapper.py index ab16056aac47..de04123b7e55 100644 --- a/mypyc/test/test_emitwrapper.py +++ b/mypyc/test/test_emitwrapper.py @@ -3,7 +3,7 @@ from mypy.test.helpers import assert_string_arrays_equal -from mypyc.codegen.emit import Emitter, EmitterContext +from mypyc.codegen.emit import Emitter, EmitterContext, ReturnHandler from mypyc.codegen.emitwrapper import generate_arg_check from mypyc.ir.rtypes import list_rprimitive, int_rprimitive from mypyc.namegen import NameGenerator @@ -15,31 +15,28 @@ def setUp(self) -> None: def test_check_list(self) -> None: emitter = Emitter(self.context) - generate_arg_check('x', list_rprimitive, emitter, 'return NULL;') + generate_arg_check('x', list_rprimitive, emitter, ReturnHandler('NULL')) lines = emitter.fragments self.assert_lines([ 'PyObject *arg_x;', 'if (likely(PyList_Check(obj_x)))', ' arg_x = obj_x;', 'else {', - ' CPy_TypeError("list", obj_x);', - ' arg_x = NULL;', + ' CPy_TypeError("list", obj_x); return NULL;', '}', - 'if (arg_x == NULL) return NULL;', ], lines) def test_check_int(self) -> None: emitter = Emitter(self.context) - generate_arg_check('x', int_rprimitive, emitter, 'return NULL;') - generate_arg_check('y', int_rprimitive, emitter, 'return NULL;', True) + generate_arg_check('x', int_rprimitive, emitter, ReturnHandler('NULL')) + generate_arg_check('y', int_rprimitive, emitter, ReturnHandler('NULL'), optional=True) lines = emitter.fragments self.assert_lines([ 'CPyTagged arg_x;', 'if (likely(PyLong_Check(obj_x)))', ' arg_x = CPyTagged_BorrowFromObject(obj_x);', 'else {', - ' CPy_TypeError("int", obj_x);', - ' return NULL;', + ' CPy_TypeError("int", obj_x); return NULL;', '}', 'CPyTagged arg_y;', 'if (obj_y == NULL) {', @@ -47,8 +44,7 @@ def test_check_int(self) -> None: '} else if (likely(PyLong_Check(obj_y)))', ' arg_y = CPyTagged_BorrowFromObject(obj_y);', 'else {', - ' CPy_TypeError("int", obj_y);', - ' return NULL;', + ' CPy_TypeError("int", obj_y); return NULL;', '}', ], lines) diff --git a/mypyc/test/test_exceptions.py b/mypyc/test/test_exceptions.py index 67df5ce5c38a..802024f2c86b 100644 --- a/mypyc/test/test_exceptions.py +++ b/mypyc/test/test_exceptions.py @@ -18,9 +18,11 @@ ICODE_GEN_BUILTINS, use_custom_builtins, MypycDataSuite, build_ir_for_single_file, assert_test_output, remove_comment_lines ) +from mypyc.analysis.blockfreq import frequently_executed_blocks files = [ - 'exceptions.test' + 'exceptions.test', + 'exceptions-freq.test', ] @@ -46,6 +48,9 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: insert_exception_handling(fn) insert_ref_count_opcodes(fn) actual.extend(format_func(fn)) + if testcase.name.endswith('_freq'): + common = frequently_executed_blocks(fn.blocks[0]) + actual.append('hot blocks: %s' % sorted(b.label for b in common)) assert_test_output(testcase, actual, 'Invalid source code output', expected_output) diff --git a/mypyc/test/test_external.py b/mypyc/test/test_external.py index f7f5463b9e91..5e8e5b54dd8a 100644 --- a/mypyc/test/test_external.py +++ b/mypyc/test/test_external.py @@ -19,7 +19,7 @@ def test_c_unit_test(self) -> None: """Run C unit tests in a subprocess.""" # Build Google Test, the C++ framework we use for testing C code. # The source code for Google Test is copied to this repository. - cppflags = [] # type: List[str] + cppflags: List[str] = [] env = os.environ.copy() if sys.platform == 'darwin': cppflags += ['-mmacosx-version-min=10.10', '-stdlib=libc++'] diff --git a/mypyc/test/test_irbuild.py b/mypyc/test/test_irbuild.py index 8c7b03f8bc39..12da67b8dc1a 100644 --- a/mypyc/test/test_irbuild.py +++ b/mypyc/test/test_irbuild.py @@ -16,24 +16,27 @@ files = [ 'irbuild-basic.test', + 'irbuild-int.test', 'irbuild-lists.test', + 'irbuild-tuple.test', 'irbuild-dict.test', + 'irbuild-set.test', + 'irbuild-str.test', + 'irbuild-bytes.test', 'irbuild-statements.test', 'irbuild-nested.test', 'irbuild-classes.test', 'irbuild-optional.test', - 'irbuild-tuple.test', 'irbuild-any.test', 'irbuild-generics.test', 'irbuild-try.test', - 'irbuild-set.test', - 'irbuild-str.test', 'irbuild-strip-asserts.test', - 'irbuild-int.test', 'irbuild-vectorcall.test', 'irbuild-unreachable.test', 'irbuild-isinstance.test', 'irbuild-dunders.test', + 'irbuild-singledispatch.test', + 'irbuild-constant-fold.test', ] diff --git a/mypyc/test/test_ircheck.py b/mypyc/test/test_ircheck.py new file mode 100644 index 000000000000..28d3c8e8c25d --- /dev/null +++ b/mypyc/test/test_ircheck.py @@ -0,0 +1,95 @@ +import unittest +from typing import List + +from mypyc.analysis.ircheck import check_func_ir, FnError +from mypyc.ir.rtypes import none_rprimitive +from mypyc.ir.ops import BasicBlock, Op, Return, Integer, Goto +from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature +from mypyc.ir.pprint import format_func + + +def assert_has_error(fn: FuncIR, error: FnError) -> None: + errors = check_func_ir(fn) + assert errors == [error] + + +def assert_no_errors(fn: FuncIR) -> None: + assert not check_func_ir(fn) + + +NONE_VALUE = Integer(0, rtype=none_rprimitive) + + +class TestIrcheck(unittest.TestCase): + def setUp(self) -> None: + self.label = 0 + + def basic_block(self, ops: List[Op]) -> BasicBlock: + self.label += 1 + block = BasicBlock(self.label) + block.ops = ops + return block + + def func_decl(self, name: str) -> FuncDecl: + return FuncDecl(name=name, class_name=None, module_name="module", sig=FuncSignature( + args=[], ret_type=none_rprimitive, + )) + + def test_valid_fn(self) -> None: + assert_no_errors(FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[self.basic_block(ops=[ + Return(value=NONE_VALUE), + ])], + )) + + def test_block_not_terminated_empty_block(self) -> None: + block = self.basic_block([]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[block], + ) + assert_has_error(fn, FnError(source=block, desc="Block not terminated")) + + def test_valid_goto(self) -> None: + block_1 = self.basic_block([Return(value=NONE_VALUE)]) + block_2 = self.basic_block([Goto(label=block_1)]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[block_1, block_2], + ) + assert_no_errors(fn) + + def test_invalid_goto(self) -> None: + block_1 = self.basic_block([Return(value=NONE_VALUE)]) + goto = Goto(label=block_1) + block_2 = self.basic_block([goto]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + # block_1 omitted + blocks=[block_2], + ) + assert_has_error(fn, FnError(source=goto, desc="Invalid control operation target: 1")) + + def test_pprint(self) -> None: + block_1 = self.basic_block([Return(value=NONE_VALUE)]) + goto = Goto(label=block_1) + block_2 = self.basic_block([goto]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + # block_1 omitted + blocks=[block_2], + ) + errors = [(goto, "Invalid control operation target: 1")] + formatted = format_func(fn, errors) + assert formatted == [ + "def func_1():", + "L0:", + " goto L1", + " ERR: Invalid control operation target: 1", + ] diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 31cd7468494a..306c151ef319 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -12,11 +12,11 @@ from typing import Any, Iterator, List, cast from mypy import build -from mypy.test.data import DataDrivenTestCase, UpdateFile +from mypy.test.data import DataDrivenTestCase from mypy.test.config import test_temp_dir from mypy.errors import CompileError from mypy.options import Options -from mypy.test.helpers import copy_and_fudge_mtime, assert_module_equivalence +from mypy.test.helpers import assert_module_equivalence, perform_file_operations from mypyc.codegen import emitmodule from mypyc.options import CompilerOptions @@ -36,6 +36,7 @@ 'run-floats.test', 'run-bools.test', 'run-strings.test', + 'run-bytes.test', 'run-tuples.test', 'run-lists.test', 'run-dicts.test', @@ -51,7 +52,10 @@ 'run-bench.test', 'run-mypy-sim.test', 'run-dunders.test', + 'run-singledispatch.test', + 'run-attrs.test', ] + if sys.version_info >= (3, 7): files.append('run-python37.test') if sys.version_info >= (3, 8): @@ -133,7 +137,8 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: self.run_case_inner(testcase) def run_case_inner(self, testcase: DataDrivenTestCase) -> None: - os.mkdir(WORKDIR) + if not os.path.isdir(WORKDIR): # (one test puts something in build...) + os.mkdir(WORKDIR) text = '\n'.join(testcase.input) @@ -159,16 +164,7 @@ def run_case_inner(self, testcase: DataDrivenTestCase) -> None: step += 1 with chdir_manager('..'): - for op in operations: - if isinstance(op, UpdateFile): - # Modify/create file - copy_and_fudge_mtime(op.source_path, op.target_path) - else: - # Delete file - try: - os.remove(op.path) - except FileNotFoundError: - pass + perform_file_operations(operations) self.run_case_step(testcase, step) def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> None: @@ -248,6 +244,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> check_serialization_roundtrip(ir) opt_level = int(os.environ.get('MYPYC_OPT_LEVEL', 0)) + debug_level = int(os.environ.get('MYPYC_DEBUG_LEVEL', 0)) setup_file = os.path.abspath(os.path.join(WORKDIR, 'setup.py')) # We pass the C file information to the build script via setup.py unfortunately @@ -256,7 +253,8 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> separate, cfiles, self.multi_file, - opt_level)) + opt_level, + debug_level)) if not run_setup(setup_file, ['build_ext', '--inplace']): if testcase.config.getoption('--mypyc-showc'): diff --git a/mypyc/test/test_serialization.py b/mypyc/test/test_serialization.py index 338be1aedb85..5737ccc7b623 100644 --- a/mypyc/test/test_serialization.py +++ b/mypyc/test/test_serialization.py @@ -4,7 +4,7 @@ # contain its own tests so that pytest will rewrite the asserts... from typing import Any, Dict, Tuple -from mypy.ordered_dict import OrderedDict +from mypy.backports import OrderedDict from collections.abc import Iterable from mypyc.ir.ops import DeserMaps diff --git a/mypyc/test/testutil.py b/mypyc/test/testutil.py index 7ef1f941aa41..985356bc469b 100644 --- a/mypyc/test/testutil.py +++ b/mypyc/test/testutil.py @@ -7,8 +7,6 @@ import shutil from typing import List, Callable, Iterator, Optional, Tuple -import pytest - from mypy import build from mypy.errors import CompileError from mypy.options import Options @@ -17,6 +15,7 @@ from mypy.test.helpers import assert_string_arrays_equal from mypyc.options import CompilerOptions +from mypyc.analysis.ircheck import assert_func_ir_valid from mypyc.ir.func_ir import FuncIR from mypyc.errors import Errors from mypyc.irbuild.main import build_ir @@ -32,7 +31,7 @@ class MypycDataSuite(DataSuite): # Need to list no files, since this will be picked up as a suite of tests - files = [] # type: List[str] + files: List[str] = [] data_prefix = test_data_prefix @@ -57,12 +56,13 @@ def use_custom_builtins(builtins_path: str, testcase: DataDrivenTestCase) -> Ite shutil.copyfile(builtins_path, builtins) default_builtins = True - # Actually peform the test case. - yield None - - if default_builtins: - # Clean up. - os.remove(builtins) + # Actually perform the test case. + try: + yield None + finally: + if default_builtins: + # Clean up. + os.remove(builtins) def perform_test(func: Callable[[DataDrivenTestCase], None], @@ -77,7 +77,7 @@ def perform_test(func: Callable[[DataDrivenTestCase], None], shutil.copyfile(builtins_path, builtins) default_builtins = True - # Actually peform the test case. + # Actually perform the test case. func(testcase) if default_builtins: @@ -116,10 +116,11 @@ def build_ir_for_single_file(input_lines: List[str], Mapper({'__main__': None}), compiler_options, errors) if errors.num_errors: - errors.flush_errors() - pytest.fail('Errors while building IR') + raise CompileError(errors.new_messages()) module = list(modules.values())[0] + for fn in module.functions: + assert_func_ir_valid(fn) return module.functions @@ -156,6 +157,8 @@ def assert_test_output(testcase: DataDrivenTestCase, message: str, expected: Optional[List[str]] = None, formatted: Optional[List[str]] = None) -> None: + __tracebackhide__ = True + expected_output = expected if expected is not None else testcase.output if expected_output != actual and testcase.config.getoption('--update-data', False): update_testcase_output(testcase, actual) diff --git a/mypyc/transform/exceptions.py b/mypyc/transform/exceptions.py index 6501286a55ae..52b25aceffe3 100644 --- a/mypyc/transform/exceptions.py +++ b/mypyc/transform/exceptions.py @@ -45,7 +45,7 @@ def add_handler_block(ir: FuncIR) -> BasicBlock: def split_blocks_at_errors(blocks: List[BasicBlock], default_error_handler: BasicBlock, func_name: Optional[str]) -> List[BasicBlock]: - new_blocks = [] # type: List[BasicBlock] + new_blocks: List[BasicBlock] = [] # First split blocks on ops that may raise. for block in blocks: @@ -60,7 +60,7 @@ def split_blocks_at_errors(blocks: List[BasicBlock], block.error_handler = None for op in ops: - target = op # type: Value + target: Value = op cur_block.ops.append(op) if isinstance(op, RegisterOp) and op.error_kind != ERR_NEVER: # Split diff --git a/mypyc/transform/refcount.py b/mypyc/transform/refcount.py index 3927c969260b..60163e385c2d 100644 --- a/mypyc/transform/refcount.py +++ b/mypyc/transform/refcount.py @@ -33,12 +33,13 @@ from mypyc.ir.func_ir import FuncIR, all_values -DecIncs = Tuple[Tuple[Tuple[Value, bool], ...], Tuple[Value, ...]] +Decs = Tuple[Tuple[Value, bool], ...] +Incs = Tuple[Value, ...] -# A of basic blocks that decrement and increment specific values and -# then jump to some target block. This lets us cut down on how much -# code we generate in some circumstances. -BlockCache = Dict[Tuple[BasicBlock, DecIncs], BasicBlock] +# A cache of basic blocks that decrement and increment specific values +# and then jump to some target block. This lets us cut down on how +# much code we generate in some circumstances. +BlockCache = Dict[Tuple[BasicBlock, Decs, Incs], BasicBlock] def insert_ref_count_opcodes(ir: FuncIR) -> None: @@ -50,12 +51,12 @@ def insert_ref_count_opcodes(ir: FuncIR) -> None: values = all_values(ir.arg_regs, ir.blocks) borrowed = {value for value in values if value.is_borrowed} - args = set(ir.arg_regs) # type: Set[Value] + args: Set[Value] = set(ir.arg_regs) live = analyze_live_regs(ir.blocks, cfg) borrow = analyze_borrowed_arguments(ir.blocks, cfg, borrowed) - defined = analyze_must_defined_regs(ir.blocks, cfg, args, values) + defined = analyze_must_defined_regs(ir.blocks, cfg, args, values, strict_errors=True) ordering = make_value_ordering(ir) - cache = {} # type: BlockCache + cache: BlockCache = {} for block in ir.blocks[:]: if isinstance(block.ops[-1], (Branch, Goto)): insert_branch_inc_and_decrefs(block, @@ -92,7 +93,7 @@ def transform_block(block: BasicBlock, pre_borrow: 'AnalysisDict[Value]', post_must_defined: 'AnalysisDict[Value]') -> None: old_ops = block.ops - ops = [] # type: List[Op] + ops: List[Op] = [] for i, op in enumerate(old_ops): key = (block, i) @@ -161,36 +162,25 @@ def f(a: int) -> None source_live_regs = pre_live[prev_key] source_borrowed = post_borrow[prev_key] source_defined = post_must_defined[prev_key] - if isinstance(block.ops[-1], Branch): - branch = block.ops[-1] + + term = block.terminator + for i, target in enumerate(term.targets()): # HAX: After we've checked against an error value the value we must not touch the # refcount since it will be a null pointer. The correct way to do this would be # to perform data flow analysis on whether a value can be null (or is always # null). - if branch.op == Branch.IS_ERROR: - omitted = {branch.value} + omitted: Iterable[Value] + if isinstance(term, Branch) and term.op == Branch.IS_ERROR and i == 0: + omitted = (term.value,) else: - omitted = set() - true_decincs = ( - after_branch_decrefs( - branch.true, pre_live, source_defined, - source_borrowed, source_live_regs, ordering, omitted), - after_branch_increfs( - branch.true, pre_live, pre_borrow, source_borrowed, ordering)) - branch.true = add_block(true_decincs, cache, blocks, branch.true) - - false_decincs = ( - after_branch_decrefs( - branch.false, pre_live, source_defined, source_borrowed, source_live_regs, - ordering), - after_branch_increfs( - branch.false, pre_live, pre_borrow, source_borrowed, ordering)) - branch.false = add_block(false_decincs, cache, blocks, branch.false) - elif isinstance(block.ops[-1], Goto): - goto = block.ops[-1] - new_decincs = ((), after_branch_increfs( - goto.label, pre_live, pre_borrow, source_borrowed, ordering)) - goto.label = add_block(new_decincs, cache, blocks, goto.label) + omitted = () + + decs = after_branch_decrefs( + target, pre_live, source_defined, + source_borrowed, source_live_regs, ordering, omitted) + incs = after_branch_increfs( + target, pre_live, pre_borrow, source_borrowed, ordering) + term.set_target(i, add_block(decs, incs, cache, blocks, target)) def after_branch_decrefs(label: BasicBlock, @@ -199,7 +189,7 @@ def after_branch_decrefs(label: BasicBlock, source_borrowed: Set[Value], source_live_regs: Set[Value], ordering: Dict[Value, int], - omitted: Iterable[Value] = ()) -> Tuple[Tuple[Value, bool], ...]: + omitted: Iterable[Value]) -> Tuple[Tuple[Value, bool], ...]: target_pre_live = pre_live[label, 0] decref = source_live_regs - target_pre_live - source_borrowed if decref: @@ -224,22 +214,21 @@ def after_branch_increfs(label: BasicBlock, return () -def add_block(decincs: DecIncs, cache: BlockCache, +def add_block(decs: Decs, incs: Incs, cache: BlockCache, blocks: List[BasicBlock], label: BasicBlock) -> BasicBlock: - decs, incs = decincs if not decs and not incs: return label # TODO: be able to share *partial* results - if (label, decincs) in cache: - return cache[label, decincs] + if (label, decs, incs) in cache: + return cache[label, decs, incs] block = BasicBlock() blocks.append(block) block.ops.extend(DecRef(reg, is_xdec=xdec) for reg, xdec in decs) block.ops.extend(IncRef(reg) for reg in incs) block.ops.append(Goto(label)) - cache[label, decincs] = block + cache[label, decs, incs] = block return block @@ -249,7 +238,7 @@ def make_value_ordering(ir: FuncIR) -> Dict[Value, int]: This omits registers that are only ever read. """ # TODO: Never initialized values?? - result = {} # type: Dict[Value, int] + result: Dict[Value, int] = {} n = 0 for arg in ir.arg_regs: diff --git a/mypyc/transform/uninit.py b/mypyc/transform/uninit.py index 8df92c36a7de..47544e511734 100644 --- a/mypyc/transform/uninit.py +++ b/mypyc/transform/uninit.py @@ -32,7 +32,7 @@ def insert_uninit_checks(ir: FuncIR) -> None: def split_blocks_at_uninits(blocks: List[BasicBlock], pre_must_defined: 'AnalysisDict[Value]') -> List[BasicBlock]: - new_blocks = [] # type: List[BasicBlock] + new_blocks: List[BasicBlock] = [] init_registers = [] init_registers_set = set() @@ -80,7 +80,7 @@ def split_blocks_at_uninits(blocks: List[BasicBlock], cur_block.ops.append(op) if init_registers: - new_ops = [] # type: List[Op] + new_ops: List[Op] = [] for reg in init_registers: err = LoadErrorValue(reg.type, undefines=True) new_ops.append(err) diff --git a/pytest.ini b/pytest.ini index ed76809091a1..b164c14b6414 100644 --- a/pytest.ini +++ b/pytest.ini @@ -19,4 +19,9 @@ python_classes = python_functions = # always run in parallel (requires pytest-xdist, see test-requirements.txt) -addopts = -nauto +# and enable strict mode: require all markers +# to be defined and raise on invalid config values +addopts = -nauto --strict-markers --strict-config + +# treat xpasses as test failures so they get converted to regular tests as soon as possible +xfail_strict = true diff --git a/setup.cfg b/setup.cfg index 8dd54a52825d..c7adc285db7b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,9 +43,8 @@ exclude = # B007: Loop control variable not used within the loop body. # B011: Don't use assert False # F821: Name not defined (generates false positives with error codes) -# F811: Redefinition of unused function (causes annoying errors with overloads) # E741: Ambiguous variable name -extend-ignore = E128,W601,E701,E704,E402,B3,B006,B007,B011,F821,F811,E741 +extend-ignore = E128,W601,E701,E704,E402,B3,B006,B007,B011,F821,E741 [coverage:run] branch = true diff --git a/setup.py b/setup.py index 87e5b8432d34..10042279a446 100644 --- a/setup.py +++ b/setup.py @@ -5,8 +5,8 @@ import os.path import sys -if sys.version_info < (3, 5, 0): - sys.stderr.write("ERROR: You need Python 3.5 or later to use mypy.\n") +if sys.version_info < (3, 6, 0): + sys.stderr.write("ERROR: You need Python 3.6 or later to use mypy.\n") exit(1) # we'll import stuff from the source tree, let's ensure is on the sys path @@ -86,7 +86,7 @@ def run(self): MYPYC_BLACKLIST = tuple(os.path.join('mypy', x) for x in ( # Need to be runnable as scripts '__main__.py', - 'sitepkgs.py', + 'pyinfo.py', os.path.join('dmypy', '__main__.py'), # Uses __getattr__/__setattr__ @@ -144,10 +144,12 @@ def run(self): from mypyc.build import mypycify opt_level = os.getenv('MYPYC_OPT_LEVEL', '3') + debug_level = os.getenv('MYPYC_DEBUG_LEVEL', '1') force_multifile = os.getenv('MYPYC_MULTI_FILE', '') == '1' ext_modules = mypycify( mypyc_targets + ['--config-file=mypy_bootstrap.ini'], opt_level=opt_level, + debug_level=debug_level, # Use multi-file compilation mode on windows because without it # our Appveyor builds run out of memory sometimes. multi_file=sys.platform == 'win32' or force_multifile, @@ -162,11 +164,11 @@ def run(self): 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Topic :: Software Development', ] @@ -182,25 +184,27 @@ def run(self): ext_modules=ext_modules, packages=find_packages(), package_data={'mypy': package_data}, - scripts=['scripts/mypyc'], entry_points={'console_scripts': ['mypy=mypy.__main__:console_entry', 'stubgen=mypy.stubgen:main', 'stubtest=mypy.stubtest:main', 'dmypy=mypy.dmypy.client:console_entry', + 'mypyc=mypyc.__main__:main', ]}, classifiers=classifiers, cmdclass=cmdclass, # When changing this, also update mypy-requirements.txt. - install_requires=["typed_ast >= 1.4.0, < 1.5.0; python_version<'3.8'", - 'typing_extensions>=3.7.4', - 'mypy_extensions >= 0.4.3, < 0.5.0', - 'toml', + install_requires=["typed_ast >= 1.4.0, < 2; python_version<'3.8'", + 'typing_extensions>=3.10', + 'mypy_extensions >= 0.4.3', + 'tomli>=1.1.0', ], # Same here. - extras_require={'dmypy': 'psutil >= 4.0', 'python2': 'typed_ast >= 1.4.0, < 1.5.0'}, - python_requires=">=3.5", + extras_require={'dmypy': 'psutil >= 4.0', 'python2': 'typed_ast >= 1.4.0, < 2'}, + python_requires=">=3.6", include_package_data=True, project_urls={ 'News': 'http://mypy-lang.org/news.html', + 'Documentation': 'https://mypy.readthedocs.io/en/stable/introduction.html', + 'Repository': 'https://github.com/python/mypy', }, ) diff --git a/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs-stubs/typed/__init__.pyi b/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs-stubs/typed/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed/__init__.py b/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed_inline/__init__.py b/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed_inline/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed_inline/py.typed b/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/typed_inline/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/untyped/__init__.py b/test-data/packages/modulefinder-site-packages/ns_pkg_w_stubs/untyped/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/typedpkg-stubs/setup.py b/test-data/packages/typedpkg-stubs/setup.py index 58d8fa968cc3..4948dc6a01df 100644 --- a/test-data/packages/typedpkg-stubs/setup.py +++ b/test-data/packages/typedpkg-stubs/setup.py @@ -2,7 +2,7 @@ This setup file installs packages to test mypy's PEP 561 implementation """ -from distutils.core import setup +from setuptools import setup setup( name='typedpkg-stubs', diff --git a/test-data/packages/typedpkg_ns/setup.py b/test-data/packages/typedpkg_ns_a/setup.py similarity index 50% rename from test-data/packages/typedpkg_ns/setup.py rename to test-data/packages/typedpkg_ns_a/setup.py index 9285e89104bb..3dab731cada9 100644 --- a/test-data/packages/typedpkg_ns/setup.py +++ b/test-data/packages/typedpkg_ns_a/setup.py @@ -1,10 +1,10 @@ -from setuptools import setup, find_packages +from setuptools import setup setup( name='typedpkg_namespace.alpha', version='1.0.0', - packages=find_packages(), namespace_packages=['typedpkg_ns'], zip_safe=False, - package_data={'typedpkg_ns.ns': ['py.typed']} + package_data={'typedpkg_ns.a': ['py.typed']}, + packages=['typedpkg_ns.a'], ) diff --git a/test-data/packages/typedpkg_ns/typedpkg_ns/__init__.py b/test-data/packages/typedpkg_ns_a/typedpkg_ns/__init__.py similarity index 100% rename from test-data/packages/typedpkg_ns/typedpkg_ns/__init__.py rename to test-data/packages/typedpkg_ns_a/typedpkg_ns/__init__.py diff --git a/test-data/packages/typedpkg_ns_a/typedpkg_ns/a/__init__.py b/test-data/packages/typedpkg_ns_a/typedpkg_ns/a/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/typedpkg_ns/typedpkg_ns/ns/bbb.py b/test-data/packages/typedpkg_ns_a/typedpkg_ns/a/bbb.py similarity index 100% rename from test-data/packages/typedpkg_ns/typedpkg_ns/ns/bbb.py rename to test-data/packages/typedpkg_ns_a/typedpkg_ns/a/bbb.py diff --git a/test-data/packages/typedpkg_ns_a/typedpkg_ns/a/py.typed b/test-data/packages/typedpkg_ns_a/typedpkg_ns/a/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/typedpkg_ns_b-stubs/setup.py b/test-data/packages/typedpkg_ns_b-stubs/setup.py new file mode 100644 index 000000000000..a5d7df83eeea --- /dev/null +++ b/test-data/packages/typedpkg_ns_b-stubs/setup.py @@ -0,0 +1,14 @@ +""" +This setup file installs packages to test mypy's PEP 561 implementation +""" + +from distutils.core import setup + +setup( + name='typedpkg_ns_b-stubs', + author="The mypy team", + version='0.1', + namespace_packages=['typedpkg_ns-stubs'], + package_data={'typedpkg_ns-stubs.b': ['__init__.pyi', 'bbb.pyi']}, + packages=['typedpkg_ns-stubs.b'], +) diff --git a/test-data/packages/typedpkg_ns_b-stubs/typedpkg_ns-stubs/b/__init__.pyi b/test-data/packages/typedpkg_ns_b-stubs/typedpkg_ns-stubs/b/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/typedpkg_ns_b-stubs/typedpkg_ns-stubs/b/bbb.pyi b/test-data/packages/typedpkg_ns_b-stubs/typedpkg_ns-stubs/b/bbb.pyi new file mode 100644 index 000000000000..e00e9e52c05f --- /dev/null +++ b/test-data/packages/typedpkg_ns_b-stubs/typedpkg_ns-stubs/b/bbb.pyi @@ -0,0 +1 @@ +def bf(a: bool) -> bool: ... diff --git a/test-data/packages/typedpkg_ns_b/setup.py b/test-data/packages/typedpkg_ns_b/setup.py new file mode 100644 index 000000000000..4f0d0d954a73 --- /dev/null +++ b/test-data/packages/typedpkg_ns_b/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup + +setup( + name='typedpkg_namespace.beta', + version='1.0.0', + namespace_packages=['typedpkg_ns'], + zip_safe=False, + package_data={'typedpkg_ns.b': []}, + packages=['typedpkg_ns.b'], +) diff --git a/test-data/packages/typedpkg_ns_b/typedpkg_ns/__init__.py b/test-data/packages/typedpkg_ns_b/typedpkg_ns/__init__.py new file mode 100644 index 000000000000..3ac255b8a577 --- /dev/null +++ b/test-data/packages/typedpkg_ns_b/typedpkg_ns/__init__.py @@ -0,0 +1,2 @@ +# namespace pkg +__import__("pkg_resources").declare_namespace(__name__) diff --git a/test-data/packages/typedpkg_ns_b/typedpkg_ns/b/__init__.py b/test-data/packages/typedpkg_ns_b/typedpkg_ns/b/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test-data/packages/typedpkg_ns_b/typedpkg_ns/b/bbb.py b/test-data/packages/typedpkg_ns_b/typedpkg_ns/b/bbb.py new file mode 100644 index 000000000000..f10802daace9 --- /dev/null +++ b/test-data/packages/typedpkg_ns_b/typedpkg_ns/b/bbb.py @@ -0,0 +1,2 @@ +def bf(a): + return not a diff --git a/test-data/stdlib-samples/3.2/random.py b/test-data/stdlib-samples/3.2/random.py index 7eecdfe04db4..82bda03f7e53 100644 --- a/test-data/stdlib-samples/3.2/random.py +++ b/test-data/stdlib-samples/3.2/random.py @@ -41,7 +41,7 @@ from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin from os import urandom as _urandom -from collections import Set as _Set, Sequence as _Sequence +from collections.abc import Set as _Set, Sequence as _Sequence from hashlib import sha512 as _sha512 from typing import ( diff --git a/test-data/stdlib-samples/3.2/shutil.py b/test-data/stdlib-samples/3.2/shutil.py index e7b5e5aacd04..bcefb7787952 100644 --- a/test-data/stdlib-samples/3.2/shutil.py +++ b/test-data/stdlib-samples/3.2/shutil.py @@ -58,7 +58,7 @@ class ReadError(EnvironmentError): """Raised when an archive cannot be read""" class RegistryError(Exception): - """Raised when a registery operation with the archiving + """Raised when a registry operation with the archiving and unpacking registeries fails""" @@ -676,7 +676,7 @@ def register_unpack_format(name: str, extensions: List[str], function: Any, _UNPACK_FORMATS[name] = extensions, function, extra_args, description def unregister_unpack_format(name: str) -> None: - """Removes the pack format from the registery.""" + """Removes the pack format from the registry.""" del _UNPACK_FORMATS[name] def _ensure_directory(path: str) -> None: diff --git a/test-data/unit/README.md b/test-data/unit/README.md index a84afa8e20af..06a5b77ef769 100644 --- a/test-data/unit/README.md +++ b/test-data/unit/README.md @@ -82,17 +82,17 @@ Running tests and linting First install any additional dependencies needed for testing: - $ python3 -m pip install -U -r test-requirements.txt + python3 -m pip install -U -r test-requirements.txt You must also have a Python 2.7 binary installed that can import the `typing` module: - $ python2 -m pip install -U typing + python2 -m pip install -U typing The unit test suites are driven by the `pytest` framework. To run all mypy tests, run `pytest` in the mypy repository: - $ pytest -q mypy + pytest -q mypy This will run all tests, including integration and regression tests, and will verify that all stubs are valid. This may take several @@ -106,59 +106,59 @@ Note that some tests will be disabled for older python versions. If you work on mypyc, you will want to also run mypyc tests: - $ pytest -q mypyc + pytest -q mypyc You can run tests from a specific module directly, a specific suite within a module, or a test in a suite (even if it's data-driven): - $ pytest -q mypy/test/testdiff.py + pytest -q mypy/test/testdiff.py - $ pytest -q mypy/test/testsemanal.py::SemAnalTypeInfoSuite + pytest -q mypy/test/testsemanal.py::SemAnalTypeInfoSuite - $ pytest -n0 mypy/test/testargs.py::ArgSuite::test_coherence + pytest -n0 mypy/test/testargs.py::ArgSuite::test_coherence - $ pytest -n0 mypy/test/testcheck.py::TypeCheckSuite::testCallingVariableWithFunctionType + pytest -n0 mypy/test/testcheck.py::TypeCheckSuite::testCallingVariableWithFunctionType To control which tests are run and how, you can use the `-k` switch: - $ pytest -q -k "MethodCall" + pytest -q -k "MethodCall" You can also run the type checker for manual testing without installing it by setting up the Python module search path suitably: - $ export PYTHONPATH=$PWD - $ python3 -m mypy PROGRAM.py + export PYTHONPATH=$PWD + python3 -m mypy PROGRAM.py You will have to manually install the `typing` module if you're running Python 3.4 or earlier. You can also execute mypy as a module - $ python3 -m mypy PROGRAM.py + python3 -m mypy PROGRAM.py You can check a module or string instead of a file: - $ python3 -m mypy PROGRAM.py - $ python3 -m mypy -m MODULE - $ python3 -m mypy -c 'import MODULE' + python3 -m mypy PROGRAM.py + python3 -m mypy -m MODULE + python3 -m mypy -c 'import MODULE' To run mypy on itself: - $ python3 -m mypy --config-file mypy_self_check.ini -p mypy + python3 -m mypy --config-file mypy_self_check.ini -p mypy To run the linter: - $ flake8 + flake8 You can also run all of the above tests using `runtests.py` (this includes type checking mypy and linting): - $ python3 runtests.py + python3 runtests.py By default, this runs everything except some mypyc tests. You can give it arguments to control what gets run, such as `self` to run mypy on itself: - $ python3 runtests.py self + python3 runtests.py self Run `python3 runtests.py mypyc-extra` to run mypyc tests that are not enabled by default. This is typically only needed if you work on mypyc. @@ -187,7 +187,7 @@ Debugging You can use interactive debuggers like `pdb` to debug failing tests. You need to pass the `-n0` option to disable parallelization: - $ pytest -n0 --pdb -k MethodCall + pytest -n0 --pdb -k MethodCall You can also write `import pdb; pdb.set_trace()` in code to enter the debugger. @@ -195,7 +195,7 @@ debugger. The `--mypy-verbose` flag can be used to enable additional debug output from most tests (as if `--verbose` had been passed to mypy): - $ pytest -n0 --mypy-verbose -k MethodCall + pytest -n0 --mypy-verbose -k MethodCall Coverage reports ---------------- diff --git a/test-data/unit/check-abstract.test b/test-data/unit/check-abstract.test index 64df7fe65cdd..6f3318a87683 100644 --- a/test-data/unit/check-abstract.test +++ b/test-data/unit/check-abstract.test @@ -442,9 +442,13 @@ class I(metaclass=ABCMeta): def g(self, x): pass class A(I): def f(self, x): pass - def g(self, x, y) -> None: pass \ - # E: Signature of "g" incompatible with supertype "I" + def g(self, x, y) -> None: pass # Fail [out] +main:10: error: Signature of "g" incompatible with supertype "I" +main:10: note: Superclass: +main:10: note: def g(self, x: Any) -> Any +main:10: note: Subclass: +main:10: note: def g(self, x: Any, y: Any) -> None [case testAbstractClassWithAllDynamicTypes2] from abc import abstractmethod, ABCMeta @@ -596,7 +600,7 @@ a.f(B()) # E: No overload variant of "f" of "A" matches argument type "B" \ # N: def f(self, x: int) -> int \ # N: def f(self, x: str) -> str -[case testOverloadedAbstractMethodVariantMissingDecorator1] +[case testOverloadedAbstractMethodVariantMissingDecorator0] from foo import * [file foo.pyi] from abc import abstractmethod, ABCMeta diff --git a/test-data/unit/check-annotated.test b/test-data/unit/check-annotated.test index e1eac154c72e..68862087d13d 100644 --- a/test-data/unit/check-annotated.test +++ b/test-data/unit/check-annotated.test @@ -126,3 +126,34 @@ class Meta: x = Annotated[int, Meta()] reveal_type(x) # N: Revealed type is "def () -> builtins.int" [builtins fixtures/tuple.pyi] + +[case testAnnotatedStringLiteralInFunc] +from typing import TypeVar +from typing_extensions import Annotated +def f1(a: Annotated[str, "metadata"]): + pass +reveal_type(f1) # N: Revealed type is "def (a: builtins.str) -> Any" +def f2(a: Annotated["str", "metadata"]): + pass +reveal_type(f2) # N: Revealed type is "def (a: builtins.str) -> Any" +def f3(a: Annotated["notdefined", "metadata"]): # E: Name "notdefined" is not defined + pass +T = TypeVar('T') +def f4(a: Annotated[T, "metatdata"]): + pass +reveal_type(f4) # N: Revealed type is "def [T] (a: T`-1) -> Any" +[builtins fixtures/tuple.pyi] + +[case testSliceAnnotated39] +# flags: --python-version 3.9 +from typing_extensions import Annotated +a: Annotated[int, 1:2] +reveal_type(a) # N: Revealed type is "builtins.int" +[builtins fixtures/tuple.pyi] + +[case testSliceAnnotated38] +# flags: --python-version 3.8 +from typing_extensions import Annotated +a: Annotated[int, 1:2] +reveal_type(a) # N: Revealed type is "builtins.int" +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index e6e5f4be8094..f4bf7c7cfa94 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -758,3 +758,44 @@ class Foo(Generic[T]): [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] + +[case testAwaitOverloadSpecialCase] +from typing import Any, Awaitable, Iterable, overload, Tuple, List, TypeVar, Generic + +T = TypeVar("T") +FT = TypeVar("FT", bound='Future[Any]') + +class Future(Awaitable[T], Iterable[T]): + pass + +class Task(Future[T]): + pass + +@overload +def wait(fs: Iterable[FT]) -> Future[Tuple[List[FT], List[FT]]]: ... \ + # E: Overloaded function signatures 1 and 2 overlap with incompatible return types +@overload +def wait(fs: Iterable[Awaitable[T]]) -> Future[Tuple[List[Task[T]], List[Task[T]]]]: ... +def wait(fs: Any) -> Any: + pass + +async def imprecise1(futures: Iterable[Task[Any]]) -> None: + done: Any + pending: Any + done, pending = await wait(futures) + reveal_type(done) # N: Revealed type is "Any" + +async def imprecise2(futures: Iterable[Awaitable[Any]]) -> None: + done, pending = await wait(futures) + reveal_type(done) # N: Revealed type is "builtins.list[__main__.Task[Any]]" + +async def precise1(futures: Iterable[Future[int]]) -> None: + done, pending = await wait(futures) + reveal_type(done) # N: Revealed type is "builtins.list[__main__.Future[builtins.int]]" + +async def precise2(futures: Iterable[Awaitable[int]]) -> None: + done, pending = await wait(futures) + reveal_type(done) # N: Revealed type is "builtins.list[__main__.Task[builtins.int]]" + +[builtins fixtures/async_await.pyi] +[typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 97e026fea38b..e7cea6c27b99 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -502,7 +502,7 @@ reveal_type(sub_str.attr) # N: Revealed type is "builtins.str*" [builtins fixtures/bool.pyi] -[case testAttrsGenericInheritance] +[case testAttrsGenericInheritance2] from typing import Generic, TypeVar import attr @@ -1390,3 +1390,45 @@ class B(A): reveal_type(B) # N: Revealed type is "def (foo: builtins.int) -> __main__.B" [builtins fixtures/bool.pyi] + +[case testAttrsClassHasAttributeWithAttributes] +import attr + +@attr.s +class A: + b: int = attr.ib() + c: str = attr.ib() + +reveal_type(A.__attrs_attrs__) # N: Revealed type is "Tuple[attr.Attribute[builtins.int], attr.Attribute[builtins.str]]" + +[builtins fixtures/attr.pyi] + +[case testAttrsClassWithSlots] +import attr + +@attr.s(slots=True) +class A: + b: int = attr.ib() + + def __attrs_post_init__(self) -> None: + self.b = 1 + self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" + +@attr.dataclass(slots=True) +class B: + __slots__ = () # would be replaced + b: int + + def __attrs_post_init__(self) -> None: + self.b = 1 + self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" + +@attr.dataclass(slots=False) +class C: + __slots__ = () # would not be replaced + b: int + + def __attrs_post_init__(self) -> None: + self.b = 1 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.C" + self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.C" +[builtins fixtures/attr.pyi] diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 184c9e58ca58..03dee485c848 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -401,9 +401,18 @@ def foo( [case testNoneHasBool] none = None b = none.__bool__() -reveal_type(b) # N: Revealed type is "builtins.bool" +reveal_type(b) # N: Revealed type is "Literal[False]" [builtins fixtures/bool.pyi] +[case testNoneHasBoolShowNoneErrorsFalse] +none = None +b = none.__bool__() +reveal_type(b) # N: Revealed type is "Literal[False]" +[builtins fixtures/bool.pyi] +[file mypy.ini] +\[mypy] +show_none_errors = False + [case testAssignmentInvariantNoteForList] from typing import List x: List[int] diff --git a/test-data/unit/check-bound.test b/test-data/unit/check-bound.test index a137132ebc67..bf13ef874579 100644 --- a/test-data/unit/check-bound.test +++ b/test-data/unit/check-bound.test @@ -39,7 +39,7 @@ class G(Generic[T]): v = None # type: G[A] w = None # type: G[B] -x = None # type: G[str] # E: Type argument "builtins.str" of "G" must be a subtype of "__main__.A" +x = None # type: G[str] # E: Type argument "str" of "G" must be a subtype of "A" y = G('a') # E: Value of type variable "T" of "G" cannot be "str" z = G(A()) z = G(B()) @@ -93,9 +93,9 @@ TA = TypeVar('TA', bound=A) class C(Generic[TA]): pass class D0(C[TA], Generic[TA]): pass -class D1(C[T], Generic[T]): pass # E: Type argument "T`1" of "C" must be a subtype of "__main__.A" +class D1(C[T], Generic[T]): pass # E: Type argument "T" of "C" must be a subtype of "A" class D2(C[A]): pass -class D3(C[str]): pass # E: Type argument "builtins.str" of "C" must be a subtype of "__main__.A" +class D3(C[str]): pass # E: Type argument "str" of "C" must be a subtype of "A" -- Using information from upper bounds diff --git a/test-data/unit/check-callable.test b/test-data/unit/check-callable.test index ee1c84edf185..697a323f2365 100644 --- a/test-data/unit/check-callable.test +++ b/test-data/unit/check-callable.test @@ -223,6 +223,56 @@ else: [builtins fixtures/callable.pyi] +[case testDecoratedCallMethods] +from typing import Any, Callable, Union, TypeVar + +F = TypeVar('F', bound=Callable) + +def decorator(f: F) -> F: + pass +def change(f: Callable) -> Callable[[Any], str]: + pass +def untyped(f): + pass + +class Some1: + @decorator + def __call__(self) -> int: + pass +class Some2: + @change + def __call__(self) -> int: + pass +class Some3: + @untyped + def __call__(self) -> int: + pass +class Some4: + __call__: Any + +s1: Some1 +s2: Some2 +s3: Some3 +s4: Some4 + +if callable(s1): + 1 + 'a' # E: Unsupported operand types for + ("int" and "str") +else: + 2 + 'b' +if callable(s2): + 1 + 'a' # E: Unsupported operand types for + ("int" and "str") +else: + 2 + 'b' +if callable(s3): + 1 + 'a' # E: Unsupported operand types for + ("int" and "str") +else: + 2 + 'b' # E: Unsupported operand types for + ("int" and "str") +if callable(s4): + 1 + 'a' # E: Unsupported operand types for + ("int" and "str") +else: + 2 + 'b' # E: Unsupported operand types for + ("int" and "str") +[builtins fixtures/callable.pyi] + [case testCallableNestedUnions] from typing import Callable, Union @@ -484,3 +534,56 @@ reveal_type(_TYPE) # N: Revealed type is "def (x: Any) -> builtins.type" _TYPE('bar') [builtins fixtures/callable.pyi] + +[case testErrorMessageAboutSelf] +# https://github.com/python/mypy/issues/11309 +class Some: + def method(self, a) -> None: pass + @classmethod + def cls_method(cls, a) -> None: pass + @staticmethod + def st_method(a) -> None: pass + + def bad_method(a) -> None: pass + @classmethod + def bad_cls_method(a) -> None: pass + @staticmethod + def bad_st_method() -> None: pass + +s: Some + +s.method(1) +s.cls_method(1) +Some.cls_method(1) +s.st_method(1) +Some.st_method(1) + +s.method(1, 2) # E: Too many arguments for "method" of "Some" +s.cls_method(1, 2) # E: Too many arguments for "cls_method" of "Some" +Some.cls_method(1, 2) # E: Too many arguments for "cls_method" of "Some" +s.st_method(1, 2) # E: Too many arguments for "st_method" of "Some" +Some.st_method(1, 2) # E: Too many arguments for "st_method" of "Some" + +s.bad_method(1) # E: Too many arguments for "bad_method" of "Some" \ + # N: Looks like the first special argument in a method is not named "self", "cls", or "mcs", maybe it is missing? +s.bad_cls_method(1) # E: Too many arguments for "bad_cls_method" of "Some" \ + # N: Looks like the first special argument in a method is not named "self", "cls", or "mcs", maybe it is missing? +Some.bad_cls_method(1) # E: Too many arguments for "bad_cls_method" of "Some" \ + # N: Looks like the first special argument in a method is not named "self", "cls", or "mcs", maybe it is missing? +s.bad_st_method(1) # E: Too many arguments for "bad_st_method" of "Some" +Some.bad_st_method(1) # E: Too many arguments for "bad_st_method" of "Some" +[builtins fixtures/callable.pyi] + +[case testClassMethodAliasStub] +from a import f +f("no") # E: Argument 1 has incompatible type "str"; expected "int" +[file a.pyi] +from b import C +f = C.f +[file b.pyi] +import a +class C(B): + @classmethod + def f(self, x: int) -> C: ... +class B: ... +[builtins fixtures/classmethod.pyi] diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test index a6a30f7731e9..cf3af49ab3a4 100644 --- a/test-data/unit/check-class-namedtuple.test +++ b/test-data/unit/check-class-namedtuple.test @@ -270,7 +270,7 @@ a = A(B()) a = A(1) # E: Argument 1 to "A" has incompatible type "int"; expected "B" [builtins fixtures/tuple.pyi] -[case testNewNamedTupleProperty] +[case testNewNamedTupleProperty36] # flags: --python-version 3.6 from typing import NamedTuple diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 642a36937e64..a2bcdade3287 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -114,6 +114,43 @@ class A: A().f = None # E: Cannot assign to a method +[case testOverrideAttributeWithMethod] +# This was crashing: +# https://github.com/python/mypy/issues/10134 +from typing import Protocol + +class Base: + __hash__ = None + +class Derived(Base): + def __hash__(self) -> int: # E: Signature of "__hash__" incompatible with supertype "Base" + pass + +# Correct: + +class CallableProtocol(Protocol): + def __call__(self, arg: int) -> int: + pass + +class CorrectBase: + attr: CallableProtocol + +class CorrectDerived(CorrectBase): + def attr(self, arg: int) -> int: + pass + +[case testOverrideMethodWithAttribute] +# The reverse should not crash as well: +from typing import Callable + +class Base: + def __hash__(self) -> int: + pass + +class Derived(Base): + __hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]") + + -- Attributes -- ---------- @@ -310,7 +347,15 @@ class B(A): def g(self, x: A) -> A: pass # Fail [out] main:6: error: Signature of "f" incompatible with supertype "A" +main:6: note: Superclass: +main:6: note: def f(self, x: A) -> None +main:6: note: Subclass: +main:6: note: def f(self, x: A, y: A) -> None main:7: error: Signature of "g" incompatible with supertype "A" +main:7: note: Superclass: +main:7: note: def g(self, x: A, y: B) -> A +main:7: note: Subclass: +main:7: note: def g(self, x: A) -> A [case testMethodOverridingAcrossDeepInheritanceHierarchy1] import typing @@ -403,10 +448,16 @@ class B(A): @int_to_none def f(self) -> int: pass @str_to_int - def g(self) -> str: pass # E: Signature of "g" incompatible with supertype "A" + def g(self) -> str: pass # Fail @int_to_none @str_to_int def h(self) -> str: pass +[out] +main:15: error: Signature of "g" incompatible with supertype "A" +main:15: note: Superclass: +main:15: note: def g(self) -> str +main:15: note: Subclass: +main:15: note: def g(*Any, **Any) -> int [case testOverrideDecorated] from typing import Callable @@ -423,9 +474,15 @@ class A: class B(A): def f(self) -> int: pass - def g(self) -> str: pass # E: Signature of "g" incompatible with supertype "A" + def g(self) -> str: pass # Fail @str_to_int def h(self) -> str: pass +[out] +main:15: error: Signature of "g" incompatible with supertype "A" +main:15: note: Superclass: +main:15: note: def g(*Any, **Any) -> int +main:15: note: Subclass: +main:15: note: def g(self) -> str [case testOverrideWithDecoratorReturningAny] def dec(f): pass @@ -1236,7 +1293,7 @@ class A: def g(self) -> None: pass class B(A): - def f(self) -> None: pass # E: Signature of "f" incompatible with supertype "A" + def f(self) -> None: pass # Fail @classmethod def g(cls) -> None: pass @@ -1245,6 +1302,13 @@ class C(A): @staticmethod def f() -> None: pass [builtins fixtures/classmethod.pyi] +[out] +main:8: error: Signature of "f" incompatible with supertype "A" +main:8: note: Superclass: +main:8: note: @classmethod +main:8: note: def f(cls) -> None +main:8: note: Subclass: +main:8: note: def f(self) -> None -- Properties -- ---------- @@ -1808,12 +1872,20 @@ from typing import overload class A: def __add__(self, x: int) -> int: pass class B(A): - @overload # E: Signature of "__add__" incompatible with supertype "A" \ - # N: Overloaded operator methods can't have wider argument types in overrides + @overload # Fail def __add__(self, x: int) -> int: pass @overload def __add__(self, x: str) -> str: pass [out] +tmp/foo.pyi:5: error: Signature of "__add__" incompatible with supertype "A" +tmp/foo.pyi:5: note: Superclass: +tmp/foo.pyi:5: note: def __add__(self, int) -> int +tmp/foo.pyi:5: note: Subclass: +tmp/foo.pyi:5: note: @overload +tmp/foo.pyi:5: note: def __add__(self, int) -> int +tmp/foo.pyi:5: note: @overload +tmp/foo.pyi:5: note: def __add__(self, str) -> str +tmp/foo.pyi:5: note: Overloaded operator methods cannot have wider argument types in overrides [case testOperatorMethodOverrideWideningArgumentType] import typing @@ -1912,13 +1984,27 @@ class A: @overload def __add__(self, x: str) -> 'A': pass class B(A): - @overload # E: Signature of "__add__" incompatible with supertype "A" \ - # N: Overloaded operator methods can't have wider argument types in overrides + @overload # Fail def __add__(self, x: int) -> A: pass @overload def __add__(self, x: str) -> A: pass @overload def __add__(self, x: type) -> A: pass +[out] +tmp/foo.pyi:8: error: Signature of "__add__" incompatible with supertype "A" +tmp/foo.pyi:8: note: Superclass: +tmp/foo.pyi:8: note: @overload +tmp/foo.pyi:8: note: def __add__(self, int) -> A +tmp/foo.pyi:8: note: @overload +tmp/foo.pyi:8: note: def __add__(self, str) -> A +tmp/foo.pyi:8: note: Subclass: +tmp/foo.pyi:8: note: @overload +tmp/foo.pyi:8: note: def __add__(self, int) -> A +tmp/foo.pyi:8: note: @overload +tmp/foo.pyi:8: note: def __add__(self, str) -> A +tmp/foo.pyi:8: note: @overload +tmp/foo.pyi:8: note: def __add__(self, type) -> A +tmp/foo.pyi:8: note: Overloaded operator methods cannot have wider argument types in overrides [case testOverloadedOperatorMethodOverrideWithSwitchedItemOrder] from foo import * @@ -1975,8 +2061,8 @@ class B: class C: def __radd__(self, other, oops) -> int: ... [out] -tmp/foo.pyi:3: error: Invalid signature "def (foo.B) -> foo.A" -tmp/foo.pyi:5: error: Invalid signature "def (foo.C, Any, Any) -> builtins.int" +tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]" +tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]" [case testReverseOperatorOrderingCase1] class A: @@ -2568,6 +2654,35 @@ b = a.bar [out] main:9: error: Incompatible types in assignment (expression has type "A", variable has type "B") +[case testDecoratedGetAttribute] +from typing import Callable, TypeVar + +T = TypeVar('T', bound=Callable) + +def decorator(f: T) -> T: + return f + +def bad(f: Callable) -> Callable[..., int]: + return f + +class A: + @decorator + def __getattribute__(self, x: str) -> A: + return A() +class B: + @bad # We test that type will be taken from decorated type, not node itself + def __getattribute__(self, x: str) -> A: + return A() + +a: A +b: B + +a1: A = a.foo +b1: B = a.bar # E: Incompatible types in assignment (expression has type "A", variable has type "B") +a2: A = b.baz # E: Incompatible types in assignment (expression has type "int", variable has type "A") +b2: B = b.roo # E: Incompatible types in assignment (expression has type "int", variable has type "B") +[builtins fixtures/tuple.pyi] + [case testGetattributeSignature] class A: def __getattribute__(self, x: str) -> A: pass @@ -2578,8 +2693,8 @@ class C: class D: def __getattribute__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (__main__.B, __main__.A) -> __main__.B" for "__getattribute__" -main:6: error: Invalid signature "def (__main__.C, builtins.str, builtins.str) -> __main__.C" for "__getattribute__" +main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattribute__" +main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattribute__" [case testGetattr] @@ -2595,6 +2710,35 @@ b = a.bar [out] main:9: error: Incompatible types in assignment (expression has type "A", variable has type "B") +[case testDecoratedGetattr] +from typing import Callable, TypeVar + +T = TypeVar('T', bound=Callable) + +def decorator(f: T) -> T: + return f + +def bad(f: Callable) -> Callable[..., int]: + return f + +class A: + @decorator + def __getattr__(self, x: str) -> A: + return A() +class B: + @bad # We test that type will be taken from decorated type, not node itself + def __getattr__(self, x: str) -> A: + return A() + +a: A +b: B + +a1: A = a.foo +b1: B = a.bar # E: Incompatible types in assignment (expression has type "A", variable has type "B") +a2: A = b.baz # E: Incompatible types in assignment (expression has type "int", variable has type "A") +b2: B = b.roo # E: Incompatible types in assignment (expression has type "int", variable has type "B") +[builtins fixtures/tuple.pyi] + [case testGetattrWithGetitem] class A: def __getattr__(self, x: str) -> 'A': @@ -2655,8 +2799,8 @@ class C: class D: def __getattr__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (__main__.B, __main__.A) -> __main__.B" for "__getattr__" -main:6: error: Invalid signature "def (__main__.C, builtins.str, builtins.str) -> __main__.C" for "__getattr__" +main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattr__" +main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattr__" [case testSetattr] from typing import Union, Any @@ -2680,7 +2824,7 @@ c = C() c.fail = 4 # E: Incompatible types in assignment (expression has type "int", variable has type "str") class D: - __setattr__ = 'hello' # E: Invalid signature "builtins.str" for "__setattr__" + __setattr__ = 'hello' # E: Invalid signature "str" for "__setattr__" d = D() d.crash = 4 # E: "D" has no attribute "crash" @@ -2701,16 +2845,45 @@ s = Sub() s.success = 4 s.fail = 'fail' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[case testDecoratedSetattr] +from typing import Any, Callable, TypeVar + +T = TypeVar('T', bound=Callable) + +def decorator(f: T) -> T: + return f + +def bad(f: Callable) -> Callable[[Any, str, int], None]: + return f + +class A: + @decorator + def __setattr__(self, k: str, v: str) -> None: + pass +class B: + @bad # We test that type will be taken from decorated type, not node itself + def __setattr__(self, k: str, v: str) -> None: + pass + +a: A +a.foo = 'a' +a.bar = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") + +b: B +b.good = 1 +b.bad = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[builtins fixtures/tuple.pyi] + [case testSetattrSignature] from typing import Any class Test: - def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "def ()" for "__setattr__" + def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "Callable[[], None]" for "__setattr__" t = Test() t.crash = 'test' # E: "Test" has no attribute "crash" class A: - def __setattr__(self): ... # E: Invalid signature "def (self: __main__.A) -> Any" for "__setattr__" + def __setattr__(self): ... # E: Invalid signature "Callable[[A], Any]" for "__setattr__" a = A() a.test = 4 # E: "A" has no attribute "test" @@ -2720,7 +2893,7 @@ b = B() b.integer = 5 class C: - def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "def (__main__.C, builtins.int, builtins.int)" for "__setattr__" + def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "Callable[[C, int, int], None]" for "__setattr__" c = C() c.check = 13 @@ -2745,6 +2918,15 @@ b.at = '3' # E: Incompatible types in assignment (expression has type "str", va if int(): integer = b.at # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[case testSetattrKeywordArg] +from typing import Any + +class C: + def __setattr__(self, key: str, value: Any, p: bool = False) -> None: ... + +c: C +c.__setattr__("x", 42, p=True) + -- CallableType objects -- ---------------- @@ -2786,7 +2968,7 @@ C(foo='') # E: Argument "foo" to "C" has incompatible type "str"; expected "Opti [case testConstructInstanceWithDynamicallyTyped__new__] class C: - def __new__(cls, foo): + def __new__(cls, foo): # N: "C" defined here obj = object.__new__(cls) return obj @@ -2848,9 +3030,9 @@ c = C(1) c.a # E: "C" has no attribute "a" C('', '') C('') # E: No overload variant of "C" matches argument type "str" \ - # N: Possible overload variant: \ + # N: Possible overload variants: \ # N: def __new__(cls, foo: int) -> C \ - # N: <1 more non-matching overload not shown> + # N: def __new__(cls, x: str, y: str) -> C [builtins fixtures/__new__.pyi] @@ -3154,7 +3336,7 @@ def foo(arg: Type[Any]): from typing import Type, Any def foo(arg: Type[Any]): reveal_type(arg.__str__) # N: Revealed type is "def () -> builtins.str" - reveal_type(arg.mro()) # N: Revealed type is "builtins.list[builtins.type]" + reveal_type(arg.mro()) # N: Revealed type is "builtins.list[builtins.type[Any]]" [builtins fixtures/type.pyi] [out] @@ -3276,9 +3458,9 @@ u = new(User) [builtins fixtures/classmethod.pyi] [out] tmp/foo.pyi:17: error: No overload variant of "User" matches argument type "str" -tmp/foo.pyi:17: note: Possible overload variant: +tmp/foo.pyi:17: note: Possible overload variants: +tmp/foo.pyi:17: note: def __init__(self) -> U tmp/foo.pyi:17: note: def __init__(self, arg: int) -> U -tmp/foo.pyi:17: note: <1 more non-matching overload not shown> tmp/foo.pyi:18: error: Too many arguments for "foo" of "User" [case testTypeUsingTypeCInUpperBound] @@ -3664,14 +3846,28 @@ class Super: def foo(self, a: C) -> C: pass class Sub(Super): - @overload # E: Signature of "foo" incompatible with supertype "Super" + @overload # Fail def foo(self, a: A) -> A: pass @overload - def foo(self, a: B) -> C: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader + def foo(self, a: B) -> C: pass # Fail @overload def foo(self, a: C) -> C: pass [builtins fixtures/classmethod.pyi] [out] +tmp/foo.pyi:16: error: Signature of "foo" incompatible with supertype "Super" +tmp/foo.pyi:16: note: Superclass: +tmp/foo.pyi:16: note: @overload +tmp/foo.pyi:16: note: def foo(self, a: A) -> A +tmp/foo.pyi:16: note: @overload +tmp/foo.pyi:16: note: def foo(self, a: C) -> C +tmp/foo.pyi:16: note: Subclass: +tmp/foo.pyi:16: note: @overload +tmp/foo.pyi:16: note: def foo(self, a: A) -> A +tmp/foo.pyi:16: note: @overload +tmp/foo.pyi:16: note: def foo(self, a: B) -> C +tmp/foo.pyi:16: note: @overload +tmp/foo.pyi:16: note: def foo(self, a: C) -> C +tmp/foo.pyi:19: error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader [case testTypeTypeOverlapsWithObjectAndType] from foo import * @@ -4086,7 +4282,7 @@ class A: def c() -> None: pass class B(A): - def a(self) -> None: pass # E: Signature of "a" incompatible with supertype "A" + def a(self) -> None: pass # Fail @classmethod def b(cls) -> None: pass @@ -4094,6 +4290,13 @@ class B(A): @staticmethod def c() -> None: pass [builtins fixtures/classmethod.pyi] +[out] +main:11: error: Signature of "a" incompatible with supertype "A" +main:11: note: Superclass: +main:11: note: @staticmethod +main:11: note: def a() -> None +main:11: note: Subclass: +main:11: note: def a(self) -> None [case testTempNode] class A(): @@ -5430,13 +5633,13 @@ A = G x: A[B[int]] # E B = G [out] -main:8:4: error: Type argument "__main__.G[builtins.int]" of "G" must be a subtype of "builtins.str" -main:8:6: error: Type argument "builtins.int" of "G" must be a subtype of "builtins.str" +main:8:4: error: Type argument "G[int]" of "G" must be a subtype of "str" +main:8:6: error: Type argument "int" of "G" must be a subtype of "str" [case testExtremeForwardReferencing] from typing import TypeVar, Generic -T = TypeVar('T') +T = TypeVar('T', covariant=True) class B(Generic[T]): ... y: A @@ -6000,6 +6203,85 @@ class C: reveal_type(self.spec) # N: Revealed type is "__main__.B" [builtins fixtures/bool.pyi] +[case testDecoratedDunderGet] +from typing import Any, Callable, TypeVar, Type + +F = TypeVar('F', bound=Callable) +T = TypeVar('T') + +def decorator(f: F) -> F: + return f + +def change(f: Callable) -> Callable[..., int]: + pass + +def untyped(f): + return f + +class A: ... + +class Descr1: + @decorator + def __get__(self, obj: T, typ: Type[T]) -> A: ... +class Descr2: + @change + def __get__(self, obj: T, typ: Type[T]) -> A: ... +class Descr3: + @untyped + def __get__(self, obj: T, typ: Type[T]) -> A: ... + +class C: + spec1 = Descr1() + spec2 = Descr2() + spec3 = Descr3() + +c: C +reveal_type(c.spec1) # N: Revealed type is "__main__.A" +reveal_type(c.spec2) # N: Revealed type is "builtins.int" +reveal_type(c.spec3) # N: Revealed type is "Any" +[builtins fixtures/bool.pyi] + +[case testDecoratedDunderSet] +from typing import Any, Callable, TypeVar, Type + +F = TypeVar('F', bound=Callable) +T = TypeVar('T') + +def decorator(f: F) -> F: + return f + +def change(f: Callable) -> Callable[[Any, Any, int], None]: + pass + +def untyped(f): + return f + +class A: ... + +class Descr1: + @decorator + def __set__(self, obj: T, value: A) -> None: ... +class Descr2: + @change + def __set__(self, obj: T, value: A) -> None: ... +class Descr3: + @untyped + def __set__(self, obj: T, value: A) -> None: ... + +class C: + spec1 = Descr1() + spec2 = Descr2() + spec3 = Descr3() + +c: C +c.spec1 = A() +c.spec1 = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "A") +c.spec2 = A() # E: Incompatible types in assignment (expression has type "A", variable has type "int") +c.spec2 = 1 +c.spec3 = A() +c.spec3 = 1 +[builtins fixtures/bool.pyi] + [case testClassLevelImport] # flags: --ignore-missing-imports class Test: @@ -6181,7 +6463,7 @@ class C(B): [out] main:4: error: Incompatible types in assignment (expression has type "str", base class "B" defined the type as "int") -[case testIgnorePrivateMethodsTypeCheck] +[case testIgnorePrivateMethodsTypeCheck2] class A: def __foo_(self) -> int: ... class B: @@ -6349,6 +6631,37 @@ class B(A): reveal_type(B()) # N: Revealed type is "__main__.B" +[case testNewReturnType10] +# https://github.com/python/mypy/issues/11398 +from typing import Type + +class MyMetaClass(type): + def __new__(cls, name, bases, attrs) -> Type['MyClass']: + pass + +class MyClass(metaclass=MyMetaClass): + pass + +[case testNewReturnType11] +# https://github.com/python/mypy/issues/11398 +class MyMetaClass(type): + def __new__(cls, name, bases, attrs) -> type: + pass + +class MyClass(metaclass=MyMetaClass): + pass + +[case testNewReturnType12] +# https://github.com/python/mypy/issues/11398 +from typing import Type + +class MyMetaClass(type): + def __new__(cls, name, bases, attrs) -> int: # E: Incompatible return type for "__new__" (returns "int", but must return a subtype of "type") + pass + +class MyClass(metaclass=MyMetaClass): + pass + [case testGenericOverride] from typing import Generic, TypeVar, Any diff --git a/test-data/unit/check-classvar.test b/test-data/unit/check-classvar.test index f572db7225f2..d84bc8d5bf9d 100644 --- a/test-data/unit/check-classvar.test +++ b/test-data/unit/check-classvar.test @@ -285,7 +285,7 @@ main:3: error: Cannot assign to class variable "x" via instance from typing import ClassVar, Generic, TypeVar T = TypeVar('T') class A(Generic[T]): - x: ClassVar[T] + x: ClassVar[T] # E: ClassVar cannot contain type variables @classmethod def foo(cls) -> T: return cls.x # OK @@ -308,7 +308,7 @@ from typing import ClassVar, Generic, Tuple, TypeVar, Union, Type T = TypeVar('T') U = TypeVar('U') class A(Generic[T, U]): - x: ClassVar[Union[T, Tuple[U, Type[U]]]] + x: ClassVar[Union[T, Tuple[U, Type[U]]]] # E: ClassVar cannot contain type variables @classmethod def foo(cls) -> Union[T, Tuple[U, Type[U]]]: return cls.x # OK diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 1334f73f9f63..3220119748e3 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -135,7 +135,7 @@ def foobar(): pass [builtins fixtures/module.pyi] [case testColumnUnexpectedOrMissingKeywordArg] -def f(): pass +def f(): pass # N:1: "f" defined here # TODO: Point to "x" instead (f(x=1)) # E:2: Unexpected keyword argument "x" for "f" def g(*, x: int) -> None: pass @@ -268,7 +268,11 @@ class B(A): class C(A): def f(self, x: int) -> int: pass # E:5: Return type "int" of "f" incompatible with return type "None" in supertype "A" class D(A): - def f(self) -> None: pass # E:5: Signature of "f" incompatible with supertype "A" + def f(self) -> None: pass # E:5: Signature of "f" incompatible with supertype "A" \ + # N:5: Superclass: \ + # N:5: def f(self, x: int) -> None \ + # N:5: Subclass: \ + # N:5: def f(self) -> None [case testColumnMissingTypeParameters] # flags: --disallow-any-generics @@ -398,7 +402,7 @@ from typing import TypeVar, List T = TypeVar('T', int, str) -def g(x): pass +def g(x): pass # N:1: "g" defined here def f(x: T) -> T: (x.bad) # E:6: "int" has no attribute "bad" \ diff --git a/test-data/unit/check-ctypes.test b/test-data/unit/check-ctypes.test index 0a0789ccab1b..e309060166b3 100644 --- a/test-data/unit/check-ctypes.test +++ b/test-data/unit/check-ctypes.test @@ -182,6 +182,6 @@ import ctypes intarr4 = ctypes.c_int * 4 x = {"a": 1, "b": 2} -intarr4(**x) # E: Too many arguments for "Array" +intarr4(**x) [builtins fixtures/floatdict.pyi] diff --git a/test-data/unit/check-custom-plugin.test b/test-data/unit/check-custom-plugin.test index 580eb6fe607a..2707d886d64e 100644 --- a/test-data/unit/check-custom-plugin.test +++ b/test-data/unit/check-custom-plugin.test @@ -213,6 +213,74 @@ class DerivedSignal(Signal[T]): ... \[mypy] plugins=/test-data/unit/plugins/attrhook.py +[case testAttributeTypeHookPluginUntypedDecoratedGetattr] +# flags: --config-file tmp/mypy.ini +from m import Magic, DerivedMagic + +magic = Magic() +reveal_type(magic.magic_field) # N: Revealed type is "builtins.str" +reveal_type(magic.non_magic_method()) # N: Revealed type is "builtins.int" +reveal_type(magic.non_magic_field) # N: Revealed type is "builtins.int" +magic.nonexistent_field # E: Field does not exist +reveal_type(magic.fallback_example) # N: Revealed type is "Any" + +derived = DerivedMagic() +reveal_type(derived.magic_field) # N: Revealed type is "builtins.str" +derived.nonexistent_field # E: Field does not exist +reveal_type(derived.fallback_example) # N: Revealed type is "Any" + +[file m.py] +from typing import Any, Callable + +def decorator(f): + pass + +class Magic: + # Triggers plugin infrastructure: + @decorator + def __getattr__(self, x: Any) -> Any: ... + def non_magic_method(self) -> int: ... + non_magic_field: int + +class DerivedMagic(Magic): ... +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/attrhook2.py + +[case testAttributeTypeHookPluginDecoratedGetattr] +# flags: --config-file tmp/mypy.ini +from m import Magic, DerivedMagic + +magic = Magic() +reveal_type(magic.magic_field) # N: Revealed type is "builtins.str" +reveal_type(magic.non_magic_method()) # N: Revealed type is "builtins.int" +reveal_type(magic.non_magic_field) # N: Revealed type is "builtins.int" +magic.nonexistent_field # E: Field does not exist +reveal_type(magic.fallback_example) # N: Revealed type is "builtins.bool" + +derived = DerivedMagic() +reveal_type(derived.magic_field) # N: Revealed type is "builtins.str" +derived.nonexistent_field # E: Field does not exist +reveal_type(derived.fallback_example) # N: Revealed type is "builtins.bool" + +[file m.py] +from typing import Any, Callable + +def decorator(f: Callable) -> Callable[[Any, str], bool]: + pass + +class Magic: + # Triggers plugin infrastructure: + @decorator + def __getattr__(self, x: Any) -> Any: ... + def non_magic_method(self) -> int: ... + non_magic_field: int + +class DerivedMagic(Magic): ... +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/attrhook2.py + [case testAttributeHookPluginForDynamicClass] # flags: --config-file tmp/mypy.ini from m import Magic, DerivedMagic @@ -223,7 +291,12 @@ reveal_type(magic.non_magic_method()) # N: Revealed type is "builtins.int" reveal_type(magic.non_magic_field) # N: Revealed type is "builtins.int" magic.nonexistent_field # E: Field does not exist reveal_type(magic.fallback_example) # N: Revealed type is "Any" -reveal_type(DerivedMagic().magic_field) # N: Revealed type is "builtins.str" + +derived = DerivedMagic() +reveal_type(derived.magic_field) # N: Revealed type is "builtins.str" +derived.nonexistent_field # E: Field does not exist +reveal_type(magic.fallback_example) # N: Revealed type is "Any" + [file m.py] from typing import Any class Magic: @@ -543,26 +616,23 @@ class Instr(Generic[T]): ... \[mypy] plugins=/test-data/unit/plugins/dyn_class.py -[case testDynamicClassPluginNegatives] +[case testDynamicClassPluginChainCall] # flags: --config-file tmp/mypy.ini -from mod import declarative_base, Column, Instr, non_declarative_base +from mod import declarative_base, Column, Instr -Bad1 = non_declarative_base() -Bad2 = Bad3 = declarative_base() +Base = declarative_base().with_optional_xxx() -class C1(Bad1): ... # E: Variable "__main__.Bad1" is not valid as a type \ - # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases \ - # E: Invalid base class "Bad1" -class C2(Bad2): ... # E: Variable "__main__.Bad2" is not valid as a type \ - # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases \ - # E: Invalid base class "Bad2" -class C3(Bad3): ... # E: Variable "__main__.Bad3" is not valid as a type \ - # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases \ - # E: Invalid base class "Bad3" +class Model(Base): + x: Column[int] + +reveal_type(Model().x) # N: Revealed type is "mod.Instr[builtins.int]" [file mod.py] from typing import Generic, TypeVar -def declarative_base(): ... -def non_declarative_base(): ... + +class Base: + def with_optional_xxx(self) -> Base: ... + +def declarative_base() -> Base: ... T = TypeVar('T') @@ -573,6 +643,35 @@ class Instr(Generic[T]): ... \[mypy] plugins=/test-data/unit/plugins/dyn_class.py +[case testDynamicClassPluginChainedAssignment] +# flags: --config-file tmp/mypy.ini +from mod import declarative_base + +Base1 = Base2 = declarative_base() + +class C1(Base1): ... +class C2(Base2): ... +[file mod.py] +def declarative_base(): ... +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/dyn_class.py + +[case testDynamicClassPluginNegatives] +# flags: --config-file tmp/mypy.ini +from mod import non_declarative_base + +Bad1 = non_declarative_base() + +class C1(Bad1): ... # E: Variable "__main__.Bad1" is not valid as a type \ + # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases \ + # E: Invalid base class "Bad1" +[file mod.py] +def non_declarative_base(): ... +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/dyn_class.py + [case testDynamicClassHookFromClassMethod] # flags: --config-file tmp/mypy.ini @@ -783,3 +882,23 @@ reveal_type(dynamic_signature(1)) # N: Revealed type is "builtins.int" [file mypy.ini] \[mypy] plugins=/test-data/unit/plugins/function_sig_hook.py + +[case testPluginCalledCorrectlyWhenMethodInDecorator] +# flags: --config-file tmp/mypy.ini +from typing import TypeVar, Callable + +T = TypeVar('T') +class Foo: + def a(self, x: Callable[[], T]) -> Callable[[], T]: ... + +b = Foo() + +@b.a +def f() -> None: + pass + +reveal_type(f()) # N: Revealed type is "builtins.str" + +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/method_in_decorator.py diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index f3a9d607f0b0..73476a646c99 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -14,7 +14,7 @@ reveal_type(Person) # N: Revealed type is "def (name: builtins.str, age: builti Person('John', 32) Person('Jonh', 21, None) # E: Too many arguments for "Person" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [typing fixtures/typing-medium.pyi] [case testDataclassesCustomInit] @@ -30,7 +30,7 @@ class A: A('1') -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesBasicInheritance] # flags: --python-version 3.7 @@ -52,7 +52,7 @@ Mammal(10) Person(32, 'John') Person(21, 'Jonh', None) # E: Too many arguments for "Person" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [typing fixtures/typing-medium.pyi] [case testDataclassesDeepInheritance] @@ -80,7 +80,7 @@ reveal_type(B) # N: Revealed type is "def (a: builtins.int, b: builtins.int) -> reveal_type(C) # N: Revealed type is "def (a: builtins.int, b: builtins.int, c: builtins.int) -> __main__.C" reveal_type(D) # N: Revealed type is "def (a: builtins.int, b: builtins.int, c: builtins.int, d: builtins.int) -> __main__.D" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesMultipleInheritance] # flags: --python-version 3.7 @@ -103,7 +103,7 @@ class C(A, B): reveal_type(C) # N: Revealed type is "def (b: builtins.bool, a: builtins.bool) -> __main__.C" -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDeepInitVarInheritance] # flags: --python-version 3.7 @@ -132,7 +132,7 @@ class D(C): reveal_type(C) # N: Revealed type is "def () -> __main__.C" reveal_type(D) # N: Revealed type is "def (b: builtins.bool) -> __main__.D" -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesOverriding] # flags: --python-version 3.7 @@ -165,7 +165,7 @@ Person(21, 'John', None) # E: Too many arguments for "Person" SpecialPerson(21, 'John', 0.5) ExtraSpecialPerson(21, 'John', 0.5) -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesOverridingWithDefaults] # Issue #5681 https://github.com/python/mypy/issues/5681 @@ -185,7 +185,7 @@ class C(Base): reveal_type(C) # N: Revealed type is "def (some_int: builtins.int, some_str: builtins.str =) -> __main__.C" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesFreezing] # flags: --python-version 3.7 @@ -198,7 +198,7 @@ class Person: john = Person('John') john.name = 'Ben' # E: Property "name" defined in "Person" is read-only -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesFields] # flags: --python-version 3.7 @@ -214,7 +214,7 @@ john = Person('John') john.age = 'invalid' # E: Incompatible types in assignment (expression has type "str", variable has type "int") john.age = 24 -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesBadInit] # flags: --python-version 3.7 @@ -224,11 +224,12 @@ from dataclasses import dataclass, field class Person: name: str age: int = field(init=None) # E: No overload variant of "field" matches argument type "None" \ - # N: Possible overload variant: \ - # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ...) -> Any \ - # N: <2 more non-matching overloads not shown> + # N: Possible overload variants: \ + # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesMultiInit] # flags: --python-version 3.7 @@ -244,7 +245,7 @@ class Person: reveal_type(Person) # N: Revealed type is "def (name: builtins.str, friend_names: builtins.list[builtins.str], enemy_names: builtins.list[builtins.str]) -> __main__.Person" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesMultiInitDefaults] # flags: --python-version 3.7 @@ -261,7 +262,7 @@ class Person: reveal_type(Person) # N: Revealed type is "def (name: builtins.str, friend_names: builtins.list[builtins.str], enemy_names: builtins.list[builtins.str], nickname: Union[builtins.str, None] =) -> __main__.Person" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaults] # flags: --python-version 3.7 @@ -275,7 +276,7 @@ class Application: reveal_type(Application) # N: Revealed type is "def (name: builtins.str =, rating: builtins.int =) -> __main__.Application" app = Application() -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaultFactories] # flags: --python-version 3.7 @@ -287,7 +288,7 @@ class Application: rating: int = field(default_factory=int) rating_count: int = field() # E: Attributes without a default cannot follow attributes with one -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaultFactoryTypeChecking] # flags: --python-version 3.7 @@ -298,7 +299,7 @@ class Application: name: str = 'Unnamed' rating: int = field(default_factory=str) # E: Incompatible types in assignment (expression has type "str", variable has type "int") -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaultOrdering] # flags: --python-version 3.7 @@ -309,7 +310,141 @@ class Application: name: str = 'Unnamed' rating: int # E: Attributes without a default cannot follow attributes with one -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnly] +# flags: --python-version 3.10 +from dataclasses import dataclass + +@dataclass(kw_only=True) +class Application: + name: str = 'Unnamed' + rating: int + +Application(rating=5) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" +Application(name=123, rating='name') # E: Argument "name" to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" +Application(rating='name', name=123) # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" # E: Argument "name" to "Application" has incompatible type "int"; expected "str" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyOnField] +# flags: --python-version 3.10 +from dataclasses import dataclass, field + +@dataclass +class Application: + name: str = 'Unnamed' + rating: int = field(kw_only=True) + +Application(rating=5) +Application('name', rating=123) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application(123, rating='name') # E: Argument 1 to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyOnFieldFalse] +# flags: --python-version 3.10 +from dataclasses import dataclass, field + +@dataclass +class Application: + name: str = 'Unnamed' + rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one + +Application(name='name', rating=5) +Application('name', 123) +Application('name', rating=123) +Application() # E: Missing positional argument "name" in call to "Application" +Application('name') # E: Too few arguments for "Application" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyWithSentinel] +# flags: --python-version 3.10 +from dataclasses import dataclass, KW_ONLY + +@dataclass +class Application: + _: KW_ONLY + name: str = 'Unnamed' + rating: int + +Application(rating=5) +Application(name='name', rating=5) +Application() # E: Missing named argument "rating" for "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyWithSentinelAndFieldOverride] +# flags: --python-version 3.10 +from dataclasses import dataclass, field, KW_ONLY + +@dataclass +class Application: + _: KW_ONLY + name: str = 'Unnamed' + rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one + +Application(name='name', rating=5) +Application() # E: Missing positional argument "name" in call to "Application" +Application('name') # E: Too many positional arguments for "Application" # E: Too few arguments for "Application" +Application('name', 123) # E: Too many positional arguments for "Application" +Application('name', rating=123) # E: Too many positional arguments for "Application" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyWithSentinelAndSubclass] +# flags: --python-version 3.10 +from dataclasses import dataclass, field, KW_ONLY + +@dataclass +class Base: + x: str + _: KW_ONLY + y: int = 0 + w: int = 1 + +@dataclass +class D(Base): + z: str + a: str = "a" + +D("Hello", "World") +D(x="Hello", z="World") +D("Hello", "World", y=1, w=2, a="b") +D("Hello") # E: Missing positional argument "z" in call to "D" +D() # E: Missing positional arguments "x", "z" in call to "D" +D(123, "World") # E: Argument 1 to "D" has incompatible type "int"; expected "str" +D("Hello", False) # E: Argument 2 to "D" has incompatible type "bool"; expected "str" +D(123, False) # E: Argument 1 to "D" has incompatible type "int"; expected "str" # E: Argument 2 to "D" has incompatible type "bool"; expected "str" + +[builtins fixtures/dataclasses.pyi] + +[case testDataclassesOrderingKwOnlyWithMultipleSentinel] +# flags: --python-version 3.10 +from dataclasses import dataclass, field, KW_ONLY + +@dataclass +class Base: + x: str + _: KW_ONLY + y: int = 0 + __: KW_ONLY # E: There may not be more than one field with the KW_ONLY type + w: int = 1 + +[builtins fixtures/dataclasses.pyi] [case testDataclassesClassmethods] # flags: --python-version 3.7 @@ -325,8 +460,7 @@ class Application: app = Application.parse('') -[builtins fixtures/list.pyi] -[builtins fixtures/classmethod.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesOverloadsAndClassmethods] # flags: --python-version 3.7 @@ -359,7 +493,7 @@ class A: reveal_type(A.foo(3)) # N: Revealed type is "builtins.int" reveal_type(A.foo("foo")) # N: Revealed type is "builtins.str" -[builtins fixtures/classmethod.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesClassVars] # flags: --python-version 3.7 @@ -377,7 +511,7 @@ application = Application("example") application.COUNTER = 1 # E: Cannot assign to class variable "COUNTER" via instance Application.COUNTER = 1 -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassOrdering] # flags: --python-version 3.7 @@ -408,7 +542,7 @@ app1 > app3 app1 <= app3 app1 >= app3 -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassOrderingWithoutEquality] # flags: --python-version 3.7 @@ -418,7 +552,7 @@ from dataclasses import dataclass class Application: # E: eq must be True if order is True ... -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassOrderingWithCustomMethods] # flags: --python-version 3.7 @@ -429,7 +563,7 @@ class Application: def __lt__(self, other: 'Application') -> bool: # E: You may not have a custom __lt__ method when order=True ... -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassDefaultsInheritance] # flags: --python-version 3.7 @@ -447,7 +581,7 @@ class SpecializedApplication(Application): reveal_type(SpecializedApplication) # N: Revealed type is "def (id: Union[builtins.int, None], name: builtins.str, rating: builtins.int =) -> __main__.SpecializedApplication" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassGenerics] # flags: --python-version 3.7 @@ -480,7 +614,7 @@ reveal_type(a.y) # N: Revealed type is "builtins.int*" reveal_type(a.z) # N: Revealed type is "builtins.list[builtins.int*]" s: str = a.bar() # E: Incompatible types in assignment (expression has type "int", variable has type "str") -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassUntypedGenericInheritance] @@ -502,6 +636,7 @@ sub = Sub(attr=1) reveal_type(sub) # N: Revealed type is "__main__.Sub" reveal_type(sub.attr) # N: Revealed type is "Any" +[builtins fixtures/dataclasses.pyi] [case testDataclassGenericSubtype] # flags: --python-version 3.7 @@ -528,6 +663,7 @@ sub_str = Sub[str](attr='ok') reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str*]" reveal_type(sub_str.attr) # N: Revealed type is "builtins.str*" +[builtins fixtures/dataclasses.pyi] [case testDataclassGenericInheritance] # flags: --python-version 3.7 @@ -554,6 +690,7 @@ reveal_type(sub.one) # N: Revealed type is "builtins.int*" reveal_type(sub.two) # N: Revealed type is "builtins.str*" reveal_type(sub.three) # N: Revealed type is "builtins.float*" +[builtins fixtures/dataclasses.pyi] [case testDataclassMultiGenericInheritance] # flags: --python-version 3.7 @@ -581,6 +718,7 @@ reveal_type(sub) # N: Revealed type is "__main__.Sub" reveal_type(sub.base_attr) # N: Revealed type is "builtins.int*" reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str*" +[builtins fixtures/dataclasses.pyi] [case testDataclassGenericsClassmethod] # flags: --python-version 3.7 @@ -602,7 +740,7 @@ class A(Generic[T]): def other(cls, x: T) -> A[T]: ... reveal_type(A(0).other) # N: Revealed type is "def (x: builtins.int*) -> __main__.A[builtins.int*]" -[builtins fixtures/classmethod.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesForwardRefs] # flags: --python-version 3.7 @@ -620,7 +758,7 @@ reveal_type(A) # N: Revealed type is "def (b: __main__.B) -> __main__.A" A(b=B(42)) A(b=42) # E: Argument "b" to "A" has incompatible type "int"; expected "B" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInitVars] @@ -650,7 +788,7 @@ app.name app.rating app.database_name # E: "SpecializedApplication" has no attribute "database_name" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInitVarsAndDefer] # flags: --python-version 3.7 @@ -670,7 +808,7 @@ app.name app.database_name # E: "Application" has no attribute "database_name" class Yes: ... -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesNoInitInitVarInheritance] # flags: --python-version 3.7 @@ -687,7 +825,7 @@ class Sub(Super): sub = Sub(5) sub.foo # E: "Sub" has no attribute "foo" sub.bar -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassFactory] # flags: --python-version 3.7 @@ -703,7 +841,7 @@ class A: reveal_type(cls) # N: Revealed type is "Type[T`-1]" reveal_type(cls()) # N: Revealed type is "T`-1" return cls() -[builtins fixtures/classmethod.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInitVarOverride] # flags: --python-version 3.7 @@ -726,7 +864,7 @@ class B(A): super().__init__(b+1) self._b = b -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInitVarNoOverride] # flags: --python-version 3.7 @@ -752,7 +890,7 @@ class B(A): B(1, 2) B(1, 'a') # E: Argument 2 to "B" has incompatible type "str"; expected "int" -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInitVarPostInitOverride] # flags: --python-version 3.7 @@ -845,7 +983,7 @@ from typing import Optional @dataclass class Foo: bar: Optional[int] = field(default=None) -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] [case testNoComplainFieldNoneStrict] @@ -857,7 +995,7 @@ from typing import Optional @dataclass class Foo: bar: Optional[int] = field(default=None) -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] [case testDisallowUntypedWorksForward] @@ -873,7 +1011,7 @@ class C(List[C]): pass reveal_type(B) # N: Revealed type is "def (x: __main__.C) -> __main__.B" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDisallowUntypedWorksForwardBad] # flags: --disallow-untyped-defs --python-version 3.7 @@ -885,7 +1023,7 @@ class B: y = undefined() # E: Name "undefined" is not defined reveal_type(B) # N: Revealed type is "def (x: Any) -> __main__.B" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testMemberExprWorksAsField] # flags: --python-version 3.7 @@ -923,7 +1061,7 @@ b = Application('', 0) a < b class Yes: ... -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassFieldDeferred] # flags: --python-version 3.7 @@ -935,7 +1073,7 @@ class C: def func() -> int: ... C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int" -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassFieldDeferredFrozen] # flags: --python-version 3.7 @@ -948,7 +1086,7 @@ class C: def func() -> int: ... c: C c.x = 1 # E: Property "x" defined in "C" is read-only -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testTypeInDataclassDeferredStar] # flags: --python-version 3.7 @@ -967,7 +1105,7 @@ C() # E: Missing positional argument "total" in call to "C" C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int" [file other.py] import lib -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDeferredDataclassInitSignature] # flags: --python-version 3.7 --no-strict-optional @@ -984,7 +1122,7 @@ class C: return cls(x=None, y=None) class Deferred: pass -[builtins fixtures/classmethod.pyi] +[builtins fixtures/dataclasses.pyi] [case testDeferredDataclassInitSignatureSubclass] # flags: --strict-optional --python-version 3.7 @@ -1000,7 +1138,7 @@ class C(B): y: str a = C(None, 'abc') -[builtins fixtures/bool.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaultsIncremental] # flags: --python-version 3.7 @@ -1032,7 +1170,7 @@ class Person: b: int a: str = 'test' -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesDefaultsMroOtherFile] # flags: --python-version 3.7 @@ -1061,7 +1199,7 @@ class A1: class A2: b: str = 'test' -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassesInheritingDuplicateField] # flags: --python-version 3.7 @@ -1077,6 +1215,8 @@ class A: # E: Name "x" already defined (possibly by an import) class B(A): pass +[builtins fixtures/dataclasses.pyi] + [case testDataclassInheritanceNoAnnotation] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1092,6 +1232,8 @@ class B(A): reveal_type(B) # N: Revealed type is "def (foo: builtins.int) -> __main__.B" +[builtins fixtures/dataclasses.pyi] + [case testDataclassInheritanceNoAnnotation2] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1107,7 +1249,19 @@ class B(A): reveal_type(B) # N: Revealed type is "def (foo: builtins.int) -> __main__.B" -[builtins fixtures/property.pyi] +[builtins fixtures/dataclasses.pyi] + +[case testDataclassHasAttributeWithFields] +# flags: --python-version 3.7 +from dataclasses import dataclass + +@dataclass +class A: + pass + +reveal_type(A.__dataclass_fields__) # N: Revealed type is "builtins.dict[builtins.str, dataclasses.Field[Any]]" + +[builtins fixtures/dict.pyi] [case testDataclassCallableProperty] # flags: --python-version 3.7 @@ -1126,6 +1280,8 @@ a.foo(1) reveal_type(a.foo) # N: Revealed type is "def (builtins.int) -> builtins.int" reveal_type(A.foo) # N: Revealed type is "def (builtins.int) -> builtins.int" [typing fixtures/typing-medium.pyi] +[builtins fixtures/dataclasses.pyi] + [case testDataclassCallableAssignment] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1141,9 +1297,11 @@ def my_foo(x: int) -> int: a = A(foo=my_foo) def another_foo(x: int) -> int: - return x + 1 + return x a.foo = another_foo +[builtins fixtures/dataclasses.pyi] + [case testDataclassCallablePropertyWrongType] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1158,6 +1316,8 @@ def my_foo(x: int) -> str: a = A(foo=my_foo) # E: Argument "foo" to "A" has incompatible type "Callable[[int], str]"; expected "Callable[[int], int]" [typing fixtures/typing-medium.pyi] +[builtins fixtures/dataclasses.pyi] + [case testDataclassCallablePropertyWrongTypeAssignment] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1177,3 +1337,122 @@ def another_foo(x: int) -> str: a.foo = another_foo # E: Incompatible types in assignment (expression has type "Callable[[int], str]", variable has type "Callable[[int], int]") [typing fixtures/typing-medium.pyi] +[builtins fixtures/dataclasses.pyi] + +[case testDataclassFieldDoesNotFailOnKwargsUnpacking] +# flags: --python-version 3.7 +# https://github.com/python/mypy/issues/10879 +from dataclasses import dataclass, field + +@dataclass +class Foo: + bar: float = field(**{"repr": False}) +[out] +main:7: error: Unpacking **kwargs in "field()" is not supported +main:7: error: No overload variant of "field" matches argument type "Dict[str, bool]" +main:7: note: Possible overload variants: +main:7: note: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T +main:7: note: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T +main:7: note: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any +[builtins fixtures/dataclasses.pyi] + +[case testDataclassFieldWithPositionalArguments] +# flags: --python-version 3.7 +from dataclasses import dataclass, field + +@dataclass +class C: + x: int = field(0) # E: "field()" does not accept positional arguments \ + # E: No overload variant of "field" matches argument type "int" \ + # N: Possible overload variants: \ + # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any +[builtins fixtures/dataclasses.pyi] + +[case testDataclassFieldWithTypedDictUnpacking] +# flags: --python-version 3.7 +from dataclasses import dataclass, field +from typing_extensions import TypedDict + +class FieldKwargs(TypedDict): + repr: bool + +field_kwargs: FieldKwargs = {"repr": False} + +@dataclass +class Foo: + bar: float = field(**field_kwargs) # E: Unpacking **kwargs in "field()" is not supported + +reveal_type(Foo(bar=1.5)) # N: Revealed type is "__main__.Foo" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithSlotsArg] +# flags: --python-version 3.10 +from dataclasses import dataclass + +@dataclass(slots=True) +class Some: + x: int + + def __init__(self, x: int) -> None: + self.x = x + self.y = 0 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" + + def __post_init__(self) -> None: + self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithSlotsDef] +# flags: --python-version 3.10 +from dataclasses import dataclass + +@dataclass(slots=False) +class Some: + __slots__ = ('x',) + x: int + + def __init__(self, x: int) -> None: + self.x = x + self.y = 0 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" + + def __post_init__(self) -> None: + self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithSlotsConflict] +# flags: --python-version 3.10 +from dataclasses import dataclass + +@dataclass(slots=True) +class Some: # E: "Some" both defines "__slots__" and is used with "slots=True" + __slots__ = ('x',) + x: int + +@dataclass(slots=True) +class EmptyDef: # E: "EmptyDef" both defines "__slots__" and is used with "slots=True" + __slots__ = () + x: int + +slots = ('x',) + +@dataclass(slots=True) +class DynamicDef: # E: "DynamicDef" both defines "__slots__" and is used with "slots=True" + __slots__ = slots + x: int +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithSlotsArgBefore310] +# flags: --python-version 3.9 +from dataclasses import dataclass + +@dataclass(slots=True) # E: Keyword argument "slots" for "dataclass" is only valid in Python 3.10 and higher +class Some: + x: int + +# Possible conflict: +@dataclass(slots=True) # E: Keyword argument "slots" for "dataclass" is only valid in Python 3.10 and higher +class Other: + __slots__ = ('x',) + x: int +[builtins fixtures/dataclasses.pyi] diff --git a/test-data/unit/check-default-plugin.test b/test-data/unit/check-default-plugin.test index 7493763d3e72..fc9f132abb62 100644 --- a/test-data/unit/check-default-plugin.test +++ b/test-data/unit/check-default-plugin.test @@ -24,6 +24,65 @@ f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, [typing fixtures/typing-medium.pyi] [builtins fixtures/tuple.pyi] +[case testContextManagerWithGenericFunctionAndSendType] +from contextlib import contextmanager +from typing import TypeVar, Generator + +T = TypeVar('T') +S = TypeVar('S') + +@contextmanager +def yield_id(item: T) -> Generator[T, S, None]: + yield item + +reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> contextlib.GeneratorContextManager[T`-1]" + +with yield_id(1) as x: + reveal_type(x) # N: Revealed type is "builtins.int*" + +f = yield_id +def g(x, y): pass +f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, Any], Any]", variable has type "Callable[[T], GeneratorContextManager[T]]") +[typing fixtures/typing-medium.pyi] +[builtins fixtures/tuple.pyi] + +[case testAsyncContextManagerWithGenericFunction] +# flags: --python-version 3.7 +from contextlib import asynccontextmanager +from typing import TypeVar, AsyncIterator + +T = TypeVar('T') + +@asynccontextmanager +async def yield_id(item: T) -> AsyncIterator[T]: + yield item + +reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" + +async with yield_id(1) as x: + reveal_type(x) # N: Revealed type is "builtins.int*" +[typing fixtures/typing-async.pyi] +[builtins fixtures/tuple.pyi] + +[case testAsyncContextManagerWithGenericFunctionAndSendType] +# flags: --python-version 3.7 +from contextlib import asynccontextmanager +from typing import TypeVar, AsyncGenerator + +T = TypeVar('T') +S = TypeVar('S') + +@asynccontextmanager +async def yield_id(item: T) -> AsyncGenerator[T, S]: + yield item + +reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" + +async with yield_id(1) as x: + reveal_type(x) # N: Revealed type is "builtins.int*" +[typing fixtures/typing-async.pyi] +[builtins fixtures/tuple.pyi] + [case testContextManagerWithUnspecifiedArguments] from contextlib import contextmanager from typing import Callable, Iterator diff --git a/test-data/unit/check-dynamic-typing.test b/test-data/unit/check-dynamic-typing.test index 87bb134cb33c..7b016c342e95 100644 --- a/test-data/unit/check-dynamic-typing.test +++ b/test-data/unit/check-dynamic-typing.test @@ -159,9 +159,9 @@ a or d if int(): c = a in d # E: Incompatible types in assignment (expression has type "bool", variable has type "C") if int(): - c = b and d # E: Incompatible types in assignment (expression has type "Union[bool, Any]", variable has type "C") + c = b and d # E: Incompatible types in assignment (expression has type "Union[Literal[False], Any]", variable has type "C") if int(): - c = b or d # E: Incompatible types in assignment (expression has type "Union[bool, Any]", variable has type "C") + c = b or d # E: Incompatible types in assignment (expression has type "Union[Literal[True], Any]", variable has type "C") if int(): b = a + d if int(): @@ -725,18 +725,28 @@ import typing class B: def f(self, x, y): pass class A(B): - def f(self, x: 'A') -> None: # E: Signature of "f" incompatible with supertype "B" + def f(self, x: 'A') -> None: # Fail pass [out] +main:5: error: Signature of "f" incompatible with supertype "B" +main:5: note: Superclass: +main:5: note: def f(self, x: Any, y: Any) -> Any +main:5: note: Subclass: +main:5: note: def f(self, x: A) -> None [case testInvalidOverrideArgumentCountWithImplicitSignature3] import typing class B: def f(self, x: A) -> None: pass class A(B): - def f(self, x, y) -> None: # E: Signature of "f" incompatible with supertype "B" + def f(self, x, y) -> None: # Fail x() [out] +main:5: error: Signature of "f" incompatible with supertype "B" +main:5: note: Superclass: +main:5: note: def f(self, x: A) -> None +main:5: note: Subclass: +main:5: note: def f(self, x: Any, y: Any) -> None [case testInvalidOverrideWithImplicitSignatureAndClassMethod1] class B: diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 5200c00d3f28..a393df079730 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -56,7 +56,7 @@ class Truth(Enum): x = '' x = Truth.true.name reveal_type(Truth.true.name) # N: Revealed type is "Literal['true']?" -reveal_type(Truth.false.value) # N: Revealed type is "builtins.bool" +reveal_type(Truth.false.value) # N: Revealed type is "Literal[False]?" [builtins fixtures/bool.pyi] [case testEnumValueExtended] @@ -66,7 +66,7 @@ class Truth(Enum): false = False def infer_truth(truth: Truth) -> None: - reveal_type(truth.value) # N: Revealed type is "builtins.bool" + reveal_type(truth.value) # N: Revealed type is "Union[Literal[True]?, Literal[False]?]" [builtins fixtures/bool.pyi] [case testEnumValueAllAuto] @@ -90,7 +90,7 @@ def infer_truth(truth: Truth) -> None: [builtins fixtures/primitives.pyi] [case testEnumValueExtraMethods] -from enum import Enum, auto +from enum import Enum class Truth(Enum): true = True false = False @@ -99,7 +99,7 @@ class Truth(Enum): return 'bar' def infer_truth(truth: Truth) -> None: - reveal_type(truth.value) # N: Revealed type is "builtins.bool" + reveal_type(truth.value) # N: Revealed type is "Union[Literal[True]?, Literal[False]?]" [builtins fixtures/bool.pyi] [case testEnumValueCustomAuto] @@ -129,6 +129,20 @@ def cannot_infer_truth(truth: Truth) -> None: reveal_type(truth.value) # N: Revealed type is "Any" [builtins fixtures/bool.pyi] +[case testEnumValueSameType] +from enum import Enum + +def newbool() -> bool: + ... + +class Truth(Enum): + true = newbool() + false = newbool() + +def infer_truth(truth: Truth) -> None: + reveal_type(truth.value) # N: Revealed type is "builtins.bool" +[builtins fixtures/bool.pyi] + [case testEnumUnique] import enum @enum.unique @@ -1360,3 +1374,375 @@ class E(IntEnum): A = N(0) reveal_type(E.A.value) # N: Revealed type is "__main__.N" + + +[case testEnumFinalValues] +from enum import Enum +class Medal(Enum): + gold = 1 + silver = 2 + +# Another value: +Medal.gold = 0 # E: Cannot assign to final attribute "gold" +# Same value: +Medal.silver = 2 # E: Cannot assign to final attribute "silver" + + +[case testEnumFinalValuesCannotRedefineValueProp] +from enum import Enum +class Types(Enum): + key = 0 + value = 1 + + +[case testEnumReusedKeys] +# https://github.com/python/mypy/issues/11248 +from enum import Enum +class Correct(Enum): + x = 'y' + y = 'x' +class Foo(Enum): + A = 1 + A = 'a' # E: Attempted to reuse member name "A" in Enum definition "Foo" \ + # E: Incompatible types in assignment (expression has type "str", variable has type "int") +reveal_type(Foo.A.value) # N: Revealed type is "builtins.int" + +class Bar(Enum): + A = 1 + B = A = 2 # E: Attempted to reuse member name "A" in Enum definition "Bar" +class Baz(Enum): + A = 1 + B, A = (1, 2) # E: Attempted to reuse member name "A" in Enum definition "Baz" +[builtins fixtures/tuple.pyi] + +[case testEnumReusedKeysOverlapWithLocalVar] +from enum import Enum +x = 1 +class Foo(Enum): + x = 2 + def method(self) -> None: + x = 3 +x = 4 +[builtins fixtures/bool.pyi] + +[case testEnumImplicitlyFinalForSubclassing] +from enum import Enum, IntEnum, Flag, IntFlag + +class NonEmptyEnum(Enum): + x = 1 +class NonEmptyIntEnum(IntEnum): + x = 1 +class NonEmptyFlag(Flag): + x = 1 +class NonEmptyIntFlag(IntFlag): + x = 1 + +class ErrorEnumWithValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyEnum") +class ErrorIntEnumWithValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntEnum") +class ErrorFlagWithValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyFlag") +class ErrorIntFlagWithValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntFlag") + +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" + pass +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" + pass +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" + pass +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" + pass +[builtins fixtures/bool.pyi] + +[case testSubclassingNonFinalEnums] +from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta + +def decorator(func): + return func + +class EmptyEnum(Enum): + pass +class EmptyIntEnum(IntEnum): + pass +class EmptyFlag(Flag): + pass +class EmptyIntFlag(IntFlag): + pass +class EmptyEnumMeta(EnumMeta): + pass + +class NonEmptyEnumSub(EmptyEnum): + x = 1 +class NonEmptyIntEnumSub(EmptyIntEnum): + x = 1 +class NonEmptyFlagSub(EmptyFlag): + x = 1 +class NonEmptyIntFlagSub(EmptyIntFlag): + x = 1 +class NonEmptyEnumMetaSub(EmptyEnumMeta): + x = 1 + +class EmptyEnumSub(EmptyEnum): + def method(self) -> None: pass + @decorator + def other(self) -> None: pass +class EmptyIntEnumSub(EmptyIntEnum): + def method(self) -> None: pass +class EmptyFlagSub(EmptyFlag): + def method(self) -> None: pass +class EmptyIntFlagSub(EmptyIntFlag): + def method(self) -> None: pass +class EmptyEnumMetaSub(EmptyEnumMeta): + def method(self) -> None: pass + +class NestedEmptyEnumSub(EmptyEnumSub): + x = 1 +class NestedEmptyIntEnumSub(EmptyIntEnumSub): + x = 1 +class NestedEmptyFlagSub(EmptyFlagSub): + x = 1 +class NestedEmptyIntFlagSub(EmptyIntFlagSub): + x = 1 +class NestedEmptyEnumMetaSub(EmptyEnumMetaSub): + x = 1 +[builtins fixtures/bool.pyi] + +[case testEnumExplicitlyAndImplicitlyFinal] +from typing import final +from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta + +@final +class EmptyEnum(Enum): + pass +@final +class EmptyIntEnum(IntEnum): + pass +@final +class EmptyFlag(Flag): + pass +@final +class EmptyIntFlag(IntFlag): + pass +@final +class EmptyEnumMeta(EnumMeta): + pass + +class EmptyEnumSub(EmptyEnum): # E: Cannot inherit from final class "EmptyEnum" + pass +class EmptyIntEnumSub(EmptyIntEnum): # E: Cannot inherit from final class "EmptyIntEnum" + pass +class EmptyFlagSub(EmptyFlag): # E: Cannot inherit from final class "EmptyFlag" + pass +class EmptyIntFlagSub(EmptyIntFlag): # E: Cannot inherit from final class "EmptyIntFlag" + pass +class EmptyEnumMetaSub(EmptyEnumMeta): # E: Cannot inherit from final class "EmptyEnumMeta" + pass + +@final +class NonEmptyEnum(Enum): + x = 1 +@final +class NonEmptyIntEnum(IntEnum): + x = 1 +@final +class NonEmptyFlag(Flag): + x = 1 +@final +class NonEmptyIntFlag(IntFlag): + x = 1 +@final +class NonEmptyEnumMeta(EnumMeta): + x = 1 + +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" + pass +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" + pass +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" + pass +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" + pass +class ErrorEnumMetaWithoutValue(NonEmptyEnumMeta): # E: Cannot inherit from final class "NonEmptyEnumMeta" + pass +[builtins fixtures/bool.pyi] + +[case testEnumFinalSubtypingEnumMetaSpecialCase] +from enum import EnumMeta +# `EnumMeta` types are not `Enum`s +class SubMeta(EnumMeta): + x = 1 +class SubSubMeta(SubMeta): + x = 2 +[builtins fixtures/bool.pyi] + +[case testEnumFinalSubtypingOverloadedSpecialCase] +from typing import overload +from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta + +class EmptyEnum(Enum): + @overload + def method(self, arg: int) -> int: + pass + @overload + def method(self, arg: str) -> str: + pass + def method(self, arg): + pass +class EmptyIntEnum(IntEnum): + @overload + def method(self, arg: int) -> int: + pass + @overload + def method(self, arg: str) -> str: + pass + def method(self, arg): + pass +class EmptyFlag(Flag): + @overload + def method(self, arg: int) -> int: + pass + @overload + def method(self, arg: str) -> str: + pass + def method(self, arg): + pass +class EmptyIntFlag(IntFlag): + @overload + def method(self, arg: int) -> int: + pass + @overload + def method(self, arg: str) -> str: + pass + def method(self, arg): + pass +class EmptyEnumMeta(EnumMeta): + @overload + def method(self, arg: int) -> int: + pass + @overload + def method(self, arg: str) -> str: + pass + def method(self, arg): + pass + +class NonEmptyEnumSub(EmptyEnum): + x = 1 +class NonEmptyIntEnumSub(EmptyIntEnum): + x = 1 +class NonEmptyFlagSub(EmptyFlag): + x = 1 +class NonEmptyIntFlagSub(EmptyIntFlag): + x = 1 +class NonEmptyEnumMetaSub(EmptyEnumMeta): + x = 1 +[builtins fixtures/bool.pyi] + +[case testEnumFinalSubtypingMethodAndValueSpecialCase] +from enum import Enum, IntEnum, Flag, IntFlag, EnumMeta + +def decorator(func): + return func + +class NonEmptyEnum(Enum): + x = 1 + def method(self) -> None: pass + @decorator + def other(self) -> None: pass +class NonEmptyIntEnum(IntEnum): + x = 1 + def method(self) -> None: pass +class NonEmptyFlag(Flag): + x = 1 + def method(self) -> None: pass +class NonEmptyIntFlag(IntFlag): + x = 1 + def method(self) -> None: pass + +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" + pass +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" + pass +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" + pass +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" + pass +[builtins fixtures/bool.pyi] + +[case testFinalEnumWithClassDef] +from enum import Enum + +class A(Enum): + class Inner: pass +class B(A): pass # E: Cannot inherit from final class "A" +[builtins fixtures/bool.pyi] + +[case testEnumFinalSpecialProps] +# https://github.com/python/mypy/issues/11699 +from enum import Enum, IntEnum + +class E(Enum): + name = 'a' + value = 'b' + _name_ = 'a1' + _value_ = 'b2' + _order_ = 'X Y' + __order__ = 'X Y' + +class EI(IntEnum): + name = 'a' + value = 1 + _name_ = 'a1' + _value_ = 2 + _order_ = 'X Y' + __order__ = 'X Y' + +E._order_ = 'a' # E: Cannot assign to final attribute "_order_" +EI.value = 2 # E: Cannot assign to final attribute "value" +[builtins fixtures/bool.pyi] + +[case testEnumNotFinalWithMethodsAndUninitializedValues] +# https://github.com/python/mypy/issues/11578 +from enum import Enum +from typing import Final + +class A(Enum): + x: int + def method(self) -> int: pass +class B(A): + x = 1 # E: Cannot override writable attribute "x" with a final one + +class A1(Enum): + x: int = 1 +class B1(A1): # E: Cannot inherit from final class "A1" + pass + +class A2(Enum): + x = 2 +class B2(A2): # E: Cannot inherit from final class "A2" + pass + +# We leave this `Final` without a value, +# because we need to test annotation only mode: +class A3(Enum): + x: Final[int] # type: ignore +class B3(A3): + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "A3") +[builtins fixtures/bool.pyi] + +[case testEnumNotFinalWithMethodsAndUninitializedValuesStub] +import lib + +[file lib.pyi] +from enum import Enum +class A(Enum): + x: int +class B(A): # E: Cannot inherit from final class "A" + x = 1 # E: Cannot override writable attribute "x" with a final one + +class C(Enum): + x = 1 +class D(C): # E: Cannot inherit from final class "C" + x: int # E: Cannot assign to final name "x" +[builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 7479b15b7bc4..2f84ee1f4c6e 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -34,7 +34,7 @@ reveal_type(1) # N: Revealed type is "Literal[1]?" 1 '' [out] main:1: error: invalid syntax [syntax] -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? [syntax] [case testErrorCodeSyntaxError2] @@ -111,6 +111,30 @@ a = 'x'.foobar(b) # type: ignore[xyz, w, attr-defined] # E: Name "b" is not de a = 'x'.foobar(b) # type: int # type: ignore[name-defined, attr-defined] b = 'x'.foobar(b) # type: int # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] +[case testErrorCodeWarnUnusedIgnores1] +# flags: --warn-unused-ignores +x # type: ignore[name-defined, attr-defined] # E: Unused "type: ignore[attr-defined]" comment + +[case testErrorCodeWarnUnusedIgnores2] +# flags: --warn-unused-ignores +"x".foobar(y) # type: ignore[name-defined, attr-defined] + +[case testErrorCodeWarnUnusedIgnores3] +# flags: --warn-unused-ignores +"x".foobar(y) # type: ignore[name-defined, attr-defined, xyz] # E: Unused "type: ignore[xyz]" comment + +[case testErrorCodeWarnUnusedIgnores4] +# flags: --warn-unused-ignores +"x".foobar(y) # type: ignore[name-defined, attr-defined, valid-type] # E: Unused "type: ignore[valid-type]" comment + +[case testErrorCodeWarnUnusedIgnores5] +# flags: --warn-unused-ignores +"x".foobar(y) # type: ignore[name-defined, attr-defined, valid-type, xyz] # E: Unused "type: ignore[valid-type, xyz]" comment + +[case testErrorCodeWarnUnusedIgnores6_NoDetailWhenSingleErrorCode] +# flags: --warn-unused-ignores +"x" # type: ignore[name-defined] # E: Unused "type: ignore" comment + [case testErrorCodeIgnoreWithExtraSpace] x # type: ignore [name-defined] x2 # type: ignore [ name-defined ] @@ -277,7 +301,11 @@ class B(A): def f(self) -> str: # E: Return type "str" of "f" incompatible with return type "int" in supertype "A" [override] return '' class C(A): - def f(self, x: int) -> int: # E: Signature of "f" incompatible with supertype "A" [override] + def f(self, x: int) -> int: # E: Signature of "f" incompatible with supertype "A" [override] \ + # N: Superclass: \ + # N: def f(self) -> int \ + # N: Subclass: \ + # N: def f(self, x: int) -> int return 0 class D: def f(self, x: int) -> int: @@ -412,7 +440,7 @@ class D(Generic[S]): pass class E(Generic[S, T]): pass x: C[object] # E: Value of type variable "T" of "C" cannot be "object" [type-var] -y: D[int] # E: Type argument "builtins.int" of "D" must be a subtype of "builtins.str" [type-var] +y: D[int] # E: Type argument "int" of "D" must be a subtype of "str" [type-var] z: D[int, int] # E: "D" expects 1 type argument, but 2 given [type-arg] def h(a: TT, s: S) -> None: @@ -468,6 +496,17 @@ a['y'] # E: TypedDict "D" has no key "y" [typeddict-item] [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] +[case testErrorCodeTypedDictNoteIgnore] +from typing_extensions import TypedDict +class A(TypedDict): + one_commonpart: int + two_commonparts: int + +a: A = {'one_commonpart': 1, 'two_commonparts': 2} +a['other_commonpart'] = 3 # type: ignore[typeddict-item] +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + [case testErrorCodeCannotDetermineType] y = x # E: Cannot determine type of "x" [has-type] reveal_type(y) # N: Revealed type is "Any" @@ -626,8 +665,8 @@ def g() -> int: '%d' % 'no' # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") [str-format] '%d + %d' % (1, 2, 3) # E: Not all arguments converted during string formatting [str-format] -'{}'.format(b'abc') # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior [str-bytes-safe] -'%s' % b'abc' # E: On Python 3 '%s' % b'abc' produces "b'abc'", not 'abc'; use '%r' % b'abc' if this is desired behavior [str-bytes-safe] +'{}'.format(b'abc') # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior [str-bytes-safe] +'%s' % b'abc' # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior [str-bytes-safe] [builtins fixtures/primitives.pyi] [typing fixtures/typing-medium.pyi] @@ -807,3 +846,90 @@ from typing_extensions import TypedDict Foo = TypedDict("Bar", {}) # E: First argument "Bar" to TypedDict() does not match variable name "Foo" [name-match] [builtins fixtures/dict.pyi] +[case testTruthyBool] +# flags: --enable-error-code truthy-bool +from typing import List, Union + +class Foo: + pass + +foo = Foo() +if foo: # E: "__main__.foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] + pass + +zero = 0 +if zero: + pass + +false = False +if false: + pass + +null = None +if null: + pass + +s = '' +if s: + pass + +good_union: Union[str, int] = 5 +if good_union: + pass +if not good_union: + pass + +bad_union: Union[Foo, object] = Foo() +if bad_union: # E: "__main__.bad_union" has type "Union[Foo, object]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] + pass +if not bad_union: # E: "__main__.bad_union" has type "object" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] + pass + +def f(): + pass +if f: # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] + pass +if not f: # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] + pass +conditional_result = 'foo' if f else 'bar' # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] + +lst: List[int] = [] +if lst: + pass +[builtins fixtures/list.pyi] + +[case testSliceInDict39] +# flags: --python-version 3.9 --show-column-numbers +from typing import Dict +b: Dict[int, x:y] +c: Dict[x:y] + +[builtins fixtures/dict.pyi] +[out] +main:3:14: error: Invalid type comment or annotation [valid-type] +main:3:14: note: did you mean to use ',' instead of ':' ? +main:4:4: error: "dict" expects 2 type arguments, but 1 given [type-arg] +main:4:9: error: Invalid type comment or annotation [valid-type] +main:4:9: note: did you mean to use ',' instead of ':' ? + +[case testSliceInDict38] +# flags: --python-version 3.8 --show-column-numbers +from typing import Dict +b: Dict[int, x:y] +c: Dict[x:y] + +[builtins fixtures/dict.pyi] +[out] +main:3:14: error: Invalid type comment or annotation [valid-type] +main:3:14: note: did you mean to use ',' instead of ':' ? +main:4:4: error: "dict" expects 2 type arguments, but 1 given [type-arg] +main:4:9: error: Invalid type comment or annotation [valid-type] +main:4:9: note: did you mean to use ',' instead of ':' ? + + +[case testSliceInCustomTensorType] +# syntactically mimics torchtyping.TensorType +class TensorType: ... +t: TensorType["batch":..., float] # type: ignore +reveal_type(t) # N: Revealed type is "__main__.TensorType" +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 7ee4ad4817a9..a275de94c9be 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -63,13 +63,7 @@ if str(): a = 1.1 class A: pass -[file builtins.py] -class object: - def __init__(self): pass -class type: pass -class function: pass -class float: pass -class str: pass +[builtins fixtures/dict.pyi] [case testComplexLiteral] a = 0.0j @@ -80,13 +74,7 @@ if str(): a = 1.1j class A: pass -[file builtins.py] -class object: - def __init__(self): pass -class type: pass -class function: pass -class complex: pass -class str: pass +[builtins fixtures/dict.pyi] [case testBytesLiteral] b, a = None, None # type: (bytes, A) @@ -99,14 +87,7 @@ if str(): if str(): a = b'foo' # E: Incompatible types in assignment (expression has type "bytes", variable has type "A") class A: pass -[file builtins.py] -class object: - def __init__(self): pass -class type: pass -class tuple: pass -class function: pass -class bytes: pass -class str: pass +[builtins fixtures/dict.pyi] [case testUnicodeLiteralInPython3] s = None # type: str @@ -316,11 +297,11 @@ if int(): if int(): b = b or b if int(): - b = b and a # E: Incompatible types in assignment (expression has type "Union[bool, A]", variable has type "bool") + b = b and a # E: Incompatible types in assignment (expression has type "Union[Literal[False], A]", variable has type "bool") if int(): b = a and b # E: Incompatible types in assignment (expression has type "Union[A, bool]", variable has type "bool") if int(): - b = b or a # E: Incompatible types in assignment (expression has type "Union[bool, A]", variable has type "bool") + b = b or a # E: Incompatible types in assignment (expression has type "Union[Literal[True], A]", variable has type "bool") if int(): b = a or b # E: Incompatible types in assignment (expression has type "Union[A, bool]", variable has type "bool") class A: pass @@ -434,18 +415,18 @@ class D(Iterable[A]): [builtins fixtures/bool.pyi] [case testNonBooleanContainsReturnValue] -a, b, c = None, None, None # type: (A, bool, int) +a, b, c = None, None, None # type: (A, bool, str) if int(): b = a not in a if int(): b = a in a if int(): - c = a not in a # E: Incompatible types in assignment (expression has type "bool", variable has type "int") + c = a not in a # E: Incompatible types in assignment (expression has type "bool", variable has type "str") if int(): - c = a in a # E: Incompatible types in assignment (expression has type "bool", variable has type "int") + c = a in a # E: Incompatible types in assignment (expression has type "bool", variable has type "str") class A: - def __contains__(self, x: 'A') -> int: pass + def __contains__(self, x: 'A') -> str: pass [builtins fixtures/bool.pyi] [case testInWithInvalidArgs] @@ -1077,6 +1058,7 @@ class A: pass [builtins fixtures/bool.pyi] + -- Slicing -- ------- @@ -1151,583 +1133,6 @@ a[:None] [builtins fixtures/slice.pyi] --- String interpolation --- -------------------- - - -[case testStringInterpolationType] -from typing import Tuple -i, f, s, t = None, None, None, None # type: (int, float, str, Tuple[int]) -'%d' % i -'%f' % f -'%s' % s -'%d' % (f,) -'%d' % (s,) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") -'%d' % t -'%d' % s # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") -'%f' % s # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") -'%x' % f # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") -'%i' % f -'%o' % f # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationSAcceptsAnyType] -from typing import Any -i, o, s = None, None, None # type: (int, object, str) -'%s %s %s' % (i, o, s) -[builtins fixtures/primitives.pyi] - -[case testStringInterpolationSBytesVsStrErrorPy3] -xb: bytes -xs: str - -'%s' % xs # OK -'%s' % xb # E: On Python 3 '%s' % b'abc' produces "b'abc'", not 'abc'; use '%r' % b'abc' if this is desired behavior -'%(name)s' % {'name': b'value'} # E: On Python 3 '%s' % b'abc' produces "b'abc'", not 'abc'; use '%r' % b'abc' if this is desired behavior -[builtins fixtures/primitives.pyi] - -[case testStringInterpolationSBytesVsStrResultsPy2] -# flags: --python-version 2.7 -xs = 'x' -xu = u'x' - -reveal_type('%s' % xu) # N: Revealed type is "builtins.unicode" -reveal_type('%s, %d' % (u'abc', 42)) # N: Revealed type is "builtins.unicode" -reveal_type('%(key)s' % {'key': xu}) # N: Revealed type is "builtins.unicode" -reveal_type('%r' % xu) # N: Revealed type is "builtins.str" -reveal_type('%s' % xs) # N: Revealed type is "builtins.str" -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationCount] -'%d %d' % 1 # E: Not enough arguments for format string -'%d %d' % (1, 2) -'%d %d' % (1, 2, 3) # E: Not all arguments converted during string formatting -t = 1, 's' -'%d %s' % t -'%s %d' % t # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") -'%d' % t # E: Not all arguments converted during string formatting -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationWithAnyType] -from typing import Any -a = None # type: Any -'%d %d' % a -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationInvalidPlaceholder] -'%W' % 1 # E: Unsupported format character "W" -'%b' % 1 # E: Format character "b" is only supported on bytes patterns - -[case testStringInterPolationPython2] -# flags: --python-version 2.7 -b'%b' % 1 # E: Format character "b" is only supported in Python 3.5 and later -b'%s' % 1 -b'%a' % 1 # E: Format character "a" is only supported in Python 3 - -[case testBytesInterpolationBefore35] -# flags: --python-version 3.4 -b'%b' % 1 # E: Unsupported left operand type for % ("bytes") - -[case testBytesInterpolation] -b'%b' % 1 # E: Incompatible types in string interpolation (expression has type "int", placeholder has type "bytes") -b'%b' % b'1' -b'%a' % 3 - -[case testStringInterpolationWidth] -'%2f' % 3.14 -'%*f' % 3.14 # E: Not enough arguments for format string -'%*f' % (4, 3.14) -'%*f' % (1.1, 3.14) # E: * wants int -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationPrecision] -'%.2f' % 3.14 -'%.*f' % 3.14 # E: Not enough arguments for format string -'%.*f' % (4, 3.14) -'%.*f' % (1.1, 3.14) # E: * wants int -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationWidthAndPrecision] -'%4.2f' % 3.14 -'%4.*f' % 3.14 # E: Not enough arguments for format string -'%*.2f' % 3.14 # E: Not enough arguments for format string -'%*.*f' % 3.14 # E: Not enough arguments for format string -'%*.*f' % (4, 2, 3.14) -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationFlagsAndLengthModifiers] -'%04hd' % 1 -'%-.4ld' % 1 -'%+*Ld' % (1, 1) -'% .*ld' % (1, 1) -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationDoublePercentage] -'%% %d' % 1 -'%3% %d' % 1 -'%*%' % 1 -'%*% %d' % 1 # E: Not enough arguments for format string -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationC] -'%c' % 1 -'%c' % 's' -'%c' % '' # E: "%c" requires int or char -'%c' % 'ab' # E: "%c" requires int or char -[builtins fixtures/primitives.pyi] - -[case testStringInterpolationMappingTypes] -'%(a)d %(b)s' % {'a': 1, 'b': 's'} -'%(a)d %(b)s' % {'a': 's', 'b': 1} # E: Incompatible types in string interpolation (expression has type "str", placeholder with key 'a' has type "Union[int, float, SupportsInt]") -b'%(x)s' % {b'x': b'data'} -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationMappingKeys] -'%()d' % {'': 2} -'%(a)d' % {'a': 1, 'b': 2, 'c': 3} -'%(q)d' % {'a': 1, 'b': 2, 'c': 3} # E: Key "q" not found in mapping -'%(a)d %%' % {'a': 1} -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationMappingDictTypes] -from typing import Any, Dict -a = None # type: Any -ds, do, di = None, None, None # type: Dict[str, int], Dict[object, int], Dict[int, int] -'%(a)' % 1 # E: Format requires a mapping (expression has type "int", expected type for mapping is "Mapping[str, Any]") -'%()d' % a -'%()d' % ds -'%()d' % do # E: Format requires a mapping (expression has type "Dict[object, int]", expected type for mapping is "Mapping[str, Any]") -b'%()d' % ds # E: Format requires a mapping (expression has type "Dict[str, int]", expected type for mapping is "Mapping[bytes, Any]") -[builtins fixtures/primitives.pyi] - -[case testStringInterpolationMappingInvalidDictTypesPy2] -# flags: --py2 --no-strict-optional -from typing import Any, Dict -di = None # type: Dict[int, int] -'%()d' % di # E: Format requires a mapping (expression has type "Dict[int, int]", expected type for mapping is "Union[Mapping[str, Any], Mapping[unicode, Any]]") -[builtins_py2 fixtures/python2.pyi] - -[case testStringInterpolationMappingInvalidSpecifiers] -'%(a)d %d' % 1 # E: String interpolation mixes specifier with and without mapping keys -'%(b)*d' % 1 # E: String interpolation contains both stars and mapping keys -'%(b).*d' % 1 # E: String interpolation contains both stars and mapping keys - -[case testStringInterpolationMappingFlagsAndLengthModifiers] -'%(a)1d' % {'a': 1} -'%(a).1d' % {'a': 1} -'%(a)#1.1ld' % {'a': 1} -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationFloatPrecision] -'%.f' % 1.2 -'%.3f' % 1.2 -'%.f' % 'x' -'%.3f' % 'x' -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] -[out] -main:3: error: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") -main:4: error: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") - -[case testStringInterpolationSpaceKey] -'%( )s' % {' ': 'foo'} - -[case testByteByteInterpolation] -def foo(a: bytes, b: bytes): - b'%s:%s' % (a, b) -foo(b'a', b'b') == b'a:b' -[builtins fixtures/tuple.pyi] - -[case testStringInterpolationStarArgs] -x = (1, 2) -"%d%d" % (*x,) -[typing fixtures/typing-medium.pyi] -[builtins fixtures/tuple.pyi] - -[case testBytePercentInterpolationSupported] -b'%s' % (b'xyz',) -b'%(name)s' % {'name': b'jane'} # E: Dictionary keys in bytes formatting must be bytes, not strings -b'%(name)s' % {b'name': 'jane'} # E: On Python 3 b'%s' requires bytes, not string -b'%c' % (123) -[builtins fixtures/tuple.pyi] - -[case testUnicodeInterpolation_python2] -u'%s' % (u'abc',) - -[case testStringInterpolationVariableLengthTuple] -from typing import Tuple -def f(t: Tuple[int, ...]) -> None: - '%d %d' % t - '%d %d %d' % t -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testStringInterpolationUnionType] -from typing import Tuple, Union -a: Union[Tuple[int, str], Tuple[str, int]] = ('A', 1) -'%s %s' % a -'%s' % a # E: Not all arguments converted during string formatting - -b: Union[Tuple[int, str], Tuple[int, int], Tuple[str, int]] = ('A', 1) -'%s %s' % b -'%s %s %s' % b # E: Not enough arguments for format string - -c: Union[Tuple[str, int], Tuple[str, int, str]] = ('A', 1) -'%s %s' % c # E: Not all arguments converted during string formatting -[builtins fixtures/tuple.pyi] - --- str.format() calls --- ------------------ - -[case testFormatCallParseErrors] -'}'.format() # E: Invalid conversion specifier in format string: unexpected } -'{'.format() # E: Invalid conversion specifier in format string: unmatched { - -'}}'.format() # OK -'{{'.format() # OK - -'{{}}}'.format() # E: Invalid conversion specifier in format string: unexpected } -'{{{}}'.format() # E: Invalid conversion specifier in format string: unexpected } - -'{}}{{}'.format() # E: Invalid conversion specifier in format string: unexpected } -'{{{}:{}}}'.format(0) # E: Cannot find replacement for positional format specifier 1 -[builtins fixtures/primitives.pyi] - -[case testFormatCallValidationErrors] -'{!}}'.format(0) # E: Invalid conversion specifier in format string: unexpected } -'{!x}'.format(0) # E: Invalid conversion type "x", must be one of "r", "s" or "a" -'{!:}'.format(0) # E: Invalid conversion specifier in format string - -'{{}:s}'.format(0) # E: Invalid conversion specifier in format string: unexpected } -'{{}.attr}'.format(0) # E: Invalid conversion specifier in format string: unexpected } -'{{}[key]}'.format(0) # E: Invalid conversion specifier in format string: unexpected } - -'{ {}:s}'.format() # E: Conversion value must not contain { or } -'{ {}.attr}'.format() # E: Conversion value must not contain { or } -'{ {}[key]}'.format() # E: Conversion value must not contain { or } -[builtins fixtures/primitives.pyi] - -[case testFormatCallEscaping] -'{}'.format() # E: Cannot find replacement for positional format specifier 0 -'{}'.format(0) # OK - -'{{}}'.format() # OK -'{{}}'.format(0) # E: Not all arguments converted during string formatting - -'{{{}}}'.format() # E: Cannot find replacement for positional format specifier 0 -'{{{}}}'.format(0) # OK - -'{{}} {} {{}}'.format(0) # OK -'{{}} {:d} {{}} {:d}'.format('a', 'b') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") - -'foo({}, {}) == {{}} ({{}} expected)'.format(0) # E: Cannot find replacement for positional format specifier 1 -'foo({}, {}) == {{}} ({{}} expected)'.format(0, 1) # OK -'foo({}, {}) == {{}} ({{}} expected)'.format(0, 1, 2) # E: Not all arguments converted during string formatting -[builtins fixtures/primitives.pyi] - -[case testFormatCallNestedFormats] -'{:{}{}}'.format(42, '*') # E: Cannot find replacement for positional format specifier 2 -'{:{}{}}'.format(42, '*', '^') # OK -'{:{}{}}'.format(42, '*', '^', 0) # E: Not all arguments converted during string formatting - -# NOTE: we don't check format specifiers that contain { or } at all -'{:{{}}}'.format() # E: Cannot find replacement for positional format specifier 0 - -'{:{:{}}}'.format() # E: Formatting nesting must be at most two levels deep -'{:{{}:{}}}'.format() # E: Invalid conversion specifier in format string: unexpected } - -'{!s:{fill:d}{align}}'.format(42, fill='*', align='^') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -[builtins fixtures/primitives.pyi] - -[case testFormatCallAutoNumbering] -'{}, {{}}, {0}'.format() # E: Cannot combine automatic field numbering and manual field specification -'{0}, {1}, {}'.format() # E: Cannot combine automatic field numbering and manual field specification - -'{0}, {1}, {0}'.format(1, 2, 3) # E: Not all arguments converted during string formatting -'{}, {other:+d}, {}'.format(1, 2, other='no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -'{0}, {other}, {}'.format() # E: Cannot combine automatic field numbering and manual field specification - -'{:{}}, {:{:.5d}{}}'.format(1, 2, 3, 'a', 5) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -[builtins fixtures/primitives.pyi] - -[case testFormatCallMatchingPositional] -'{}'.format(positional='no') # E: Cannot find replacement for positional format specifier 0 \ - # E: Not all arguments converted during string formatting -'{.x}, {}, {}'.format(1, 'two', 'three') # E: "int" has no attribute "x" -'Reverse {2.x}, {1}, {0}'.format(1, 2, 'three') # E: "str" has no attribute "x" -''.format(1, 2) # E: Not all arguments converted during string formatting -[builtins fixtures/primitives.pyi] - -[case testFormatCallMatchingNamed] -'{named}'.format(0) # E: Cannot find replacement for named format specifier "named" \ - # E: Not all arguments converted during string formatting -'{one.x}, {two}'.format(one=1, two='two') # E: "int" has no attribute "x" -'{one}, {two}, {.x}'.format(1, one='two', two='three') # E: "int" has no attribute "x" -''.format(stuff='yes') # E: Not all arguments converted during string formatting -[builtins fixtures/primitives.pyi] - -[case testFormatCallMatchingVarArg] -from typing import List -args: List[int] = [] -'{}, {}'.format(1, 2, *args) # Don't flag this because args may be empty - -strings: List[str] -'{:d}, {[0].x}'.format(*strings) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") \ - # E: "str" has no attribute "x" -# TODO: this is a runtime error, but error message is confusing -'{[0][:]:d}'.format(*strings) # E: Syntax error in format specifier "0[0][" -[builtins fixtures/primitives.pyi] - -[case testFormatCallMatchingKwArg] -from typing import Dict -kwargs: Dict[str, str] = {} -'{one}, {two}'.format(one=1, two=2, **kwargs) # Don't flag this because args may be empty - -'{stuff:.3d}'.format(**kwargs) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -'{stuff[0]:f}, {other}'.format(**kwargs) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") -'{stuff[0]:c}'.format(**kwargs) -[builtins fixtures/primitives.pyi] - -[case testFormatCallCustomFormatSpec] -from typing import Union -class Bad: - ... -class Good: - def __format__(self, spec: str) -> str: ... - -'{:OMG}'.format(Good()) -'{:OMG}'.format(Bad()) # E: Unrecognized format specification "OMG" -'{!s:OMG}'.format(Good()) # E: Unrecognized format specification "OMG" -'{:{}OMG{}}'.format(Bad(), 'too', 'dynamic') - -x: Union[Good, Bad] -'{:OMG}'.format(x) # E: Unrecognized format specification "OMG" -[builtins fixtures/primitives.pyi] - -[case testFormatCallFormatTypes] -'{:x}'.format(42) -'{:E}'.format(42) -'{:g}'.format(42) -'{:x}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -'{:E}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") -'{:g}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") -'{:n}'.format(3.14) -'{:d}'.format(3.14) # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") - -'{:s}'.format(42) -'{:s}'.format('yes') - -'{:z}'.format('what') # E: Unsupported format character "z" -'{:Z}'.format('what') # E: Unsupported format character "Z" -[builtins fixtures/primitives.pyi] - -[case testFormatCallFormatTypesChar] -'{:c}'.format(42) -'{:c}'.format('no') # E: ":c" requires int or char -'{:c}'.format('c') - -class C: - ... -'{:c}'.format(C()) # E: Incompatible types in string interpolation (expression has type "C", placeholder has type "Union[int, float, str]") -x: str -'{:c}'.format(x) -[builtins fixtures/primitives.pyi] - -[case testFormatCallFormatTypesCustomFormat] -from typing import Union -class Bad: - ... -class Good: - def __format__(self, spec: str) -> str: ... - -x: Union[Good, Bad] -y: Union[Good, int] -z: Union[Bad, int] -t: Union[Good, str] -'{:d}'.format(x) # E: Incompatible types in string interpolation (expression has type "Bad", placeholder has type "int") -'{:d}'.format(y) -'{:d}'.format(z) # E: Incompatible types in string interpolation (expression has type "Bad", placeholder has type "int") -'{:d}'.format(t) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -[builtins fixtures/primitives.pyi] - -[case testFormatCallFormatTypesBytes] -from typing import Union, TypeVar, NewType, Generic - -A = TypeVar('A', str, bytes) -B = TypeVar('B', bound=bytes) - -x: Union[str, bytes] -a: str -b: bytes - -N = NewType('N', bytes) -n: N - -'{}'.format(a) -'{}'.format(b) # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior -'{}'.format(x) # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior -'{}'.format(n) # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior - -class C(Generic[B]): - x: B - def meth(self) -> None: - '{}'.format(self.x) # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior - -def func(x: A) -> A: - '{}'.format(x) # E: On Python 3 '{}'.format(b'abc') produces "b'abc'", not 'abc'; use '{!r}'.format(b'abc') if this is desired behavior - return x - -'{!r}'.format(b) -'{!r}'.format(x) -'{!r}'.format(n) - -class D(bytes): - def __str__(self) -> str: - return "overrides __str__ of bytes" - -'{}'.format(D()) -[builtins fixtures/primitives.pyi] - -[case testFormatCallFormatTypesBytesNotPy2] -# flags: --py2 -from typing import Union, TypeVar, NewType, Generic - -A = TypeVar('A', str, unicode) -B = TypeVar('B', bound=str) - -x = '' # type: Union[str, unicode] -a = '' -b = b'' - -N = NewType('N', str) -n = N(b'') - -'{}'.format(a) -'{}'.format(b) -'{}'.format(x) -'{}'.format(n) - -u'{}'.format(a) -u'{}'.format(b) -u'{}'.format(x) -u'{}'.format(n) - -class C(Generic[B]): - x = None # type: B - def meth(self): - # type: () -> None - '{}'.format(self.x) - -def func(x): - # type: (A) -> A - '{}'.format(x) - return x - -'{!r}'.format(b) -'{!r}'.format(x) -'{!r}'.format(n) -[builtins_py2 fixtures/python2.pyi] - -[case testFormatCallFinal] -from typing_extensions import Final - -FMT: Final = '{.x}, {:{:d}}' - -FMT.format(1, 2, 'no') # E: "int" has no attribute "x" \ - # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -[builtins fixtures/primitives.pyi] - -[case testFormatCallFinalChar] -from typing_extensions import Final - -GOOD: Final = 'c' -BAD: Final = 'no' -OK: Final[str] = '...' - -'{:c}'.format(GOOD) -'{:c}'.format(BAD) # E: ":c" requires int or char -'{:c}'.format(OK) -[builtins fixtures/primitives.pyi] - -[case testFormatCallForcedConversions] -'{!r}'.format(42) -'{!s}'.format(42) -'{!s:d}'.format(42) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") -'{!s:s}'.format('OK') -'{} and {!x}'.format(0, 1) # E: Invalid conversion type "x", must be one of "r", "s" or "a" -[builtins fixtures/primitives.pyi] - -[case testFormatCallAccessorsBasic] -from typing import Any -x: Any - -'{.x:{[0]}}'.format('yes', 42) # E: "str" has no attribute "x" \ - # E: Value of type "int" is not indexable - -'{.1+}'.format(x) # E: Syntax error in format specifier "0.1+" -'{name.x[x]()[x]:.2f}'.format(name=x) # E: Only index and member expressions are allowed in format field accessors; got "name.x[x]()[x]" -[builtins fixtures/primitives.pyi] - -[case testFormatCallAccessorsIndices] -from typing_extensions import TypedDict - -class User(TypedDict): - id: int - name: str - -u: User -'{user[name]:.3f}'.format(user=u) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") - -def f() -> str: ... -'{[f()]}'.format(u) # E: Invalid index expression in format field accessor "[f()]" -[builtins fixtures/primitives.pyi] - -[case testFormatCallFlags] -from typing import Union - -class Good: - def __format__(self, spec: str) -> str: ... - -'{:#}'.format(42) - -'{:#}'.format('no') # E: Numeric flags are only allowed for numeric types -'{!s:#}'.format(42) # E: Numeric flags are only allowed for numeric types - -'{:#s}'.format(42) # E: Numeric flags are only allowed for numeric types -'{:+s}'.format(42) # E: Numeric flags are only allowed for numeric types - -'{:+d}'.format(42) -'{:#d}'.format(42) - -x: Union[float, Good] -'{:+f}'.format(x) -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -[case testFormatCallSpecialCases] -'{:08b}'.format(int('3')) - -class S: - def __int__(self) -> int: ... - -'{:+d}'.format(S()) # E: Incompatible types in string interpolation (expression has type "S", placeholder has type "int") -'%d' % S() # This is OK however -'{:%}'.format(0.001) -[builtins fixtures/primitives.pyi] -[typing fixtures/typing-medium.pyi] - -- Lambdas -- ------- @@ -2085,15 +1490,7 @@ if str(): ....a # E: "ellipsis" has no attribute "a" class A: pass -[file builtins.py] -class object: - def __init__(self): pass -class ellipsis: - def __init__(self): pass - __class__ = object() -class type: pass -class function: pass -class str: pass +[builtins fixtures/dict.pyi] [out] @@ -2325,6 +1722,19 @@ def f() -> None: [out] main:3: note: Revealed type is "builtins.int" +[case testLambdaTypedContext] +def f() -> None: + lambda: 'a'.missing() # E: "str" has no attribute "missing" + +[case testLambdaUnypedContext] +def f(): + lambda: 'a'.missing() + +[case testLambdaCheckUnypedContext] +# flags: --check-untyped-defs +def f(): + lambda: 'a'.missing() # E: "str" has no attribute "missing" + [case testEqNone] None == None [builtins fixtures/ops.pyi] diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index 497ed9b1d2b2..e2dc4f203855 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -317,13 +317,6 @@ x = None # type: Any x @ 1 x @= 1 -[case testIncorrectTypeCommentIndex] - -from typing import Dict -x = None # type: Dict[x: y] -[out] -main:3: error: syntax error in type comment - [case testPrintStatementTrailingCommaFastParser_python2] print 0, diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 3e321abd46d6..02f6b034c512 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -178,6 +178,67 @@ reveal_type(g) # N: Revealed type is "Any" reveal_type(h) # N: Revealed type is "def (*Any, **Any) -> Any" reveal_type(i) # N: Revealed type is "Any" +[case testDisallowUntypedDecoratorsCallableInstanceDecoratedCall] +# flags: --disallow-untyped-decorators +from typing import Callable, TypeVar + +C = TypeVar('C', bound=Callable) + +def typed_decorator(c: C) -> C: + return c + +def untyped_decorator(c): + return c + +class TypedDecorator: + @typed_decorator + def __call__(self, c: Callable) -> Callable: + return function + +class UntypedDecorator1: + @untyped_decorator + def __call__(self, c): + return function + +class UntypedDecorator2: + @untyped_decorator # E: Untyped decorator makes function "__call__" untyped + def __call__(self, c: Callable) -> Callable: + return function + +class UntypedDecorator3: + @typed_decorator + @untyped_decorator # E: Untyped decorator makes function "__call__" untyped + def __call__(self, c: Callable) -> Callable: + return function + +class UntypedDecorator4: + @untyped_decorator # E: Untyped decorator makes function "__call__" untyped + @typed_decorator + def __call__(self, c: Callable) -> Callable: + return function + +@TypedDecorator() +def f() -> None: pass + +@UntypedDecorator1() # E: Untyped decorator makes function "g1" untyped +def g1() -> None: pass + +@UntypedDecorator2() # E: Untyped decorator makes function "g2" untyped +def g2() -> None: pass + +@UntypedDecorator3() # E: Untyped decorator makes function "g3" untyped +def g3() -> None: pass + +@UntypedDecorator4() # E: Untyped decorator makes function "g4" untyped +def g4() -> None: pass + +reveal_type(f) # N: Revealed type is "def (*Any, **Any) -> Any" +reveal_type(g1) # N: Revealed type is "Any" +reveal_type(g2) # N: Revealed type is "Any" +reveal_type(g3) # N: Revealed type is "Any" +reveal_type(g4) # N: Revealed type is "Any" +[builtins fixtures/bool.pyi] + [case testDisallowUntypedDecoratorsNonCallableInstance] # flags: --disallow-untyped-decorators class Decorator: @@ -1193,6 +1254,8 @@ import attr class Unannotated: foo = attr.ib() +[builtins fixtures/attr.pyi] + [case testDisallowIncompleteDefsAttrsWithAnnotations] # flags: --disallow-incomplete-defs import attr @@ -1201,6 +1264,8 @@ import attr class Annotated: bar: int = attr.ib() +[builtins fixtures/attr.pyi] + [case testDisallowIncompleteDefsAttrsPartialAnnotations] # flags: --disallow-incomplete-defs import attr @@ -1210,6 +1275,8 @@ class PartiallyAnnotated: # E: Function is missing a type annotation for one or bar: int = attr.ib() baz = attr.ib() +[builtins fixtures/attr.pyi] + [case testAlwaysTrueAlwaysFalseFlags] # flags: --always-true=YOLO --always-true=YOLO1 --always-false=BLAH1 --always-false BLAH --ignore-missing-imports from somewhere import YOLO, BLAH @@ -1519,6 +1586,16 @@ __all__ = ('b',) [out] main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled +[case testNoImplicitReexportGetAttr] +# flags: --no-implicit-reexport --python-version 3.7 +from other_module_2 import a # E: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled +[file other_module_1.py] +from typing import Any +def __getattr__(name: str) -> Any: ... +[file other_module_2.py] +from other_module_1 import a +[builtins fixtures/tuple.pyi] + [case textNoImplicitReexportSuggestions] # flags: --no-implicit-reexport from other_module_2 import attr_1 diff --git a/test-data/unit/check-formatting.test b/test-data/unit/check-formatting.test new file mode 100644 index 000000000000..783c31c18770 --- /dev/null +++ b/test-data/unit/check-formatting.test @@ -0,0 +1,651 @@ + +-- String interpolation +-- -------------------- + +[case testStringInterpolationType] +from typing import Tuple +i, f, s, t = None, None, None, None # type: (int, float, str, Tuple[int]) +'%d' % i +'%f' % f +'%s' % s +'%d' % (f,) +'%d' % (s,) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") +'%d' % t +'%d' % s # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") +'%f' % s # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") +'%x' % f # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") +'%i' % f +'%o' % f # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationSAcceptsAnyType] +from typing import Any +i, o, s = None, None, None # type: (int, object, str) +'%s %s %s' % (i, o, s) +[builtins fixtures/primitives.pyi] + +[case testStringInterpolationSBytesVsStrErrorPy3] +xb: bytes +xs: str + +'%s' % xs # OK +'%s' % xb # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior +'%(name)s' % {'name': b'value'} # E: On Python 3 formatting "b'abc'" with "%s" produces "b'abc'", not "abc"; use "%r" if this is desired behavior +[builtins fixtures/primitives.pyi] + +[case testStringInterpolationSBytesVsStrResultsPy2] +# flags: --python-version 2.7 +xs = 'x' +xu = u'x' + +reveal_type('%s' % xu) # N: Revealed type is "builtins.unicode" +reveal_type('%s, %d' % (u'abc', 42)) # N: Revealed type is "builtins.unicode" +reveal_type('%(key)s' % {'key': xu}) # N: Revealed type is "builtins.unicode" +reveal_type('%r' % xu) # N: Revealed type is "builtins.str" +reveal_type('%s' % xs) # N: Revealed type is "builtins.str" +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationCount] +'%d %d' % 1 # E: Not enough arguments for format string +'%d %d' % (1, 2) +'%d %d' % (1, 2, 3) # E: Not all arguments converted during string formatting +t = 1, 's' +'%d %s' % t +'%s %d' % t # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsInt]") +'%d' % t # E: Not all arguments converted during string formatting +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationWithAnyType] +from typing import Any +a = None # type: Any +'%d %d' % a +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationInvalidPlaceholder] +'%W' % 1 # E: Unsupported format character "W" +'%b' % 1 # E: Format character "b" is only supported on bytes patterns + +[case testStringInterPolationPython2] +# flags: --python-version 2.7 +b'%b' % 1 # E: Format character "b" is only supported in Python 3.5 and later +b'%s' % 1 +b'%a' % 1 # E: Format character "a" is only supported in Python 3 + +[case testStringInterpolationWidth] +'%2f' % 3.14 +'%*f' % 3.14 # E: Not enough arguments for format string +'%*f' % (4, 3.14) +'%*f' % (1.1, 3.14) # E: * wants int +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationPrecision] +'%.2f' % 3.14 +'%.*f' % 3.14 # E: Not enough arguments for format string +'%.*f' % (4, 3.14) +'%.*f' % (1.1, 3.14) # E: * wants int +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationWidthAndPrecision] +'%4.2f' % 3.14 +'%4.*f' % 3.14 # E: Not enough arguments for format string +'%*.2f' % 3.14 # E: Not enough arguments for format string +'%*.*f' % 3.14 # E: Not enough arguments for format string +'%*.*f' % (4, 2, 3.14) +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationFlagsAndLengthModifiers] +'%04hd' % 1 +'%-.4ld' % 1 +'%+*Ld' % (1, 1) +'% .*ld' % (1, 1) +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationDoublePercentage] +'%% %d' % 1 +'%3% %d' % 1 +'%*%' % 1 +'%*% %d' % 1 # E: Not enough arguments for format string +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterPolationCPython2] +# flags: --py2 --no-strict-optional +'%c' % 1 +'%c' % 1.0 # E: "%c" requires int or char (expression has type "float") +'%c' % 's' +'%c' % '' # E: "%c" requires int or char +'%c' % 'ab' # E: "%c" requires int or char +'%c' % b'a' +'%c' % b'' # E: "%c" requires int or char +'%c' % b'ab' # E: "%c" requires int or char +[builtins_py2 fixtures/python2.pyi] + +[case testStringInterpolationC] +# flags: --python-version 3.6 +'%c' % 1 +'%c' % 1.0 # E: "%c" requires int or char (expression has type "float") +'%c' % 's' +'%c' % '' # E: "%c" requires int or char +'%c' % 'ab' # E: "%c" requires int or char +'%c' % b'a' # E: "%c" requires int or char (expression has type "bytes") +'%c' % b'' # E: "%c" requires int or char (expression has type "bytes") +'%c' % b'ab' # E: "%c" requires int or char (expression has type "bytes") +[builtins fixtures/primitives.pyi] + +[case testStringInterpolationMappingTypes] +'%(a)d %(b)s' % {'a': 1, 'b': 's'} +'%(a)d %(b)s' % {'a': 's', 'b': 1} # E: Incompatible types in string interpolation (expression has type "str", placeholder with key 'a' has type "Union[int, float, SupportsInt]") +b'%(x)s' % {b'x': b'data'} +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationMappingKeys] +'%()d' % {'': 2} +'%(a)d' % {'a': 1, 'b': 2, 'c': 3} +'%(q)d' % {'a': 1, 'b': 2, 'c': 3} # E: Key "q" not found in mapping +'%(a)d %%' % {'a': 1} +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationMappingDictTypes] +from typing import Any, Dict +a = None # type: Any +ds, do, di = None, None, None # type: Dict[str, int], Dict[object, int], Dict[int, int] +'%(a)' % 1 # E: Format requires a mapping (expression has type "int", expected type for mapping is "Mapping[str, Any]") +'%()d' % a +'%()d' % ds +'%()d' % do # E: Format requires a mapping (expression has type "Dict[object, int]", expected type for mapping is "Mapping[str, Any]") +b'%()d' % ds # E: Format requires a mapping (expression has type "Dict[str, int]", expected type for mapping is "Mapping[bytes, Any]") +[builtins fixtures/primitives.pyi] + +[case testStringInterpolationMappingInvalidDictTypesPy2] +# flags: --py2 --no-strict-optional +from typing import Any, Dict +di = None # type: Dict[int, int] +'%()d' % di # E: Format requires a mapping (expression has type "Dict[int, int]", expected type for mapping is "Union[Mapping[str, Any], Mapping[unicode, Any]]") +[builtins_py2 fixtures/python2.pyi] + +[case testStringInterpolationMappingInvalidSpecifiers] +'%(a)d %d' % 1 # E: String interpolation mixes specifier with and without mapping keys +'%(b)*d' % 1 # E: String interpolation contains both stars and mapping keys +'%(b).*d' % 1 # E: String interpolation contains both stars and mapping keys + +[case testStringInterpolationMappingFlagsAndLengthModifiers] +'%(a)1d' % {'a': 1} +'%(a).1d' % {'a': 1} +'%(a)#1.1ld' % {'a': 1} +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationFloatPrecision] +'%.f' % 1.2 +'%.3f' % 1.2 +'%.f' % 'x' +'%.3f' % 'x' +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] +[out] +main:3: error: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") +main:4: error: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float, SupportsFloat]") + +[case testStringInterpolationSpaceKey] +'%( )s' % {' ': 'foo'} + +[case testStringInterpolationStarArgs] +x = (1, 2) +"%d%d" % (*x,) +[typing fixtures/typing-medium.pyi] +[builtins fixtures/tuple.pyi] + +[case testStringInterpolationVariableLengthTuple] +from typing import Tuple +def f(t: Tuple[int, ...]) -> None: + '%d %d' % t + '%d %d %d' % t +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testStringInterpolationUnionType] +from typing import Tuple, Union +a: Union[Tuple[int, str], Tuple[str, int]] = ('A', 1) +'%s %s' % a +'%s' % a # E: Not all arguments converted during string formatting + +b: Union[Tuple[int, str], Tuple[int, int], Tuple[str, int]] = ('A', 1) +'%s %s' % b +'%s %s %s' % b # E: Not enough arguments for format string + +c: Union[Tuple[str, int], Tuple[str, int, str]] = ('A', 1) +'%s %s' % c # E: Not all arguments converted during string formatting +[builtins fixtures/tuple.pyi] + +[case testStringInterpolationIterableType] +from typing import Sequence, List, Tuple, Iterable + +t1: Sequence[str] = ('A', 'B') +t2: List[str] = ['A', 'B'] +t3: Tuple[str, ...] = ('A', 'B') +t4: Tuple[str, str] = ('A', 'B') +t5: Iterable[str] = ('A', 'B') +'%s %s' % t1 +'%s %s' % t2 +'%s %s' % t3 +'%s %s %s' % t3 +'%s %s' % t4 +'%s %s %s' % t4 # E: Not enough arguments for format string +'%s %s' % t5 +[builtins fixtures/tuple.pyi] + +[case testUnicodeInterpolation_python2] +u'%s' % (u'abc',) + + +-- Bytes interpolation +-- -------------------- + + +[case testBytesInterpolationBefore35] +# flags: --python-version 3.4 +b'%b' % 1 # E: Unsupported left operand type for % ("bytes") + +[case testBytesInterpolation] +b'%b' % 1 # E: Incompatible types in string interpolation (expression has type "int", placeholder has type "bytes") +b'%b' % b'1' +b'%a' % 3 + +[case testBytesInterPolationCPython2] +# flags: --py2 --no-strict-optional +b'%c' % 1 +b'%c' % 1.0 # E: "%c" requires int or char (expression has type "float") +b'%c' % 's' +b'%c' % '' # E: "%c" requires int or char +b'%c' % 'ab' # E: "%c" requires int or char +b'%c' % b'a' +b'%c' % b'' # E: "%c" requires int or char +b'%c' % b'aa' # E: "%c" requires int or char +[builtins_py2 fixtures/python2.pyi] + +[case testBytesInterpolationC] +# flags: --python-version 3.6 +b'%c' % 1 +b'%c' % 1.0 # E: "%c" requires an integer in range(256) or a single byte (expression has type "float") +b'%c' % 's' # E: "%c" requires an integer in range(256) or a single byte (expression has type "str") +b'%c' % '' # E: "%c" requires an integer in range(256) or a single byte (expression has type "str") +b'%c' % 'ab' # E: "%c" requires an integer in range(256) or a single byte (expression has type "str") +b'%c' % b'a' +b'%c' % b'' # E: "%c" requires an integer in range(256) or a single byte +b'%c' % b'aa' # E: "%c" requires an integer in range(256) or a single byte +[builtins fixtures/primitives.pyi] + +[case testByteByteInterpolation] +def foo(a: bytes, b: bytes): + b'%s:%s' % (a, b) +foo(b'a', b'b') == b'a:b' +[builtins fixtures/tuple.pyi] + +[case testBytePercentInterpolationSupported] +b'%s' % (b'xyz',) +b'%(name)s' % {'name': b'jane'} # E: Dictionary keys in bytes formatting must be bytes, not strings +b'%(name)s' % {b'name': 'jane'} # E: On Python 3 b'%s' requires bytes, not string +b'%c' % (123) +[builtins fixtures/tuple.pyi] + + +-- str.format() calls +-- ------------------ + + +[case testFormatCallParseErrors] +'}'.format() # E: Invalid conversion specifier in format string: unexpected } +'{'.format() # E: Invalid conversion specifier in format string: unmatched { + +'}}'.format() # OK +'{{'.format() # OK + +'{{}}}'.format() # E: Invalid conversion specifier in format string: unexpected } +'{{{}}'.format() # E: Invalid conversion specifier in format string: unexpected } + +'{}}{{}'.format() # E: Invalid conversion specifier in format string: unexpected } +'{{{}:{}}}'.format(0) # E: Cannot find replacement for positional format specifier 1 +[builtins fixtures/primitives.pyi] + +[case testFormatCallValidationErrors] +'{!}}'.format(0) # E: Invalid conversion specifier in format string: unexpected } +'{!x}'.format(0) # E: Invalid conversion type "x", must be one of "r", "s" or "a" +'{!:}'.format(0) # E: Invalid conversion specifier in format string + +'{{}:s}'.format(0) # E: Invalid conversion specifier in format string: unexpected } +'{{}.attr}'.format(0) # E: Invalid conversion specifier in format string: unexpected } +'{{}[key]}'.format(0) # E: Invalid conversion specifier in format string: unexpected } + +'{ {}:s}'.format() # E: Conversion value must not contain { or } +'{ {}.attr}'.format() # E: Conversion value must not contain { or } +'{ {}[key]}'.format() # E: Conversion value must not contain { or } +[builtins fixtures/primitives.pyi] + +[case testFormatCallEscaping] +'{}'.format() # E: Cannot find replacement for positional format specifier 0 +'{}'.format(0) # OK + +'{{}}'.format() # OK +'{{}}'.format(0) # E: Not all arguments converted during string formatting + +'{{{}}}'.format() # E: Cannot find replacement for positional format specifier 0 +'{{{}}}'.format(0) # OK + +'{{}} {} {{}}'.format(0) # OK +'{{}} {:d} {{}} {:d}'.format('a', 'b') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") + +'foo({}, {}) == {{}} ({{}} expected)'.format(0) # E: Cannot find replacement for positional format specifier 1 +'foo({}, {}) == {{}} ({{}} expected)'.format(0, 1) # OK +'foo({}, {}) == {{}} ({{}} expected)'.format(0, 1, 2) # E: Not all arguments converted during string formatting +[builtins fixtures/primitives.pyi] + +[case testFormatCallNestedFormats] +'{:{}{}}'.format(42, '*') # E: Cannot find replacement for positional format specifier 2 +'{:{}{}}'.format(42, '*', '^') # OK +'{:{}{}}'.format(42, '*', '^', 0) # E: Not all arguments converted during string formatting + +# NOTE: we don't check format specifiers that contain { or } at all +'{:{{}}}'.format() # E: Cannot find replacement for positional format specifier 0 + +'{:{:{}}}'.format() # E: Formatting nesting must be at most two levels deep +'{:{{}:{}}}'.format() # E: Invalid conversion specifier in format string: unexpected } + +'{!s:{fill:d}{align}}'.format(42, fill='*', align='^') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +[builtins fixtures/primitives.pyi] + +[case testFormatCallAutoNumbering] +'{}, {{}}, {0}'.format() # E: Cannot combine automatic field numbering and manual field specification +'{0}, {1}, {}'.format() # E: Cannot combine automatic field numbering and manual field specification + +'{0}, {1}, {0}'.format(1, 2, 3) # E: Not all arguments converted during string formatting +'{}, {other:+d}, {}'.format(1, 2, other='no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +'{0}, {other}, {}'.format() # E: Cannot combine automatic field numbering and manual field specification + +'{:{}}, {:{:.5d}{}}'.format(1, 2, 3, 'a', 5) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +[builtins fixtures/primitives.pyi] + +[case testFormatCallMatchingPositional] +'{}'.format(positional='no') # E: Cannot find replacement for positional format specifier 0 \ + # E: Not all arguments converted during string formatting +'{.x}, {}, {}'.format(1, 'two', 'three') # E: "int" has no attribute "x" +'Reverse {2.x}, {1}, {0}'.format(1, 2, 'three') # E: "str" has no attribute "x" +''.format(1, 2) # E: Not all arguments converted during string formatting +[builtins fixtures/primitives.pyi] + +[case testFormatCallMatchingNamed] +'{named}'.format(0) # E: Cannot find replacement for named format specifier "named" \ + # E: Not all arguments converted during string formatting +'{one.x}, {two}'.format(one=1, two='two') # E: "int" has no attribute "x" +'{one}, {two}, {.x}'.format(1, one='two', two='three') # E: "int" has no attribute "x" +''.format(stuff='yes') # E: Not all arguments converted during string formatting +[builtins fixtures/primitives.pyi] + +[case testFormatCallMatchingVarArg] +from typing import List +args: List[int] = [] +'{}, {}'.format(1, 2, *args) # Don't flag this because args may be empty + +strings: List[str] +'{:d}, {[0].x}'.format(*strings) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") \ + # E: "str" has no attribute "x" +# TODO: this is a runtime error, but error message is confusing +'{[0][:]:d}'.format(*strings) # E: Syntax error in format specifier "0[0][" +[builtins fixtures/primitives.pyi] + +[case testFormatCallMatchingKwArg] +from typing import Dict +kwargs: Dict[str, str] = {} +'{one}, {two}'.format(one=1, two=2, **kwargs) # Don't flag this because args may be empty + +'{stuff:.3d}'.format(**kwargs) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +'{stuff[0]:f}, {other}'.format(**kwargs) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") +'{stuff[0]:c}'.format(**kwargs) +[builtins fixtures/primitives.pyi] + +[case testFormatCallCustomFormatSpec] +from typing import Union +class Bad: + ... +class Good: + def __format__(self, spec: str) -> str: ... + +'{:OMG}'.format(Good()) +'{:OMG}'.format(Bad()) # E: Unrecognized format specification "OMG" +'{!s:OMG}'.format(Good()) # E: Unrecognized format specification "OMG" +'{:{}OMG{}}'.format(Bad(), 'too', 'dynamic') + +x: Union[Good, Bad] +'{:OMG}'.format(x) # E: Unrecognized format specification "OMG" +[builtins fixtures/primitives.pyi] + +[case testFormatCallFormatTypes] +'{:x}'.format(42) +'{:E}'.format(42) +'{:g}'.format(42) +'{:x}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +'{:E}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") +'{:g}'.format('no') # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") +'{:n}'.format(3.14) +'{:d}'.format(3.14) # E: Incompatible types in string interpolation (expression has type "float", placeholder has type "int") + +'{:s}'.format(42) +'{:s}'.format('yes') + +'{:z}'.format('what') # E: Unsupported format character "z" +'{:Z}'.format('what') # E: Unsupported format character "Z" +[builtins fixtures/primitives.pyi] + +[case testFormatCallFormatTypesChar] +'{:c}'.format(42) +'{:c}'.format('no') # E: ":c" requires int or char +'{:c}'.format('c') + +class C: + ... +'{:c}'.format(C()) # E: Incompatible types in string interpolation (expression has type "C", placeholder has type "Union[int, str]") +x: str +'{:c}'.format(x) +[builtins fixtures/primitives.pyi] + +[case testFormatCallFormatTypesCustomFormat] +from typing import Union +class Bad: + ... +class Good: + def __format__(self, spec: str) -> str: ... + +x: Union[Good, Bad] +y: Union[Good, int] +z: Union[Bad, int] +t: Union[Good, str] +'{:d}'.format(x) # E: Incompatible types in string interpolation (expression has type "Bad", placeholder has type "int") +'{:d}'.format(y) +'{:d}'.format(z) # E: Incompatible types in string interpolation (expression has type "Bad", placeholder has type "int") +'{:d}'.format(t) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +[builtins fixtures/primitives.pyi] + +[case testFormatCallFormatTypesBytes] +from typing import Union, TypeVar, NewType, Generic + +A = TypeVar('A', str, bytes) +B = TypeVar('B', bound=bytes) + +x: Union[str, bytes] +a: str +b: bytes + +N = NewType('N', bytes) +n: N + +'{}'.format(a) +'{}'.format(b) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior +'{}'.format(x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior +'{}'.format(n) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior + +f'{b}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior +f'{x}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior +f'{n}' # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior + +class C(Generic[B]): + x: B + def meth(self) -> None: + '{}'.format(self.x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior + +def func(x: A) -> A: + '{}'.format(x) # E: On Python 3 formatting "b'abc'" with "{}" produces "b'abc'", not "abc"; use "{!r}" if this is desired behavior + return x + +'{!r}'.format(a) +'{!r}'.format(b) +'{!r}'.format(x) +'{!r}'.format(n) +f'{a}' +f'{a!r}' +f'{b!r}' +f'{x!r}' +f'{n!r}' + +class D(bytes): + def __str__(self) -> str: + return "overrides __str__ of bytes" + +'{}'.format(D()) +[builtins fixtures/primitives.pyi] + +[case testFormatCallFormatTypesBytesNotPy2] +# flags: --py2 +from typing import Union, TypeVar, NewType, Generic + +A = TypeVar('A', str, unicode) +B = TypeVar('B', bound=str) + +x = '' # type: Union[str, unicode] +a = '' +b = b'' + +N = NewType('N', str) +n = N(b'') + +'{}'.format(a) +'{}'.format(b) +'{}'.format(x) +'{}'.format(n) + +u'{}'.format(a) +u'{}'.format(b) +u'{}'.format(x) +u'{}'.format(n) + +class C(Generic[B]): + x = None # type: B + def meth(self): + # type: () -> None + '{}'.format(self.x) + +def func(x): + # type: (A) -> A + '{}'.format(x) + return x + +'{!r}'.format(b) +'{!r}'.format(x) +'{!r}'.format(n) +[builtins_py2 fixtures/python2.pyi] + +[case testFormatCallFinal] +from typing_extensions import Final + +FMT: Final = '{.x}, {:{:d}}' + +FMT.format(1, 2, 'no') # E: "int" has no attribute "x" \ + # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +[builtins fixtures/primitives.pyi] + +[case testFormatCallFinalChar] +from typing_extensions import Final + +GOOD: Final = 'c' +BAD: Final = 'no' +OK: Final[str] = '...' + +'{:c}'.format(GOOD) +'{:c}'.format(BAD) # E: ":c" requires int or char +'{:c}'.format(OK) +[builtins fixtures/primitives.pyi] + +[case testFormatCallForcedConversions] +'{!r}'.format(42) +'{!s}'.format(42) +'{!s:d}'.format(42) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "int") +'{!s:s}'.format('OK') +'{} and {!x}'.format(0, 1) # E: Invalid conversion type "x", must be one of "r", "s" or "a" +[builtins fixtures/primitives.pyi] + +[case testFormatCallAccessorsBasic] +from typing import Any +x: Any + +'{.x:{[0]}}'.format('yes', 42) # E: "str" has no attribute "x" \ + # E: Value of type "int" is not indexable + +'{.1+}'.format(x) # E: Syntax error in format specifier "0.1+" +'{name.x[x]()[x]:.2f}'.format(name=x) # E: Only index and member expressions are allowed in format field accessors; got "name.x[x]()[x]" +[builtins fixtures/primitives.pyi] + +[case testFormatCallAccessorsIndices] +from typing_extensions import TypedDict + +class User(TypedDict): + id: int + name: str + +u: User +'{user[name]:.3f}'.format(user=u) # E: Incompatible types in string interpolation (expression has type "str", placeholder has type "Union[int, float]") + +def f() -> str: ... +'{[f()]}'.format(u) # E: Invalid index expression in format field accessor "[f()]" +[builtins fixtures/primitives.pyi] + +[case testFormatCallFlags] +from typing import Union + +class Good: + def __format__(self, spec: str) -> str: ... + +'{:#}'.format(42) + +'{:#}'.format('no') # E: Numeric flags are only allowed for numeric types +'{!s:#}'.format(42) # E: Numeric flags are only allowed for numeric types + +'{:#s}'.format(42) # E: Numeric flags are only allowed for numeric types +'{:+s}'.format(42) # E: Numeric flags are only allowed for numeric types + +'{:+d}'.format(42) +'{:#d}'.format(42) + +x: Union[float, Good] +'{:+f}'.format(x) +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] + +[case testFormatCallSpecialCases] +'{:08b}'.format(int('3')) + +class S: + def __int__(self) -> int: ... + +'{:+d}'.format(S()) # E: Incompatible types in string interpolation (expression has type "S", placeholder has type "int") +'%d' % S() # This is OK however +'{:%}'.format(0.001) +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-medium.pyi] diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index dba9cbcc6b31..bdf75b2dc58c 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -37,7 +37,13 @@ class B(A): def f(self, *, b: str, a: int) -> None: pass class C(A): - def f(self, *, b: int, a: str) -> None: pass # E: Signature of "f" incompatible with supertype "A" + def f(self, *, b: int, a: str) -> None: pass # Fail +[out] +main:10: error: Signature of "f" incompatible with supertype "A" +main:10: note: Superclass: +main:10: note: def f(self, *, a: int, b: str) -> None +main:10: note: Subclass: +main:10: note: def f(self, *, b: int, a: str) -> None [case testPositionalOverridingArgumentNameInsensitivity] import typing @@ -62,8 +68,13 @@ class A(object): def f(self, a: int, b: str) -> None: pass class B(A): - def f(self, b: int, a: str) -> None: pass # E: Signature of "f" incompatible with supertype "A" - + def f(self, b: int, a: str) -> None: pass # Fail +[out] +main:7: error: Signature of "f" incompatible with supertype "A" +main:7: note: Superclass: +main:7: note: def f(self, a: int, b: str) -> None +main:7: note: Subclass: +main:7: note: def f(self, b: int, a: str) -> None [case testSubtypingFunctionTypes] from typing import Callable @@ -636,9 +647,9 @@ a = None # type: A a.g() a.g(B()) a.g(a) # E: No overload variant matches argument type "A" \ - # N: Possible overload variant: \ - # N: def f(self, b: B) -> None \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def f(self) -> None \ + # N: def f(self, b: B) -> None [case testMethodAsDataAttributeInferredFromDynamicallyTypedMethod] @@ -1474,7 +1485,7 @@ x = None # type: Any if x: def f(x: int) -> None: pass # E: All conditional function variants must have identical signatures -[case testConditionalRedefinitionOfAnUnconditionalFunctionDefinition1] +[case testConditionalRedefinitionOfAnUnconditionalFunctionDefinition2] from typing import Any def f(x: int) -> None: pass # N: "f" defined here x = None # type: Any @@ -2201,7 +2212,7 @@ from typing import Callable class A: def f(self) -> None: # In particular, test that the error message contains "g" of "A". - self.g() # E: Too few arguments for "g" of "A" + self.g() # E: Too few arguments for "g" of "A" self.g(1) @dec def g(self, x: str) -> None: pass @@ -2219,6 +2230,12 @@ reveal_type(h) # N: Revealed type is "builtins.function" h(7) # E: Cannot call function of unknown type [builtins fixtures/bool.pyi] +[case testFunctionWithNameUnderscore] +def _(x: int) -> None: pass + +_(1) +_('x') # E: Argument 1 to "_" has incompatible type "str"; expected "int" + -- Positional-only arguments -- ------------------------- diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index 5cfe77b9c0fc..b6060f3922fe 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -239,3 +239,46 @@ t09: tuple[int, ...] = (1, 2, 3) from typing import Tuple t10: Tuple[int, ...] = t09 [builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinTuple] +# flags: --python-version 3.9 + +A = tuple[int, ...] +a: A = () +b: A = (1, 2, 3) +c: A = ('x', 'y') # E: Incompatible types in assignment (expression has type "Tuple[str, str]", variable has type "Tuple[int, ...]") + +B = tuple[int, str] +x: B = (1, 'x') +y: B = ('x', 1) # E: Incompatible types in assignment (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") + +reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*]" +[builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinTupleInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(m.b) # N: Revealed type is "Tuple[builtins.int, builtins.str]" + +[file m.pyi] +A = tuple[int, ...] +a: A +B = tuple[int, str] +b: B +[builtins fixtures/tuple.pyi] + +[case testTypeAliasWithBuiltinListInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(m.b) # N: Revealed type is "builtins.list[builtins.list[builtins.int]]" + +[file m.pyi] +A = list[int] +a: A +B = list[list[int]] +b: B +class C(list[int]): + pass +[builtins fixtures/list.pyi] diff --git a/test-data/unit/check-generic-subtyping.test b/test-data/unit/check-generic-subtyping.test index f1fbed9fe654..f97e3015fa32 100644 --- a/test-data/unit/check-generic-subtyping.test +++ b/test-data/unit/check-generic-subtyping.test @@ -270,9 +270,14 @@ class A: class B(A): def f(self, x: List[S], y: List[T]) -> None: pass class C(A): - def f(self, x: List[T], y: List[T]) -> None: pass # E: Signature of "f" incompatible with supertype "A" + def f(self, x: List[T], y: List[T]) -> None: pass # Fail [builtins fixtures/list.pyi] [out] +main:11: error: Signature of "f" incompatible with supertype "A" +main:11: note: Superclass: +main:11: note: def [T, S] f(self, x: List[T], y: List[S]) -> None +main:11: note: Subclass: +main:11: note: def [T] f(self, x: List[T], y: List[T]) -> None [case testOverrideGenericMethodInNonGenericClassGeneralize] from typing import TypeVar @@ -294,7 +299,10 @@ main:12: error: Argument 2 of "f" is incompatible with supertype "A"; supertype main:12: note: This violates the Liskov substitution principle main:12: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides main:14: error: Signature of "f" incompatible with supertype "A" - +main:14: note: Superclass: +main:14: note: def [S] f(self, x: int, y: S) -> None +main:14: note: Subclass: +main:14: note: def [T1 <: str, S] f(self, x: T1, y: S) -> None -- Inheritance from generic types with implicit dynamic supertype -- -------------------------------------------------------------- @@ -809,4 +817,219 @@ class Y(Generic[T]): def f(self) -> T: return U() # E: Incompatible return value type (got "U", expected "T") + +[case testTypeVarBoundToOldUnionAttributeAccess] +from typing import Union, TypeVar + +class U: + a: float +class V: + b: float +class W: + c: float + +T = TypeVar("T", bound=Union[U, V, W]) + +def f(x: T) -> None: + x.a # E + x.b = 1.0 # E + del x.c # E + +[out] +main:13: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a" +main:13: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a" +main:14: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b" +main:14: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b" +main:15: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c" +main:15: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c" + + +[case testTypeVarBoundToNewUnionAttributeAccess] +# flags: --python-version 3.10 +from typing import TypeVar + +class U: + a: int +class V: + b: int +class W: + c: int + +T = TypeVar("T", bound=U | V | W) + +def f(x: T) -> None: + x.a # E + x.b = 1 # E + del x.c # E + +[builtins fixtures/tuple.pyi] +[out] +main:14: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a" +main:14: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a" +main:15: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b" +main:15: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b" +main:16: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c" +main:16: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c" + + +[case testSubtypingIterableUnpacking1] +# https://github.com/python/mypy/issues/11138 +from typing import Generic, Iterator, TypeVar +T = TypeVar("T") +U = TypeVar("U") + +class X1(Iterator[U], Generic[T, U]): + pass + +x1: X1[str, int] +reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int*]" + +class X2(Iterator[T], Generic[T, U]): + pass + +x2: X2[str, int] +reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.str*]" + +class X3(Generic[T, U], Iterator[U]): + pass + +x3: X3[str, int] +reveal_type(list(x3)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type([*x3]) # N: Revealed type is "builtins.list[builtins.int*]" + +class X4(Generic[T, U], Iterator[T]): + pass + +x4: X4[str, int] +reveal_type(list(x4)) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type([*x4]) # N: Revealed type is "builtins.list[builtins.str*]" + +class X5(Iterator[T]): + pass + +x5: X5[str] +reveal_type(list(x5)) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type([*x5]) # N: Revealed type is "builtins.list[builtins.str*]" + +class X6(Generic[T, U], Iterator[bool]): + pass + +x6: X6[str, int] +reveal_type(list(x6)) # N: Revealed type is "builtins.list[builtins.bool*]" +reveal_type([*x6]) # N: Revealed type is "builtins.list[builtins.bool*]" +[builtins fixtures/list.pyi] + +[case testSubtypingIterableUnpacking2] +from typing import Generic, Iterator, TypeVar, Mapping +T = TypeVar("T") +U = TypeVar("U") + +class X1(Generic[T, U], Iterator[U], Mapping[U, T]): + pass + +x1: X1[str, int] +reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int*]" + +class X2(Generic[T, U], Iterator[U], Mapping[T, U]): + pass + +x2: X2[str, int] +reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int*]" +[builtins fixtures/list.pyi] + +[case testSubtypingMappingUnpacking1] +# https://github.com/python/mypy/issues/11138 +from typing import Generic, TypeVar, Mapping +T = TypeVar("T") +U = TypeVar("U") + +class X1(Generic[T, U], Mapping[U, T]): + pass + +x1: X1[str, int] +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" + +class X2(Generic[T, U], Mapping[T, U]): + pass + +x2: X2[str, int] +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.str*]" +reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" + +class X3(Generic[T, U], Mapping[bool, float]): + pass + +x3: X3[str, int] +reveal_type(iter(x3)) # N: Revealed type is "typing.Iterator[builtins.bool*]" +reveal_type({**x3}) # N: Revealed type is "builtins.dict[builtins.bool*, builtins.float*]" +[builtins fixtures/dict.pyi] + +[case testSubtypingMappingUnpacking2] +from typing import Generic, TypeVar, Mapping +T = TypeVar("T") +U = TypeVar("U") + +class X1(Generic[T, U], Mapping[U, T]): + pass + +def func_with_kwargs(**kwargs: int): + pass + +x1: X1[str, int] +reveal_type(iter(x1)) +reveal_type({**x1}) +func_with_kwargs(**x1) [out] +main:12: note: Revealed type is "typing.Iterator[builtins.int*]" +main:13: note: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +main:14: error: Keywords must be strings +main:14: error: Argument 1 to "func_with_kwargs" has incompatible type "**X1[str, int]"; expected "int" +[builtins fixtures/dict.pyi] + +[case testSubtypingMappingUnpacking3] +from typing import Generic, TypeVar, Mapping, Iterable +T = TypeVar("T") +U = TypeVar("U") + +class X1(Generic[T, U], Mapping[U, T], Iterable[U]): + pass + +x1: X1[str, int] +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" + +# Some people would expect this to raise an error, but this currently does not: +# `Mapping` has `Iterable[U]` base class, `X2` has direct `Iterable[T]` base class. +# It would be impossible to define correct `__iter__` method for incompatible `T` and `U`. +class X2(Generic[T, U], Mapping[U, T], Iterable[T]): + pass + +x2: X2[str, int] +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int*]" +reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +[builtins fixtures/dict.pyi] + +[case testNotDirectIterableAndMappingSubtyping] +from typing import Generic, TypeVar, Dict, Iterable, Iterator, List +T = TypeVar("T") +U = TypeVar("U") + +class X1(Generic[T, U], Dict[U, T], Iterable[U]): + def __iter__(self) -> Iterator[U]: pass + +x1: X1[str, int] +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" + +class X2(Generic[T, U], List[U]): + def __iter__(self) -> Iterator[U]: pass + +x2: X2[str, int] +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int*]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int*]" +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 50676de65764..ed0b680e21aa 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -52,7 +52,7 @@ class C: pass [out] main:8: error: Incompatible types in assignment (expression has type "C", variable has type "B") -[case testGenericMemberVariable] +[case testGenericMemberVariable2] from typing import TypeVar, Generic T = TypeVar('T') a, b, c = None, None, None # type: (A[B], B, C) @@ -1672,7 +1672,7 @@ def f(x: T) -> str: [case testTypeVarReversibleOperatorTuple] from typing import TypeVar, Tuple class A(Tuple[int, int]): - def __mul__(cls, other: Tuple[int, int]) -> str: return "" + def __mul__(cls, other: Tuple[int, int]) -> str: return "" # type: ignore # overriding default __mul__ T = TypeVar("T", bound=A) def f(x: T) -> str: return reveal_type(x * (1, 2) ) # N: Revealed type is "builtins.str" @@ -2079,9 +2079,9 @@ reveal_type(Base.make_some(1, 1)) # N: Revealed type is "builtins.tuple[__main_ class Sub(Base[str]): ... Sub.make_some(1) # E: No overload variant of "make_some" of "Base" matches argument type "int" \ - # N: Possible overload variant: \ + # N: Possible overload variants: \ # N: def make_some(cls, item: str) -> Sub \ - # N: <1 more non-matching overload not shown> + # N: def make_some(cls, item: str, n: int) -> Tuple[Sub, ...] [builtins fixtures/classmethod.pyi] [case testNoGenericAccessOnImplicitAttributes] @@ -2118,7 +2118,7 @@ class B(A[T], Generic[T, S]): reveal_type(B.foo) # N: Revealed type is "def [T, S] () -> Tuple[T`1, __main__.B[T`1, S`2]]" [builtins fixtures/classmethod.pyi] -[case testGenericClassAlternativeConstructorPrecise] +[case testGenericClassAlternativeConstructorPrecise2] from typing import Generic, TypeVar, Type, Tuple, Any T = TypeVar('T') @@ -2430,3 +2430,77 @@ class C: ... def test() -> Optional[S]: reveal_type(A().gen(C())) # N: Revealed type is "__main__.C*" return None + +[case testGenericJoinCovariant] +from typing import Generic, TypeVar, List + +T = TypeVar("T", covariant=True) + +class Container(Generic[T]): ... +class Base: ... +class A(Base): ... +class B(Base): ... + +a: A +b: B + +a_c: Container[A] +b_c: Container[B] + +reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.Base*]" +reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[__main__.Container*[__main__.Base]]" +[builtins fixtures/list.pyi] + +[case testGenericJoinContravariant] +from typing import Generic, TypeVar, List + +T = TypeVar("T", contravariant=True) + +class Container(Generic[T]): ... +class A: ... +class B(A): ... + +a_c: Container[A] +b_c: Container[B] + +# TODO: this can be more precise than "object", see a comment in mypy/join.py +reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[builtins.object*]" +[builtins fixtures/list.pyi] + +[case testGenericJoinRecursiveTypes] +from typing import Sequence, TypeVar + +class A(Sequence[A]): ... +class B(Sequence[B]): ... + +a: A +b: B + +reveal_type([a, b]) # N: Revealed type is "builtins.list[typing.Sequence*[builtins.object]]" +[builtins fixtures/list.pyi] + +[case testGenericJoinRecursiveInvariant] +from typing import Generic, TypeVar + +T = TypeVar("T") +class I(Generic[T]): ... + +class A(I[A]): ... +class B(I[B]): ... + +a: A +b: B +reveal_type([a, b]) # N: Revealed type is "builtins.list[builtins.object*]" +[builtins fixtures/list.pyi] + +[case testGenericJoinNestedInvariantAny] +from typing import Any, Generic, TypeVar + +T = TypeVar("T") +class I(Generic[T]): ... + +a: I[I[int]] +b: I[I[Any]] +reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.I*[__main__.I[Any]]]" +reveal_type([b, a]) # N: Revealed type is "builtins.list[__main__.I*[__main__.I[Any]]]" +[builtins fixtures/list.pyi] diff --git a/test-data/unit/check-ignore.test b/test-data/unit/check-ignore.test index 686dece1c911..048410ecbab7 100644 --- a/test-data/unit/check-ignore.test +++ b/test-data/unit/check-ignore.test @@ -222,7 +222,7 @@ yield # type: ignore # E: "yield" outside function [case testIgnoreWholeModule1] # flags: --warn-unused-ignores # type: ignore -IGNORE # type: ignore # E: unused "type: ignore" comment +IGNORE # type: ignore # E: Unused "type: ignore" comment [case testIgnoreWholeModule2] # type: ignore diff --git a/test-data/unit/check-incomplete-fixture.test b/test-data/unit/check-incomplete-fixture.test index 8c5ec0899069..f06dad293184 100644 --- a/test-data/unit/check-incomplete-fixture.test +++ b/test-data/unit/check-incomplete-fixture.test @@ -12,14 +12,6 @@ import m m.x # E: "object" has no attribute "x" [file m.py] -[case testListMissingFromStubs] -from typing import List -def f(x: List[int]) -> None: pass -[out] -main:1: error: Module "typing" has no attribute "List" -main:1: note: Maybe your test fixture does not define "builtins.list"? -main:1: note: Consider adding [builtins fixtures/list.pyi] to your test description - [case testDictMissingFromStubs] from typing import Dict def f(x: Dict[int]) -> None: pass diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 216dcae36338..ec1dff4977d4 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -2886,7 +2886,7 @@ tmp/m/a.py:1: error: Unsupported operand types for + ("int" and "str") [case testDisallowAnyExprIncremental] # cmd: mypy -m main -# flags: --disallow-any-expr +# flags: --disallow-any-expr [file ns.py] class Namespace: @@ -3671,7 +3671,7 @@ pass [out] [out2] [out3] -tmp/a.py:2: error: unused "type: ignore" comment +tmp/a.py:2: error: Unused "type: ignore" comment -- Test that a non cache_fine_grained run can use a fine-grained cache [case testRegularUsesFgCache] @@ -3682,9 +3682,11 @@ x = 0 [file mypy.ini] \[mypy] cache_fine_grained = True +local_partial_types = True [file mypy.ini.2] \[mypy] cache_fine_grained = False +local_partial_types = True -- Nothing should get rechecked [rechecked] [stale] @@ -3828,7 +3830,7 @@ class A: E = 7 F: ClassVar[int] = 22 -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] @@ -3861,7 +3863,7 @@ from dataclasses import dataclass class A: x: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] tmp/b.py:8: note: Revealed type is "def (x: builtins.int) -> b.B" @@ -3906,7 +3908,7 @@ class NoInit: class NoCmp: x: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] tmp/b.py:4: error: Property "x" defined in "Frozen" is read-only @@ -3961,7 +3963,7 @@ from dataclasses import dataclass class A: a: int -[builtins fixtures/attr.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] tmp/b.py:3: note: Revealed type is "def (a: builtins.int) -> a.A" @@ -4008,7 +4010,7 @@ from dataclasses import dataclass class B(A): y: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] main:3: error: Argument 2 to "B" has incompatible type "str"; expected "int" @@ -4042,7 +4044,7 @@ from dataclasses import dataclass class B(A): y: str -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] main:3: error: Argument 2 to "B" has incompatible type "str"; expected "int" @@ -4085,7 +4087,7 @@ from dataclasses import dataclass class C(A, B): c: bool -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] tmp/c.py:7: error: Incompatible types in assignment (expression has type "bool", base class "B" defined the type as "str") @@ -4117,7 +4119,7 @@ from dataclasses import dataclass class A: a: int = 6 -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out1] [out2] main:3: error: Argument 1 to "A" has incompatible type "int"; expected "str" @@ -5561,3 +5563,73 @@ class D: [out2] tmp/a.py:2: note: Revealed type is "builtins.list[builtins.int]" tmp/a.py:3: note: Revealed type is "builtins.list[builtins.str]" + +[case testIncrementalNamespacePackage1] +# flags: --namespace-packages +import m +[file m.py] +from foo.bar import x +x + 0 +[file foo/bar.py] +x = 0 +[rechecked] +[stale] + +[case testIncrementalNamespacePackage2] +# flags: --namespace-packages +import m +[file m.py] +from foo import bar +bar.x + 0 +[file foo/bar.py] +x = 0 +[rechecked] +[stale] + +[case testExplicitReexportImportCycleWildcard] +# flags: --no-implicit-reexport +import pkg.a +[file pkg/__init__.pyi] + +[file pkg/a.pyi] +MYPY = False +if MYPY: + from pkg.b import B + +[file pkg/b.pyi] +import pkg.a +MYPY = False +if MYPY: + from pkg.c import C +class B: + pass + +[file pkg/c.pyi] +from pkg.a import * +class C: + pass +[rechecked] +[stale] + + +[case testEnumAreStillFinalAfterCache] +import a +class Ok(a.RegularEnum): + x = 1 +class NotOk(a.FinalEnum): + x = 1 +[file a.py] +from enum import Enum +class RegularEnum(Enum): + x: int +class FinalEnum(Enum): + x = 1 +[builtins fixtures/isinstance.pyi] +[out] +main:3: error: Cannot override writable attribute "x" with a final one +main:4: error: Cannot inherit from final class "FinalEnum" +main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") +[out2] +main:3: error: Cannot override writable attribute "x" with a final one +main:4: error: Cannot inherit from final class "FinalEnum" +main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index 82a412eeb359..e3ec55c516db 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -1375,3 +1375,47 @@ def f(x: Callable[..., T]) -> T: x: G[str] = f(G) [out] + +[case testConditionalExpressionWithEmptyListAndUnionWithAny] +from typing import Union, List, Any + +def f(x: Union[List[str], Any]) -> None: + a = x if x else [] + reveal_type(a) # N: Revealed type is "Union[builtins.list[Union[builtins.str, Any]], builtins.list[builtins.str], Any]" +[builtins fixtures/list.pyi] + +[case testConditionalExpressionWithEmptyIteableAndUnionWithAny] +from typing import Union, Iterable, Any + +def f(x: Union[Iterable[str], Any]) -> None: + a = x if x else [] + reveal_type(a) # N: Revealed type is "Union[builtins.list[Union[builtins.str, Any]], typing.Iterable[builtins.str], Any]" +[builtins fixtures/list.pyi] + +[case testInferMultipleAnyUnionCovariant] +from typing import Any, Mapping, Sequence, Union + +def foo(x: Union[Mapping[Any, Any], Mapping[Any, Sequence[Any]]]) -> None: + ... +foo({1: 2}) +[builtins fixtures/dict.pyi] + +[case testInferMultipleAnyUnionInvariant] +from typing import Any, Dict, Sequence, Union + +def foo(x: Union[Dict[Any, Any], Dict[Any, Sequence[Any]]]) -> None: + ... +foo({1: 2}) +[builtins fixtures/dict.pyi] + +[case testInferMultipleAnyUnionDifferentVariance] +from typing import Any, Dict, Mapping, Sequence, Union + +def foo(x: Union[Dict[Any, Any], Mapping[Any, Sequence[Any]]]) -> None: + ... +foo({1: 2}) + +def bar(x: Union[Mapping[Any, Any], Dict[Any, Sequence[Any]]]) -> None: + ... +bar({1: 2}) +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index de5a9a5806c6..adf4a7b60420 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -287,8 +287,8 @@ main:6: error: Need more than 3 values to unpack (4 expected) [case testInvalidRvalueTypeInInferredMultipleLvarDefinition] import typing def f() -> None: - a, b = f # E: "def ()" object is not iterable - c, d = A() # E: "__main__.A" object is not iterable + a, b = f # E: "Callable[[], None]" object is not iterable + c, d = A() # E: "A" object is not iterable class A: pass [builtins fixtures/for.pyi] [out] @@ -296,8 +296,8 @@ class A: pass [case testInvalidRvalueTypeInInferredNestedTupleAssignment] import typing def f() -> None: - a1, (a2, b) = A(), f # E: "def ()" object is not iterable - a3, (c, d) = A(), A() # E: "__main__.A" object is not iterable + a1, (a2, b) = A(), f # E: "Callable[[], None]" object is not iterable + a3, (c, d) = A(), A() # E: "A" object is not iterable class A: pass [builtins fixtures/for.pyi] [out] @@ -791,10 +791,10 @@ AnyStr = TypeVar('AnyStr', bytes, str) def f(x: Union[AnyStr, int], *a: AnyStr) -> None: pass f('foo') f('foo', 'bar') -f('foo', b'bar') # E: Value of type variable "AnyStr" of "f" cannot be "object" +f('foo', b'bar') # E: Value of type variable "AnyStr" of "f" cannot be "Sequence[object]" f(1) f(1, 'foo') -f(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "f" cannot be "object" +f(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "f" cannot be "Sequence[object]" [builtins fixtures/primitives.pyi] @@ -1004,7 +1004,7 @@ main:4: error: Incompatible types in assignment (expression has type "A", variab main:5: error: Incompatible types in assignment (expression has type "B", variable has type "C") main:6: error: Incompatible types in assignment (expression has type "C", variable has type "A") main:10: error: Need more than 2 values to unpack (3 expected) -main:12: error: "__main__.B" object is not iterable +main:12: error: "B" object is not iterable [case testInferenceOfFor3] @@ -1547,9 +1547,9 @@ def f(blocks: Any): # E: Name "Any" is not defined \ def f(blocks: object): to_process = [] to_process = list(blocks) # E: No overload variant of "list" matches argument type "object" \ - # N: Possible overload variant: \ - # N: def [T] __init__(self, x: Iterable[T]) -> List[T] \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def [T] __init__(self) -> List[T] \ + # N: def [T] __init__(self, x: Iterable[T]) -> List[T] [builtins fixtures/list.pyi] [case testInferListInitializedToEmptyAndAssigned] @@ -1975,7 +1975,7 @@ T = TypeVar('T') class A: def f(self) -> None: - self.g() # E: Too few arguments for "g" of "A" + self.g() # E: Too few arguments for "g" of "A" self.g(1) @dec def g(self, x: str) -> None: pass @@ -2614,7 +2614,7 @@ class C(B): reveal_type(B.x) # N: Revealed type is "None" reveal_type(C.x) # N: Revealed type is "None" -[case testLocalPartialTypesWithInheritance2] +[case testLocalPartialTypesWithInheritance3] # flags: --local-partial-types from typing import Optional @@ -2652,7 +2652,7 @@ class C: def f(self, x) -> None: C.a.y # E: Item "None" of "Optional[Any]" has no attribute "y" -[case testLocalPartialTypesAccessPartialNoneAttribute] +[case testLocalPartialTypesAccessPartialNoneAttribute2] # flags: --local-partial-types class C: a = None # E: Need type annotation for "a" @@ -2751,12 +2751,6 @@ def foo() -> None: pass _().method() # E: "_" has no attribute "method" -[case testUnusedTargetNotDef] -def foo() -> None: - def _() -> int: - pass - _() + '' # E: Unsupported operand types for + ("int" and "str") - [case testUnusedTargetForLoop] def f() -> None: a = [(0, '', 0)] @@ -3176,3 +3170,43 @@ reveal_type(f(lambda: 1)) # N: Revealed type is "builtins.int*" def g() -> None: pass reveal_type(f(g)) # N: Revealed type is "None" + +[case testInferredTypeIsSimpleNestedList] +from typing import Any, Union, List + +y: Union[List[Any], Any] +x: Union[List[Any], Any] +x = [y] +reveal_type(x) # N: Revealed type is "builtins.list[Any]" +[builtins fixtures/list.pyi] + +[case testInferredTypeIsSimpleNestedIterable] +from typing import Any, Union, Iterable + +y: Union[Iterable[Any], Any] +x: Union[Iterable[Any], Any] +x = [y] +reveal_type(x) # N: Revealed type is "builtins.list[Any]" +[builtins fixtures/list.pyi] + +[case testInferredTypeIsSimpleNestedListLoop] +from typing import Any, Union, List + +def test(seq: List[Union[List, Any]]) -> None: + k: Union[List, Any] + for k in seq: + if bool(): + k = [k] + reveal_type(k) # N: Revealed type is "builtins.list[Any]" +[builtins fixtures/list.pyi] + +[case testInferredTypeIsSimpleNestedIterableLoop] +from typing import Any, Union, List, Iterable + +def test(seq: List[Union[Iterable, Any]]) -> None: + k: Union[Iterable, Any] + for k in seq: + if bool(): + k = [k] + reveal_type(k) # N: Revealed type is "builtins.list[Any]" +[builtins fixtures/list.pyi] diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 6c6efaee001c..f531947d1faf 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -2348,6 +2348,53 @@ if isinstance(y, B): reveal_type(y) # E: Statement is unreachable [builtins fixtures/isinstance.pyi] +[case testIsInstanceAdHocIntersectionReversed] +# flags: --warn-unreachable + +from abc import abstractmethod +from typing_extensions import Literal + +class A0: + def f(self) -> Literal[0]: + ... + +class A1: + def f(self) -> Literal[1]: + ... + +class A2: + def f(self) -> Literal[2]: + ... + +class B: + @abstractmethod + def f(self) -> Literal[1, 2]: + ... + + def t0(self) -> None: + if isinstance(self, A0): # E: Subclass of "B" and "A0" cannot exist: would have incompatible method signatures + x0: Literal[0] = self.f() # E: Statement is unreachable + + def t1(self) -> None: + if isinstance(self, A1): + reveal_type(self) # N: Revealed type is "__main__." + x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1]", variable has type "Literal[0]") + x1: Literal[1] = self.f() + + def t2(self) -> None: + if isinstance(self, (A0, A1)): # E: Subclass of "B" and "A0" cannot exist: would have incompatible method signatures + reveal_type(self) # N: Revealed type is "__main__.1" + x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1]", variable has type "Literal[0]") + x1: Literal[1] = self.f() + + def t3(self) -> None: + if isinstance(self, (A1, A2)): + reveal_type(self) # N: Revealed type is "Union[__main__.2, __main__.]" + x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Union[Literal[1], Literal[2]]", variable has type "Literal[0]") + x1: Literal[1] = self.f() # E: Incompatible types in assignment (expression has type "Union[Literal[1], Literal[2]]", variable has type "Literal[1]") + +[builtins fixtures/isinstance.pyi] + [case testIsInstanceAdHocIntersectionGenerics] # flags: --warn-unreachable from typing import Generic, TypeVar diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 8753fed15f5a..7f0b8af3ba0e 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -252,7 +252,7 @@ class B: pass [case testCallingDynamicallyTypedFunctionWithKeywordArgs] import typing -def f(x, y=A()): pass +def f(x, y=A()): pass # N: "f" defined here f(x=A(), y=A()) f(y=A(), x=A()) f(y=A()) # E: Missing positional argument "x" in call to "f" @@ -299,8 +299,9 @@ d = None # type: Dict[str, A] f(**d) f(x=A(), **d) d2 = None # type: Dict[str, B] -f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, B]"; expected "A" -f(x=A(), **d2) # E: Argument 2 to "f" has incompatible type "**Dict[str, B]"; expected "A" +f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, B]"; expected "A" +f(x=A(), **d2) # E: Argument 2 to "f" has incompatible type "**Dict[str, B]"; expected "A" +f(**{'x': B()}) # E: Argument 1 to "f" has incompatible type "**Dict[str, B]"; expected "A" class A: pass class B: pass [builtins fixtures/dict.pyi] @@ -396,7 +397,7 @@ class A: pass from typing import Any, Dict def f(*args: 'A') -> None: pass d = None # type: Dict[Any, Any] -f(**d) # E: Too many arguments for "f" +f(**d) class A: pass [builtins fixtures/dict.pyi] @@ -489,5 +490,67 @@ g(**d) # E: Argument 1 to "g" has incompatible type "**Dict[str, object]"; expe m = {} # type: Mapping[str, object] f(**m) -g(**m) # TODO: Should be an error +g(**m) # E: Argument 1 to "g" has incompatible type "**Mapping[str, object]"; expected "int" +[builtins fixtures/dict.pyi] + +[case testPassingEmptyDictWithStars] +def f(): pass +def g(x=1): pass + +f(**{}) +g(**{}) +[builtins fixtures/dict.pyi] + +[case testKeywordUnpackWithDifferentTypes] +# https://github.com/python/mypy/issues/11144 +from typing import Dict, Generic, TypeVar, Mapping + +T = TypeVar("T") +T2 = TypeVar("T2") + +class A(Dict[T, T2]): + ... + +class B(Mapping[T, T2]): + ... + +class C(Generic[T, T2]): + ... + +class D: + ... + +def foo(**i: float) -> float: + ... + +a: A[str, str] +b: B[str, str] +c: C[str, float] +d: D +e = {"a": "b"} + +foo(k=1.5) +foo(**a) +foo(**b) +foo(**c) +foo(**d) +foo(**e) + +# Correct: + +class Good(Mapping[str, float]): + ... + +good1: Good +good2: A[str, float] +good3: B[str, float] +foo(**good1) +foo(**good2) +foo(**good3) +[out] +main:29: error: Argument 1 to "foo" has incompatible type "**A[str, str]"; expected "float" +main:30: error: Argument 1 to "foo" has incompatible type "**B[str, str]"; expected "float" +main:31: error: Argument after ** must be a mapping, not "C[str, float]" +main:32: error: Argument after ** must be a mapping, not "D" +main:33: error: Argument 1 to "foo" has incompatible type "**Dict[str, str]"; expected "float" [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test index e96d72c7358b..37ae12419151 100644 --- a/test-data/unit/check-literal.test +++ b/test-data/unit/check-literal.test @@ -2687,11 +2687,8 @@ def force2(x: Tuple[Literal[1], Literal[2]]) -> None: pass reveal_type(a) # N: Revealed type is "Literal[1]?" reveal_type(b) # N: Revealed type is "Tuple[Literal[1]?, Literal[2]?]" -# TODO: This test seems somewhat broken and might need a rewrite (and a fix somewhere in mypy). -# See https://github.com/python/mypy/issues/7399#issuecomment-554188073 for more context. -force1(reveal_type(a)) # N: Revealed type is "Literal[1]" -force2(reveal_type(b)) # E: Argument 1 to "force2" has incompatible type "Tuple[int, int]"; expected "Tuple[Literal[1], Literal[2]]" \ - # N: Revealed type is "Tuple[Literal[1]?, Literal[2]?]" +force1(a) # ok +force2(b) # ok [builtins fixtures/tuple.pyi] [out] @@ -3304,3 +3301,48 @@ else: reveal_type(w) # E: Statement is unreachable [builtins fixtures/bool.pyi] + +[case testLiteralAndInstanceSubtyping] +# https://github.com/python/mypy/issues/7399 +# https://github.com/python/mypy/issues/11232 +from typing import Tuple, Union +from typing_extensions import Literal, Final + +x: bool + +def f() -> Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]: + if x: + return (True, 5) + else: + return (False, 'oops') + +reveal_type(f()) # N: Revealed type is "Union[Tuple[Literal[True], builtins.int], Tuple[Literal[False], builtins.str]]" + +def does_work() -> Tuple[Literal[1]]: + x: Final = (1,) + return x + +def also_works() -> Tuple[Literal[1]]: + x: Tuple[Literal[1]] = (1,) + return x + +def invalid_literal_value() -> Tuple[Literal[1]]: + x: Final = (2,) + return x # E: Incompatible return value type (got "Tuple[int]", expected "Tuple[Literal[1]]") + +def invalid_literal_type() -> Tuple[Literal[1]]: + x: Final = (True,) + return x # E: Incompatible return value type (got "Tuple[bool]", expected "Tuple[Literal[1]]") + +def incorrect_return1() -> Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]: + if x: + return (False, 5) # E: Incompatible return value type (got "Tuple[bool, int]", expected "Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]") + else: + return (True, 'oops') # E: Incompatible return value type (got "Tuple[bool, str]", expected "Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]") + +def incorrect_return2() -> Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]: + if x: + return (bool(), 5) # E: Incompatible return value type (got "Tuple[bool, int]", expected "Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]") + else: + return (bool(), 'oops') # E: Incompatible return value type (got "Tuple[bool, str]", expected "Union[Tuple[Literal[True], int], Tuple[Literal[False], str]]") +[builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-modules-case.test b/test-data/unit/check-modules-case.test index bc2e91aacfdc..b9e48888fea3 100644 --- a/test-data/unit/check-modules-case.test +++ b/test-data/unit/check-modules-case.test @@ -1,6 +1,14 @@ -- Type checker test cases dealing with modules and imports on case-insensitive filesystems. [case testCaseSensitivityDir] +# flags: --no-namespace-packages +from a import B # E: Module "a" has no attribute "B" + +[file a/__init__.py] +[file a/b/__init__.py] + +[case testCaseSensitivityDirNamespacePackages] +# flags: --namespace-packages from a import B # E: Module "a" has no attribute "B" [file a/__init__.py] diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index ddabfe252253..071fcf54f2b6 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1,7 +1,7 @@ -- Type checker test cases dealing with modules and imports. -- Towards the end there are tests for PEP 420 (namespace packages, i.e. __init__.py-less packages). -[case testAccessImportedDefinitions] +[case testAccessImportedDefinitions0] import m import typing m.f() # E: Missing positional argument "a" in call to "f" @@ -14,7 +14,7 @@ class A: pass def f(a: A) -> None: pass x = A() -[case testAccessImportedDefinitions] +[case testAccessImportedDefinitions1] import m import typing m.f(object()) # E: Argument 1 to "f" has incompatible type "object"; expected "A" @@ -1676,10 +1676,10 @@ reveal_type(n2.b) # N: Revealed type is "builtins.str" reveal_type(m3.a) # N: Revealed type is "builtins.str" reveal_type(n3.b) # N: Revealed type is "builtins.str" -x, y = m # E: "types.ModuleType" object is not iterable +x, y = m # E: Module object is not iterable x, y, z = m, n # E: Need more than 2 values to unpack (3 expected) x, y = m, m, m # E: Too many values to unpack (2 expected, 3 provided) -x, (y, z) = m, n # E: "types.ModuleType" object is not iterable +x, (y, z) = m, n # E: Module object is not iterable x, (y, z) = m, (n, n, n) # E: Too many values to unpack (2 expected, 3 provided) [file m.py] @@ -2000,7 +2000,7 @@ reveal_type(has_getattr.any_attribute) def __getattr__(x: int, y: str) -> str: ... [out] -tmp/has_getattr.pyi:1: error: Invalid signature "def (builtins.int, builtins.str) -> builtins.str" for "__getattr__" +tmp/has_getattr.pyi:1: error: Invalid signature "Callable[[int, str], str]" for "__getattr__" main:3: note: Revealed type is "builtins.str" [builtins fixtures/module.pyi] @@ -2014,7 +2014,7 @@ reveal_type(has_getattr.any_attribute) __getattr__ = 3 [out] -tmp/has_getattr.pyi:1: error: Invalid signature "builtins.int" for "__getattr__" +tmp/has_getattr.pyi:1: error: Invalid signature "int" for "__getattr__" main:3: note: Revealed type is "Any" [builtins fixtures/module.pyi] @@ -2141,7 +2141,7 @@ def make_getattr_bad() -> Callable[[], int]: ... __getattr__ = make_getattr_bad() [out] -tmp/non_stub.py:4: error: Invalid signature "def () -> builtins.int" for "__getattr__" +tmp/non_stub.py:4: error: Invalid signature "Callable[[], int]" for "__getattr__" main:3: note: Revealed type is "builtins.int" [case testModuleLevelGetattrImportedGood] @@ -2167,7 +2167,7 @@ from has_getattr import __getattr__ def __getattr__() -> int: ... [out] -tmp/has_getattr.py:1: error: Invalid signature "def () -> builtins.int" for "__getattr__" +tmp/has_getattr.py:1: error: Invalid signature "Callable[[], int]" for "__getattr__" main:3: note: Revealed type is "builtins.int" [builtins fixtures/module.pyi] @@ -2888,6 +2888,16 @@ from mystery import a, b as b, c as d tmp/stub.pyi:1: error: Cannot find implementation or library stub for module named "mystery" tmp/stub.pyi:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +[case testPackagePath] +import p +reveal_type(p.__path__) # N: Revealed type is "builtins.list[builtins.str]" +p.m.__path__ # E: "object" has no attribute "__path__" + +[file p/__init__.py] +from . import m as m +[file p/m.py] +[builtins fixtures/list.pyi] + [case testReExportAllInStub] from m1 import C from m1 import D # E: Module "m1" has no attribute "D" @@ -2982,3 +2992,182 @@ T = TypeVar("T") class F(M): x: C class C: ... + +[case testLimitLegacyStubErrorVolume] +# flags: --disallow-any-expr --soft-error-limit=5 +import certifi # E: Cannot find implementation or library stub for module named "certifi" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # N: (Skipping most remaining errors due to unresolved imports or missing stubs; fix these first) +certifi.x +certifi.x +certifi.x +certifi.x + +[case testDoNotLimitErrorVolumeIfNotImportErrors] +# flags: --disallow-any-expr --soft-error-limit=5 +def f(): pass +certifi = f() # E: Expression has type "Any" +1() # E: "int" not callable +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +1() # E: "int" not callable + +[case testDoNotLimitImportErrorVolume] +# flags: --disallow-any-expr --soft-error-limit=3 +import xyz1 # E: Cannot find implementation or library stub for module named "xyz1" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +import xyz2 # E: Cannot find implementation or library stub for module named "xyz2" +import xyz3 # E: Cannot find implementation or library stub for module named "xyz3" +import xyz4 # E: Cannot find implementation or library stub for module named "xyz4" + +[case testUnlimitedStubErrorVolume] +# flags: --disallow-any-expr --soft-error-limit=-1 +import certifi # E: Cannot find implementation or library stub for module named "certifi" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" +certifi.x # E: Expression has type "Any" + +[case testIgnoreErrorFromMissingStubs1] +# flags: --config-file tmp/pyproject.toml +import certifi +from foobar1 import x +import foobar2 +[file pyproject.toml] +\[tool.mypy] +ignore_missing_imports = true +\[[tool.mypy.overrides]] +module = "certifi" +ignore_missing_imports = true +\[[tool.mypy.overrides]] +module = "foobar1" +ignore_missing_imports = true + +[case testIgnoreErrorFromMissingStubs2] +# flags: --config-file tmp/pyproject.toml +import certifi +from foobar1 import x +import foobar2 # E: Cannot find implementation or library stub for module named "foobar2" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +[file pyproject.toml] +\[tool.mypy] +ignore_missing_imports = false +\[[tool.mypy.overrides]] +module = "certifi" +ignore_missing_imports = true +\[[tool.mypy.overrides]] +module = "foobar1" +ignore_missing_imports = true + +[case testIgnoreErrorFromGoogleCloud] +# flags: --ignore-missing-imports +import google.cloud +from google.cloud import x + +[case testErrorFromGoogleCloud] +import google.cloud +from google.cloud import x +[out] +main:1: error: Cannot find implementation or library stub for module named "google.cloud" +main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:1: error: Cannot find implementation or library stub for module named "google" + +[case testMissingSubmoduleOfInstalledStubPackage] +import bleach.xyz +from bleach.abc import fgh +[file bleach/__init__.pyi] +[out] +main:1: error: Cannot find implementation or library stub for module named "bleach.xyz" +main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:2: error: Cannot find implementation or library stub for module named "bleach.abc" + +[case testMissingSubmoduleOfInstalledStubPackageIgnored] +# flags: --ignore-missing-imports +import bleach.xyz +from bleach.abc import fgh +[file bleach/__init__.pyi] + +[case testCyclicUndefinedImportWithName] +import a +[file a.py] +from b import no_such_export +[file b.py] +from a import no_such_export # E: Module "a" has no attribute "no_such_export" + +[case testCyclicUndefinedImportWithStar1] +import a +[file a.py] +from b import no_such_export +[file b.py] +from a import * +[out] +tmp/b.py:1: error: Cannot resolve name "no_such_export" (possible cyclic definition) +tmp/a.py:1: error: Module "b" has no attribute "no_such_export" + +[case testCyclicUndefinedImportWithStar2] +import a +[file a.py] +from b import no_such_export +[file b.py] +from c import * +[file c.py] +from a import * +[out] +tmp/c.py:1: error: Cannot resolve name "no_such_export" (possible cyclic definition) +tmp/b.py:1: error: Cannot resolve name "no_such_export" (possible cyclic definition) +tmp/a.py:1: error: Module "b" has no attribute "no_such_export" + +[case testCyclicUndefinedImportWithStar3] +import test1 +[file test1.py] +from dir1 import * +[file dir1/__init__.py] +from .test2 import * +[file dir1/test2.py] +from test1 import aaaa # E: Module "test1" has no attribute "aaaa" diff --git a/test-data/unit/check-multiple-inheritance.test b/test-data/unit/check-multiple-inheritance.test index a7701dab0c39..a8d053f9504e 100644 --- a/test-data/unit/check-multiple-inheritance.test +++ b/test-data/unit/check-multiple-inheritance.test @@ -502,7 +502,7 @@ class A(Base1, Base2): [out] main:10: error: Incompatible types in assignment (expression has type "GenericBase[Base2]", base class "Base1" defined the type as "GenericBase[Base1]") -[case testMultipleInheritance_NestedVariableOverriddenWithCompatibleType] +[case testMultipleInheritance_NestedVariableOverriddenWithCompatibleType2] from typing import TypeVar, Generic T = TypeVar('T', covariant=True) class GenericBase(Generic[T]): diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index d47b069ea45e..440884333c69 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -35,7 +35,7 @@ X = namedtuple('X', ('x', 'y')) # type: ignore [case testNamedTupleNoUnderscoreFields] from collections import namedtuple -X = namedtuple('X', 'x, _y, _z') # E: namedtuple() field names cannot start with an underscore: _y, _z +X = namedtuple('X', 'x, _y, _z') # E: "namedtuple()" field names cannot start with an underscore: _y, _z [builtins fixtures/tuple.pyi] [case testNamedTupleAccessingAttributes] @@ -162,7 +162,7 @@ X(0) # ok X(0, 1) # ok X(0, 1, 2) # E: Too many arguments for "X" -Y = namedtuple('Y', ['x', 'y'], defaults=(1, 2, 3)) # E: Too many defaults given in call to namedtuple() +Y = namedtuple('Y', ['x', 'y'], defaults=(1, 2, 3)) # E: Too many defaults given in call to "namedtuple()" Z = namedtuple('Z', ['x', 'y'], defaults='not a tuple') # E: List or tuple literal expected as the defaults argument to namedtuple() # E: Argument "defaults" to "namedtuple" has incompatible type "str"; expected "Optional[Iterable[Any]]" [builtins fixtures/list.pyi] @@ -576,7 +576,7 @@ T = TypeVar('T', bound='M') class G(Generic[T]): x: T -yb: G[int] # E: Type argument "builtins.int" of "G" must be a subtype of "Tuple[builtins.int, fallback=__main__.M]" +yb: G[int] # E: Type argument "int" of "G" must be a subtype of "M" yg: G[M] reveal_type(G[M]().x.x) # N: Revealed type is "builtins.int" reveal_type(G[M]().x[0]) # N: Revealed type is "builtins.int" @@ -973,3 +973,111 @@ B = namedtuple('X', ['a']) # E: First argument to namedtuple() should be C = NamedTuple('X', [('a', 'Y')]) # E: First argument to namedtuple() should be "C", not "X" class Y: ... [builtins fixtures/tuple.pyi] + +[case testNamedTupleTypeIsASuperTypeOfOtherNamedTuples] +from typing import Tuple, NamedTuple + +class Bar(NamedTuple): + name: str = "Bar" + +class Baz(NamedTuple): + a: str + b: str + +class Biz(Baz): ... +class Other: ... +class Both1(Bar, Other): ... +class Both2(Other, Bar): ... +class Both3(Biz, Other): ... + +def print_namedtuple(obj: NamedTuple) -> None: + reveal_type(obj.name) # N: Revealed type is "builtins.str" + +b1: Bar +b2: Baz +b3: Biz +b4: Both1 +b5: Both2 +b6: Both3 +print_namedtuple(b1) # ok +print_namedtuple(b2) # ok +print_namedtuple(b3) # ok +print_namedtuple(b4) # ok +print_namedtuple(b5) # ok +print_namedtuple(b6) # ok + +print_namedtuple(1) # E: Argument 1 to "print_namedtuple" has incompatible type "int"; expected "NamedTuple" +print_namedtuple(('bar',)) # E: Argument 1 to "print_namedtuple" has incompatible type "Tuple[str]"; expected "NamedTuple" +print_namedtuple((1, 2)) # E: Argument 1 to "print_namedtuple" has incompatible type "Tuple[int, int]"; expected "NamedTuple" +print_namedtuple((b1,)) # E: Argument 1 to "print_namedtuple" has incompatible type "Tuple[Bar]"; expected "NamedTuple" +t: Tuple[str, ...] +print_namedtuple(t) # E: Argument 1 to "print_namedtuple" has incompatible type "Tuple[str, ...]"; expected "NamedTuple" + +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] + +[case testNamedTupleTypeIsASuperTypeOfOtherNamedTuplesReturns] +from typing import Tuple, NamedTuple + +class Bar(NamedTuple): + n: int + +class Baz(NamedTuple): + a: str + b: str + +class Biz(Bar): ... +class Other: ... +class Both1(Bar, Other): ... +class Both2(Other, Bar): ... +class Both3(Biz, Other): ... + +def good1() -> NamedTuple: + b: Bar + return b +def good2() -> NamedTuple: + b: Baz + return b +def good3() -> NamedTuple: + b: Biz + return b +def good4() -> NamedTuple: + b: Both1 + return b +def good5() -> NamedTuple: + b: Both2 + return b +def good6() -> NamedTuple: + b: Both3 + return b + +def bad1() -> NamedTuple: + return 1 # E: Incompatible return value type (got "int", expected "NamedTuple") +def bad2() -> NamedTuple: + return () # E: Incompatible return value type (got "Tuple[]", expected "NamedTuple") +def bad3() -> NamedTuple: + return (1, 2) # E: Incompatible return value type (got "Tuple[int, int]", expected "NamedTuple") + +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] + +[case testBoolInTuplesRegression] +# https://github.com/python/mypy/issues/11701 +from typing import NamedTuple, Literal, List, Tuple + +C = NamedTuple("C", [("x", Literal[True, False])]) + +T = Tuple[Literal[True, False]] + +# Was error here: +# Incompatible types in assignment (expression has type "List[C]", variable has type "List[C]") +x: List[C] = [C(True)] + +t: T + +# Was error here: +# Incompatible types in assignment (expression has type "List[Tuple[bool]]", +# variable has type "List[Tuple[Union[Literal[True], Literal[False]]]]") +y: List[T] = [t] +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 4fdd8f3b1033..d6b25ef456d9 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -170,7 +170,7 @@ if x5["key"] is Key.A: reveal_type(x5) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key': Literal[__main__.Key.A], 'foo': builtins.int})" else: reveal_type(x5) # N: Revealed type is "TypedDict('__main__.TypedDict2', {'key': Literal[__main__.Key.B], 'foo': builtins.str})" -[builtins fixtures/tuple.pyi] +[builtins fixtures/narrowing.pyi] [case testNarrowingParentWithIsInstanceBasic] # flags: --python-version 3.7 @@ -236,7 +236,7 @@ if isinstance(x5["key"], int): reveal_type(x5) # N: Revealed type is "TypedDict('__main__.TypedDict1', {'key': builtins.int})" else: reveal_type(x5) # N: Revealed type is "TypedDict('__main__.TypedDict2', {'key': builtins.str})" -[builtins fixtures/isinstance.pyi] +[builtins fixtures/narrowing.pyi] [case testNarrowingParentMultipleKeys] # flags: --warn-unreachable @@ -655,6 +655,27 @@ else: reveal_type(y["model"]) # N: Revealed type is "Union[TypedDict('__main__.Model1', {'key': Literal['A']}), TypedDict('__main__.Model2', {'key': Literal['B']})]" [builtins fixtures/primitives.pyi] +[case testNarrowingExprPropagation] +from typing import Union +from typing_extensions import Literal + +class A: + tag: Literal['A'] + +class B: + tag: Literal['B'] + +abo: Union[A, B, None] + +if abo is not None and abo.tag == "A": + reveal_type(abo.tag) # N: Revealed type is "Literal['A']" + reveal_type(abo) # N: Revealed type is "__main__.A" + +if not (abo is None or abo.tag != "B"): + reveal_type(abo.tag) # N: Revealed type is "Literal['B']" + reveal_type(abo) # N: Revealed type is "__main__.B" +[builtins fixtures/primitives.pyi] + [case testNarrowingEqualityFlipFlop] # flags: --warn-unreachable --strict-equality from typing_extensions import Literal, Final @@ -1026,8 +1047,81 @@ else: if str_or_bool_literal is not True and str_or_bool_literal is not False: reveal_type(str_or_bool_literal) # N: Revealed type is "builtins.str" else: - reveal_type(str_or_bool_literal) # N: Revealed type is "Union[Literal[False], Literal[True]]" + reveal_type(str_or_bool_literal) # N: Revealed type is "builtins.bool" +[builtins fixtures/primitives.pyi] + +[case testNarrowingBooleanIdentityCheck] +# flags: --strict-optional +from typing import Optional +from typing_extensions import Literal + +bool_val: bool + +if bool_val is not False: + reveal_type(bool_val) # N: Revealed type is "Literal[True]" +else: + reveal_type(bool_val) # N: Revealed type is "Literal[False]" + +opt_bool_val: Optional[bool] + +if opt_bool_val is not None: + reveal_type(opt_bool_val) # N: Revealed type is "builtins.bool" +if opt_bool_val is not False: + reveal_type(opt_bool_val) # N: Revealed type is "Union[Literal[True], None]" +else: + reveal_type(opt_bool_val) # N: Revealed type is "Literal[False]" +[builtins fixtures/primitives.pyi] + +[case testNarrowingBooleanTruthiness] +# flags: --strict-optional +from typing import Optional +from typing_extensions import Literal + +bool_val: bool + +if bool_val: + reveal_type(bool_val) # N: Revealed type is "Literal[True]" +else: + reveal_type(bool_val) # N: Revealed type is "Literal[False]" +reveal_type(bool_val) # N: Revealed type is "builtins.bool" + +opt_bool_val: Optional[bool] + +if opt_bool_val: + reveal_type(opt_bool_val) # N: Revealed type is "Literal[True]" +else: + reveal_type(opt_bool_val) # N: Revealed type is "Union[Literal[False], None]" +reveal_type(opt_bool_val) # N: Revealed type is "Union[builtins.bool, None]" +[builtins fixtures/primitives.pyi] + +[case testNarrowingBooleanBoolOp] +# flags: --strict-optional +from typing import Optional +from typing_extensions import Literal + +bool_a: bool +bool_b: bool + +if bool_a and bool_b: + reveal_type(bool_a) # N: Revealed type is "Literal[True]" + reveal_type(bool_b) # N: Revealed type is "Literal[True]" +else: + reveal_type(bool_a) # N: Revealed type is "builtins.bool" + reveal_type(bool_b) # N: Revealed type is "builtins.bool" + +if not bool_a or bool_b: + reveal_type(bool_a) # N: Revealed type is "builtins.bool" + reveal_type(bool_b) # N: Revealed type is "builtins.bool" +else: + reveal_type(bool_a) # N: Revealed type is "Literal[True]" + reveal_type(bool_b) # N: Revealed type is "Literal[False]" + +if True and bool_b: + reveal_type(bool_b) # N: Revealed type is "Literal[True]" + +x = True and bool_b +reveal_type(x) # N: Revealed type is "builtins.bool" [builtins fixtures/primitives.pyi] [case testNarrowingTypedDictUsingEnumLiteral] @@ -1073,3 +1167,81 @@ def f(t: Type[C]) -> None: else: reveal_type(t) # N: Revealed type is "Type[__main__.C]" reveal_type(t) # N: Revealed type is "Type[__main__.C]" + +[case testNarrowingUsingTypeVar] +# flags: --strict-optional +from typing import Type, TypeVar + +class A: pass +class B(A): pass + +T = TypeVar("T", bound=A) + +def f(t: Type[T], a: A, b: B) -> None: + if type(a) is t: + reveal_type(a) # N: Revealed type is "T`-1" + else: + reveal_type(a) # N: Revealed type is "__main__.A" + + if type(b) is t: + reveal_type(b) # N: Revealed type is "" + else: + reveal_type(b) # N: Revealed type is "__main__.B" + +[case testNarrowingNestedUnionOfTypedDicts] +from typing import Union +from typing_extensions import Literal, TypedDict + +class A(TypedDict): + tag: Literal["A"] + a: int + +class B(TypedDict): + tag: Literal["B"] + b: int + +class C(TypedDict): + tag: Literal["C"] + c: int + +AB = Union[A, B] +ABC = Union[AB, C] +abc: ABC + +if abc["tag"] == "A": + reveal_type(abc) # N: Revealed type is "TypedDict('__main__.A', {'tag': Literal['A'], 'a': builtins.int})" +elif abc["tag"] == "C": + reveal_type(abc) # N: Revealed type is "TypedDict('__main__.C', {'tag': Literal['C'], 'c': builtins.int})" +else: + reveal_type(abc) # N: Revealed type is "TypedDict('__main__.B', {'tag': Literal['B'], 'b': builtins.int})" + +[builtins fixtures/primitives.pyi] + + +[case testNarrowingRuntimeCover] +from typing import Dict, List, Union + +def unreachable(x: Union[str, List[str]]) -> None: + if isinstance(x, str): + reveal_type(x) # N: Revealed type is "builtins.str" + elif isinstance(x, list): + reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]" + else: + reveal_type(x) # N: Revealed type is "" + +def all_parts_covered(x: Union[str, List[str], List[int], int]) -> None: + if isinstance(x, str): + reveal_type(x) # N: Revealed type is "builtins.str" + elif isinstance(x, list): + reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.str], builtins.list[builtins.int]]" + else: + reveal_type(x) # N: Revealed type is "builtins.int" + +def two_type_vars(x: Union[str, Dict[str, int], Dict[bool, object], int]) -> None: + if isinstance(x, str): + reveal_type(x) # N: Revealed type is "builtins.str" + elif isinstance(x, dict): + reveal_type(x) # N: Revealed type is "Union[builtins.dict[builtins.str, builtins.int], builtins.dict[builtins.bool, builtins.object]]" + else: + reveal_type(x) # N: Revealed type is "builtins.int" +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index bf997169b2b5..8a039ad278f3 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -304,6 +304,7 @@ from a import x def f(): pass [targets a, b, a, a.y, b.f, __main__] +[builtins fixtures/tuple.pyi] [case testNewAnalyzerRedefinitionAndDeferral1b] import a @@ -762,7 +763,7 @@ class D(C[TY], Generic[TY]): pass class Y(Defer): pass class Defer: ... -x: D[int] # E: Type argument "builtins.int" of "D" must be a subtype of "__main__.Y" +x: D[int] # E: Type argument "int" of "D" must be a subtype of "Y" y: D[Y] [case testNewAnalyzerTypeVarForwardReferenceErrors] @@ -1638,7 +1639,7 @@ class C(Generic[T]): pass class D(B): pass -x: C[D] # E: Type argument "__main__.D" of "C" must be a subtype of "__main__.E" +x: C[D] # E: Type argument "D" of "C" must be a subtype of "E" y: C[F] class B: pass @@ -1677,14 +1678,14 @@ class A(C[str]): # E [out] main:2: note: In module imported here: tmp/a.py: note: In function "f": -tmp/a.py:6: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:7: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:6: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:7: error: Type argument "str" of "C" must be a subtype of "int" tmp/a.py: note: In class "A": -tmp/a.py:8: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:9: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:8: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:9: error: Type argument "str" of "C" must be a subtype of "int" tmp/a.py: note: In member "g" of class "A": -tmp/a.py:10: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:11: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:10: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:11: error: Type argument "str" of "C" must be a subtype of "int" [case testNewAnalyzerTypeArgBoundCheckDifferentNodes] from typing import TypeVar, Generic, NamedTuple, NewType, Union, Any, cast, overload @@ -1694,45 +1695,45 @@ T = TypeVar('T', bound=int) class C(Generic[T]): pass class C2(Generic[T]): pass -A = C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" \ +A = C[str] # E: Type argument "str" of "C" must be a subtype of "int" \ # E: Value of type variable "T" of "C" cannot be "str" -B = Union[C[str], int] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -S = TypeVar('S', bound=C[str]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -U = TypeVar('U', C[str], str) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +B = Union[C[str], int] # E: Type argument "str" of "C" must be a subtype of "int" +S = TypeVar('S', bound=C[str]) # E: Type argument "str" of "C" must be a subtype of "int" +U = TypeVar('U', C[str], str) # E: Type argument "str" of "C" must be a subtype of "int" N = NamedTuple('N', [ - ('x', C[str])]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + ('x', C[str])]) # E: Type argument "str" of "C" must be a subtype of "int" class N2(NamedTuple): - x: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + x: C[str] # E: Type argument "str" of "C" must be a subtype of "int" class TD(TypedDict): - x: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + x: C[str] # E: Type argument "str" of "C" must be a subtype of "int" class TD2(TD): - y: C2[str] # E: Type argument "builtins.str" of "C2" must be a subtype of "builtins.int" + y: C2[str] # E: Type argument "str" of "C2" must be a subtype of "int" NT = NewType('NT', - C[str]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + C[str]) # E: Type argument "str" of "C" must be a subtype of "int" class D( - C[str]): # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + C[str]): # E: Type argument "str" of "C" must be a subtype of "int" pass -TD3 = TypedDict('TD3', {'x': C[str]}) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +TD3 = TypedDict('TD3', {'x': C[str]}) # E: Type argument "str" of "C" must be a subtype of "int" a: Any -for i in a: # type: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +for i in a: # type: C[str] # E: Type argument "str" of "C" must be a subtype of "int" pass -with a as w: # type: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +with a as w: # type: C[str] # E: Type argument "str" of "C" must be a subtype of "int" pass -cast(C[str], a) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +cast(C[str], a) # E: Type argument "str" of "C" must be a subtype of "int" C[str]() # E: Value of type variable "T" of "C" cannot be "str" def f(s: S, y: U) -> None: pass # No error here @overload -def g(x: C[str]) -> int: ... # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +def g(x: C[str]) -> int: ... # E: Type argument "str" of "C" must be a subtype of "int" @overload def g(x: int) -> int: ... -def g(x: Union[C[str], int]) -> int: # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" - y: C[object] # E: Type argument "builtins.object" of "C" must be a subtype of "builtins.int" +def g(x: Union[C[str], int]) -> int: # E: Type argument "str" of "C" must be a subtype of "int" + y: C[object] # E: Type argument "object" of "C" must be a subtype of "int" return 0 [builtins fixtures/tuple.pyi] @@ -1744,7 +1745,7 @@ import a from typing import TypeVar, Generic x: C[None] -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] T = TypeVar('T', bound=int) @@ -1754,8 +1755,8 @@ class C(Generic[T]): [file a.py] from b import C -x: C[None] # E: Type argument "None" of "C" must be a subtype of "builtins.int" -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +x: C[None] # E: Type argument "None" of "C" must be a subtype of "int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] [file mypy.ini] @@ -1773,7 +1774,7 @@ import a from typing import TypeVar, Generic x: C[None] -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] T = TypeVar('T', bound=int) @@ -1783,8 +1784,8 @@ class C(Generic[T]): [file a.py] from b import C -x: C[None] # E: Type argument "None" of "C" must be a subtype of "builtins.int" -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +x: C[None] # E: Type argument "None" of "C" must be a subtype of "int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] [file pyproject.toml] @@ -1992,17 +1993,17 @@ S = TypeVar('S', bound=Tuple[G[A], ...]) class GG(Generic[S]): pass g: GG[Tuple[G[B], G[C]]] \ - # E: Type argument "Tuple[__main__.G[__main__.B], __main__.G[__main__.C]]" of "GG" must be a subtype of "builtins.tuple[__main__.G[__main__.A]]" \ - # E: Type argument "__main__.B" of "G" must be a subtype of "__main__.A" \ - # E: Type argument "__main__.C" of "G" must be a subtype of "__main__.A" + # E: Type argument "Tuple[G[B], G[C]]" of "GG" must be a subtype of "Tuple[G[A], ...]" \ + # E: Type argument "B" of "G" must be a subtype of "A" \ + # E: Type argument "C" of "G" must be a subtype of "A" T = TypeVar('T', bound=A, covariant=True) class G(Generic[T]): pass -t: Tuple[G[B], G[C]] # E: Type argument "__main__.B" of "G" must be a subtype of "__main__.A" \ - # E: Type argument "__main__.C" of "G" must be a subtype of "__main__.A" -reveal_type(t.__iter__) # N: Revealed type is "def () -> typing.Iterator[__main__.G*[__main__.B]]" +t: Tuple[G[B], G[C]] # E: Type argument "B" of "G" must be a subtype of "A" \ + # E: Type argument "C" of "G" must be a subtype of "A" +reveal_type(t.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.object*]" [builtins fixtures/tuple.pyi] [case testNewAnalyzerClassKeywordsForward] @@ -2200,7 +2201,7 @@ class B(Generic[T]): x: T class C: ... -x: B[int] # E: Type argument "builtins.int" of "B" must be a subtype of "__main__.B[Any]" +x: B[int] # E: Type argument "int" of "B" must be a subtype of "B[Any]" y: B[B[Any]] reveal_type(y.x) # N: Revealed type is "__main__.B*[Any]" @@ -2225,7 +2226,7 @@ x: B[int] y: B[B[Any]] reveal_type(y.x) [out] -tmp/b.py:8: error: Type argument "builtins.int" of "B" must be a subtype of "b.B[Any]" +tmp/b.py:8: error: Type argument "int" of "B" must be a subtype of "B[Any]" tmp/b.py:10: note: Revealed type is "b.B*[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target @@ -2254,7 +2255,7 @@ x: B[int] y: B[B[Any]] reveal_type(y.x) [out] -tmp/b.py:9: error: Type argument "builtins.int" of "B" must be a subtype of "b.B[Any]" +tmp/b.py:9: error: Type argument "int" of "B" must be a subtype of "B[Any]" tmp/b.py:11: note: Revealed type is "b.B*[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target @@ -2313,7 +2314,7 @@ reveal_type(x) # N: Revealed type is "builtins.int" C = int -[case testNewAnalyzerCastForward2] +[case testNewAnalyzerCastForward3] from typing import cast, NamedTuple x = cast('C', None) @@ -2390,7 +2391,8 @@ import p import p reveal_type(p.y) [file p.pyi] -from pp import x as y +from pp import x +y = x [file pp.pyi] def __getattr__(attr): ... [out2] diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index eedd5899c949..c6d3d1f48649 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -832,3 +832,248 @@ main:4: error: Argument 1 to "asdf" has incompatible type "List[str]"; expected main:4: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance main:4: note: Consider using "Sequence" instead, which is covariant [builtins fixtures/list.pyi] + +[case testOptionalBackwards1] +from typing import Any, Optional + +def f1(b: bool) -> Optional[int]: + if b: + z = 10 + reveal_type(z) # N: Revealed type is "builtins.int" + else: + z = None + reveal_type(z) # N: Revealed type is "None" + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + return z + +def f2(b: bool) -> int: + if b: + z = 10 + else: + z = None + return z # E: Incompatible return value type (got "Optional[int]", expected "int") + +def f3(b: bool) -> int: + # XXX: This one is a little questionable! Maybe we *do* want to allow this? + z = 10 + if b: + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + return z + +def f4() -> Optional[int]: + z = 10 + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + + return z + +def f5() -> None: + z = 10 + + def f() -> None: + nonlocal z + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f6(b: bool) -> None: + if b: + z = 10 + else: + z = 11 + + def f() -> None: + nonlocal z + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f7(b: bool) -> None: + if b: + z = 10 + else: + z = 11 + + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f8(b: bool, c: bool) -> Optional[int]: + if b: + if c: + z = 10 + else: + z = 11 + else: + z = None + return z + +def f9(b: bool) -> None: + if b: + z: int = 10 + else: + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f10(b: bool) -> None: + z: int + if b: + z = 10 + else: + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f11(b: bool, c: bool) -> None: + if b: + z = 10 + elif c: + z = 30 + else: + z = None + +def f12(b: bool, a: Any) -> None: + if b: + z = a + else: + z = None + reveal_type(z) # N: Revealed type is "Any" + +def f13(b: bool, a: Any) -> None: + if b: + try: + z = f2(True) + except Exception: + raise RuntimeError + else: + z = None + +def f14(b: bool, a: Any) -> None: + if b: + with a: + z = 10 + else: + z = None + +def f15() -> None: + try: + z = f2(True) + except Exception: + z = None + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + +def f16(z: Any) -> None: + for x in z: + if x == 0: + y = 50 + break + else: + y = None + reveal_type(y) # N: Revealed type is "Union[builtins.int, None]" + +def f17(b: bool, c: bool, d: bool) -> None: + if b: + z = 2 + elif c: + z = None + elif d: + z = 3 + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + +def f18(b: bool, c: bool, d: bool) -> None: + if b: + z = 4 + else: + if c: + z = 5 + else: + z = None + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + +def f19(b: bool, c: bool, d: bool) -> None: + if b: + z = 5 + else: + z = None + if c: + z = 6 + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + +def f20(b: bool) -> None: + if b: + x: Any = 5 + else: + x = None + reveal_type(x) # N: Revealed type is "Any" + +def f_unannot(): pass + +def f21(b: bool) -> None: + if b: + x = f_unannot() + else: + x = None + reveal_type(x) # N: Revealed type is "Any" + +def f22(b: bool) -> None: + if b: + z = 10 + if not b: + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +def f23(b: bool) -> None: + if b: + z = 10 + if b: + z = 11 + else: + z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +[builtins fixtures/exception.pyi] + +[case testOptionalBackwards2] + +def f1(b: bool) -> None: + if b: + x = [] # E: Need type annotation for "x" (hint: "x: List[] = ...") + else: + x = None + +def f2(b: bool) -> None: + if b: + x = [] + x.append(1) + else: + x = None + reveal_type(x) # N: Revealed type is "Union[builtins.list[builtins.int], None]" + + +[builtins fixtures/list.pyi] + +[case testOptionalBackwards3] + +# We don't allow this sort of updating for globals or attributes currently. +gb: bool +if gb: + Z = 10 +else: + Z = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + +class Foo: + def __init__(self, b: bool) -> None: + if b: + self.x = 5 + else: + self.x = None # E: Incompatible types in assignment (expression has type "None", variable has type "int") + + def foo(self) -> None: + reveal_type(self.x) # N: Revealed type is "builtins.int" + +[case testOptionalBackwards4] +from typing import Any, Optional + +def f1(b: bool) -> Optional[int]: + if b: + z = 10 + reveal_type(z) # N: Revealed type is "builtins.int" + else: + # Force the node to get deferred between the two assignments + Defer().defer + z = None + reveal_type(z) # N: Revealed type is "None" + reveal_type(z) # N: Revealed type is "Union[builtins.int, None]" + return z + +class Defer: + def __init__(self) -> None: + self.defer = 10 diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 632436c4118e..d903c895c45c 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -525,21 +525,21 @@ if int(): if int(): b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") f(b) # E: No overload variant of "f" matches argument type "B" \ - # N: Possible overload variant: \ + # N: Possible overload variants: \ # N: def f(x: A) -> A \ - # N: <1 more non-matching overload not shown> + # N: def f(x: B, y: A) -> B if int(): b = f(b, a) if int(): a = f(b, a) # E: Incompatible types in assignment (expression has type "B", variable has type "A") f(a, a) # E: No overload variant of "f" matches argument types "A", "A" \ - # N: Possible overload variant: \ - # N: def f(x: B, y: A) -> B \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def f(x: A) -> A \ + # N: def f(x: B, y: A) -> B f(b, b) # E: No overload variant of "f" matches argument types "B", "B" \ - # N: Possible overload variant: \ - # N: def f(x: B, y: A) -> B \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def f(x: A) -> A \ + # N: def f(x: B, y: A) -> B @overload def f(x: 'A') -> 'A': pass @@ -1003,22 +1003,36 @@ class Parent: @overload def f(self, x: B) -> B: ... class Child1(Parent): - @overload # E: Signature of "f" incompatible with supertype "Parent" \ - # N: Overload variants must be defined in the same order as they are in "Parent" + @overload # Fail def f(self, x: A) -> B: ... @overload def f(self, x: int) -> int: ... class Child2(Parent): - @overload # E: Signature of "f" incompatible with supertype "Parent" \ - # N: Overload variants must be defined in the same order as they are in "Parent" + @overload # Fail def f(self, x: B) -> C: ... @overload def f(self, x: int) -> int: ... class Child3(Parent): - @overload # E: Signature of "f" incompatible with supertype "Parent" + @overload # Fail def f(self, x: B) -> A: ... @overload def f(self, x: int) -> int: ... +[out] +tmp/foo.pyi:13: error: Signature of "f" incompatible with supertype "Parent" +tmp/foo.pyi:13: note: Overload variants must be defined in the same order as they are in "Parent" +tmp/foo.pyi:18: error: Signature of "f" incompatible with supertype "Parent" +tmp/foo.pyi:18: note: Overload variants must be defined in the same order as they are in "Parent" +tmp/foo.pyi:23: error: Signature of "f" incompatible with supertype "Parent" +tmp/foo.pyi:23: note: Superclass: +tmp/foo.pyi:23: note: @overload +tmp/foo.pyi:23: note: def f(self, x: int) -> int +tmp/foo.pyi:23: note: @overload +tmp/foo.pyi:23: note: def f(self, x: B) -> B +tmp/foo.pyi:23: note: Subclass: +tmp/foo.pyi:23: note: @overload +tmp/foo.pyi:23: note: def f(self, x: B) -> A +tmp/foo.pyi:23: note: @overload +tmp/foo.pyi:23: note: def f(self, x: int) -> int [case testOverrideOverloadedMethodWithMoreGeneralArgumentTypes] from foo import * @@ -1054,12 +1068,12 @@ class A: @overload def f(self, x: str) -> str: return '' class B(A): - @overload + @overload # Fail def f(self, x: IntSub) -> int: return 0 @overload def f(self, x: str) -> str: return '' class C(A): - @overload + @overload # Fail def f(self, x: int) -> int: return 0 @overload def f(self, x: StrSub) -> str: return '' @@ -1070,7 +1084,27 @@ class D(A): def f(self, x: str) -> str: return '' [out] tmp/foo.pyi:12: error: Signature of "f" incompatible with supertype "A" +tmp/foo.pyi:12: note: Superclass: +tmp/foo.pyi:12: note: @overload +tmp/foo.pyi:12: note: def f(self, x: int) -> int +tmp/foo.pyi:12: note: @overload +tmp/foo.pyi:12: note: def f(self, x: str) -> str +tmp/foo.pyi:12: note: Subclass: +tmp/foo.pyi:12: note: @overload +tmp/foo.pyi:12: note: def f(self, x: IntSub) -> int +tmp/foo.pyi:12: note: @overload +tmp/foo.pyi:12: note: def f(self, x: str) -> str tmp/foo.pyi:17: error: Signature of "f" incompatible with supertype "A" +tmp/foo.pyi:17: note: Superclass: +tmp/foo.pyi:17: note: @overload +tmp/foo.pyi:17: note: def f(self, x: int) -> int +tmp/foo.pyi:17: note: @overload +tmp/foo.pyi:17: note: def f(self, x: str) -> str +tmp/foo.pyi:17: note: Subclass: +tmp/foo.pyi:17: note: @overload +tmp/foo.pyi:17: note: def f(self, x: int) -> int +tmp/foo.pyi:17: note: @overload +tmp/foo.pyi:17: note: def f(self, x: StrSub) -> str [case testOverloadingAndDucktypeCompatibility] from foo import * @@ -1174,15 +1208,15 @@ def f(x: int, y: str) -> int: pass @overload def f(*x: str) -> str: pass f(*(1,))() # E: No overload variant of "f" matches argument type "Tuple[int]" \ - # N: Possible overload variant: \ - # N: def f(*x: str) -> str \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def f(x: int, y: str) -> int \ + # N: def f(*x: str) -> str f(*('',))() # E: "str" not callable f(*(1, ''))() # E: "int" not callable f(*(1, '', 1))() # E: No overload variant of "f" matches argument type "Tuple[int, str, int]" \ - # N: Possible overload variant: \ - # N: def f(*x: str) -> str \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def f(x: int, y: str) -> int \ + # N: def f(*x: str) -> str [builtins fixtures/tuple.pyi] [case testPreferExactSignatureMatchInOverload] @@ -1315,10 +1349,10 @@ def g(x: int, *a: AnyStr) -> None: pass g('foo') g('foo', 'bar') -g('foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "object" +g('foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "Sequence[object]" g(1) g(1, 'foo') -g(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "object" +g(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "Sequence[object]" [builtins fixtures/primitives.pyi] [case testOverloadOverlapWithTypeVarsWithValuesOrdering] @@ -1983,14 +2017,14 @@ class ParentWithTypedImpl: def f(self, arg: Union[int, str]) -> Union[int, str]: ... class Child1(ParentWithTypedImpl): - @overload # E: Signature of "f" incompatible with supertype "ParentWithTypedImpl" + @overload # Fail def f(self, arg: int) -> int: ... @overload def f(self, arg: StrSub) -> str: ... def f(self, arg: Union[int, StrSub]) -> Union[int, str]: ... class Child2(ParentWithTypedImpl): - @overload # E: Signature of "f" incompatible with supertype "ParentWithTypedImpl" + @overload # Fail def f(self, arg: int) -> int: ... @overload def f(self, arg: StrSub) -> str: ... @@ -2004,20 +2038,65 @@ class ParentWithDynamicImpl: def f(self, arg: Any) -> Any: ... class Child3(ParentWithDynamicImpl): - @overload # E: Signature of "f" incompatible with supertype "ParentWithDynamicImpl" + @overload # Fail def f(self, arg: int) -> int: ... @overload def f(self, arg: StrSub) -> str: ... def f(self, arg: Union[int, StrSub]) -> Union[int, str]: ... class Child4(ParentWithDynamicImpl): - @overload # E: Signature of "f" incompatible with supertype "ParentWithDynamicImpl" + @overload # Fail def f(self, arg: int) -> int: ... @overload def f(self, arg: StrSub) -> str: ... def f(self, arg: Any) -> Any: ... [builtins fixtures/tuple.pyi] +[out] +main:13: error: Signature of "f" incompatible with supertype "ParentWithTypedImpl" +main:13: note: Superclass: +main:13: note: @overload +main:13: note: def f(self, arg: int) -> int +main:13: note: @overload +main:13: note: def f(self, arg: str) -> str +main:13: note: Subclass: +main:13: note: @overload +main:13: note: def f(self, arg: int) -> int +main:13: note: @overload +main:13: note: def f(self, arg: StrSub) -> str +main:20: error: Signature of "f" incompatible with supertype "ParentWithTypedImpl" +main:20: note: Superclass: +main:20: note: @overload +main:20: note: def f(self, arg: int) -> int +main:20: note: @overload +main:20: note: def f(self, arg: str) -> str +main:20: note: Subclass: +main:20: note: @overload +main:20: note: def f(self, arg: int) -> int +main:20: note: @overload +main:20: note: def f(self, arg: StrSub) -> str +main:34: error: Signature of "f" incompatible with supertype "ParentWithDynamicImpl" +main:34: note: Superclass: +main:34: note: @overload +main:34: note: def f(self, arg: int) -> int +main:34: note: @overload +main:34: note: def f(self, arg: str) -> str +main:34: note: Subclass: +main:34: note: @overload +main:34: note: def f(self, arg: int) -> int +main:34: note: @overload +main:34: note: def f(self, arg: StrSub) -> str +main:41: error: Signature of "f" incompatible with supertype "ParentWithDynamicImpl" +main:41: note: Superclass: +main:41: note: @overload +main:41: note: def f(self, arg: int) -> int +main:41: note: @overload +main:41: note: def f(self, arg: str) -> str +main:41: note: Subclass: +main:41: note: @overload +main:41: note: def f(self, arg: int) -> int +main:41: note: @overload +main:41: note: def f(self, arg: StrSub) -> str [case testOverloadAnyIsConsideredValidReturnSubtype] from typing import Any, overload, Optional @@ -2423,9 +2502,9 @@ reveal_type(foo(*x)) # N: Revealed type is "__main__.C" y: List[str] foo(*y) # E: No overload variant of "foo" matches argument type "List[str]" \ # N: Possible overload variants: \ - # N: def foo(x: int, y: int, z: int, *args: int) -> C \ # N: def foo(x: int) -> A \ - # N: def foo(x: int, y: int) -> B + # N: def foo(x: int, y: int) -> B \ + # N: def foo(x: int, y: int, z: int, *args: int) -> C [builtins fixtures/list.pyi] [case testOverloadMultipleVarargDefinition] @@ -4060,7 +4139,7 @@ class Parent: def foo(cls, x): pass class BadChild(Parent): - @overload # E: Signature of "foo" incompatible with supertype "Parent" + @overload # Fail @classmethod def foo(cls, x: C) -> int: ... @@ -4084,6 +4163,22 @@ class GoodChild(Parent): def foo(cls, x): pass [builtins fixtures/classmethod.pyi] +[out] +main:20: error: Signature of "foo" incompatible with supertype "Parent" +main:20: note: Superclass: +main:20: note: @overload +main:20: note: @classmethod +main:20: note: def foo(cls, x: B) -> int +main:20: note: @overload +main:20: note: @classmethod +main:20: note: def foo(cls, x: str) -> str +main:20: note: Subclass: +main:20: note: @overload +main:20: note: @classmethod +main:20: note: def foo(cls, x: C) -> int +main:20: note: @overload +main:20: note: @classmethod +main:20: note: def foo(cls, x: str) -> str [case testOverloadClassMethodMixingInheritance] from typing import overload @@ -4101,7 +4196,7 @@ class BadParent: def foo(cls, x): pass class BadChild(BadParent): - @overload # E: Signature of "foo" incompatible with supertype "BadParent" + @overload # Fail def foo(cls, x: int) -> int: ... @overload @@ -4131,6 +4226,20 @@ class GoodChild(GoodParent): def foo(cls, x): pass [builtins fixtures/classmethod.pyi] +[out] +main:16: error: Signature of "foo" incompatible with supertype "BadParent" +main:16: note: Superclass: +main:16: note: @overload +main:16: note: @classmethod +main:16: note: def foo(cls, x: int) -> int +main:16: note: @overload +main:16: note: @classmethod +main:16: note: def foo(cls, x: str) -> str +main:16: note: Subclass: +main:16: note: @overload +main:16: note: def foo(cls, x: int) -> int +main:16: note: @overload +main:16: note: def foo(cls, x: str) -> str [case testOverloadClassMethodImplementation] from typing import overload, Union @@ -4205,7 +4314,7 @@ class Wrapper3: def foo(x: Union[int, str]): pass # E: Self argument missing for a non-static method (or an invalid type for self) [builtins fixtures/staticmethod.pyi] -[case testOverloadWithSwappedDecorators] +[case testOverloadWithSwappedDecorators2] from typing import overload class Wrapper1: @@ -4268,7 +4377,7 @@ class Parent: def foo(x): pass class BadChild(Parent): - @overload # E: Signature of "foo" incompatible with supertype "Parent" + @overload # Fail @staticmethod def foo(x: C) -> int: ... @@ -4292,6 +4401,22 @@ class GoodChild(Parent): def foo(x): pass [builtins fixtures/staticmethod.pyi] +[out] +main:20: error: Signature of "foo" incompatible with supertype "Parent" +main:20: note: Superclass: +main:20: note: @overload +main:20: note: @staticmethod +main:20: note: def foo(x: B) -> int +main:20: note: @overload +main:20: note: @staticmethod +main:20: note: def foo(x: str) -> str +main:20: note: Subclass: +main:20: note: @overload +main:20: note: @staticmethod +main:20: note: def foo(x: C) -> int +main:20: note: @overload +main:20: note: @staticmethod +main:20: note: def foo(x: str) -> str [case testOverloadStaticMethodMixingInheritance] from typing import overload @@ -4309,7 +4434,7 @@ class BadParent: def foo(x): pass class BadChild(BadParent): - @overload # E: Signature of "foo" incompatible with supertype "BadParent" + @overload # Fail def foo(self, x: int) -> int: ... @overload @@ -4339,6 +4464,20 @@ class GoodChild(GoodParent): def foo(x): pass [builtins fixtures/staticmethod.pyi] +[out] +main:16: error: Signature of "foo" incompatible with supertype "BadParent" +main:16: note: Superclass: +main:16: note: @overload +main:16: note: @staticmethod +main:16: note: def foo(x: int) -> int +main:16: note: @overload +main:16: note: @staticmethod +main:16: note: def foo(x: str) -> str +main:16: note: Subclass: +main:16: note: @overload +main:16: note: def foo(self, x: int) -> int +main:16: note: @overload +main:16: note: def foo(self, x: str) -> str [case testOverloadStaticMethodImplementation] from typing import overload, Union @@ -4624,8 +4763,7 @@ class A: # This is unsafe override because of the problem below class B(A): - @overload # E: Signature of "__add__" incompatible with supertype "A" \ - # N: Overloaded operator methods can't have wider argument types in overrides + @overload # Fail def __add__(self, x : 'Other') -> 'B' : ... @overload def __add__(self, x : 'A') -> 'A': ... @@ -4645,10 +4783,20 @@ class Other: return NotImplemented actually_b: A = B() -reveal_type(actually_b + Other()) # N: Revealed type is "__main__.Other" +reveal_type(actually_b + Other()) # Note # Runtime type is B, this is why we report the error on overriding. [builtins fixtures/isinstance.pyi] [out] +main:12: error: Signature of "__add__" incompatible with supertype "A" +main:12: note: Superclass: +main:12: note: def __add__(self, A) -> A +main:12: note: Subclass: +main:12: note: @overload +main:12: note: def __add__(self, Other) -> B +main:12: note: @overload +main:12: note: def __add__(self, A) -> A +main:12: note: Overloaded operator methods cannot have wider argument types in overrides +main:32: note: Revealed type is "__main__.Other" [case testOverloadErrorMessageManyMatches] from typing import overload @@ -4674,7 +4822,9 @@ f(3) # E: No overload variant of "f" matches argument type "int" \ # N: Possible overload variants: \ # N: def f(x: A) -> None \ # N: def f(x: B) -> None \ - # N: <2 more similar overloads not shown, out of 5 total overloads> + # N: def f(x: C) -> None \ + # N: def f(x: D) -> None \ + # N: def f(x: int, y: int) -> None @overload def g(x: A) -> None: ... @@ -4740,9 +4890,9 @@ def f() -> None: pass g(str(), str()) # E: No overload variant of "g" matches argument types "str", "str" \ - # N: Possible overload variant: \ - # N: def [T] g(x: T, y: int) -> T \ - # N: <1 more non-matching overload not shown> + # N: Possible overload variants: \ + # N: def g(x: str) -> str \ + # N: def [T] g(x: T, y: int) -> T reveal_type(g(str(), int())) # N: Revealed type is "builtins.str*" [out] @@ -4793,9 +4943,9 @@ reveal_type(attr("hi")) # N: Revealed type is "builtins.int" x: Any reveal_type(attr(x)) # N: Revealed type is "Any" attr("hi", 1) # E: No overload variant of "attr" matches argument types "str", "int" \ - # N: Possible overload variant: \ + # N: Possible overload variants: \ # N: def [T in (int, float)] attr(default: T = ..., blah: int = ...) -> T \ - # N: <1 more non-matching overload not shown> + # N: def attr(default: Any = ...) -> int [file lib.pyi] from typing import overload, Any, TypeVar @@ -4816,9 +4966,9 @@ reveal_type(attr("hi")) # N: Revealed type is "builtins.int" x: Any reveal_type(attr(x)) # N: Revealed type is "Any" attr("hi", 1) # E: No overload variant of "attr" matches argument types "str", "int" \ - # N: Possible overload variant: \ + # N: Possible overload variants: \ # N: def [T <: int] attr(default: T = ..., blah: int = ...) -> T \ - # N: <1 more non-matching overload not shown> + # N: def attr(default: Any = ...) -> int [file lib.pyi] from typing import overload, TypeVar, Any @@ -5173,3 +5323,101 @@ def f2(g: G[A, Any]) -> A: ... # E: Overloaded function signatures 1 and 2 over @overload def f2(g: G[A, B], x: int = ...) -> B: ... def f2(g: Any, x: int = ...) -> Any: ... + +[case testOverloadTypeVsCallable] +from typing import TypeVar, Type, Callable, Any, overload +class Foo: + def __init__(self, **kwargs: Any): pass +_T = TypeVar('_T') +@overload +def register(cls: Type[_T]) -> int: ... +@overload +def register(cls: Callable[..., _T]) -> str: ... +def register(cls: Any) -> Any: return None + + +x = register(Foo) +reveal_type(x) # N: Revealed type is "builtins.int" +[builtins fixtures/dict.pyi] + + +[case testOverloadWithObjectDecorator] +from typing import Any, Callable, Union, overload + +class A: + def __call__(self, *arg, **kwargs) -> None: ... + +def dec_a(f: Callable[..., Any]) -> A: + return A() + +@overload +def f_a(arg: int) -> None: ... +@overload +def f_a(arg: str) -> None: ... +@dec_a +def f_a(arg): ... + +class B: + def __call__(self, arg: Union[int, str]) -> None: ... + +def dec_b(f: Callable[..., Any]) -> B: + return B() + +@overload +def f_b(arg: int) -> None: ... +@overload +def f_b(arg: str) -> None: ... +@dec_b +def f_b(arg): ... + +class C: + def __call__(self, arg: int) -> None: ... + +def dec_c(f: Callable[..., Any]) -> C: + return C() + +@overload +def f_c(arg: int) -> None: ... +@overload +def f_c(arg: str) -> None: ... +@dec_c # E: Overloaded function implementation does not accept all possible arguments of signature 2 +def f_c(arg): ... +[builtins fixtures/dict.pyi] + +[case testOverloadWithErrorDecorator] +from typing import Any, Callable, TypeVar, overload + +def dec_d(f: Callable[..., Any]) -> int: ... + +@overload +def f_d(arg: int) -> None: ... +@overload +def f_d(arg: str) -> None: ... +@dec_d # E: "int" not callable +def f_d(arg): ... + +Bad1 = TypeVar('Good') # type: ignore + +def dec_e(f: Bad1) -> Bad1: ... # type: ignore + +@overload +def f_e(arg: int) -> None: ... +@overload +def f_e(arg: str) -> None: ... +@dec_e # E: Bad1? not callable +def f_e(arg): ... + +class Bad2: + def __getattr__(self, attr): + # __getattr__ is not called for implicit `__call__` + if attr == "__call__": + return lambda *a, **kw: print(a, kw) + raise AttributeError + +@overload +def f_f(arg: int) -> None: ... +@overload +def f_f(arg: str) -> None: ... +@Bad2() # E: "Bad2" not callable +def f_f(arg): ... +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index c7f6594eb20d..f6123915aada 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1,11 +1,9 @@ [case testBasicParamSpec] -# flags: --wip-pep-612 from typing_extensions import ParamSpec P = ParamSpec('P') [builtins fixtures/tuple.pyi] [case testParamSpecLocations] -# flags: --wip-pep-612 from typing import Callable, List from typing_extensions import ParamSpec, Concatenate P = ParamSpec('P') @@ -17,7 +15,7 @@ def foo1(x: Callable[P, int]) -> Callable[P, str]: ... def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' -# TODO(shantanu): uncomment once we have support for Concatenate +# TODO(PEP612): uncomment once we have support for Concatenate # def foo3(x: Concatenate[int, P]) -> int: ... $ E: Invalid location for Concatenate def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P" \ @@ -29,3 +27,382 @@ def foo5(x: Callable[[int, str], P]) -> None: ... # E: Invalid location for Par def foo6(x: Callable[[P], int]) -> None: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' [builtins fixtures/tuple.pyi] + +[case testParamSpecContextManagerLike] +from typing import Callable, List, Iterator, TypeVar +from typing_extensions import ParamSpec +P = ParamSpec('P') +T = TypeVar('T') + +def tmpcontextmanagerlike(x: Callable[P, Iterator[T]]) -> Callable[P, List[T]]: ... + +@tmpcontextmanagerlike +def whatever(x: int) -> Iterator[int]: + yield x + +reveal_type(whatever) # N: Revealed type is "def (x: builtins.int) -> builtins.list[builtins.int*]" +reveal_type(whatever(217)) # N: Revealed type is "builtins.list[builtins.int*]" +[builtins fixtures/tuple.pyi] + +[case testInvalidParamSpecType] +# flags: --python-version 3.10 +from typing import ParamSpec + +P = ParamSpec("P") + +class MyFunction(P): # E: Invalid base class "P" + ... + +[case testParamSpecRevealType] +from typing import Callable +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +def f(x: Callable[P, int]) -> None: ... +reveal_type(f) # N: Revealed type is "def [P] (x: def (*P.args, **P.kwargs) -> builtins.int)" +[builtins fixtures/tuple.pyi] + +[case testParamSpecSimpleFunction] +from typing import Callable, TypeVar +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +def changes_return_type_to_str(x: Callable[P, int]) -> Callable[P, str]: ... + +def returns_int(a: str, b: bool) -> int: ... + +reveal_type(changes_return_type_to_str(returns_int)) # N: Revealed type is "def (a: builtins.str, b: builtins.bool) -> builtins.str" +[builtins fixtures/tuple.pyi] + +[case testParamSpecSimpleClass] +from typing import Callable, TypeVar, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +class C(Generic[P]): + def __init__(self, x: Callable[P, None]) -> None: ... + + def m(self, *args: P.args, **kwargs: P.kwargs) -> int: + return 1 + +def f(x: int, y: str) -> None: ... + +reveal_type(C(f)) # N: Revealed type is "__main__.C[def (x: builtins.int, y: builtins.str)]" +reveal_type(C(f).m) # N: Revealed type is "def (x: builtins.int, y: builtins.str) -> builtins.int" +[builtins fixtures/dict.pyi] + +[case testParamSpecClassWithPrefixArgument] +from typing import Callable, TypeVar, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +class C(Generic[P]): + def __init__(self, x: Callable[P, None]) -> None: ... + + def m(self, a: str, *args: P.args, **kwargs: P.kwargs) -> int: + return 1 + +def f(x: int, y: str) -> None: ... + +reveal_type(C(f).m) # N: Revealed type is "def (a: builtins.str, x: builtins.int, y: builtins.str) -> builtins.int" +reveal_type(C(f).m('', 1, '')) # N: Revealed type is "builtins.int" +[builtins fixtures/dict.pyi] + +[case testParamSpecDecorator] +from typing import Callable, TypeVar, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') +R = TypeVar('R') + +class W(Generic[P, R]): + f: Callable[P, R] + x: int + def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: + reveal_type(self.f(*args, **kwargs)) # N: Revealed type is "R`2" + return self.f(*args, **kwargs) + +def dec() -> Callable[[Callable[P, R]], W[P, R]]: + pass + +@dec() +def f(a: int, b: str) -> None: ... + +reveal_type(f) # N: Revealed type is "__main__.W[def (a: builtins.int, b: builtins.str), None]" +reveal_type(f(1, '')) # N: Revealed type is "None" +reveal_type(f.x) # N: Revealed type is "builtins.int" + +## TODO: How should this work? +# +# class C: +# @dec() +# def m(self, x: int) -> str: ... +# +# reveal_type(C().m(x=1)) +[builtins fixtures/dict.pyi] + +[case testParamSpecFunction] +from typing import Callable, TypeVar +from typing_extensions import ParamSpec + +P = ParamSpec('P') +R = TypeVar('R') + +def f(x: Callable[P, R], *args: P.args, **kwargs: P.kwargs) -> R: + return x(*args, **kwargs) + +def g(x: int, y: str) -> None: ... + +reveal_type(f(g, 1, y='x')) # N: Revealed type is "None" +f(g, 'x', y='x') # E: Argument 2 to "f" has incompatible type "str"; expected "int" +f(g, 1, y=1) # E: Argument "y" to "f" has incompatible type "int"; expected "str" +f(g) # E: Missing positional arguments "x", "y" in call to "f" + +[builtins fixtures/dict.pyi] + +[case testParamSpecSpecialCase] +from typing import Callable, TypeVar +from typing_extensions import ParamSpec + +P = ParamSpec('P') +T = TypeVar('T') + +def register(func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> Callable[P, T]: ... + +def f(x: int, y: str, z: int, a: str) -> None: ... + +x = register(f, 1, '', 1, '') +[builtins fixtures/dict.pyi] + +[case testParamSpecInferredFromAny] +from typing import Callable, Any +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +def f(x: Callable[P, int]) -> Callable[P, str]: ... + +g: Any +reveal_type(f(g)) # N: Revealed type is "def (*Any, **Any) -> builtins.str" + +f(g)(1, 3, x=1, y=2) +[builtins fixtures/tuple.pyi] + +[case testParamSpecDecoratorImplementation] +from typing import Callable, Any, TypeVar, List +from typing_extensions import ParamSpec + +P = ParamSpec('P') +T = TypeVar('T') + +def dec(f: Callable[P, T]) -> Callable[P, List[T]]: + def wrapper(*args: P.args, **kwargs: P.kwargs) -> List[T]: + return [f(*args, **kwargs)] + return wrapper + +@dec +def g(x: int, y: str = '') -> int: ... + +reveal_type(g) # N: Revealed type is "def (x: builtins.int, y: builtins.str =) -> builtins.list[builtins.int*]" +[builtins fixtures/dict.pyi] + +[case testParamSpecArgsAndKwargsTypes] +from typing import Callable, TypeVar, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +class C(Generic[P]): + def __init__(self, x: Callable[P, None]) -> None: ... + + def m(self, *args: P.args, **kwargs: P.kwargs) -> None: + reveal_type(args) # N: Revealed type is "P.args`1" + reveal_type(kwargs) # N: Revealed type is "P.kwargs`1" +[builtins fixtures/dict.pyi] + +[case testParamSpecSubtypeChecking1] +from typing import Callable, TypeVar, Generic, Any +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +class C(Generic[P]): + def __init__(self, x: Callable[P, None]) -> None: ... + + def m(self, *args: P.args, **kwargs: P.kwargs) -> None: + args = args + kwargs = kwargs + o: object + o = args + o = kwargs + o2: object + args = o2 # E: Incompatible types in assignment (expression has type "object", variable has type "P.args") + kwargs = o2 # E: Incompatible types in assignment (expression has type "object", variable has type "P.kwargs") + a: Any + a = args + a = kwargs + args = kwargs # E: Incompatible types in assignment (expression has type "P.kwargs", variable has type "P.args") + kwargs = args # E: Incompatible types in assignment (expression has type "P.args", variable has type "P.kwargs") + args = a + kwargs = a +[builtins fixtures/dict.pyi] + +[case testParamSpecSubtypeChecking2] +from typing import Callable, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') +P2 = ParamSpec('P2') + +class C(Generic[P]): + pass + +def f(c1: C[P], c2: C[P2]) -> None: + c1 = c1 + c2 = c2 + c1 = c2 # E: Incompatible types in assignment (expression has type "C[P2]", variable has type "C[P]") + c2 = c1 # E: Incompatible types in assignment (expression has type "C[P]", variable has type "C[P2]") + +def g(f: Callable[P, None], g: Callable[P2, None]) -> None: + f = f + g = g + f = g # E: Incompatible types in assignment (expression has type "Callable[P2, None]", variable has type "Callable[P, None]") + g = f # E: Incompatible types in assignment (expression has type "Callable[P, None]", variable has type "Callable[P2, None]") +[builtins fixtures/dict.pyi] + +[case testParamSpecJoin] +from typing import Callable, Generic, TypeVar +from typing_extensions import ParamSpec + +P = ParamSpec('P') +P2 = ParamSpec('P2') +P3 = ParamSpec('P3') +T = TypeVar('T') + +def join(x: T, y: T) -> T: ... + +class C(Generic[P, P2]): + def m(self, f: Callable[P, None], g: Callable[P2, None]) -> None: + reveal_type(join(f, f)) # N: Revealed type is "def (*P.args, **P.kwargs)" + reveal_type(join(f, g)) # N: Revealed type is "builtins.function*" + + def m2(self, *args: P.args, **kwargs: P.kwargs) -> None: + reveal_type(join(args, args)) # N: Revealed type is "P.args`1" + reveal_type(join(kwargs, kwargs)) # N: Revealed type is "P.kwargs`1" + reveal_type(join(args, kwargs)) # N: Revealed type is "builtins.object*" + def f(*args2: P2.args, **kwargs2: P2.kwargs) -> None: + reveal_type(join(args, args2)) # N: Revealed type is "builtins.object*" + reveal_type(join(kwargs, kwargs2)) # N: Revealed type is "builtins.object*" + + def m3(self, c: C[P, P3]) -> None: + reveal_type(join(c, c)) # N: Revealed type is "__main__.C*[P`1, P3`-1]" + reveal_type(join(self, c)) # N: Revealed type is "builtins.object*" +[builtins fixtures/dict.pyi] + +[case testParamSpecClassWithAny] +from typing import Callable, Generic, Any +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +class C(Generic[P]): + def __init__(self, x: Callable[P, None]) -> None: ... + + def m(self, *args: P.args, **kwargs: P.kwargs) -> int: + return 1 + +c: C[Any] +reveal_type(c) # N: Revealed type is "__main__.C[Any]" +reveal_type(c.m) # N: Revealed type is "def (*args: Any, **kwargs: Any) -> builtins.int" +c.m(4, 6, y='x') +c = c + +def f() -> None: pass + +c2 = C(f) +c2 = c +c3 = C(f) +c = c3 +[builtins fixtures/dict.pyi] + +[case testParamSpecInferredFromLambda] +from typing import Callable, TypeVar +from typing_extensions import ParamSpec + +P = ParamSpec('P') +T = TypeVar('T') + +# Similar to atexit.register +def register(f: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> Callable[P, T]: ... # N: "register" defined here + +def f(x: int) -> None: pass + +reveal_type(register(lambda: f(1))) # N: Revealed type is "def ()" +reveal_type(register(lambda x: f(x), x=1)) # N: Revealed type is "def (x: Any)" +register(lambda x: f(x)) # E: Missing positional argument "x" in call to "register" +register(lambda x: f(x), y=1) # E: Unexpected keyword argument "y" for "register" +[builtins fixtures/dict.pyi] + +[case testParamSpecInvalidCalls] +from typing import Callable, Generic +from typing_extensions import ParamSpec + +P = ParamSpec('P') +P2 = ParamSpec('P2') + +class C(Generic[P, P2]): + def m1(self, *args: P.args, **kwargs: P.kwargs) -> None: + self.m1(*args, **kwargs) + self.m2(*args, **kwargs) # E: Argument 1 to "m2" of "C" has incompatible type "*P.args"; expected "P2.args" \ + # E: Argument 2 to "m2" of "C" has incompatible type "**P.kwargs"; expected "P2.kwargs" + self.m1(*kwargs, **args) # E: Argument 1 to "m1" of "C" has incompatible type "*P.kwargs"; expected "P.args" \ + # E: Argument 2 to "m1" of "C" has incompatible type "**P.args"; expected "P.kwargs" + self.m3(*args, **kwargs) # E: Argument 1 to "m3" of "C" has incompatible type "*P.args"; expected "int" \ + # E: Argument 2 to "m3" of "C" has incompatible type "**P.kwargs"; expected "int" + self.m4(*args, **kwargs) # E: Argument 1 to "m4" of "C" has incompatible type "*P.args"; expected "int" \ + # E: Argument 2 to "m4" of "C" has incompatible type "**P.kwargs"; expected "int" + + self.m1(*args, **args) # E: Argument 2 to "m1" of "C" has incompatible type "**P.args"; expected "P.kwargs" + self.m1(*kwargs, **kwargs) # E: Argument 1 to "m1" of "C" has incompatible type "*P.kwargs"; expected "P.args" + + def m2(self, *args: P2.args, **kwargs: P2.kwargs) -> None: + pass + + def m3(self, *args: int, **kwargs: int) -> None: + pass + + def m4(self, x: int) -> None: + pass +[builtins fixtures/dict.pyi] + +[case testParamSpecOverUnannotatedDecorator] +from typing import Callable, Iterator, TypeVar, ContextManager, Any +from typing_extensions import ParamSpec + +from nonexistent import deco2 # type: ignore + +T = TypeVar("T") +P = ParamSpec("P") +T_co = TypeVar("T_co", covariant=True) + +class CM(ContextManager[T_co]): + def __call__(self, func: T) -> T: ... + +def deco1( + func: Callable[P, Iterator[T]]) -> Callable[P, CM[T]]: ... + +@deco1 +@deco2 +def f(): + pass + +reveal_type(f) # N: Revealed type is "def (*Any, **Any) -> __main__.CM[Any]" + +with f() as x: + pass +[builtins fixtures/dict.pyi] +[typing fixtures/typing-full.pyi] diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index f13d2bc597da..6768263e9832 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -39,6 +39,57 @@ def fun2() -> P: def fun3() -> P: return B() # E: Incompatible return value type (got "B", expected "P") +[case testProtocolAttrAccessDecoratedGetAttrDunder] +from typing import Any, Protocol, Callable + +def typed_decorator(fun: Callable) -> Callable[[Any, str], str]: + pass + +def untyped_decorator(fun): + pass + +class P(Protocol): + @property + def x(self) -> int: + pass + +class A: + @untyped_decorator + def __getattr__(self, key: str) -> int: + pass + +class B: + @typed_decorator + def __getattr__(self, key: str) -> int: + pass + +class C: + def __getattr__(self, key: str) -> int: + pass + +def fun(x: P) -> None: + pass + +a: A +reveal_type(a.x) +fun(a) + +b: B +reveal_type(b.x) +fun(b) + +c: C +reveal_type(c.x) +fun(c) +[out] +main:32: note: Revealed type is "Any" +main:36: note: Revealed type is "builtins.str" +main:37: error: Argument 1 to "fun" has incompatible type "B"; expected "P" +main:37: note: Following member(s) of "B" have conflicts: +main:37: note: x: expected "int", got "str" +main:40: note: Revealed type is "builtins.int" +[builtins fixtures/bool.pyi] + [case testSimpleProtocolOneAbstractMethod] from typing import Protocol from abc import abstractmethod @@ -486,6 +537,64 @@ class P2(Protocol[T_co]): # E: Covariant type variable "T_co" used in protocol w lst: List[T_co] [builtins fixtures/list.pyi] + +[case testProtocolConstraintsUnsolvableWithSelfAnnotation1] +# https://github.com/python/mypy/issues/11020 +from typing import overload, Protocol, TypeVar + +I = TypeVar('I', covariant=True) +V_contra = TypeVar('V_contra', contravariant=True) + +class C(Protocol[I]): + def __abs__(self: 'C[V_contra]') -> 'C[V_contra]': + ... + + @overload + def f(self: 'C', q: int) -> int: + ... + @overload + def f(self: 'C[float]', q: float) -> 'C[float]': + ... +[builtins fixtures/bool.pyi] + + +[case testProtocolConstraintsUnsolvableWithSelfAnnotation2] +# https://github.com/python/mypy/issues/11020 +from typing import Protocol, TypeVar + +I = TypeVar('I', covariant=True) +V = TypeVar('V') + +class C(Protocol[I]): + def g(self: 'C[V]') -> 'C[V]': + ... + +class D: + pass + +x: C = D() # E: Incompatible types in assignment (expression has type "D", variable has type "C[Any]") +[builtins fixtures/bool.pyi] + + +[case testProtocolConstraintsUnsolvableWithSelfAnnotation3] +# https://github.com/python/mypy/issues/11020 +from typing import Protocol, TypeVar + +I = TypeVar('I', covariant=True) +V = TypeVar('V') + +class C(Protocol[I]): + def g(self: 'C[V]') -> 'C[V]': + ... + +class D: + def g(self) -> D: + ... + +x: C = D() +[builtins fixtures/bool.pyi] + + [case testProtocolVarianceWithUnusedVariable] from typing import Protocol, TypeVar T = TypeVar('T') @@ -2082,7 +2191,10 @@ main:18: note: @overload main:18: note: def f(self, x: int) -> int main:18: note: @overload main:18: note: def f(self, x: str) -> str -main:18: note: <2 more overloads not shown> +main:18: note: @overload +main:18: note: def f(self, x: C1) -> C2 +main:18: note: @overload +main:18: note: def f(self, x: C2) -> C1 main:18: note: Got: main:18: note: def f(self) -> None @@ -2124,7 +2236,7 @@ class B(Protocol): def execute(self, stmt: Any, *args: Any, **kwargs: Any) -> None: ... def cool(self) -> None: ... -def func1(arg: A) -> None: ... +def func1(arg: A) -> None: ... def func2(arg: Optional[A]) -> None: ... x: B @@ -2647,3 +2759,39 @@ class DataArray(ObjectHashable): def f(self, x: Hashable) -> None: reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object*]" [builtins fixtures/tuple.pyi] + + +[case testPartialAttributeNoneType] +# flags: --no-strict-optional +from typing import Optional, Protocol, runtime_checkable + +@runtime_checkable +class MyProtocol(Protocol): + def is_valid(self) -> bool: ... + text: Optional[str] + +class MyClass: + text = None + def is_valid(self) -> bool: + reveal_type(self.text) # N: Revealed type is "None" + assert isinstance(self, MyProtocol) +[builtins fixtures/isinstance.pyi] +[typing fixtures/typing-full.pyi] + + +[case testPartialAttributeNoneTypeStrictOptional] +# flags: --strict-optional +from typing import Optional, Protocol, runtime_checkable + +@runtime_checkable +class MyProtocol(Protocol): + def is_valid(self) -> bool: ... + text: Optional[str] + +class MyClass: + text = None + def is_valid(self) -> bool: + reveal_type(self.text) # N: Revealed type is "None" + assert isinstance(self, MyProtocol) +[builtins fixtures/isinstance.pyi] +[typing fixtures/typing-full.pyi] diff --git a/test-data/unit/check-python2.test b/test-data/unit/check-python2.test index f9837b8cfd03..d658fe013401 100644 --- a/test-data/unit/check-python2.test +++ b/test-data/unit/check-python2.test @@ -27,10 +27,16 @@ class A: # type: (str) -> None pass +class B: + def write(self): + # type: () -> int + pass + print >>A(), '' print >>None, '' print >>1, '' # E: "int" has no attribute "write" print >>(None + ''), None # E: Unsupported left operand type for + ("None") +print >> B(), '' # E: Argument "file" to "print" has incompatible type "def () -> builtins.int"; expected "def (builtins.str) -> Any" [case testDivision] class A: diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test new file mode 100644 index 000000000000..3bcac61855b4 --- /dev/null +++ b/test-data/unit/check-python310.test @@ -0,0 +1,7 @@ +[case testMatchStatementNotSupported] +# flags: --python-version 3.10 +match str(): # E: Match statement is not supported + case 'x': + 1 + '' + case _: + 1 + b'' diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index 996218d4d7f8..ce1f9841e240 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -18,7 +18,7 @@ def f(): ... # E: Function is missing a return type annotation \ def d(f): ... # type: ignore @d # type: ignore -def f(): ... # type: ignore # E: unused "type: ignore" comment +def f(): ... # type: ignore # E: Unused "type: ignore" comment [case testIgnoreDecoratedFunction2] # flags: --disallow-untyped-defs @@ -91,28 +91,28 @@ def g(x: int): ... [case testIgnoreScopeUnused1] # flags: --warn-unused-ignores -( # type: ignore # E: unused "type: ignore" comment - "IGNORE" # type: ignore # E: unused "type: ignore" comment - + # type: ignore # E: unused "type: ignore" comment +( # type: ignore # E: Unused "type: ignore" comment + "IGNORE" # type: ignore # E: Unused "type: ignore" comment + + # type: ignore # E: Unused "type: ignore" comment 0 # type: ignore -) # type: ignore # E: unused "type: ignore" comment +) # type: ignore # E: Unused "type: ignore" comment [builtins fixtures/primitives.pyi] [case testIgnoreScopeUnused2] # flags: --warn-unused-ignores -( # type: ignore # E: unused "type: ignore" comment +( # type: ignore # E: Unused "type: ignore" comment "IGNORE" - # type: ignore - 0 # type: ignore # E: unused "type: ignore" comment -) # type: ignore # E: unused "type: ignore" comment + 0 # type: ignore # E: Unused "type: ignore" comment +) # type: ignore # E: Unused "type: ignore" comment [case testIgnoreScopeUnused3] # flags: --warn-unused-ignores -( # type: ignore # E: unused "type: ignore" comment +( # type: ignore # E: Unused "type: ignore" comment "IGNORE" / 0 # type: ignore -) # type: ignore # E: unused "type: ignore" comment +) # type: ignore # E: Unused "type: ignore" comment [case testPEP570ArgTypesMissing] # flags: --disallow-untyped-defs @@ -192,6 +192,23 @@ def f(p1: bytes, p2: float, /) -> None: reveal_type(p1) # N: Revealed type is "builtins.bytes" reveal_type(p2) # N: Revealed type is "builtins.float" +[case testPEP570Unannotated] +def f(arg, /): ... # N: "f" defined here +g = lambda arg, /: arg +def h(arg=0, /): ... # N: "h" defined here +i = lambda arg=0, /: arg + +f(1) +g(1) +h() +h(1) +i() +i(1) +f(arg=0) # E: Unexpected keyword argument "arg" for "f" +g(arg=0) # E: Unexpected keyword argument "arg" +h(arg=0) # E: Unexpected keyword argument "arg" for "h" +i(arg=0) # E: Unexpected keyword argument "arg" + [case testWalrus] # flags: --strict-optional from typing import NamedTuple, Optional, List @@ -206,7 +223,7 @@ while b := "x": l = [y2 := 1, y2 + 2, y2 + 3] reveal_type(y2) # N: Revealed type is "builtins.int" reveal_type(l) # N: Revealed type is "builtins.list[builtins.int*]" - + filtered_data = [y3 for x in l if (y3 := a) is not None] reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int*]" reveal_type(y3) # N: Revealed type is "builtins.int" @@ -367,6 +384,57 @@ reveal_type(z2) # E: Name "z2" is not defined # N: Revealed type is "Any" [builtins fixtures/isinstancelist.pyi] +[case testWalrusConditionalTypeBinder] +from typing import Union +from typing_extensions import Literal + +class Good: + @property + def is_good(self) -> Literal[True]: ... + +class Bad: + @property + def is_good(self) -> Literal[False]: ... + +def get_thing() -> Union[Good, Bad]: ... + +if (thing := get_thing()).is_good: + reveal_type(thing) # N: Revealed type is "__main__.Good" +else: + reveal_type(thing) # N: Revealed type is "__main__.Bad" +[builtins fixtures/property.pyi] + +[case testWalrusConditionalTypeCheck] +# flags: --strict-optional +from typing import Optional + +maybe_str: Optional[str] + +if (is_str := maybe_str is not None): + reveal_type(is_str) # N: Revealed type is "Literal[True]" + reveal_type(maybe_str) # N: Revealed type is "builtins.str" +else: + reveal_type(is_str) # N: Revealed type is "Literal[False]" + reveal_type(maybe_str) # N: Revealed type is "None" + +reveal_type(maybe_str) # N: Revealed type is "Union[builtins.str, None]" +[builtins fixtures/bool.pyi] + +[case testWalrusConditionalTypeCheck2] +from typing import Optional + +maybe_str: Optional[str] + +if (x := maybe_str) is not None: + reveal_type(x) # N: Revealed type is "builtins.str" + reveal_type(maybe_str) # N: Revealed type is "Union[builtins.str, None]" +else: + reveal_type(x) # N: Revealed type is "None" + reveal_type(maybe_str) # N: Revealed type is "Union[builtins.str, None]" + +reveal_type(maybe_str) # N: Revealed type is "Union[builtins.str, None]" +[builtins fixtures/bool.pyi] + [case testWalrusPartialTypes] from typing import List @@ -383,6 +451,77 @@ def check_partial_list() -> None: reveal_type(z) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] +[case testWalrusAssignmentAndConditionScopeForLiteral] +# flags: --warn-unreachable + +if (x := 0): + reveal_type(x) # E: Statement is unreachable +else: + reveal_type(x) # N: Revealed type is "builtins.int" + +reveal_type(x) # N: Revealed type is "builtins.int" + +[case testWalrusAssignmentAndConditionScopeForProperty] +# flags: --warn-unreachable + +from typing_extensions import Literal + +class PropertyWrapper: + @property + def f(self) -> str: ... + @property + def always_false(self) -> Literal[False]: ... + +wrapper = PropertyWrapper() + +if x := wrapper.f: + reveal_type(x) # N: Revealed type is "builtins.str" +else: + reveal_type(x) # N: Revealed type is "builtins.str" + +reveal_type(x) # N: Revealed type is "builtins.str" + +if y := wrapper.always_false: + reveal_type(y) # E: Statement is unreachable +else: + reveal_type(y) # N: Revealed type is "Literal[False]" + +reveal_type(y) # N: Revealed type is "Literal[False]" +[builtins fixtures/property.pyi] + +[case testWalrusAssignmentAndConditionScopeForFunction] +# flags: --warn-unreachable + +from typing_extensions import Literal + +def f() -> str: ... + +if x := f(): + reveal_type(x) # N: Revealed type is "builtins.str" +else: + reveal_type(x) # N: Revealed type is "builtins.str" + +reveal_type(x) # N: Revealed type is "builtins.str" + +def always_false() -> Literal[False]: ... + +if y := always_false(): + reveal_type(y) # E: Statement is unreachable +else: + reveal_type(y) # N: Revealed type is "Literal[False]" + +reveal_type(y) # N: Revealed type is "Literal[False]" + +def always_false_with_parameter(x: int) -> Literal[False]: ... + +if z := always_false_with_parameter(5): + reveal_type(z) # E: Statement is unreachable +else: + reveal_type(z) # N: Revealed type is "Literal[False]" + +reveal_type(z) # N: Revealed type is "Literal[False]" +[builtins fixtures/tuple.pyi] + [case testWalrusExpr] def func() -> None: foo = Foo() @@ -401,3 +540,33 @@ def main(a: object) -> None: reveal_type(x) # N: Revealed type is "builtins.float" reveal_type(a) # N: Revealed type is "builtins.object" [builtins fixtures/tuple.pyi] + +[case testWalrusRedefined] +def foo() -> None: + x = 0 + [x := x + y for y in [1, 2, 3]] +[builtins fixtures/dict.pyi] + +[case testOverloadWithPositionalOnlySelf] +from typing import overload, Optional + +class Foo: + @overload + def f(self, a: str, /) -> None: ... + + @overload + def f(self, *, b: bool = False) -> None: ... + + def f(self, a: Optional[str] = None, /, *, b: bool = False) -> None: # E: Overloaded function implementation does not accept all possible arguments of signature 2 + ... + +class Bar: + @overload + def f(self, a: str, /) -> None: ... + + @overload # Notice `/` in sig below: + def f(self, /, *, b: bool = False) -> None: ... + + def f(self, a: Optional[str] = None, /, *, b: bool = False) -> None: + ... +[builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-redefine.test b/test-data/unit/check-redefine.test index 5530777dd4db..85208df0932a 100644 --- a/test-data/unit/check-redefine.test +++ b/test-data/unit/check-redefine.test @@ -474,3 +474,99 @@ with A() as x: reveal_type(x) # N: Revealed type is "builtins.int" with B() as x: x = 0 # E: Incompatible types in assignment (expression has type "int", variable has type "str") + + +[case testRedefineModuleAsException] +import typing +try: + pass +except Exception as typing: + pass +[builtins fixtures/exception.pyi] + +[case testRedefiningUnderscoreFunctionIsntAnError] +def _(arg): + pass + +def _(arg): + pass + +[case testTypeErrorsInUnderscoreFunctionsReported] +def _(arg: str): + x = arg + 1 # E: Unsupported left operand type for + ("str") + +def _(arg: int) -> int: + return 'a' # E: Incompatible return value type (got "str", expected "int") + +[case testCallingUnderscoreFunctionIsNotAllowed-skip] +# Skipped because of https://github.com/python/mypy/issues/11774 +def _(arg: str) -> None: + pass + +def _(arg: int) -> int: + return arg + +_('a') # E: Calling function named "_" is not allowed + +y = _(5) # E: Calling function named "_" is not allowed + +[case testFunctionStillTypeCheckedWhenAliasedAsUnderscoreDuringImport] +from a import f as _ + +_(1) # E: Argument 1 to "f" has incompatible type "int"; expected "str" +reveal_type(_('a')) # N: Revealed type is "builtins.str" + +[file a.py] +def f(arg: str) -> str: + return arg + +[case testCallToFunctionStillTypeCheckedWhenAssignedToUnderscoreVariable] +from a import g +_ = g + +_('a') # E: Argument 1 has incompatible type "str"; expected "int" +reveal_type(_(1)) # N: Revealed type is "builtins.int" + +[file a.py] +def g(arg: int) -> int: + return arg + +[case testRedefiningUnderscoreFunctionWithDecoratorWithUnderscoreFunctionsNextToEachOther] +def dec(f): + return f + +@dec +def _(arg): + pass + +@dec +def _(arg): + pass + +[case testRedefiningUnderscoreFunctionWithDecoratorInDifferentPlaces] +def dec(f): + return f + +def dec2(f): + return f + +@dec +def _(arg): + pass + +def f(arg): + pass + +@dec2 +def _(arg): + pass + +[case testOverwritingImportedFunctionThatWasAliasedAsUnderscore] +from a import f as _ + +def _(arg: str) -> str: # E: Name "_" already defined (possibly by an import) + return arg + +[file a.py] +def f(s: str) -> str: + return s diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index a1fa234e6d0d..afd75111743d 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -802,6 +802,37 @@ class Bad(metaclass=Meta): Good.do_x() Bad.do_x() # E: Invalid self argument "Type[Bad]" to attribute function "do_x" with type "Callable[[Type[T]], T]" +[case testSelfTypeProtocolClassmethodMatch] +from typing import Type, TypeVar, Protocol + +T = TypeVar('T') + +class HasDoX(Protocol): + @classmethod + def do_x(cls: Type[T]) -> T: + ... + +class Good: + @classmethod + def do_x(cls) -> 'Good': + ... + +class Bad: + @classmethod + def do_x(cls) -> Good: + ... + +good: HasDoX = Good() +bad: HasDoX = Bad() +[builtins fixtures/classmethod.pyi] +[out] +main:21: error: Incompatible types in assignment (expression has type "Bad", variable has type "HasDoX") +main:21: note: Following member(s) of "Bad" have conflicts: +main:21: note: Expected: +main:21: note: def do_x(cls) -> Bad +main:21: note: Got: +main:21: note: def do_x(cls) -> Good + [case testSelfTypeNotSelfType] # Friendlier error messages for common mistakes. See #2950 class A: diff --git a/test-data/unit/check-singledispatch.test b/test-data/unit/check-singledispatch.test new file mode 100644 index 000000000000..8fe049437c57 --- /dev/null +++ b/test-data/unit/check-singledispatch.test @@ -0,0 +1,326 @@ +[case testIncorrectDispatchArgumentWhenDoesntMatchFallback] +from functools import singledispatch + +class A: pass +class B(A): pass + +@singledispatch +def fun(arg: A) -> None: + pass +@fun.register +def fun_b(arg: B) -> None: + pass + +fun(1) # E: Argument 1 to "fun" has incompatible type "int"; expected "A" + +# probably won't be required after singledispatch is special cased +[builtins fixtures/args.pyi] + +[case testMultipleUnderscoreFunctionsIsntError] +from functools import singledispatch + +@singledispatch +def fun(arg) -> None: + pass +@fun.register +def _(arg: str) -> None: + pass +@fun.register +def _(arg: int) -> None: + pass + +[builtins fixtures/args.pyi] + +[case testCheckNonDispatchArgumentsWithTypeAlwaysTheSame] +from functools import singledispatch + +class A: pass +class B(A): pass + +@singledispatch +def f(arg: A, arg2: str) -> None: + pass + +@f.register +def g(arg: B, arg2: str) -> None: + pass + +f(A(), 'a') +f(A(), 5) # E: Argument 2 to "f" has incompatible type "int"; expected "str" + +f(B(), 'a') +f(B(), 1) # E: Argument 2 to "f" has incompatible type "int"; expected "str" + +[builtins fixtures/args.pyi] + +[case testImplementationHasSameDispatchTypeAsFallback-xfail] +from functools import singledispatch + +# TODO: differentiate between fallback and other implementations in error message +@singledispatch +def f(arg: int) -> None: # E: singledispatch implementation 1 will never be used: implementation 2's dispatch type is the same + pass + +@f.register +def g(arg: int) -> None: + pass + +[builtins fixtures/args.pyi] + +[case testRegisterHasDifferentTypeThanTypeSignature-xfail] +from functools import singledispatch + +@singledispatch +def f(arg) -> None: + pass + +@f.register(str) +def g(arg: int) -> None: # E: Argument to register "str" is incompatible with type "int" in function signature + pass + +[builtins fixtures/args.pyi] + +[case testDispatchBasedOnTypeAnnotationsRequires37-xfail] +# flags: --python-version 3.6 +# the docs for singledispatch say that register didn't accept type annotations until python 3.7 +from functools import singledispatch + +@singledispatch +def f(arg) -> None: + pass +@f.register +def g(arg: int) -> None: # E: Singledispatch based on type annotations is only supported in Python 3.7 and greater + pass + +[builtins fixtures/args.pyi] + +[case testTypePassedAsArgumentToRegister] +from functools import singledispatch + +@singledispatch +def f(arg: int) -> None: + pass +@f.register(str) +def g(arg) -> None: # E: Dispatch type "str" must be subtype of fallback function first argument "int" + pass + +[builtins fixtures/args.pyi] + +[case testCustomClassPassedAsTypeToRegister] +from functools import singledispatch +class A: pass + +@singledispatch +def f(arg: int) -> None: + pass +@f.register(A) +def g(arg) -> None: # E: Dispatch type "A" must be subtype of fallback function first argument "int" + pass + +[builtins fixtures/args.pyi] + +[case testMultiplePossibleImplementationsForKnownType] +from functools import singledispatch +from typing import Union + +class A: pass +class B(A): pass +class C: pass + +@singledispatch +def f(arg: Union[A, C]) -> None: + pass + +@f.register +def g(arg: B) -> None: + pass + +@f.register +def h(arg: C) -> None: + pass + +x: Union[B, C] +f(x) + +[builtins fixtures/args.pyi] + +[case testOnePartOfUnionDoesNotHaveCorrespondingImplementation] +from functools import singledispatch +from typing import Union + +class A: pass +class B(A): pass +class C: pass + +@singledispatch +def f(arg: Union[A, C]) -> None: + pass + +@f.register +def g(arg: B) -> None: + pass + +@f.register +def h(arg: C) -> None: + pass + +x: Union[B, C, int] +f(x) # E: Argument 1 to "f" has incompatible type "Union[B, C, int]"; expected "Union[A, C]" + +[builtins fixtures/args.pyi] + +[case testABCAllowedAsDispatchType] +from functools import singledispatch +from collections.abc import Mapping + +@singledispatch +def f(arg) -> None: + pass + +@f.register +def g(arg: Mapping) -> None: + pass + +[builtins fixtures/args.pyi] +[builtins fixtures/list.pyi] +[builtins fixtures/dict.pyi] + +[case testIncorrectArgumentsInSingledispatchFunctionDefinition] +from functools import singledispatch + +@singledispatch +def f() -> None: # E: Singledispatch function requires at least one argument + pass + +@singledispatch +def g(**kwargs) -> None: # E: First argument to singledispatch function must be a positional argument + pass + +@singledispatch +def h(*, x) -> None: # E: First argument to singledispatch function must be a positional argument + pass + +@singledispatch +def i(*, x=1) -> None: # E: First argument to singledispatch function must be a positional argument + pass + +[builtins fixtures/args.pyi] + +[case testDispatchTypeIsNotASubtypeOfFallbackFirstArgument] +from functools import singledispatch + +class A: pass +class B(A): pass +class C: pass + +@singledispatch +def f(arg: A) -> None: + pass + +@f.register +def g(arg: B) -> None: + pass + +@f.register +def h(arg: C) -> None: # E: Dispatch type "C" must be subtype of fallback function first argument "A" + pass + +[builtins fixtures/args.pyi] + +[case testMultipleSingledispatchFunctionsIntermixed] +from functools import singledispatch + +class A: pass +class B(A): pass +class C: pass + +@singledispatch +def f(arg: A) -> None: + pass + +@singledispatch +def h(arg: C) -> None: + pass + +@f.register +def g(arg: B) -> None: + pass + +[builtins fixtures/args.pyi] + +[case testAnyInConstructorArgsWithClassPassedToRegister] +from functools import singledispatch +from typing import Any + +class Base: pass +class ConstExpr: + def __init__(self, **kwargs: Any) -> None: pass + +@singledispatch +def f(arg: Base) -> ConstExpr: + pass + +@f.register(ConstExpr) +def g(arg: ConstExpr) -> ConstExpr: # E: Dispatch type "ConstExpr" must be subtype of fallback function first argument "Base" + pass + + +[builtins fixtures/args.pyi] + +[case testRegisteredImplementationUsedBeforeDefinition] +from functools import singledispatch +from typing import Union + +class Node: pass +class MypyFile(Node): pass +class Missing: pass + +@singledispatch +def f(a: Union[Node, Missing]) -> None: + pass + +@f.register +def g(a: MypyFile) -> None: + x: Missing + f(x) + +@f.register +def h(a: Missing) -> None: + pass + +[builtins fixtures/args.pyi] + +[case testIncorrectArgumentTypeWhenCallingRegisteredImplDirectly] +from functools import singledispatch + +@singledispatch +def f(arg, arg2: str) -> bool: + return False + +@f.register +def g(arg: int, arg2: str) -> bool: + pass + +@f.register(str) +def h(arg, arg2: str) -> bool: + pass + +g('a', 'a') # E: Argument 1 to "g" has incompatible type "str"; expected "int" +g(1, 1) # E: Argument 2 to "g" has incompatible type "int"; expected "str" + +# don't show errors for incorrect first argument here, because there's no type annotation for the +# first argument +h(1, 'a') +h('a', 1) # E: Argument 2 to "h" has incompatible type "int"; expected "str" + +[builtins fixtures/args.pyi] + +[case testDontCrashWhenRegisteringAfterError] +import functools +a = functools.singledispatch('a') # E: Need type annotation for "a" # E: Argument 1 to "singledispatch" has incompatible type "str"; expected "Callable[..., ]" + +@a.register(int) +def default(val) -> int: + return 3 + +[builtins fixtures/args.pyi] diff --git a/test-data/unit/check-slots.test b/test-data/unit/check-slots.test new file mode 100644 index 000000000000..254aa983f82f --- /dev/null +++ b/test-data/unit/check-slots.test @@ -0,0 +1,520 @@ +[case testSlotsDefinitionWithStrAndListAndTuple] +class A: + __slots__ = "a" + def __init__(self) -> None: + self.a = 1 + self.b = 2 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" + +class B: + __slots__ = ("a", "b") + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.c = 3 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" + +class C: + __slots__ = ['c'] + def __init__(self) -> None: + self.a = 1 # E: Trying to assign name "a" that is not in "__slots__" of type "__main__.C" + self.c = 3 + +class WithVariable: + __fields__ = ['a', 'b'] + __slots__ = __fields__ + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.c = 3 +[builtins fixtures/tuple.pyi] +[builtins fixtures/list.pyi] + + +[case testSlotsDefinitionWithDict] +class D: + __slots__ = {'key': 'docs'} + def __init__(self) -> None: + self.key = 1 + self.missing = 2 # E: Trying to assign name "missing" that is not in "__slots__" of type "__main__.D" +[builtins fixtures/dict.pyi] + + +[case testSlotsDefinitionWithDynamicDict] +slot_kwargs = {'b': 'docs'} +class WithDictKwargs: + __slots__ = {'a': 'docs', **slot_kwargs} + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.c = 3 +[builtins fixtures/dict.pyi] + + +[case testSlotsDefinitionWithSet] +class E: + __slots__ = {'e'} + def __init__(self) -> None: + self.e = 1 + self.missing = 2 # E: Trying to assign name "missing" that is not in "__slots__" of type "__main__.E" +[builtins fixtures/set.pyi] + + +[case testSlotsDefinitionOutsideOfClass] +__slots__ = ("a", "b") +class A: + def __init__(self) -> None: + self.x = 1 + self.y = 2 +[builtins fixtures/tuple.pyi] + + +[case testSlotsDefinitionWithClassVar] +class A: + __slots__ = ('a',) + b = 4 + + def __init__(self) -> None: + self.a = 1 + + # You cannot override class-level variables, but you can use them: + b = self.b + self.b = 2 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" + + self.c = 3 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" + +A.b = 1 +[builtins fixtures/tuple.pyi] + + +[case testSlotsDefinitionMultipleVars1] +class A: + __slots__ = __fields__ = ("a", "b") + def __init__(self) -> None: + self.x = 1 + self.y = 2 +[builtins fixtures/tuple.pyi] + + +[case testSlotsDefinitionMultipleVars2] +class A: + __fields__ = __slots__ = ("a", "b") + def __init__(self) -> None: + self.x = 1 + self.y = 2 +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentEmptySlots] +class A: + __slots__ = () + def __init__(self) -> None: + self.a = 1 + self.b = 2 + +a = A() +a.a = 1 +a.b = 2 +a.missing = 2 +[out] +main:4: error: Trying to assign name "a" that is not in "__slots__" of type "__main__.A" +main:5: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" +main:8: error: Trying to assign name "a" that is not in "__slots__" of type "__main__.A" +main:9: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" +main:10: error: "A" has no attribute "missing" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithSuper] +class A: + __slots__ = ("a",) +class B(A): + __slots__ = ("b", "c") + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self._one = 1 + +b = B() +b.a = 1 +b.b = 2 +b.c = 3 +b._one = 1 +b._two = 2 +[out] +main:9: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" +main:14: error: "B" has no attribute "c" +main:15: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" +main:16: error: "B" has no attribute "_two" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithSuperDuplicateSlots] +class A: + __slots__ = ("a",) +class B(A): + __slots__ = ("a", "b",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self._one = 1 # E: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithMixin] +class A: + __slots__ = ("a",) +class Mixin: + __slots__ = ("m",) +class B(A, Mixin): + __slots__ = ("b",) + + def __init__(self) -> None: + self.a = 1 + self.m = 2 + self._one = 1 + +b = B() +b.a = 1 +b.m = 2 +b.b = 2 +b._two = 2 +[out] +main:11: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" +main:16: error: "B" has no attribute "b" +main:17: error: "B" has no attribute "_two" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithSlottedSuperButNoChildSlots] +class A: + __slots__ = ("a",) +class B(A): + def __init__(self) -> None: + self.a = 1 + self.b = 1 + +b = B() +b.a = 1 +b.b = 2 +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithoutSuperSlots] +class A: + pass # no slots +class B(A): + __slots__ = ("a", "b") + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 + +b = B() +b.a = 1 +b.b = 2 +b.missing = 3 +b.extra = 4 # E: "B" has no attribute "extra" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithoutSuperMixingSlots] +class A: + __slots__ = () +class Mixin: + pass # no slots +class B(A, Mixin): + __slots__ = ("a", "b") + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 + +b = B() +b.a = 1 +b.b = 2 +b.missing = 3 +b.extra = 4 # E: "B" has no attribute "extra" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithExplicitSetattr] +class A: + __slots__ = ("a",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + + def __setattr__(self, k, v) -> None: + ... + +a = A() +a.a = 1 +a.b = 2 +a.c = 3 +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithParentSetattr] +class Parent: + __slots__ = () + + def __setattr__(self, k, v) -> None: + ... + +class A(Parent): + __slots__ = ("a",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + +a = A() +a.a = 1 +a.b = 2 +a.c = 3 +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithProps] +from typing import Any + +custom_prop: Any + +class A: + __slots__ = ("a",) + + @property + def first(self) -> int: + ... + + @first.setter + def first(self, arg: int) -> None: + ... + +class B(A): + __slots__ = ("b",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.c = 3 + + @property + def second(self) -> int: + ... + + @second.setter + def second(self, arg: int) -> None: + ... + + def get_third(self) -> int: + ... + + def set_third(self, arg: int) -> None: + ... + + third = custom_prop(get_third, set_third) + +b = B() +b.a = 1 +b.b = 2 +b.c = 3 +b.first = 1 +b.second = 2 +b.third = 3 +b.extra = 'extra' +[out] +main:22: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" +main:43: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" +main:47: error: "B" has no attribute "extra" +[builtins fixtures/tuple.pyi] +[builtins fixtures/property.pyi] + + +[case testSlotsAssignmentWithUnionProps] +from typing import Any, Callable, Union + +custom_obj: Any + +class custom_property(object): + def __set__(self, *args, **kwargs): + ... + +class A: + __slots__ = ("a",) + + def __init__(self) -> None: + self.a = 1 + + b: custom_property + c: Union[Any, custom_property] + d: Union[Callable, custom_property] + e: Callable + +a = A() +a.a = 1 +a.b = custom_obj +a.c = custom_obj +a.d = custom_obj +# TODO: Should this be allowed? +a.e = custom_obj # E: Cannot assign to a method +[out] +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] + + +[case testSlotsAssignmentWithMethodReassign] +class A: + __slots__ = () + + def __init__(self) -> None: + self.method = lambda: None # E: Cannot assign to a method + + def method(self) -> None: + ... + +a = A() +a.method = lambda: None # E: Cannot assign to a method +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithExplicitDict] +class A: + __slots__ = ("a",) +class B(A): + __slots__ = ("__dict__",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + +b = B() +b.a = 1 +b.b = 2 +b.c = 3 # E: "B" has no attribute "c" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithExplicitSuperDict] +class A: + __slots__ = ("__dict__",) +class B(A): + __slots__ = ("a",) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + +b = B() +b.a = 1 +b.b = 2 +b.c = 3 # E: "B" has no attribute "c" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentWithVariable] +slot_name = "b" +class A: + __slots__ = ("a", slot_name) + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.c = 3 + +a = A() +a.a = 1 +a.b = 2 +a.c = 3 +a.d = 4 # E: "A" has no attribute "d" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentMultipleLeftValues] +class A: + __slots__ = ("a", "b") + def __init__(self) -> None: + self.a, self.b, self.c = (1, 2, 3) # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" +[builtins fixtures/tuple.pyi] + + +[case testSlotsAssignmentMultipleAssignments] +class A: + __slots__ = ("a",) + def __init__(self) -> None: + self.a = self.b = self.c = 1 +[out] +main:4: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" +main:4: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" +[builtins fixtures/tuple.pyi] + + +[case testSlotsWithTupleCall] +class A: + # TODO: for now this way of writing tuples are not recognised + __slots__ = tuple(("a", "b")) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 +[builtins fixtures/tuple.pyi] + + +[case testSlotsWithListCall] +class A: + # TODO: for now this way of writing lists are not recognised + __slots__ = list(("a", "b")) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 +[builtins fixtures/tuple.pyi] +[builtins fixtures/list.pyi] + + +[case testSlotsWithSetCall] +class A: + # TODO: for now this way of writing sets are not recognised + __slots__ = set(("a", "b")) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 +[builtins fixtures/tuple.pyi] +[builtins fixtures/set.pyi] + + +[case testSlotsWithDictCall] +class A: + # TODO: for now this way of writing dicts are not recognised + __slots__ = dict((("a", "docs"), ("b", "docs"))) + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] + + +[case testSlotsWithAny] +from typing import Any + +some_obj: Any + +class A: + # You can do anything with `Any`: + __slots__ = some_obj + + def __init__(self) -> None: + self.a = 1 + self.b = 2 + self.missing = 3 +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 33e10650476d..62d82f94a6c1 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -406,8 +406,7 @@ class MyError(BaseException): pass [out] main:5: error: Exception must be derived from BaseException -[case testRaiseClassobject] -import typing +[case testRaiseClassObject] class A: pass class MyError(BaseException): pass def f(): pass @@ -418,6 +417,33 @@ raise object # E: Exception must be derived from BaseException raise f # E: Exception must be derived from BaseException [builtins fixtures/exception.pyi] +[case testRaiseClassObjectCustomInit] +class MyBaseError(BaseException): + def __init__(self, required) -> None: + ... +class MyError(Exception): + def __init__(self, required1, required2) -> None: + ... +class MyKwError(Exception): + def __init__(self, *, kwonly) -> None: + ... +class MyErrorWithDefault(Exception): + def __init__(self, optional=1) -> None: + ... +raise BaseException +raise Exception +raise BaseException(1) +raise Exception(2) +raise MyBaseError(4) +raise MyError(5, 6) +raise MyKwError(kwonly=7) +raise MyErrorWithDefault(8) +raise MyErrorWithDefault +raise MyBaseError # E: Too few arguments for "MyBaseError" +raise MyError # E: Too few arguments for "MyError" +raise MyKwError # E: Missing named argument "kwonly" for "MyKwError" +[builtins fixtures/exception.pyi] + [case testRaiseExceptionType] import typing x = None # type: typing.Type[BaseException] diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index ee7126972661..6c4c63dc5c2d 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -405,7 +405,7 @@ a, b = None, None # type: (A, B) a1, b1 = a, a # type: (A, B) # E: Incompatible types in assignment (expression has type "A", variable has type "B") a2, b2 = b, b # type: (A, B) # E: Incompatible types in assignment (expression has type "B", variable has type "A") -a3, b3 = a # type: (A, B) # E: "__main__.A" object is not iterable +a3, b3 = a # type: (A, B) # E: "A" object is not iterable a4, b4 = None # type: (A, B) # E: "None" object is not iterable a5, b5 = a, b, a # type: (A, B) # E: Too many values to unpack (2 expected, 3 provided) @@ -421,8 +421,8 @@ a, b = None, None # type: (A, B) def f(): pass a, b = None # E: "None" object is not iterable -a, b = a # E: "__main__.A" object is not iterable -a, b = f # E: "def () -> Any" object is not iterable +a, b = a # E: "A" object is not iterable +a, b = f # E: "Callable[[], Any]" object is not iterable class A: pass class B: pass @@ -1468,7 +1468,33 @@ x9, y9, x10, y10, z5 = *points2, 1, *points2 # E: Contiguous iterable with same () = [] # E: can't assign to () [case testAssignEmptyBogus] -() = 1 # E: "Literal[1]?" object is not iterable +() = 1 # E: "int" object is not iterable +[builtins fixtures/tuple.pyi] + +[case testMultiplyTupleByIntegerLiteral] +from typing import Tuple +t = ('',) * 2 +reveal_type(t) # N: Revealed type is "Tuple[builtins.str, builtins.str]" +t2 = ('',) * -1 +reveal_type(t2) # N: Revealed type is "Tuple[]" +t3 = ('', 1) * 2 +reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" +def f() -> Tuple[str, ...]: + return ('', ) +reveal_type(f() * 2) # N: Revealed type is "builtins.tuple[builtins.str*]" +[builtins fixtures/tuple.pyi] + +[case testMultiplyTupleByIntegerLiteralReverse] +from typing import Tuple +t = 2 * ('',) +reveal_type(t) # N: Revealed type is "Tuple[builtins.str, builtins.str]" +t2 = -1 * ('',) +reveal_type(t2) # N: Revealed type is "Tuple[]" +t3 = 2 * ('', 1) +reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" +def f() -> Tuple[str, ...]: + return ('', ) +reveal_type(2 * f()) # N: Revealed type is "builtins.tuple[builtins.str*]" [builtins fixtures/tuple.pyi] [case testSingleUndefinedTypeAndTuple] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 2701858895d1..a697c32d7c49 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -659,3 +659,64 @@ reveal_type(w) # N: Revealed type is "__main__.Out.In" reveal_type(x) # N: Revealed type is "__main__.Out.In.Inner" reveal_type(y) # N: Revealed type is "__main__.Out.In.Inner" reveal_type(z) # N: Revealed type is "__main__.Out.In" + + +[case testSimplePep613] +from typing_extensions import TypeAlias +x: TypeAlias = str +a: x +reveal_type(a) # N: Revealed type is "builtins.str" + +y: TypeAlias = "str" +b: y +reveal_type(b) # N: Revealed type is "builtins.str" + +z: TypeAlias = "int | str" +c: z +reveal_type(c) # N: Revealed type is "Union[builtins.int, builtins.str]" +[builtins fixtures/tuple.pyi] + +[case testForwardRefPep613] +from typing_extensions import TypeAlias + +x: TypeAlias = "MyClass" +a: x +reveal_type(a) # N: Revealed type is "__main__.MyClass" + +class MyClass: ... +[builtins fixtures/tuple.pyi] + +[case testInvalidPep613] +from typing_extensions import TypeAlias + +x: TypeAlias = list(int) # E: Invalid type alias: expression is not a valid type \ + # E: Too many arguments for "list" +a: x +[builtins fixtures/tuple.pyi] + +[case testFunctionScopePep613] +from typing_extensions import TypeAlias + +def f() -> None: + x: TypeAlias = str + a: x + reveal_type(a) # N: Revealed type is "builtins.str" + + y: TypeAlias = "str" + b: y + reveal_type(b) # N: Revealed type is "builtins.str" +[builtins fixtures/tuple.pyi] + +[case testImportCyclePep613] +# cmd: mypy -m t t2 +[file t.py] +MYPY = False +if MYPY: + from t2 import A +x: A +reveal_type(x) # N: Revealed type is "builtins.str" +[file t2.py] +from typing_extensions import TypeAlias +A: TypeAlias = str +[builtins fixtures/bool.pyi] +[out] diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 8b28d2ef9ace..921d2ab5c46e 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -75,6 +75,14 @@ Point = TypedDict('Point', {'x': int, 'y': int}) p = Point(x='meaning_of_life', y=1337) # E: Incompatible types (expression has type "str", TypedDict item "x" has type "int") [builtins fixtures/dict.pyi] +[case testCannotCreateTypedDictInstanceWithInlineTypedDict] +from mypy_extensions import TypedDict +D = TypedDict('D', { + 'x': TypedDict('E', { # E: Inline TypedDict types not supported; use assignment to define TypedDict + 'y': int + }) +}) +[builtins fixtures/dict.pyi] -- Define TypedDict (Class syntax) @@ -171,6 +179,21 @@ p: Point2D reveal_type(p) # N: Revealed type is "TypedDict('__main__.Point2D', {'x': builtins.int, 'y': builtins.int})" [builtins fixtures/dict.pyi] +[case testCannotCreateTypedDictWithDuplicateBases] +# https://github.com/python/mypy/issues/3673 +from typing import TypedDict + +class A(TypedDict): + x: str + y: int + +class B(A, A): # E: Duplicate base class "A" + z: str + +class C(TypedDict, TypedDict): # E: Duplicate base class "TypedDict" + c1: int +[typing fixtures/typing-typeddict.pyi] + [case testCannotCreateTypedDictWithClassWithOtherStuff] # flags: --python-version 3.6 from mypy_extensions import TypedDict @@ -185,6 +208,19 @@ p = Point(x=42, y=1337, z='whatever') reveal_type(p) # N: Revealed type is "TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int, 'z': Any})" [builtins fixtures/dict.pyi] +[case testCannotCreateTypedDictWithClassWithFunctionUsedToCrash] +# https://github.com/python/mypy/issues/11079 +from typing import TypedDict +class D(TypedDict): + y: int + def x(self, key: int): # E: Invalid statement in TypedDict definition; expected "field_name: field_type" + pass + +d = D(y=1) +reveal_type(d) # N: Revealed type is "TypedDict('__main__.D', {'y': builtins.int})" +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + [case testCanCreateTypedDictTypeWithUnderscoreItemName] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int, '_fallback': object}) @@ -1228,7 +1264,7 @@ from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': 1, 'y': 1}) # E: Invalid type: try using Literal[1] instead? [builtins fixtures/dict.pyi] -[case testCannotCreateTypedDictTypeWithInvalidName] +[case testCannotCreateTypedDictTypeWithInvalidName2] from mypy_extensions import TypedDict X = TypedDict('Y', {'x': int}) # E: First argument "Y" to TypedDict() does not match variable name "X" [builtins fixtures/dict.pyi] @@ -1440,7 +1476,7 @@ T = TypeVar('T', bound='M') class G(Generic[T]): x: T -yb: G[int] # E: Type argument "builtins.int" of "G" must be a subtype of "TypedDict('__main__.M', {'x': builtins.int})" +yb: G[int] # E: Type argument "int" of "G" must be a subtype of "M" yg: G[M] z: int = G[M]().x['x'] @@ -1584,8 +1620,8 @@ d = None # type: Dict[Any, Any] f1(**td, **d) f1(**d, **td) -f2(**td, **d) # E: Too many arguments for "f2" -f2(**d, **td) # E: Too many arguments for "f2" +f2(**td, **d) +f2(**d, **td) [builtins fixtures/dict.pyi] [case testTypedDictNonMappingMethods] @@ -1668,8 +1704,8 @@ s = '' del a[s] # E: Expected TypedDict key to be string literal del b[s] # E: Expected TypedDict key to be string literal alias = b.__delitem__ -alias('x') # E: Argument 1 has incompatible type "str"; expected "NoReturn" -alias(s) # E: Argument 1 has incompatible type "str"; expected "NoReturn" +alias('x') +alias(s) [builtins fixtures/dict.pyi] [case testPluginUnionsOfTypedDicts] @@ -2096,7 +2132,7 @@ class TD(TypedDict): d: TD = {b'foo': 2} # E: Expected TypedDict key to be string literal d[b'foo'] = 3 # E: TypedDict key must be a string literal; expected one of ("foo") \ - # E: Argument 1 has incompatible type "bytes"; expected "str" + # E: Argument 1 to "__setitem__" has incompatible type "bytes"; expected "str" d[b'foo'] # E: TypedDict key must be a string literal; expected one of ("foo") d[3] # E: TypedDict key must be a string literal; expected one of ("foo") d[True] # E: TypedDict key must be a string literal; expected one of ("foo") @@ -2109,3 +2145,246 @@ from mypy_extensions import TypedDict Foo = TypedDict('Foo', {'camelCaseKey': str}) value: Foo = {} # E: Missing key "camelCaseKey" for TypedDict "Foo" [builtins fixtures/dict.pyi] + +-- Required[] + +[case testDoesRecognizeRequiredInTypedDictWithClass] +from typing import TypedDict +from typing import Required +class Movie(TypedDict, total=False): + title: Required[str] + year: int +m = Movie(title='The Matrix') +m = Movie() # E: Missing key "title" for TypedDict "Movie" +[typing fixtures/typing-typeddict.pyi] + +[case testDoesRecognizeRequiredInTypedDictWithAssignment] +from typing import TypedDict +from typing import Required +Movie = TypedDict('Movie', { + 'title': Required[str], + 'year': int, +}, total=False) +m = Movie(title='The Matrix') +m = Movie() # E: Missing key "title" for TypedDict "Movie" +[typing fixtures/typing-typeddict.pyi] + +[case testDoesDisallowRequiredOutsideOfTypedDict] +from typing import Required +x: Required[int] = 42 # E: Required[] can be only used in a TypedDict definition +[typing fixtures/typing-typeddict.pyi] + +[case testDoesOnlyAllowRequiredInsideTypedDictAtTopLevel] +from typing import TypedDict +from typing import Union +from typing import Required +Movie = TypedDict('Movie', { + 'title': Union[ + Required[str], # E: Required[] can be only used in a TypedDict definition + bytes + ], + 'year': int, +}, total=False) +[typing fixtures/typing-typeddict.pyi] + +[case testDoesDisallowRequiredInsideRequired] +from typing import TypedDict +from typing import Union +from typing import Required +Movie = TypedDict('Movie', { + 'title': Required[Union[ + Required[str], # E: Required[] can be only used in a TypedDict definition + bytes + ]], + 'year': int, +}, total=False) +[typing fixtures/typing-typeddict.pyi] + +[case testRequiredOnlyAllowsOneItem] +from typing import TypedDict +from typing import Required +class Movie(TypedDict, total=False): + title: Required[str, bytes] # E: Required[] must have exactly one type argument + year: int +[typing fixtures/typing-typeddict.pyi] + + +-- NotRequired[] + +[case testDoesRecognizeNotRequiredInTypedDictWithClass] +from typing import TypedDict +from typing import NotRequired +class Movie(TypedDict): + title: str + year: NotRequired[int] +m = Movie(title='The Matrix') +m = Movie() # E: Missing key "title" for TypedDict "Movie" +[typing fixtures/typing-typeddict.pyi] + +[case testDoesRecognizeNotRequiredInTypedDictWithAssignment] +from typing import TypedDict +from typing import NotRequired +Movie = TypedDict('Movie', { + 'title': str, + 'year': NotRequired[int], +}) +m = Movie(title='The Matrix') +m = Movie() # E: Missing key "title" for TypedDict "Movie" +[typing fixtures/typing-typeddict.pyi] + +[case testDoesDisallowNotRequiredOutsideOfTypedDict] +from typing import NotRequired +x: NotRequired[int] = 42 # E: NotRequired[] can be only used in a TypedDict definition +[typing fixtures/typing-typeddict.pyi] + +[case testDoesOnlyAllowNotRequiredInsideTypedDictAtTopLevel] +from typing import TypedDict +from typing import Union +from typing import NotRequired +Movie = TypedDict('Movie', { + 'title': Union[ + NotRequired[str], # E: NotRequired[] can be only used in a TypedDict definition + bytes + ], + 'year': int, +}) +[typing fixtures/typing-typeddict.pyi] + +[case testDoesDisallowNotRequiredInsideNotRequired] +from typing import TypedDict +from typing import Union +from typing import NotRequired +Movie = TypedDict('Movie', { + 'title': NotRequired[Union[ + NotRequired[str], # E: NotRequired[] can be only used in a TypedDict definition + bytes + ]], + 'year': int, +}) +[typing fixtures/typing-typeddict.pyi] + +[case testNotRequiredOnlyAllowsOneItem] +from typing import TypedDict +from typing import NotRequired +class Movie(TypedDict): + title: NotRequired[str, bytes] # E: NotRequired[] must have exactly one type argument + year: int +[typing fixtures/typing-typeddict.pyi] + +-- Union dunders + +[case testTypedDictUnionGetItem] +from typing import TypedDict, Union + +class Foo1(TypedDict): + z: str + a: int +class Foo2(TypedDict): + z: str + b: int + +def func(foo: Union[Foo1, Foo2]) -> str: + reveal_type(foo["z"]) # N: Revealed type is "builtins.str" + # ok, but type is incorrect: + reveal_type(foo.__getitem__("z")) # N: Revealed type is "builtins.object*" + + reveal_type(foo["a"]) # N: Revealed type is "Union[builtins.int, Any]" \ + # E: TypedDict "Foo2" has no key "a" + reveal_type(foo["b"]) # N: Revealed type is "Union[Any, builtins.int]" \ + # E: TypedDict "Foo1" has no key "b" + reveal_type(foo["missing"]) # N: Revealed type is "Any" \ + # E: TypedDict "Foo1" has no key "missing" \ + # E: TypedDict "Foo2" has no key "missing" + reveal_type(foo[1]) # N: Revealed type is "Any" \ + # E: TypedDict key must be a string literal; expected one of ("z", "a") \ + # E: TypedDict key must be a string literal; expected one of ("z", "b") + + return foo["z"] +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + + +[case testTypedDictUnionSetItem] +from typing import TypedDict, Union + +class Foo1(TypedDict): + z: str + a: int +class Foo2(TypedDict): + z: str + b: int + +def func(foo: Union[Foo1, Foo2]): + foo["z"] = "a" # ok + foo.__setitem__("z", "a") # ok + + foo["z"] = 1 # E: Value of "z" has incompatible type "int"; expected "str" + + foo["a"] = 1 # E: TypedDict "Foo2" has no key "a" + foo["b"] = 2 # E: TypedDict "Foo1" has no key "b" + + foo["missing"] = 1 # E: TypedDict "Foo1" has no key "missing" \ + # E: TypedDict "Foo2" has no key "missing" + foo[1] = "m" # E: TypedDict key must be a string literal; expected one of ("z", "a") \ + # E: TypedDict key must be a string literal; expected one of ("z", "b") \ + # E: Argument 1 to "__setitem__" has incompatible type "int"; expected "str" +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + + +[case testTypedDictUnionDelItem] +from typing import TypedDict, Union + +class Foo1(TypedDict): + z: str + a: int +class Foo2(TypedDict): + z: str + b: int + +def func(foo: Union[Foo1, Foo2]): + del foo["z"] # E: Key "z" of TypedDict "Foo1" cannot be deleted \ + # E: Key "z" of TypedDict "Foo2" cannot be deleted + foo.__delitem__("z") # E: Key "z" of TypedDict "Foo1" cannot be deleted \ + # E: Key "z" of TypedDict "Foo2" cannot be deleted + + del foo["a"] # E: Key "a" of TypedDict "Foo1" cannot be deleted \ + # E: TypedDict "Foo2" has no key "a" + del foo["b"] # E: TypedDict "Foo1" has no key "b" \ + # E: Key "b" of TypedDict "Foo2" cannot be deleted + + del foo["missing"] # E: TypedDict "Foo1" has no key "missing" \ + # E: TypedDict "Foo2" has no key "missing" + del foo[1] # E: Expected TypedDict key to be string literal \ + # E: Argument 1 to "__delitem__" has incompatible type "int"; expected "str" +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + + +[case testTypedDictTypeVarUnionSetItem] +from typing import TypedDict, Union, TypeVar + +F1 = TypeVar('F1', bound='Foo1') +F2 = TypeVar('F2', bound='Foo2') + +class Foo1(TypedDict): + z: str + a: int +class Foo2(TypedDict): + z: str + b: int + +def func(foo: Union[F1, F2]): + foo["z"] = "a" # ok + foo["z"] = 1 # E: Value of "z" has incompatible type "int"; expected "str" + + foo["a"] = 1 # E: TypedDict "Foo2" has no key "a" + foo["b"] = 2 # E: TypedDict "Foo1" has no key "b" + + foo["missing"] = 1 # E: TypedDict "Foo1" has no key "missing" \ + # E: TypedDict "Foo2" has no key "missing" + foo[1] = "m" # E: TypedDict key must be a string literal; expected one of ("z", "a") \ + # E: TypedDict key must be a string literal; expected one of ("z", "b") \ + # E: Argument 1 to "__setitem__" has incompatible type "int"; expected "str" +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] diff --git a/test-data/unit/check-typeguard.test b/test-data/unit/check-typeguard.test index fa340cb04044..32fe5e750989 100644 --- a/test-data/unit/check-typeguard.test +++ b/test-data/unit/check-typeguard.test @@ -82,6 +82,7 @@ def is_str_list(a: List[object]) -> TypeGuard[List[str]]: pass def main(a: List[object]): if is_str_list(a): reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" + reveal_type(a) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/tuple.pyi] [case testTypeGuardUnionIn] @@ -91,6 +92,7 @@ def is_foo(a: Union[int, str]) -> TypeGuard[str]: pass def main(a: Union[str, int]) -> None: if is_foo(a): reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(a) # N: Revealed type is "Union[builtins.str, builtins.int]" [builtins fixtures/tuple.pyi] [case testTypeGuardUnionOut] @@ -245,7 +247,7 @@ def main1(a: object) -> None: [builtins fixtures/tuple.pyi] -[case testTypeGuardOverload-skip] +[case testTypeGuardOverload] # flags: --strict-optional from typing import overload, Any, Callable, Iterable, Iterator, List, Optional, TypeVar from typing_extensions import TypeGuard @@ -292,8 +294,14 @@ from typing_extensions import TypeGuard class C: def is_float(self, a: object) -> TypeGuard[float]: pass class D(C): - def is_float(self, a: object) -> bool: pass # E: Signature of "is_float" incompatible with supertype "C" + def is_float(self, a: object) -> bool: pass # Fail [builtins fixtures/tuple.pyi] +[out] +main:5: error: Signature of "is_float" incompatible with supertype "C" +main:5: note: Superclass: +main:5: note: def is_float(self, a: object) -> TypeGuard[float] +main:5: note: Subclass: +main:5: note: def is_float(self, a: object) -> bool [case testTypeGuardInAnd] from typing import Any @@ -315,3 +323,227 @@ def coverage(obj: Any) -> bool: return True return False [builtins fixtures/classmethod.pyi] + +[case testAssignToTypeGuardedVariable1] +from typing_extensions import TypeGuard + +class A: pass +class B(A): pass + +def guard(a: A) -> TypeGuard[B]: + pass + +a = A() +if not guard(a): + a = A() +[builtins fixtures/tuple.pyi] + +[case testAssignToTypeGuardedVariable2] +from typing_extensions import TypeGuard + +class A: pass +class B: pass + +def guard(a: A) -> TypeGuard[B]: + pass + +a = A() +if not guard(a): + a = A() +[builtins fixtures/tuple.pyi] + +[case testAssignToTypeGuardedVariable3] +from typing_extensions import TypeGuard + +class A: pass +class B: pass + +def guard(a: A) -> TypeGuard[B]: + pass + +a = A() +if guard(a): + reveal_type(a) # N: Revealed type is "__main__.B" + a = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(a) # N: Revealed type is "__main__.B" + a = A() + reveal_type(a) # N: Revealed type is "__main__.A" +reveal_type(a) # N: Revealed type is "__main__.A" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardNestedRestrictionAny] +from typing_extensions import TypeGuard +from typing import Any + +class A: ... +def f(x: object) -> TypeGuard[A]: ... +def g(x: object) -> None: ... + +def test(x: Any) -> None: + if not(f(x) or x): + return + g(reveal_type(x)) # N: Revealed type is "Union[__main__.A, Any]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardNestedRestrictionUnionOther] +from typing_extensions import TypeGuard +from typing import Any + +class A: ... +class B: ... +def f(x: object) -> TypeGuard[A]: ... +def f2(x: object) -> TypeGuard[B]: ... +def g(x: object) -> None: ... + +def test(x: object) -> None: + if not(f(x) or f2(x)): + return + g(reveal_type(x)) # N: Revealed type is "Union[__main__.A, __main__.B]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardComprehensionSubtype] +from typing import List +from typing_extensions import TypeGuard + +class Base: ... +class Foo(Base): ... +class Bar(Base): ... + +def is_foo(item: object) -> TypeGuard[Foo]: + return isinstance(item, Foo) + +def is_bar(item: object) -> TypeGuard[Bar]: + return isinstance(item, Bar) + +def foobar(items: List[object]): + a: List[Base] = [x for x in items if is_foo(x) or is_bar(x)] + b: List[Base] = [x for x in items if is_foo(x)] + c: List[Bar] = [x for x in items if is_foo(x)] # E: List comprehension has incompatible type List[Foo]; expected List[Bar] +[builtins fixtures/tuple.pyi] + +[case testTypeGuardNestedRestrictionUnionIsInstance-xfail] +from typing_extensions import TypeGuard +from typing import Any, List + +class A: ... +def f(x: List[object]) -> TypeGuard[List[str]]: ... +def g(x: object) -> None: ... + +def test(x: List[object]) -> None: + if not(f(x) or isinstance(x, A)): + return + g(reveal_type(x)) # N: Revealed type is "Union[builtins.list[builtins.str], __main__.]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardMultipleCondition-xfail] +from typing_extensions import TypeGuard +from typing import Any, List + +class Foo: ... +class Bar: ... + +def is_foo(item: object) -> TypeGuard[Foo]: + return isinstance(item, Foo) + +def is_bar(item: object) -> TypeGuard[Bar]: + return isinstance(item, Bar) + +def foobar(x: object): + if not isinstance(x, Foo) or not isinstance(x, Bar): + return + reveal_type(x) # N: Revealed type is "__main__." + +def foobar_typeguard(x: object): + if not is_foo(x) or not is_bar(x): + return + reveal_type(x) # N: Revealed type is "__main__." +[builtins fixtures/tuple.pyi] + +[case testTypeGuardAsFunctionArgAsBoolSubtype] +from typing import Callable +from typing_extensions import TypeGuard + +def accepts_bool(f: Callable[[object], bool]): pass + +def with_bool_typeguard(o: object) -> TypeGuard[bool]: pass +def with_str_typeguard(o: object) -> TypeGuard[str]: pass +def with_bool(o: object) -> bool: pass + +accepts_bool(with_bool_typeguard) +accepts_bool(with_str_typeguard) +accepts_bool(with_bool) +[builtins fixtures/tuple.pyi] + +[case testTypeGuardAsFunctionArg] +from typing import Callable +from typing_extensions import TypeGuard + +def accepts_typeguard(f: Callable[[object], TypeGuard[bool]]): pass +def different_typeguard(f: Callable[[object], TypeGuard[str]]): pass + +def with_typeguard(o: object) -> TypeGuard[bool]: pass +def with_bool(o: object) -> bool: pass + +accepts_typeguard(with_typeguard) +accepts_typeguard(with_bool) # E: Argument 1 to "accepts_typeguard" has incompatible type "Callable[[object], bool]"; expected "Callable[[object], TypeGuard[bool]]" + +different_typeguard(with_typeguard) # E: Argument 1 to "different_typeguard" has incompatible type "Callable[[object], TypeGuard[bool]]"; expected "Callable[[object], TypeGuard[str]]" +different_typeguard(with_bool) # E: Argument 1 to "different_typeguard" has incompatible type "Callable[[object], bool]"; expected "Callable[[object], TypeGuard[str]]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardAsGenericFunctionArg] +from typing import Callable, TypeVar +from typing_extensions import TypeGuard + +T = TypeVar('T') + +def accepts_typeguard(f: Callable[[object], TypeGuard[T]]): pass + +def with_bool_typeguard(o: object) -> TypeGuard[bool]: pass +def with_str_typeguard(o: object) -> TypeGuard[str]: pass +def with_bool(o: object) -> bool: pass + +accepts_typeguard(with_bool_typeguard) +accepts_typeguard(with_str_typeguard) +accepts_typeguard(with_bool) # E: Argument 1 to "accepts_typeguard" has incompatible type "Callable[[object], bool]"; expected "Callable[[object], TypeGuard[bool]]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardAsOverloadedFunctionArg] +# https://github.com/python/mypy/issues/11307 +from typing import Callable, TypeVar, Generic, Any, overload +from typing_extensions import TypeGuard + +_T = TypeVar('_T') + +class filter(Generic[_T]): + @overload + def __init__(self, function: Callable[[object], TypeGuard[_T]]) -> None: pass + @overload + def __init__(self, function: Callable[[_T], Any]) -> None: pass + def __init__(self, function): pass + +def is_int_typeguard(a: object) -> TypeGuard[int]: pass +def returns_bool(a: object) -> bool: pass + +reveal_type(filter(is_int_typeguard)) # N: Revealed type is "__main__.filter[builtins.int*]" +reveal_type(filter(returns_bool)) # N: Revealed type is "__main__.filter[builtins.object*]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardSubtypingVariance] +from typing import Callable +from typing_extensions import TypeGuard + +class A: pass +class B(A): pass +class C(B): pass + +def accepts_typeguard(f: Callable[[object], TypeGuard[B]]): pass + +def with_typeguard_a(o: object) -> TypeGuard[A]: pass +def with_typeguard_b(o: object) -> TypeGuard[B]: pass +def with_typeguard_c(o: object) -> TypeGuard[C]: pass + +accepts_typeguard(with_typeguard_a) # E: Argument 1 to "accepts_typeguard" has incompatible type "Callable[[object], TypeGuard[A]]"; expected "Callable[[object], TypeGuard[B]]" +accepts_typeguard(with_typeguard_b) +accepts_typeguard(with_typeguard_c) +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-typevar-values.test b/test-data/unit/check-typevar-values.test index 3f77996ec959..2c25e9adc8bb 100644 --- a/test-data/unit/check-typevar-values.test +++ b/test-data/unit/check-typevar-values.test @@ -631,3 +631,74 @@ def g(s: S) -> Callable[[S], None]: ... def f(x: S) -> None: h = g(x) h(x) + +[case testTypeVarWithTypedDictBoundInIndexExpression] +from typing import TypeVar +from typing_extensions import TypedDict + +class Data(TypedDict): + x: int + + +T = TypeVar("T", bound=Data) + + +def f(data: T) -> None: + reveal_type(data["x"]) # N: Revealed type is "builtins.int" +[builtins fixtures/tuple.pyi] + +[case testTypeVarWithUnionTypedDictBoundInIndexExpression] +from typing import TypeVar, Union, Dict +from typing_extensions import TypedDict + +class Data(TypedDict): + x: int + + +T = TypeVar("T", bound=Union[Data, Dict[str, str]]) + + +def f(data: T) -> None: + reveal_type(data["x"]) # N: Revealed type is "Union[builtins.int, builtins.str*]" + +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] + +[case testTypeVarWithTypedDictValueInIndexExpression] +from typing import TypeVar, Union, Dict +from typing_extensions import TypedDict + +class Data(TypedDict): + x: int + + +T = TypeVar("T", Data, Dict[str, str]) + + +def f(data: T) -> None: + _: Union[str, int] = data["x"] +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] + +[case testSelfTypeVarIndexExpr] +from typing import TypeVar, Union, Type +from typing_extensions import TypedDict + +T = TypeVar("T", bound="Indexable") + +class Indexable: + def __init__(self, index: str) -> None: + self.index = index + + def __getitem__(self: T, index: str) -> T: + return self._new_instance(index) + + @classmethod + def _new_instance(cls: Type[T], index: str) -> T: + return cls("foo") + + def m(self: T) -> T: + return self["foo"] + +[builtins fixtures/tuple.pyi] +[builtins fixtures/classmethod.pyi] diff --git a/test-data/unit/check-union-or-syntax.test b/test-data/unit/check-union-or-syntax.test index 11dff9523162..3e5a19b8fe61 100644 --- a/test-data/unit/check-union-or-syntax.test +++ b/test-data/unit/check-union-or-syntax.test @@ -11,7 +11,6 @@ def f(x: int | str) -> int | str: reveal_type(f) # N: Revealed type is "def (x: Union[builtins.int, builtins.str]) -> Union[builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] - [case testUnionOrSyntaxWithThreeBuiltinsTypes] # flags: --python-version 3.10 def f(x: int | str | float) -> int | str | float: @@ -21,7 +20,6 @@ def f(x: int | str | float) -> int | str | float: return x reveal_type(f) # N: Revealed type is "def (x: Union[builtins.int, builtins.str, builtins.float]) -> Union[builtins.int, builtins.str, builtins.float]" - [case testUnionOrSyntaxWithTwoTypes] # flags: --python-version 3.10 class A: pass @@ -33,7 +31,6 @@ def f(x: A | B) -> A | B: return x reveal_type(f) # N: Revealed type is "def (x: Union[__main__.A, __main__.B]) -> Union[__main__.A, __main__.B]" - [case testUnionOrSyntaxWithThreeTypes] # flags: --python-version 3.10 class A: pass @@ -46,26 +43,22 @@ def f(x: A | B | C) -> A | B | C: return x reveal_type(f) # N: Revealed type is "def (x: Union[__main__.A, __main__.B, __main__.C]) -> Union[__main__.A, __main__.B, __main__.C]" - [case testUnionOrSyntaxWithLiteral] # flags: --python-version 3.10 from typing_extensions import Literal reveal_type(Literal[4] | str) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] - [case testUnionOrSyntaxWithBadOperator] # flags: --python-version 3.10 x: 1 + 2 # E: Invalid type comment or annotation - [case testUnionOrSyntaxWithBadOperands] # flags: --python-version 3.10 x: int | 42 # E: Invalid type: try using Literal[42] instead? y: 42 | int # E: Invalid type: try using Literal[42] instead? z: str | 42 | int # E: Invalid type: try using Literal[42] instead? - [case testUnionOrSyntaxWithGenerics] # flags: --python-version 3.10 from typing import List @@ -73,7 +66,6 @@ x: List[int | str] reveal_type(x) # N: Revealed type is "builtins.list[Union[builtins.int, builtins.str]]" [builtins fixtures/list.pyi] - [case testUnionOrSyntaxWithQuotedFunctionTypes] # flags: --python-version 3.4 from typing import Union @@ -87,47 +79,120 @@ def g(x: "int | str | None") -> "int | None": return 42 reveal_type(g) # N: Revealed type is "def (x: Union[builtins.int, builtins.str, None]) -> Union[builtins.int, None]" - [case testUnionOrSyntaxWithQuotedVariableTypes] # flags: --python-version 3.6 y: "int | str" = 42 reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]" - [case testUnionOrSyntaxWithTypeAliasWorking] # flags: --python-version 3.10 -from typing import Union -T = Union[int, str] +T = int | str x: T reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" +S = list[int] | str | None +y: S +reveal_type(y) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.str, None]" +U = str | None +z: U +reveal_type(z) # N: Revealed type is "Union[builtins.str, None]" + +def f(): pass +X = int | str | f() +b: X # E: Variable "__main__.X" is not valid as a type \ + # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +[builtins fixtures/type.pyi] -[case testUnionOrSyntaxWithTypeAliasNotAllowed] +[case testUnionOrSyntaxWithinRuntimeContextNotAllowed] # flags: --python-version 3.9 from __future__ import annotations -T = int | str # E: Unsupported left operand type for | ("Type[int]") +from typing import List +T = int | str # E: Invalid type alias: expression is not a valid type \ + # E: Unsupported left operand type for | ("Type[int]") +class C(List[int | str]): # E: Type expected within [...] \ + # E: Invalid base class "List" + pass +C() [builtins fixtures/tuple.pyi] +[case testUnionOrSyntaxWithinRuntimeContextNotAllowed2] +# flags: --python-version 3.9 +from __future__ import annotations +from typing import cast +cast(str | int, 'x') # E: Cast target is not a type +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-full.pyi] [case testUnionOrSyntaxInComment] # flags: --python-version 3.6 x = 1 # type: int | str - [case testUnionOrSyntaxFutureImport] # flags: --python-version 3.7 from __future__ import annotations x: int | None [builtins fixtures/tuple.pyi] - [case testUnionOrSyntaxMissingFutureImport] # flags: --python-version 3.9 x: int | None # E: X | Y syntax for unions requires Python 3.10 - [case testUnionOrSyntaxInStubFile] # flags: --python-version 3.6 from lib import x [file lib.pyi] x: int | None + +[case testUnionOrSyntaxInMiscRuntimeContexts] +# flags: --python-version 3.10 +from typing import cast + +class C(list[int | None]): + pass + +def f() -> object: pass + +reveal_type(cast(str | None, f())) # N: Revealed type is "Union[builtins.str, None]" +reveal_type(list[str | None]()) # N: Revealed type is "builtins.list[Union[builtins.str, None]]" +[builtins fixtures/type.pyi] + +[case testUnionOrSyntaxRuntimeContextInStubFile] +import lib +reveal_type(lib.x) # N: Revealed type is "Union[builtins.int, builtins.list[builtins.str], None]" +reveal_type(lib.y) # N: Revealed type is "builtins.list[Union[builtins.int, None]]" + +[file lib.pyi] +A = int | list[str] | None +x: A +B = list[int | None] +y: B +class C(list[int | None]): + pass +[builtins fixtures/list.pyi] + +[case testUnionOrSyntaxInIsinstance] +# flags: --python-version 3.10 +class C: pass + +def f(x: int | str | C) -> None: + if isinstance(x, int | str): + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" + else: + reveal_type(x) # N: Revealed type is "__main__.C" + +def g(x: int | str | tuple[int, str] | C) -> None: + if isinstance(x, int | str | tuple): + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str, Tuple[builtins.int, builtins.str]]" + else: + reveal_type(x) # N: Revealed type is "__main__.C" +[builtins fixtures/isinstance_python3_10.pyi] + +[case testUnionOrSyntaxInIsinstanceNotSupported] +# flags: --python-version 3.9 +from typing import Union +def f(x: Union[int, str, None]) -> None: + if isinstance(x, int | str): # E: Unsupported left operand type for | ("Type[int]") + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" + else: + reveal_type(x) # N: Revealed type is "None" +[builtins fixtures/isinstance.pyi] diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index e8921f30cdcf..cf1ff5650d49 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -241,7 +241,7 @@ def f(x: M[C]) -> None: y = x.get(None) reveal_type(y) # N: Revealed type is "__main__.C" -[case testUnionSimplificationSpecialCases] +[case testUnionSimplificationSpecialCases2] from typing import Any, TypeVar, Union class C(Any): pass @@ -556,7 +556,7 @@ reveal_type(d1) # N: Revealed type is "Union[Any, builtins.float]" reveal_type(d2) # N: Revealed type is "Union[Any, builtins.float]" e: Union[Any, Tuple[float, float], int] -(e1, e2) = e # E: "builtins.int" object is not iterable +(e1, e2) = e # E: "int" object is not iterable [builtins fixtures/tuple.pyi] [case testUnionMultiassignNotJoin] @@ -694,7 +694,7 @@ reveal_type(d) # N: Revealed type is "builtins.list[builtins.int*]" from typing import Union bad: Union[int, str] -x, y = bad # E: "builtins.int" object is not iterable \ +x, y = bad # E: "int" object is not iterable \ # E: Unpacking a string is disallowed reveal_type(x) # N: Revealed type is "Any" reveal_type(y) # N: Revealed type is "Any" @@ -1059,3 +1059,100 @@ x: Union[None, Any] y: Union[int, None] reveal_type(f(x, y)) # N: Revealed type is "Union[None, Any, builtins.int]" reveal_type(f(y, x)) # N: Revealed type is "Union[builtins.int, None, Any]" + +[case testNestedProtocolUnions] +from typing import Union, Iterator, Iterable +def foo( + values: Union[ + Iterator[Union[ + Iterator[Union[Iterator[int], Iterable[int]]], + Iterable[Union[Iterator[int], Iterable[int]]], + ]], + Iterable[Union[ + Iterator[Union[Iterator[int], Iterable[int]]], + Iterable[Union[Iterator[int], Iterable[int]]], + ]], + ] +) -> Iterator[int]: + for i in values: + for j in i: + for k in j: + yield k +foo([[[1]]]) +[builtins fixtures/list.pyi] + +[case testNestedProtocolGenericUnions] +from typing import Union, Iterator, List +def foo( + values: Union[ + Iterator[Union[ + Iterator[Union[Iterator[int], List[int]]], + List[Union[Iterator[int], List[int]]], + ]], + List[Union[ + Iterator[Union[Iterator[int], List[int]]], + List[Union[Iterator[int], List[int]]], + ]], + ] +) -> Iterator[int]: + for i in values: + for j in i: + for k in j: + yield k +foo([[[1]]]) +[builtins fixtures/list.pyi] + +[case testNestedProtocolGenericUnionsDeep] +from typing import TypeVar, Union, Iterator, List +T = TypeVar("T") +Iter = Union[Iterator[T], List[T]] +def foo( + values: Iter[Iter[Iter[Iter[Iter[int]]]]], +) -> Iterator[int]: + for i in values: + for j in i: + for k in j: + for l in k: + for m in l: + yield m +foo([[[[[1]]]]]) +[builtins fixtures/list.pyi] + +[case testNestedInstanceUnsimplifiedUnion] +from typing import TypeVar, Union, Iterator, List, Any +T = TypeVar("T") + +Iter = Union[Iterator[T], List[T]] +def foo( + values: Iter[Union[Any, Any]], +) -> Iterator[Any]: + for i in values: + yield i +foo([1]) +[builtins fixtures/list.pyi] + +[case testNestedInstanceTypeAlias] +from typing import TypeVar, Union, Iterator, List, Any +T = TypeVar("T") + +Iter = Union[Iterator[T], List[T]] +def foo( + values: Iter["Any"], +) -> Iterator[Any]: + for i in values: + yield i +foo([1]) +[builtins fixtures/list.pyi] + +[case testNestedInstanceTypeAliasUnsimplifiedUnion] +from typing import TypeVar, Union, Iterator, List, Any +T = TypeVar("T") + +Iter = Union[Iterator[T], List[T]] +def foo( + values: Iter["Union[Any, Any]"], +) -> Iterator[Any]: + for i in values: + yield i +foo([1]) +[builtins fixtures/list.pyi] diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index e4235e82fc98..de85f5188bb8 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -533,11 +533,11 @@ f = (PY3 or PY2) and 's' g = (PY2 or PY3) or 's' h = (PY3 or PY2) or 's' reveal_type(a) # N: Revealed type is "builtins.bool" -reveal_type(b) # N: Revealed type is "builtins.str" -reveal_type(c) # N: Revealed type is "builtins.str" +reveal_type(b) # N: Revealed type is "Literal['s']" +reveal_type(c) # N: Revealed type is "Literal['s']" reveal_type(d) # N: Revealed type is "builtins.bool" -reveal_type(e) # N: Revealed type is "builtins.str" -reveal_type(f) # N: Revealed type is "builtins.str" +reveal_type(e) # N: Revealed type is "Literal['s']" +reveal_type(f) # N: Revealed type is "Literal['s']" reveal_type(g) # N: Revealed type is "builtins.bool" reveal_type(h) # N: Revealed type is "builtins.bool" [builtins fixtures/ops.pyi] @@ -615,6 +615,30 @@ if MYPY or mypy_only: pass [builtins fixtures/ops.pyi] +[case testSemanticAnalysisFalseButTypeNarrowingTrue] +# flags: --always-false COMPILE_TIME_FALSE +from typing import Literal + +indeterminate: str +COMPILE_TIME_FALSE: Literal[True] # type-narrowing: mapped in 'if' only +a = COMPILE_TIME_FALSE or indeterminate +reveal_type(a) # N: Revealed type is "builtins.str" +b = indeterminate or COMPILE_TIME_FALSE +reveal_type(b) # N: Revealed type is "Union[builtins.str, Literal[True]]" +[typing fixtures/typing-medium.pyi] + +[case testSemanticAnalysisTrueButTypeNarrowingFalse] +# flags: --always-true COMPILE_TIME_TRUE +from typing import Literal + +indeterminate: str +COMPILE_TIME_TRUE: Literal[False] # type narrowed to `else` only +a = COMPILE_TIME_TRUE or indeterminate +reveal_type(a) # N: Revealed type is "Literal[False]" +b = indeterminate or COMPILE_TIME_TRUE +reveal_type(b) # N: Revealed type is "Union[builtins.str, Literal[False]]" + +[typing fixtures/typing-medium.pyi] [case testConditionalAssertWithoutElse] import typing @@ -730,35 +754,46 @@ if sys.version_info[0] >= 2: reveal_type('') # N: Revealed type is "Literal['']?" [builtins fixtures/ops.pyi] -[case testUnreachableFlagWithBadControlFlow] +[case testUnreachableFlagWithBadControlFlow1] # flags: --warn-unreachable a: int if isinstance(a, int): reveal_type(a) # N: Revealed type is "builtins.int" else: reveal_type(a) # E: Statement is unreachable +[builtins fixtures/isinstancelist.pyi] +[case testUnreachableFlagWithBadControlFlow2] +# flags: --warn-unreachable b: int while isinstance(b, int): reveal_type(b) # N: Revealed type is "builtins.int" else: reveal_type(b) # E: Statement is unreachable +[builtins fixtures/isinstancelist.pyi] +[case testUnreachableFlagWithBadControlFlow3] +# flags: --warn-unreachable def foo(c: int) -> None: reveal_type(c) # N: Revealed type is "builtins.int" assert not isinstance(c, int) reveal_type(c) # E: Statement is unreachable +[builtins fixtures/isinstancelist.pyi] +[case testUnreachableFlagWithBadControlFlow4] +# flags: --warn-unreachable d: int if False: reveal_type(d) # E: Statement is unreachable +[builtins fixtures/isinstancelist.pyi] +[case testUnreachableFlagWithBadControlFlow5] +# flags: --warn-unreachable e: int if True: reveal_type(e) # N: Revealed type is "builtins.int" else: reveal_type(e) # E: Statement is unreachable - [builtins fixtures/isinstancelist.pyi] [case testUnreachableFlagStatementAfterReturn] @@ -908,6 +943,7 @@ def foo() -> bool: ... lst = [1, 2, 3, 4] a = True or foo() # E: Right operand of "or" is never evaluated +b = 42 or False # E: Right operand of "or" is never evaluated d = False and foo() # E: Right operand of "and" is never evaluated e = True or (True or (True or foo())) # E: Right operand of "or" is never evaluated f = (True or foo()) or (True or foo()) # E: Right operand of "or" is never evaluated @@ -1305,3 +1341,90 @@ async def f_malformed_2() -> int: [typing fixtures/typing-full.pyi] [builtins fixtures/tuple.pyi] + +[case testUnreachableUntypedFunction] +# flags: --warn-unreachable + +def test_untyped_fn(obj): + assert obj.prop is True + + obj.update(prop=False) + obj.reload() + + assert obj.prop is False + reveal_type(obj.prop) + +def test_typed_fn(obj) -> None: + assert obj.prop is True + + obj.update(prop=False) + obj.reload() + + assert obj.prop is False + reveal_type(obj.prop) # E: Statement is unreachable + +[case testUnreachableCheckedUntypedFunction] +# flags: --warn-unreachable --check-untyped-defs + +def test_untyped_fn(obj): + assert obj.prop is True + + obj.update(prop=False) + obj.reload() + + assert obj.prop is False + reveal_type(obj.prop) # E: Statement is unreachable + +[case testConditionalTypeVarException] +# every part of this test case was necessary to trigger the crash +import sys +from typing import TypeVar + +T = TypeVar("T", int, str) + +def f(t: T) -> None: + if sys.platform == "lol": + try: + pass + except BaseException as e: + pass +[builtins fixtures/dict.pyi] + + +[case testUnreachableLiteral] +# flags: --warn-unreachable +from typing_extensions import Literal + +def nope() -> Literal[False]: ... + +def f() -> None: + if nope(): + x = 1 # E: Statement is unreachable +[builtins fixtures/dict.pyi] + +[case testUnreachableModuleBody1] +# flags: --warn-unreachable +from typing import NoReturn +def foo() -> NoReturn: + raise Exception("foo") +foo() +x = 1 # E: Statement is unreachable +[builtins fixtures/exception.pyi] + +[case testUnreachableModuleBody2] +# flags: --warn-unreachable +raise Exception +x = 1 # E: Statement is unreachable +[builtins fixtures/exception.pyi] + +[case testUnreachableNoReturnBinaryOps] +# flags: --warn-unreachable +from typing import NoReturn + +a: NoReturn +a and 1 # E: Right operand of "and" is never evaluated +a or 1 # E: Right operand of "or" is never evaluated +a or a # E: Right operand of "or" is never evaluated +1 and a and 1 # E: Right operand of "and" is never evaluated +a and a # E: Right operand of "and" is never evaluated +[builtins fixtures/exception.pyi] diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index d648381f2fc3..57a578401c51 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -414,23 +414,23 @@ main:4: error: Argument 2 to "f" has incompatible type "*List[A]"; expected "B" main:5: error: Argument 3 to "f" has incompatible type "*List[A]"; expected "B" main:6: error: Argument 1 to "f" has incompatible type "*Tuple[A, A, B]"; expected "Optional[B]" -[case testVarArgsAfterKeywordArgInCall1-skip] +[case testVarArgsAfterKeywordArgInCall1] # see: mypy issue #2729 def f(x: int, y: str) -> None: pass f(x=1, *[2]) [builtins fixtures/list.pyi] [out] -main:2: error: "f" gets multiple values for keyword argument "x" -main:2: error: Argument 2 to "f" has incompatible type *List[int]; expected "str" +main:3: error: "f" gets multiple values for keyword argument "x" +main:3: error: Argument 1 to "f" has incompatible type "*List[int]"; expected "str" -[case testVarArgsAfterKeywordArgInCall2-skip] +[case testVarArgsAfterKeywordArgInCall2] # see: mypy issue #2729 def f(x: int, y: str) -> None: pass f(y='x', *[1]) [builtins fixtures/list.pyi] [out] -main:2: error: "f" gets multiple values for keyword argument "y" -main:2: error: Argument 2 to "f" has incompatible type *List[int]; expected "str" +main:3: error: "f" gets multiple values for keyword argument "y" +main:3: error: Argument 1 to "f" has incompatible type "*List[int]"; expected "str" [case testVarArgsAfterKeywordArgInCall3] def f(x: int, y: str) -> None: pass @@ -734,3 +734,29 @@ b = {'b': 1} f(a) # E: Argument 1 to "f" has incompatible type "List[int]"; expected "Listener" g(b) # E: Argument 1 to "g" has incompatible type "Dict[str, int]"; expected "DictReader" [builtins fixtures/dict.pyi] + +[case testInvariantTypeConfusingNames2] +from typing import Iterable, Generic, TypeVar, List + +T = TypeVar('T') + +class I(Iterable[T]): + ... + +class Bad(Generic[T]): + ... + +def bar(*args: float) -> float: + ... + +good1: Iterable[float] +good2: List[float] +good3: I[float] +bad1: I[str] +bad2: Bad[float] +bar(*good1) +bar(*good2) +bar(*good3) +bar(*bad1) # E: Argument 1 to "bar" has incompatible type "*I[str]"; expected "float" +bar(*bad2) # E: List or tuple expected as variable arguments +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-warnings.test b/test-data/unit/check-warnings.test index 165812531e60..10c7968be475 100644 --- a/test-data/unit/check-warnings.test +++ b/test-data/unit/check-warnings.test @@ -51,7 +51,7 @@ a = 1 if int(): a = 'a' # type: ignore if int(): - a = 2 # type: ignore # E: unused "type: ignore" comment + a = 2 # type: ignore # E: Unused "type: ignore" comment if int(): a = 'b' # E: Incompatible types in assignment (expression has type "str", variable has type "int") @@ -63,8 +63,8 @@ from m import * # type: ignore [file m.py] pass [out] -main:3: error: unused "type: ignore" comment -main:4: error: unused "type: ignore" comment +main:3: error: Unused "type: ignore" comment +main:4: error: Unused "type: ignore" comment -- No return diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 2b5db57807b5..6fa4d210a826 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -79,7 +79,7 @@ dir/subdir/b.py:1: error: Name "undef" is not defined [file pkg/__init__.py] [file pkg/a.py] undef -import a +import pkg.a [file pkg/subdir/a.py] undef import pkg.a @@ -306,13 +306,13 @@ mypy.ini: [mypy-*]: Per-module sections should only specify per-module flags (py [file mypy.ini] \[mypy] mypy_path = - foo:bar - , baz -[file foo/foo.pyi] + foo_dir:bar_dir + , baz_dir +[file foo_dir/foo.pyi] def foo(x: int) -> str: ... -[file bar/bar.pyi] +[file bar_dir/bar.pyi] def bar(x: str) -> list: ... -[file baz/baz.pyi] +[file baz_dir/baz.pyi] def baz(x: list) -> dict: ... [file file.py] import no_stubs @@ -642,10 +642,6 @@ reveal_type(a**(-2)) # N: Revealed type is "builtins.float" reveal_type(a**b) # N: Revealed type is "Any" reveal_type(a.__pow__(2)) # N: Revealed type is "builtins.int" reveal_type(a.__pow__(a)) # N: Revealed type is "Any" -a.__pow__() # E: All overload variants of "__pow__" of "int" require at least one argument \ - # N: Possible overload variants: \ - # N: def __pow__(self, Literal[2], Optional[int] = ...) -> int \ - # N: def __pow__(self, int, Optional[int] = ...) -> Any [case testDisallowAnyGenericsBuiltinCollections] # cmd: mypy m.py @@ -791,7 +787,7 @@ c.py:2: error: Argument 1 to "bar" has incompatible type "str"; expected "int" [case testSrcPEP420Packages] # cmd: mypy -p anamespace --namespace-packages [file mypy.ini] -\[mypy]] +\[mypy] mypy_path = src [file src/setup.cfg] [file src/anamespace/foo/__init__.py] @@ -946,7 +942,13 @@ emarg/foo.py:1: error: Name "fail" is not defined emarg/hatch/villip/mankangulisk.py:1: error: Name "fail" is not defined [case testPackageRootEmpty] -# cmd: mypy --package-root= a/b/c.py main.py +# cmd: mypy --no-namespace-packages --package-root= a/b/c.py main.py +[file a/b/c.py] +[file main.py] +import a.b.c + +[case testPackageRootEmptyNamespacePackage] +# cmd: mypy --namespace-packages --package-root= a/b/c.py main.py [file a/b/c.py] [file main.py] import a.b.c @@ -1141,6 +1143,7 @@ import foo.bar 1+'x' [out] src/foo/bar.py: error: Source file found twice under different module names: "src.foo.bar" and "foo.bar" +src/foo/bar.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info == Return code: 2 [case testEnableInvalidErrorCode] @@ -1276,3 +1279,89 @@ x = 0 # type: str y = 0 # type: str [out] pkg.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") + +[case testCmdlineNonInteractiveWithoutInstallTypes] +# cmd: mypy --non-interactive -m pkg +[out] +error: --non-interactive is only supported with --install-types +== Return code: 2 + +[case testCmdlineNonInteractiveInstallTypesNothingToDo] +# cmd: mypy --install-types --non-interactive -m pkg +[file pkg.py] +1() +[out] +pkg.py:1: error: "int" not callable + +[case testCmdlineNonInteractiveInstallTypesNothingToDoNoError] +# cmd: mypy --install-types --non-interactive -m pkg +[file pkg.py] +1 + 2 +[out] + +[case testCmdlineNonInteractiveInstallTypesNoSitePackages] +# cmd: mypy --install-types --non-interactive --no-site-packages -m pkg +[out] +error: --install-types not supported without python executable or site packages +== Return code: 2 + +[case testCmdlineInteractiveInstallTypesNothingToDo] +# cmd: mypy --install-types -m pkg +[file pkg.py] +1() +[out] +pkg.py:1: error: "int" not callable + +[case testCmdlineExclude] +# cmd: mypy --exclude abc . +[file abc/apkg.py] +1() +[file b/bpkg.py] +1() +[file c/cpkg.py] +1() +[out] +c/cpkg.py:1: error: "int" not callable +b/bpkg.py:1: error: "int" not callable + +[case testCmdlineMultipleExclude] +# cmd: mypy --exclude abc --exclude b/ . +[file abc/apkg.py] +1() +[file b/bpkg.py] +1() +[file c/cpkg.py] +1() +[out] +c/cpkg.py:1: error: "int" not callable + +[case testCmdlineCfgExclude] +# cmd: mypy . +[file mypy.ini] +\[mypy] +exclude = abc +[file abc/apkg.py] +1() +[file b/bpkg.py] +1() +[file c/cpkg.py] +1() +[out] +c/cpkg.py:1: error: "int" not callable +b/bpkg.py:1: error: "int" not callable + +[case testCmdlineCfgMultipleExclude] +# cmd: mypy . +[file mypy.ini] +\[mypy] +exclude = + abc + b +[file abc/apkg.py] +1() +[file b/bpkg.py] +1() +[file c/cpkg.py] +1() +[out] +c/cpkg.py:1: error: "int" not callable diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 862ae57bc096..c73be05e1be3 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -274,7 +274,7 @@ bar.py:3: (str) bar.py:4: (arg=str) $ dmypy suggest foo.foo (str) -> int -$ {python} -c "import shutil; shutil.copy('foo.py.2', 'foo.py')" +$ {python} -c "import shutil; shutil.copy('foo2.py', 'foo.py')" $ dmypy check foo.py bar.py bar.py:3: error: Incompatible types in assignment (expression has type "int", variable has type "str") == Return code: 1 @@ -284,7 +284,7 @@ def foo(arg): class Bar: def bar(self): pass var = 0 -[file foo.py.2] +[file foo2.py] def foo(arg: str) -> int: return 12 class Bar: diff --git a/test-data/unit/deps-expressions.test b/test-data/unit/deps-expressions.test index dccae38de300..20d727433193 100644 --- a/test-data/unit/deps-expressions.test +++ b/test-data/unit/deps-expressions.test @@ -191,7 +191,7 @@ def g(a: A) -> int: -> m.g -> m.g -[case testIndexExpr] +[case testIndexExpr2] class A: def __getitem__(self, x: int) -> int: pass diff --git a/test-data/unit/deps.test b/test-data/unit/deps.test index 8c074abc83a2..d833a05e201a 100644 --- a/test-data/unit/deps.test +++ b/test-data/unit/deps.test @@ -1430,11 +1430,11 @@ class A: @dataclass class B(A): y: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] -> , m - -> + -> -> , m.B.__init__ -> -> diff --git a/test-data/unit/diff.test b/test-data/unit/diff.test index ee3519478c45..7369ea247e26 100644 --- a/test-data/unit/diff.test +++ b/test-data/unit/diff.test @@ -1470,3 +1470,17 @@ x: Union[Callable[[Arg(int, 'y')], None], [builtins fixtures/tuple.pyi] [out] __main__.x + +[case testChangeParamSpec] +from typing import ParamSpec, TypeVar +A = ParamSpec('A') +B = ParamSpec('B') +C = TypeVar('C') +[file next.py] +from typing import ParamSpec, TypeVar +A = ParamSpec('A') +B = TypeVar('B') +C = ParamSpec('C') +[out] +__main__.B +__main__.C diff --git a/test-data/unit/fine-grained-blockers.test b/test-data/unit/fine-grained-blockers.test index ed7ed5783c79..66a68115afa5 100644 --- a/test-data/unit/fine-grained-blockers.test +++ b/test-data/unit/fine-grained-blockers.test @@ -156,7 +156,7 @@ class C: a.py:1: error: invalid syntax == main:5: error: Missing positional argument "x" in call to "f" of "C" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -176,7 +176,7 @@ main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missin a.py:1: error: invalid syntax == main:2: error: Too many arguments for "f" -[out version>=3.10] +[out version==3.10.0] main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports == @@ -259,7 +259,7 @@ a.py:1: error: invalid syntax a.py:1: error: invalid syntax == a.py:2: error: Missing positional argument "x" in call to "f" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -330,7 +330,7 @@ a.py:1: error: invalid syntax main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports b.py:1: error: Cannot find implementation or library stub for module named "a" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -338,7 +338,7 @@ main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports b.py:1: error: Cannot find implementation or library stub for module named "a" -[case testDeleteFileWithBlockingError-only_when_cache] +[case testDeleteFileWithBlockingError2-only_when_cache] -- Different cache/no-cache tests because: -- Error message ordering differs import a @@ -358,7 +358,7 @@ a.py:1: error: invalid syntax b.py:1: error: Cannot find implementation or library stub for module named "a" b.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main:1: error: Cannot find implementation or library stub for module named "a" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -388,7 +388,7 @@ a.py:1: error: invalid syntax == b.py:2: error: Module has no attribute "f" b.py:3: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -411,7 +411,7 @@ def f() -> None: pass /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax == a.py:1: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax. Perhaps you forgot a comma? == @@ -490,7 +490,7 @@ a.py:1: error: invalid syntax /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax == a.py:2: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -515,13 +515,13 @@ a.py:1: error: invalid syntax == b.py:2: error: Incompatible return value type (got "str", expected "int") == -[out version>=3.10] +[out version==3.10.0] a.py:1: error: invalid syntax. Perhaps you forgot a comma? == b.py:2: error: Incompatible return value type (got "str", expected "int") == -[case testDecodeErrorBlocker-posix] +[case testDecodeErrorBlocker1-posix] import a a.f(1) [file a.py] @@ -537,7 +537,7 @@ mypy: can't decode file 'tmp/a.py': 'ascii' codec can't decode byte 0xc3 in posi == main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" -[case testDecodeErrorBlocker-windows] +[case testDecodeErrorBlocker2-windows] import a a.f(1) [file a.py] diff --git a/test-data/unit/fine-grained-follow-imports.test b/test-data/unit/fine-grained-follow-imports.test index 1bb62adbe552..b4767ea1a94d 100644 --- a/test-data/unit/fine-grained-follow-imports.test +++ b/test-data/unit/fine-grained-follow-imports.test @@ -418,8 +418,7 @@ def f(x: str) -> None: pass [file p/m.py.3] def f(x: str) -> None: pass -[delete p/m.py.4] -[delete p/__init__.py.4] +[delete p.4] [out] == @@ -429,7 +428,7 @@ main.py:3: error: Missing positional argument "x" in call to "f" main.py:3: error: Missing positional argument "x" in call to "f" == -[case testFollowImportsNormalPackage-only_when_cache] +[case testFollowImportsNormalPackage2-only_when_cache] # flags: --follow-imports=normal # cmd: mypy main.py @@ -445,8 +444,7 @@ def f(x: str) -> None: pass 1() -[delete p/m.py.3] -[delete p/__init__.py.3] +[delete p.3] [out] == @@ -638,6 +636,7 @@ import p2.m2 p1/m1.py:1: error: "int" not callable main.py:2: error: Cannot find implementation or library stub for module named "p2.m2" main.py:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main.py:2: error: Cannot find implementation or library stub for module named "p2" == p2/m2.py:1: error: "str" not callable p1/m1.py:1: error: "int" not callable @@ -682,7 +681,7 @@ import bar src/bar.py:1: error: "int" not callable src/foo.py:2: error: "str" not callable -[case testFollowImportsNormalSearchPathUpdate-only_when_cache] +[case testFollowImportsNormalSearchPathUpdate2-only_when_cache] # flags: --follow-imports=normal # cmd: mypy main.py # cmd2: mypy main.py src/foo.py diff --git a/test-data/unit/fine-grained-modules.test b/test-data/unit/fine-grained-modules.test index a38820d9170a..856eaaad083c 100644 --- a/test-data/unit/fine-grained-modules.test +++ b/test-data/unit/fine-grained-modules.test @@ -410,7 +410,7 @@ main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missin -- TODO: Fix this bug. It is a real bug that was been papered over -- by the test harness. -[case testDeletionOfSubmoduleTriggersImportFrom1-only_when_cache-skip] +[case testDeletionOfSubmoduleTriggersImportFrom1_2-only_when_cache-skip] -- Different cache/no-cache tests because: -- missing module error message mismatch from p import q @@ -854,8 +854,7 @@ p.f(1) from p.a import f [file p/a.py] def f(x: str) -> None: pass -[delete p/__init__.py.2] -[delete p/a.py.2] +[delete p.2] [out] main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" == @@ -870,7 +869,7 @@ p.a.f(1) [file p/a.py] def f(x: str) -> None: pass [delete p/a.py.2] -[delete p/__init__.py.3] +[delete p.3] [builtins fixtures/module.pyi] [out] main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" @@ -884,28 +883,30 @@ main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missin main:2: error: Cannot find implementation or library stub for module named "p" [case testDeletePackage4] +# flags: --no-namespace-packages import p.a p.a.f(1) [file p/a.py] def f(x: str) -> None: pass [file p/__init__.py] [delete p/__init__.py.2] -[delete p/a.py.3] +[delete p.3] [out] -main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" +main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" == -main:1: error: Cannot find implementation or library stub for module named "p.a" -main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports -main:1: error: Cannot find implementation or library stub for module named "p" +main:2: error: Cannot find implementation or library stub for module named "p.a" +main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:2: error: Cannot find implementation or library stub for module named "p" == -main:1: error: Cannot find implementation or library stub for module named "p.a" -main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports -main:1: error: Cannot find implementation or library stub for module named "p" +main:2: error: Cannot find implementation or library stub for module named "p.a" +main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:2: error: Cannot find implementation or library stub for module named "p" [case testDeletePackage5] -# cmd1: mypy main p/a.py p/__init__.py -# cmd2: mypy main p/a.py -# cmd3: mypy main +# flags: --no-namespace-packages +# cmd1: mypy -m main -m p.a -m p.__init__ +# cmd2: mypy -m main -m p.a +# cmd3: mypy -m main import p.a p.a.f(1) @@ -913,23 +914,24 @@ p.a.f(1) def f(x: str) -> None: pass [file p/__init__.py] [delete p/__init__.py.2] -[delete p/a.py.3] +[delete p.3] [out] -main:6: error: Argument 1 to "f" has incompatible type "int"; expected "str" +main:7: error: Argument 1 to "f" has incompatible type "int"; expected "str" == -main:5: error: Cannot find implementation or library stub for module named "p.a" -main:5: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports -main:5: error: Cannot find implementation or library stub for module named "p" +main:6: error: Cannot find implementation or library stub for module named "p.a" +main:6: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:6: error: Cannot find implementation or library stub for module named "p" == -main:5: error: Cannot find implementation or library stub for module named "p.a" -main:5: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports -main:5: error: Cannot find implementation or library stub for module named "p" +main:6: error: Cannot find implementation or library stub for module named "p.a" +main:6: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +main:6: error: Cannot find implementation or library stub for module named "p" [case testDeletePackage6] -# cmd1: mypy p/a.py p/b.py p/__init__.py -# cmd2: mypy p/a.py p/b.py -# cmd3: mypy p/a.py p/b.py +# flags: --no-namespace-packages +# cmd1: mypy -m p.a -m p.b -m p.__init__ +# cmd2: mypy -m p.a -m p.b +# cmd3: mypy -m p.a -m p.b [file p/a.py] def f(x: str) -> None: pass [file p/b.py] @@ -1437,7 +1439,7 @@ x = 1 [file b/foo.py] [file b/__init__.py.2] # Dummy change -[builtins fixtures/bool.pyi] +[builtins fixtures/primitives.pyi] [out] == @@ -1750,7 +1752,7 @@ class Foo: == a.py:3: error: Argument 1 to "foo" of "Foo" has incompatible type "int"; expected "str" -[case testAddAndUseClass4] +[case testAddAndUseClass4_2] [file a.py] [file a.py.2] from p.b import * @@ -2193,13 +2195,13 @@ import waitress [file a.py.2] # nothing [file a.py.3] -import pynamodb +import requests [out] a.py:1: error: Library stubs not installed for "waitress" (or incompatible with Python 3.6) a.py:1: note: Hint: "python3 -m pip install types-waitress" a.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports == == -a.py:1: error: Library stubs not installed for "pynamodb" (or incompatible with Python 3.6) -a.py:1: note: Hint: "python3 -m pip install types-pynamodb" +a.py:1: error: Library stubs not installed for "requests" (or incompatible with Python 3.6) +a.py:1: note: Hint: "python3 -m pip install types-requests" a.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 2c5559a0688d..ad67ff19dfd2 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -361,7 +361,7 @@ n.py:2: error: "A" has no attribute "g" == n.py:2: error: "A" has no attribute "g" -[case testContinueToReportErrorAtTopLevel-only_when_cache] +[case testContinueToReportErrorAtTopLevel2-only_when_cache] -- Different cache/no-cache tests because: -- Error message ordering differs import n @@ -688,7 +688,7 @@ class A: == b.py:8: error: Argument 1 to "B" has incompatible type "int"; expected "str" == -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassUpdate2] # flags: --python-version 3.7 @@ -719,7 +719,7 @@ B(1, 2) [out] == b.py:8: error: Argument 1 to "B" has incompatible type "int"; expected "str" -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [case testDataclassUpdate3] # flags: --python-version 3.7 @@ -743,7 +743,7 @@ from dataclasses import dataclass class A: a: int other: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Missing positional argument "b" in call to "B" @@ -770,7 +770,7 @@ from dataclasses import dataclass class A: a: int other: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Missing positional argument "b" in call to "B" @@ -804,7 +804,7 @@ from dataclasses import dataclass class A: a: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Missing positional argument "b" in call to "B" @@ -831,7 +831,7 @@ from dataclasses import dataclass @dataclass class A: a: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Unsupported left operand type for < ("B") @@ -864,7 +864,7 @@ from dataclasses import dataclass class A: a: int other: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Missing positional argument "c" in call to "C" @@ -904,7 +904,7 @@ from dataclasses import dataclass class A: a: int -[builtins fixtures/list.pyi] +[builtins fixtures/dataclasses.pyi] [out] == main:3: error: Missing positional argument "c" in call to "C" @@ -4922,7 +4922,7 @@ class D(Generic[T]): pass [out] == -a.py:3: error: Type argument "c.A" of "D" must be a subtype of "c.B" +a.py:3: error: Type argument "A" of "D" must be a subtype of "B" [case testTypeVarValuesRuntime] from mod import I, S, D @@ -7128,15 +7128,60 @@ class C: == mod.py:9: error: Incompatible types in assignment (expression has type "int", variable has type "str") -[case testOverloadedMethodSupertype] +[case testOverloadedMethodSupertype-only_when_cache] +-- Different cache/no-cache tests because +-- CallableType.def_extras.first_arg differs ("self"/None) from typing import overload, Any import b class Child(b.Parent): + @overload # Fail + def f(self, arg: int) -> int: ... + @overload + def f(self, arg: str) -> str: ... + def f(self, arg: Any) -> Any: ... +[file b.py] +from typing import overload, Any +class C: pass +class Parent: @overload def f(self, arg: int) -> int: ... @overload def f(self, arg: str) -> str: ... def f(self, arg: Any) -> Any: ... +[file b.py.2] +from typing import overload, Any +class C: pass +class Parent: + @overload + def f(self, arg: int) -> int: ... + @overload + def f(self, arg: str) -> C: ... + def f(self, arg: Any) -> Any: ... +[out] +== +main:4: error: Signature of "f" incompatible with supertype "Parent" +main:4: note: Superclass: +main:4: note: @overload +main:4: note: def f(self, arg: int) -> int +main:4: note: @overload +main:4: note: def f(self, arg: str) -> C +main:4: note: Subclass: +main:4: note: @overload +main:4: note: def f(self, arg: int) -> int +main:4: note: @overload +main:4: note: def f(self, arg: str) -> str + +[case testOverloadedMethodSupertype2-only_when_nocache] +-- Different cache/no-cache tests because +-- CallableType.def_extras.first_arg differs ("self"/None) +from typing import overload, Any +import b +class Child(b.Parent): + @overload # Fail + def f(self, arg: int) -> int: ... + @overload + def f(self, arg: str) -> str: ... + def f(self, arg: Any) -> Any: ... [file b.py] from typing import overload, Any class C: pass @@ -7158,6 +7203,16 @@ class Parent: [out] == main:4: error: Signature of "f" incompatible with supertype "Parent" +main:4: note: Superclass: +main:4: note: @overload +main:4: note: def f(self, arg: int) -> int +main:4: note: @overload +main:4: note: def f(self, arg: str) -> C +main:4: note: Subclass: +main:4: note: @overload +main:4: note: def f(arg: int) -> int +main:4: note: @overload +main:4: note: def f(arg: str) -> str [case testOverloadedInitSupertype] import a @@ -7186,9 +7241,9 @@ class C: [out] == a.py:2: error: No overload variant of "B" matches argument type "int" -a.py:2: note: Possible overload variant: +a.py:2: note: Possible overload variants: a.py:2: note: def __init__(self, x: str) -> B -a.py:2: note: <1 more non-matching overload not shown> +a.py:2: note: def __init__(self, x: str, y: int) -> B [case testOverloadedToNormalMethodMetaclass] import a @@ -8309,7 +8364,56 @@ class D: == a.py:3: error: Cannot override final attribute "meth" (previously declared in base class "C") -[case testFinalBodyReprocessedAndStillFinalOverloaded] +[case testFinalBodyReprocessedAndStillFinalOverloaded-only_when_cache] +-- Different cache/no-cache tests because +-- CallableType.def_extras.first_arg differs ("self"/None) +import a +[file a.py] +from c import C +class A: + def meth(self) -> None: ... + +[file a.py.3] +from c import C +class A(C): + def meth(self) -> None: ... + +[file c.py] +from typing import final, overload, Union +from d import D + +class C: + @overload + def meth(self, x: int) -> int: ... + @overload + def meth(self, x: str) -> str: ... + @final + def meth(self, x: Union[int, str]) -> Union[int, str]: + D(int()) + return x +[file d.py] +class D: + def __init__(self, x: int) -> None: ... +[file d.py.2] +from typing import Optional +class D: + def __init__(self, x: Optional[int]) -> None: ... +[out] +== +== +a.py:3: error: Cannot override final attribute "meth" (previously declared in base class "C") +a.py:3: error: Signature of "meth" incompatible with supertype "C" +a.py:3: note: Superclass: +a.py:3: note: @overload +a.py:3: note: def meth(self, x: int) -> int +a.py:3: note: @overload +a.py:3: note: def meth(self, x: str) -> str +a.py:3: note: Subclass: +a.py:3: note: def meth(self) -> None + +[case testFinalBodyReprocessedAndStillFinalOverloaded2-only_when_nocache] +-- Different cache/no-cache tests because +-- CallableType.def_extras.first_arg differs ("self"/None) import a [file a.py] from c import C @@ -8346,6 +8450,13 @@ class D: == a.py:3: error: Cannot override final attribute "meth" (previously declared in base class "C") a.py:3: error: Signature of "meth" incompatible with supertype "C" +a.py:3: note: Superclass: +a.py:3: note: @overload +a.py:3: note: def meth(x: int) -> int +a.py:3: note: @overload +a.py:3: note: def meth(x: str) -> str +a.py:3: note: Subclass: +a.py:3: note: def meth(self) -> None [case testIfMypyUnreachableClass] from a import x @@ -9622,3 +9733,28 @@ class C: [out] == main:5: error: Unsupported left operand type for + ("str") +[case testNoneAttribute] +from typing import Generic, TypeVar + +T = TypeVar('T', int, str) + +class ExampleClass(Generic[T]): + def __init__( + self + ) -> None: + self.example_attribute = None +[out] +== +[case testStrictNoneAttribute] +# flags: --strict-optional +from typing import Generic, TypeVar + +T = TypeVar('T', int, str) + +class ExampleClass(Generic[T]): + def __init__( + self + ) -> None: + self.example_attribute = None +[out] +== diff --git a/test-data/unit/fixtures/__init_subclass__.pyi b/test-data/unit/fixtures/__init_subclass__.pyi index 79fd04fd964e..c5a17f60688e 100644 --- a/test-data/unit/fixtures/__init_subclass__.pyi +++ b/test-data/unit/fixtures/__init_subclass__.pyi @@ -1,5 +1,7 @@ # builtins stub with object.__init_subclass__ +from typing import Mapping, Iterable # needed for ArgumentInferContext + class object: def __init_subclass__(cls) -> None: pass diff --git a/test-data/unit/fixtures/alias.pyi b/test-data/unit/fixtures/alias.pyi index 5909cb616794..08b145f4efd1 100644 --- a/test-data/unit/fixtures/alias.pyi +++ b/test-data/unit/fixtures/alias.pyi @@ -1,5 +1,7 @@ # Builtins test fixture with a type alias 'bytes' +from typing import Mapping, Iterable # needed for `ArgumentInferContext` + class object: def __init__(self) -> None: pass class type: diff --git a/test-data/unit/fixtures/args.pyi b/test-data/unit/fixtures/args.pyi index 0a38ceeece2e..ffe54375f68e 100644 --- a/test-data/unit/fixtures/args.pyi +++ b/test-data/unit/fixtures/args.pyi @@ -1,6 +1,6 @@ # Builtins stub used to support *args, **kwargs. -from typing import TypeVar, Generic, Iterable, Tuple, Dict, Any, overload, Mapping +from typing import TypeVar, Generic, Iterable, Sequence, Tuple, Dict, Any, overload, Mapping Tco = TypeVar('Tco', covariant=True) T = TypeVar('T') @@ -20,7 +20,9 @@ class type: class tuple(Iterable[Tco], Generic[Tco]): pass -class dict(Iterable[T], Mapping[T, S], Generic[T, S]): pass +class dict(Mapping[T, S], Generic[T, S]): pass + +class list(Sequence[T], Generic[T]): pass class int: def __eq__(self, o: object) -> bool: pass diff --git a/test-data/unit/fixtures/attr.pyi b/test-data/unit/fixtures/attr.pyi index deb1906d931e..c209abfef0d9 100644 --- a/test-data/unit/fixtures/attr.pyi +++ b/test-data/unit/fixtures/attr.pyi @@ -25,3 +25,4 @@ class complex: class str: pass class unicode: pass class ellipsis: pass +class tuple: pass diff --git a/test-data/unit/fixtures/bool.pyi b/test-data/unit/fixtures/bool.pyi index b4f99451aea6..245526d78907 100644 --- a/test-data/unit/fixtures/bool.pyi +++ b/test-data/unit/fixtures/bool.pyi @@ -10,9 +10,11 @@ class object: class type: pass class tuple(Generic[T]): pass class function: pass -class bool: pass class int: pass +class bool(int): pass class float: pass class str: pass class unicode: pass class ellipsis: pass +class list: pass +class property: pass diff --git a/test-data/unit/fixtures/callable.pyi b/test-data/unit/fixtures/callable.pyi index 80fcf6ba10bf..4ad72bee93ec 100644 --- a/test-data/unit/fixtures/callable.pyi +++ b/test-data/unit/fixtures/callable.pyi @@ -10,6 +10,8 @@ class type: class tuple(Generic[T]): pass +class classmethod: pass +class staticmethod: pass class function: pass def isinstance(x: object, t: Union[type, Tuple[type, ...]]) -> bool: pass @@ -25,3 +27,4 @@ class str: def __add__(self, other: 'str') -> 'str': pass def __eq__(self, other: 'str') -> bool: pass class ellipsis: pass +class list: ... diff --git a/test-data/unit/fixtures/dataclasses.pyi b/test-data/unit/fixtures/dataclasses.pyi new file mode 100644 index 000000000000..206843a88b24 --- /dev/null +++ b/test-data/unit/fixtures/dataclasses.pyi @@ -0,0 +1,43 @@ +from typing import ( + Generic, Iterator, Iterable, Mapping, Optional, Sequence, Tuple, + TypeVar, Union, overload, +) + +_T = TypeVar('_T') +_U = TypeVar('_U') +KT = TypeVar('KT') +VT = TypeVar('VT') + +class object: + def __init__(self) -> None: pass + def __eq__(self, o: object) -> bool: pass + def __ne__(self, o: object) -> bool: pass + +class type: pass +class ellipsis: pass +class tuple(Generic[_T]): pass +class int: pass +class float: pass +class str: pass +class bool(int): pass + +class dict(Mapping[KT, VT]): + @overload + def __init__(self, **kwargs: VT) -> None: pass + @overload + def __init__(self, arg: Iterable[Tuple[KT, VT]], **kwargs: VT) -> None: pass + def __getitem__(self, key: KT) -> VT: pass + def __setitem__(self, k: KT, v: VT) -> None: pass + def __iter__(self) -> Iterator[KT]: pass + def __contains__(self, item: object) -> int: pass + def update(self, a: Mapping[KT, VT]) -> None: pass + @overload + def get(self, k: KT) -> Optional[VT]: pass + @overload + def get(self, k: KT, default: Union[KT, _T]) -> Union[VT, _T]: pass + def __len__(self) -> int: ... + +class list(Generic[_T], Sequence[_T]): pass +class function: pass +class classmethod: pass +property = object() diff --git a/test-data/unit/fixtures/dict.pyi b/test-data/unit/fixtures/dict.pyi index ab8127badd4c..fd509de8a6c2 100644 --- a/test-data/unit/fixtures/dict.pyi +++ b/test-data/unit/fixtures/dict.pyi @@ -48,8 +48,12 @@ class list(Sequence[T]): # needed by some test cases class tuple(Generic[T]): pass class function: pass class float: pass +class complex: pass class bool(int): pass -class ellipsis: pass +class ellipsis: + __class__: object def isinstance(x: object, t: Union[type, Tuple[type, ...]]) -> bool: pass class BaseException: pass + +def iter(__iterable: Iterable[T]) -> Iterator[T]: pass diff --git a/test-data/unit/fixtures/floatdict.pyi b/test-data/unit/fixtures/floatdict.pyi index 7d2f55a6f6dd..7baa7ca9206f 100644 --- a/test-data/unit/fixtures/floatdict.pyi +++ b/test-data/unit/fixtures/floatdict.pyi @@ -36,7 +36,7 @@ class list(Iterable[T], Generic[T]): def append(self, x: T) -> None: pass def extend(self, x: Iterable[T]) -> None: pass -class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): +class dict(Mapping[KT, VT], Generic[KT, VT]): @overload def __init__(self, **kwargs: VT) -> None: pass @overload diff --git a/test-data/unit/fixtures/floatdict_python2.pyi b/test-data/unit/fixtures/floatdict_python2.pyi index aa22c5464d6b..f177355d5d4b 100644 --- a/test-data/unit/fixtures/floatdict_python2.pyi +++ b/test-data/unit/fixtures/floatdict_python2.pyi @@ -36,7 +36,7 @@ class list(Iterable[T], Generic[T]): def append(self, x: T) -> None: pass def extend(self, x: Iterable[T]) -> None: pass -class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): +class dict(Mapping[KT, VT], Generic[KT, VT]): @overload def __init__(self, **kwargs: VT) -> None: pass @overload diff --git a/test-data/unit/fixtures/isinstance_python3_10.pyi b/test-data/unit/fixtures/isinstance_python3_10.pyi new file mode 100644 index 000000000000..abb37ea81c00 --- /dev/null +++ b/test-data/unit/fixtures/isinstance_python3_10.pyi @@ -0,0 +1,29 @@ +# For Python 3.10+ only +from typing import Tuple, TypeVar, Generic, Union, cast, Any, Type +import types + +T = TypeVar('T') + +class object: + def __init__(self) -> None: pass + +class type(Generic[T]): + def __init__(self, x) -> None: pass + def __or__(self, x) -> types.Union: pass + +class tuple(Generic[T]): pass + +class function: pass + +def isinstance(x: object, t: Union[Type[object], Tuple[Type[object], ...], types.Union]) -> bool: pass +def issubclass(x: object, t: Union[Type[object], Tuple[Type[object], ...]]) -> bool: pass + +class int: + def __add__(self, other: 'int') -> 'int': pass +class float: pass +class bool(int): pass +class str: + def __add__(self, other: 'str') -> 'str': pass +class ellipsis: pass + +NotImplemented = cast(Any, None) diff --git a/test-data/unit/fixtures/list.pyi b/test-data/unit/fixtures/list.pyi index c4baf89ffc13..31dc333b3d4f 100644 --- a/test-data/unit/fixtures/list.pyi +++ b/test-data/unit/fixtures/list.pyi @@ -16,6 +16,7 @@ class list(Sequence[T]): @overload def __init__(self, x: Iterable[T]) -> None: pass def __iter__(self) -> Iterator[T]: pass + def __len__(self) -> int: pass def __contains__(self, item: object) -> bool: pass def __add__(self, x: list[T]) -> list[T]: pass def __mul__(self, x: int) -> list[T]: pass @@ -26,9 +27,12 @@ class list(Sequence[T]): class tuple(Generic[T]): pass class function: pass -class int: pass -class float: pass -class str: pass +class int: + def __bool__(self) -> bool: pass +class float: + def __bool__(self) -> bool: pass +class str: + def __len__(self) -> bool: pass class bool(int): pass property = object() # Dummy definition. diff --git a/test-data/unit/fixtures/narrowing.pyi b/test-data/unit/fixtures/narrowing.pyi new file mode 100644 index 000000000000..89ee011c1c80 --- /dev/null +++ b/test-data/unit/fixtures/narrowing.pyi @@ -0,0 +1,20 @@ +# Builtins stub used in check-narrowing test cases. +from typing import Generic, Sequence, Tuple, Type, TypeVar, Union + + +Tco = TypeVar('Tco', covariant=True) +KT = TypeVar("KT") +VT = TypeVar("VT") + +class object: + def __init__(self) -> None: pass + +class type: pass +class tuple(Sequence[Tco], Generic[Tco]): pass +class function: pass +class ellipsis: pass +class int: pass +class str: pass +class dict(Generic[KT, VT]): pass + +def isinstance(x: object, t: Union[Type[object], Tuple[Type[object], ...]]) -> bool: pass diff --git a/test-data/unit/fixtures/python2.pyi b/test-data/unit/fixtures/python2.pyi index 44cb9de9be1d..51af59c8bd45 100644 --- a/test-data/unit/fixtures/python2.pyi +++ b/test-data/unit/fixtures/python2.pyi @@ -18,6 +18,8 @@ class unicode: def format(self, *args, **kwars) -> unicode: ... class bool(int): pass +bytes = str + T = TypeVar('T') S = TypeVar('S') class list(Iterable[T], Generic[T]): diff --git a/test-data/unit/fixtures/set.pyi b/test-data/unit/fixtures/set.pyi index c2e1f6f75237..9852bbc9fcc6 100644 --- a/test-data/unit/fixtures/set.pyi +++ b/test-data/unit/fixtures/set.pyi @@ -17,6 +17,7 @@ class bool: pass class ellipsis: pass class set(Iterable[T], Generic[T]): + def __init__(self, iterable: Iterable[T] = ...) -> None: ... def __iter__(self) -> Iterator[T]: pass def __contains__(self, item: object) -> bool: pass def __ior__(self, x: Set[T]) -> None: pass diff --git a/test-data/unit/fixtures/tuple.pyi b/test-data/unit/fixtures/tuple.pyi index a101595c6f30..5f7fb01f4b07 100644 --- a/test-data/unit/fixtures/tuple.pyi +++ b/test-data/unit/fixtures/tuple.pyi @@ -1,7 +1,8 @@ # Builtins stub used in tuple-related test cases. -from typing import Iterable, Iterator, TypeVar, Generic, Sequence, Any, overload, Tuple +from typing import Iterable, Iterator, TypeVar, Generic, Sequence, Any, overload, Tuple, Type +T = TypeVar("T") Tco = TypeVar('Tco', covariant=True) class object: @@ -11,9 +12,11 @@ class type: def __init__(self, *a: object) -> None: pass def __call__(self, *a: object) -> object: pass class tuple(Sequence[Tco], Generic[Tco]): + def __new__(cls: Type[T], iterable: Iterable[Tco] = ...) -> T: ... def __iter__(self) -> Iterator[Tco]: pass def __contains__(self, item: object) -> bool: pass def __getitem__(self, x: int) -> Tco: pass + def __mul__(self, n: int) -> Tuple[Tco, ...]: pass def __rmul__(self, n: int) -> Tuple[Tco, ...]: pass def __add__(self, x: Tuple[Tco, ...]) -> Tuple[Tco, ...]: pass def count(self, obj: object) -> int: pass @@ -30,8 +33,6 @@ class str: pass # For convenience class bytes: pass class unicode: pass -T = TypeVar('T') - class list(Sequence[T], Generic[T]): @overload def __getitem__(self, i: int) -> T: ... diff --git a/test-data/unit/fixtures/type.pyi b/test-data/unit/fixtures/type.pyi index 35cf0ad3ce73..755b45ff0bb5 100644 --- a/test-data/unit/fixtures/type.pyi +++ b/test-data/unit/fixtures/type.pyi @@ -1,6 +1,6 @@ # builtins stub used in type-related test cases. -from typing import Generic, TypeVar, List +from typing import Generic, TypeVar, List, Union T = TypeVar('T') @@ -10,8 +10,9 @@ class object: class list(Generic[T]): pass -class type: +class type(Generic[T]): __name__: str + def __or__(self, other: Union[type, None]) -> type: pass def mro(self) -> List['type']: pass class tuple(Generic[T]): pass diff --git a/test-data/unit/fixtures/typing-full.pyi b/test-data/unit/fixtures/typing-full.pyi index 6aa2f9d291bb..3de9f934b255 100644 --- a/test-data/unit/fixtures/typing-full.pyi +++ b/test-data/unit/fixtures/typing-full.pyi @@ -10,7 +10,7 @@ from abc import abstractmethod, ABCMeta class GenericMeta(type): pass -cast = 0 +def cast(t, o): ... overload = 0 Any = 0 Union = 0 diff --git a/test-data/unit/fixtures/typing-namedtuple.pyi b/test-data/unit/fixtures/typing-namedtuple.pyi new file mode 100644 index 000000000000..3404dc69de44 --- /dev/null +++ b/test-data/unit/fixtures/typing-namedtuple.pyi @@ -0,0 +1,18 @@ +TypeVar = 0 +Generic = 0 +Any = 0 +overload = 0 +Type = 0 +Literal = 0 + +T_co = TypeVar('T_co', covariant=True) +KT = TypeVar('KT') + +class Iterable(Generic[T_co]): pass +class Iterator(Iterable[T_co]): pass +class Sequence(Iterable[T_co]): pass +class Mapping(Iterable[KT], Generic[KT, T_co]): pass + +class Tuple(Sequence): pass +class NamedTuple(Tuple): + name: str diff --git a/test-data/unit/fixtures/typing-typeddict.pyi b/test-data/unit/fixtures/typing-typeddict.pyi index f460a7bfd167..72f500707094 100644 --- a/test-data/unit/fixtures/typing-typeddict.pyi +++ b/test-data/unit/fixtures/typing-typeddict.pyi @@ -23,6 +23,8 @@ Final = 0 Literal = 0 TypedDict = 0 NoReturn = 0 +Required = 0 +NotRequired = 0 T = TypeVar('T') T_co = TypeVar('T_co', covariant=True) diff --git a/test-data/unit/hacks.txt b/test-data/unit/hacks.txt index 501a722fa359..43114a8af004 100644 --- a/test-data/unit/hacks.txt +++ b/test-data/unit/hacks.txt @@ -39,7 +39,7 @@ y = '' # This could be valid if a new 'y' is defined here ``` Note that some of the checks may turn out to be redundant, as the -exact rules for what constitues a redefinition are still up for +exact rules for what constitutes a redefinition are still up for debate. This is okay since the extra if statements generally don't otherwise affect semantics. diff --git a/test-data/unit/lib-stub/attr/__init__.pyi b/test-data/unit/lib-stub/attr/__init__.pyi index 475cfb7571a5..6ce4b3a64ed5 100644 --- a/test-data/unit/lib-stub/attr/__init__.pyi +++ b/test-data/unit/lib-stub/attr/__init__.pyi @@ -1,4 +1,4 @@ -from typing import TypeVar, overload, Callable, Any, Type, Optional, Union, Sequence, Mapping +from typing import TypeVar, overload, Callable, Any, Type, Optional, Union, Sequence, Mapping, Generic _T = TypeVar('_T') _C = TypeVar('_C', bound=type) @@ -115,6 +115,8 @@ def attrs(maybe_cls: None = ..., ) -> Callable[[_C], _C]: ... +class Attribute(Generic[_T]): pass + # aliases s = attributes = attrs ib = attr = attrib diff --git a/test-data/unit/lib-stub/builtins.pyi b/test-data/unit/lib-stub/builtins.pyi index 7ba4002ed4ac..8c4f504fb2e7 100644 --- a/test-data/unit/lib-stub/builtins.pyi +++ b/test-data/unit/lib-stub/builtins.pyi @@ -11,6 +11,7 @@ class type: # These are provided here for convenience. class int: def __add__(self, other: int) -> int: pass +class bool(int): pass class float: pass class str: pass @@ -19,4 +20,8 @@ class bytes: pass class function: pass class ellipsis: pass +from typing import Generic, Sequence, TypeVar +_T = TypeVar('_T') +class list(Generic[_T], Sequence[_T]): pass + # Definition of None is implicit diff --git a/test-data/unit/lib-stub/dataclasses.pyi b/test-data/unit/lib-stub/dataclasses.pyi index 160cfcd066ba..e0491e14876b 100644 --- a/test-data/unit/lib-stub/dataclasses.pyi +++ b/test-data/unit/lib-stub/dataclasses.pyi @@ -5,26 +5,31 @@ _T = TypeVar('_T') class InitVar(Generic[_T]): ... +class KW_ONLY: ... @overload def dataclass(_cls: Type[_T]) -> Type[_T]: ... @overload def dataclass(*, init: bool = ..., repr: bool = ..., eq: bool = ..., order: bool = ..., - unsafe_hash: bool = ..., frozen: bool = ...) -> Callable[[Type[_T]], Type[_T]]: ... + unsafe_hash: bool = ..., frozen: bool = ..., match_args: bool = ..., + kw_only: bool = ..., slots: bool = ...) -> Callable[[Type[_T]], Type[_T]]: ... @overload def field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ...) -> _T: ... + metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...,) -> _T: ... @overload def field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ...) -> _T: ... + metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...,) -> _T: ... @overload def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., - metadata: Optional[Mapping[str, Any]] = ...) -> Any: ... + metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...,) -> Any: ... + + +class Field(Generic[_T]): pass diff --git a/test-data/unit/lib-stub/types.pyi b/test-data/unit/lib-stub/types.pyi index 02113aea3834..6fc596ecbf13 100644 --- a/test-data/unit/lib-stub/types.pyi +++ b/test-data/unit/lib-stub/types.pyi @@ -1,4 +1,5 @@ from typing import TypeVar +import sys _T = TypeVar('_T') @@ -8,3 +9,7 @@ class bool: ... class ModuleType: __file__ = ... # type: str + +if sys.version_info >= (3, 10): + class Union: + def __or__(self, x) -> Union: ... diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index 2f42633843e0..b9f1752aee1b 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -43,6 +43,7 @@ class Generator(Iterator[T], Generic[T, U, V]): class Sequence(Iterable[T_co]): def __getitem__(self, n: Any) -> T_co: pass -class Mapping(Generic[T, T_co]): pass +# Mapping type is oversimplified intentionally. +class Mapping(Iterable[T], Generic[T, T_co]): pass def final(meth: T) -> T: pass diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 478e5dc1b283..5b32449e71cf 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -24,6 +24,8 @@ Annotated: _SpecialForm = ... ParamSpec: _SpecialForm Concatenate: _SpecialForm +TypeAlias: _SpecialForm + TypeGuard: _SpecialForm # Fallback type for all typed dicts (does not exist at runtime). diff --git a/test-data/unit/parse-errors.test b/test-data/unit/parse-errors.test index a0b7a037a082..9123ce0cf509 100644 --- a/test-data/unit/parse-errors.test +++ b/test-data/unit/parse-errors.test @@ -295,7 +295,7 @@ file:1: error: invalid syntax [out] file:1: error: invalid syntax -[case testInvalidConditionInConditionalExpression2] +[case testInvalidConditionInConditionalExpression3] 1 if x else for y in z [out] file:1: error: invalid syntax diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 22b1ab28481d..ff892ce0ce05 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -935,7 +935,7 @@ MypyFile:1( x not y [out] main:1: error: invalid syntax -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? [case testNotIs] @@ -946,9 +946,24 @@ x not is y # E: invalid syntax 1 ~ 2 [out] main:1: error: invalid syntax -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? +[case testSliceInList39] +# flags: --python-version 3.9 +x = [1, 2][1:2] +[out] +MypyFile:1( + AssignmentStmt:2( + NameExpr(x) + IndexExpr:2( + ListExpr:2( + IntExpr(1) + IntExpr(2)) + SliceExpr:2( + IntExpr(1) + IntExpr(2))))) + [case testDictionaryExpression] {} {1:x} @@ -3108,7 +3123,7 @@ MypyFile:1( NameExpr(x) NameExpr(y))))) -[case testConditionalExpressionInListComprehension] +[case testConditionalExpressionInListComprehension2] a = [ 1 if x else 2 for x in y ] [out] MypyFile:1( @@ -3314,7 +3329,7 @@ MypyFile:1() [out] MypyFile:1() -[case testLatinUnixEncoding] +[case testLatinUnixEncoding2] # coding: iso-latin-1 [out] MypyFile:1() diff --git a/test-data/unit/pep561.test b/test-data/unit/pep561.test index a4f96ede9f41..839ca110b94c 100644 --- a/test-data/unit/pep561.test +++ b/test-data/unit/pep561.test @@ -119,10 +119,10 @@ reveal_type(a) testTypedPkgSimpleEditableEgg.py:5: note: Revealed type is "builtins.tuple[builtins.str]" [case testTypedPkgNamespaceImportFrom] -# pkgs: typedpkg, typedpkg_ns +# pkgs: typedpkg, typedpkg_ns_a from typedpkg.pkg.aaa import af -from typedpkg_ns.ns.bbb import bf -from typedpkg_ns.ns.dne import dne +from typedpkg_ns.a.bbb import bf +from typedpkg_ns.a.dne import dne af("abc") bf(False) @@ -132,16 +132,16 @@ af(False) bf(2) dne("abc") [out] -testTypedPkgNamespaceImportFrom.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.ns.dne" +testTypedPkgNamespaceImportFrom.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.a.dne" testTypedPkgNamespaceImportFrom.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports testTypedPkgNamespaceImportFrom.py:10: error: Argument 1 to "af" has incompatible type "bool"; expected "str" testTypedPkgNamespaceImportFrom.py:11: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" [case testTypedPkgNamespaceImportAs] -# pkgs: typedpkg, typedpkg_ns +# pkgs: typedpkg, typedpkg_ns_a import typedpkg.pkg.aaa as nm; af = nm.af -import typedpkg_ns.ns.bbb as am; bf = am.bf -from typedpkg_ns.ns.dne import dne +import typedpkg_ns.a.bbb as am; bf = am.bf +from typedpkg_ns.a.dne import dne af("abc") bf(False) @@ -151,16 +151,16 @@ af(False) bf(2) dne("abc") [out] -testTypedPkgNamespaceImportAs.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.ns.dne" +testTypedPkgNamespaceImportAs.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.a.dne" testTypedPkgNamespaceImportAs.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports testTypedPkgNamespaceImportAs.py:10: error: Argument 1 has incompatible type "bool"; expected "str" testTypedPkgNamespaceImportAs.py:11: error: Argument 1 has incompatible type "int"; expected "bool" [case testTypedPkgNamespaceRegImport] -# pkgs: typedpkg, typedpkg_ns +# pkgs: typedpkg, typedpkg_ns_a import typedpkg.pkg.aaa; af = typedpkg.pkg.aaa.af -import typedpkg_ns.ns.bbb; bf = typedpkg_ns.ns.bbb.bf -from typedpkg_ns.ns.dne import dne +import typedpkg_ns.a.bbb; bf = typedpkg_ns.a.bbb.bf +from typedpkg_ns.a.dne import dne af("abc") bf(False) @@ -171,7 +171,54 @@ bf(2) dne("abc") [out] -testTypedPkgNamespaceRegImport.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.ns.dne" +testTypedPkgNamespaceRegImport.py:4: error: Cannot find implementation or library stub for module named "typedpkg_ns.a.dne" testTypedPkgNamespaceRegImport.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports testTypedPkgNamespaceRegImport.py:10: error: Argument 1 has incompatible type "bool"; expected "str" testTypedPkgNamespaceRegImport.py:11: error: Argument 1 has incompatible type "int"; expected "bool" + +-- This is really testing the test framework to make sure incremental works +[case testPep561TestIncremental] +# pkgs: typedpkg +import a +[file a.py] +[file a.py.2] +1 + 'no' +[out] +[out2] +a.py:1: error: Unsupported operand types for + ("int" and "str") + +[case testTypedPkgNamespaceRegFromImportTwice] +# pkgs: typedpkg_ns_a +from typedpkg_ns import a +-- dummy should trigger a second iteration +[file dummy.py.2] +[out] +[out2] + +[case testNamespacePkgWStubs] +# pkgs: typedpkg_ns_a, typedpkg_ns_b, typedpkg_ns_b-stubs +# flags: --no-namespace-packages +import typedpkg_ns.a.bbb as a +import typedpkg_ns.b.bbb as b +a.bf(False) +b.bf(False) +a.bf(1) +b.bf(1) +[out] +testNamespacePkgWStubs.py:4: error: Skipping analyzing "typedpkg_ns.b.bbb": module is installed, but missing library stubs or py.typed marker +testNamespacePkgWStubs.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +testNamespacePkgWStubs.py:4: error: Skipping analyzing "typedpkg_ns.b": module is installed, but missing library stubs or py.typed marker +testNamespacePkgWStubs.py:7: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" + +[case testNamespacePkgWStubsWithNamespacePackagesFlag] +# pkgs: typedpkg_ns_a, typedpkg_ns_b, typedpkg_ns_b-stubs +# flags: --namespace-packages +import typedpkg_ns.a.bbb as a +import typedpkg_ns.b.bbb as b +a.bf(False) +b.bf(False) +a.bf(1) +b.bf(1) +[out] +testNamespacePkgWStubsWithNamespacePackagesFlag.py:7: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" +testNamespacePkgWStubsWithNamespacePackagesFlag.py:8: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" diff --git a/test-data/unit/plugins/arg_kinds.py b/test-data/unit/plugins/arg_kinds.py index 9e80d5436461..5392e64c4f11 100644 --- a/test-data/unit/plugins/arg_kinds.py +++ b/test-data/unit/plugins/arg_kinds.py @@ -1,7 +1,4 @@ -import sys from typing import Optional, Callable - -from mypy.nodes import Context from mypy.plugin import Plugin, MethodContext, FunctionContext from mypy.types import Type @@ -21,12 +18,12 @@ def get_method_hook(self, fullname: str def extract_arg_kinds_from_function(ctx: FunctionContext) -> Type: - ctx.api.fail(str(ctx.arg_kinds), ctx.context) + ctx.api.fail(str([[x.value for x in y] for y in ctx.arg_kinds]), ctx.context) return ctx.default_return_type def extract_arg_kinds_from_method(ctx: MethodContext) -> Type: - ctx.api.fail(str(ctx.arg_kinds), ctx.context) + ctx.api.fail(str([[x.value for x in y] for y in ctx.arg_kinds]), ctx.context) return ctx.default_return_type diff --git a/test-data/unit/plugins/common_api_incremental.py b/test-data/unit/plugins/common_api_incremental.py index 070bc61ceb3f..2dcd559777ec 100644 --- a/test-data/unit/plugins/common_api_incremental.py +++ b/test-data/unit/plugins/common_api_incremental.py @@ -24,7 +24,7 @@ def add_info_hook(ctx) -> None: info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id) class_def.info = info - obj = ctx.api.builtin_type('builtins.object') + obj = ctx.api.named_type('builtins.object') info.mro = [info, obj.type] info.bases = [obj] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) diff --git a/test-data/unit/plugins/decimal_to_int.py b/test-data/unit/plugins/decimal_to_int.py index 98e747ed74c0..21fd3b518b7d 100644 --- a/test-data/unit/plugins/decimal_to_int.py +++ b/test-data/unit/plugins/decimal_to_int.py @@ -1,8 +1,5 @@ -import builtins -from typing import Optional, Callable -from mypy.plugin import Plugin, AnalyzeTypeContext -from mypy.types import CallableType, Type +from mypy.plugin import Plugin class MyPlugin(Plugin): diff --git a/test-data/unit/plugins/depshook.py b/test-data/unit/plugins/depshook.py index 037e2861e4dc..76277f3cb82b 100644 --- a/test-data/unit/plugins/depshook.py +++ b/test-data/unit/plugins/depshook.py @@ -1,4 +1,4 @@ -from typing import Optional, Callable, List, Tuple +from typing import List, Tuple from mypy.plugin import Plugin from mypy.nodes import MypyFile diff --git a/test-data/unit/plugins/dyn_class.py b/test-data/unit/plugins/dyn_class.py index 56ef89e17869..54bf377aa8ef 100644 --- a/test-data/unit/plugins/dyn_class.py +++ b/test-data/unit/plugins/dyn_class.py @@ -23,7 +23,7 @@ def add_info_hook(ctx): info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id) class_def.info = info - obj = ctx.api.builtin_type('builtins.object') + obj = ctx.api.named_type('builtins.object') info.mro = [info, obj.type] info.bases = [obj] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) diff --git a/test-data/unit/plugins/dyn_class_from_method.py b/test-data/unit/plugins/dyn_class_from_method.py index 8a18f7f1e8e1..4c3904907750 100644 --- a/test-data/unit/plugins/dyn_class_from_method.py +++ b/test-data/unit/plugins/dyn_class_from_method.py @@ -18,7 +18,7 @@ def add_info_hook(ctx: DynamicClassDefContext): class_def.info = info queryset_type_fullname = ctx.call.args[0].fullname queryset_info = ctx.api.lookup_fully_qualified_or_none(queryset_type_fullname).node # type: TypeInfo - obj = ctx.api.builtin_type('builtins.object') + obj = ctx.api.named_type('builtins.object') info.mro = [info, queryset_info, obj.type] info.bases = [Instance(queryset_info, [])] ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) diff --git a/test-data/unit/plugins/method_in_decorator.py b/test-data/unit/plugins/method_in_decorator.py new file mode 100644 index 000000000000..99774dfcc7ef --- /dev/null +++ b/test-data/unit/plugins/method_in_decorator.py @@ -0,0 +1,19 @@ +from mypy.types import CallableType, Type +from typing import Callable, Optional +from mypy.plugin import MethodContext, Plugin + + +class MethodDecoratorPlugin(Plugin): + def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], Type]]: + if 'Foo.a' in fullname: + return method_decorator_callback + return None + +def method_decorator_callback(ctx: MethodContext) -> Type: + if isinstance(ctx.default_return_type, CallableType): + str_type = ctx.api.named_generic_type('builtins.str', []) + return ctx.default_return_type.copy_modified(ret_type=str_type) + return ctx.default_return_type + +def plugin(version): + return MethodDecoratorPlugin diff --git a/test-data/unit/plugins/type_anal_hook.py b/test-data/unit/plugins/type_anal_hook.py index 66b24bcf323d..86d18d8c8611 100644 --- a/test-data/unit/plugins/type_anal_hook.py +++ b/test-data/unit/plugins/type_anal_hook.py @@ -1,7 +1,7 @@ from typing import Optional, Callable from mypy.plugin import Plugin, AnalyzeTypeContext -from mypy.types import Type, UnboundType, TypeList, AnyType, CallableType, TypeOfAny +from mypy.types import Type, TypeList, AnyType, CallableType, TypeOfAny # The official name changed to NoneType but we have an alias for plugin compat reasons # so we'll keep testing that here. from mypy.types import NoneTyp diff --git a/test-data/unit/python2eval.test b/test-data/unit/python2eval.test index c9618438668a..d9fb729ff3be 100644 --- a/test-data/unit/python2eval.test +++ b/test-data/unit/python2eval.test @@ -433,3 +433,17 @@ _testDefaultDictInference.py:5: note: Revealed type is "collections.defaultdict[ from collections import abc [out] _testIgnorePython3StdlibStubs_python2.py:1: error: Module "collections" has no attribute "abc" + +[case testNoApprovedPython2StubInstalled_python2] +# flags: --ignore-missing-imports +import scribe +from scribe import x +import maxminddb +import foobar_asdf +[out] +_testNoApprovedPython2StubInstalled_python2.py:2: error: Library stubs not installed for "scribe" (or incompatible with Python 2.7) +_testNoApprovedPython2StubInstalled_python2.py:2: note: Hint: "python3 -m pip install types-scribe" +_testNoApprovedPython2StubInstalled_python2.py:2: note: (or run "mypy --install-types" to install all missing stub packages) +_testNoApprovedPython2StubInstalled_python2.py:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +_testNoApprovedPython2StubInstalled_python2.py:4: error: Library stubs not installed for "maxminddb" (or incompatible with Python 2.7) +_testNoApprovedPython2StubInstalled_python2.py:4: note: Hint: "python3 -m pip install types-maxminddb" diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 49f308af3610..90588a86d8bf 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -797,7 +797,7 @@ t + 1 _program.py:3: error: No overload variant of "__add__" of "tuple" matches argument type "int" _program.py:3: note: Possible overload variants: _program.py:3: note: def __add__(self, Tuple[str, ...]) -> Tuple[str, ...] -_program.py:3: note: def __add__(self, Tuple[Any, ...]) -> Tuple[Any, ...] +_program.py:3: note: def [_T] __add__(self, Tuple[_T, ...]) -> Tuple[Union[str, _T], ...] [case testMultiplyTupleByIntegerReverse] n = 4 @@ -807,7 +807,7 @@ t + 1 _program.py:3: error: No overload variant of "__add__" of "tuple" matches argument type "int" _program.py:3: note: Possible overload variants: _program.py:3: note: def __add__(self, Tuple[str, ...]) -> Tuple[str, ...] -_program.py:3: note: def __add__(self, Tuple[Any, ...]) -> Tuple[Any, ...] +_program.py:3: note: def [_T] __add__(self, Tuple[_T, ...]) -> Tuple[Union[str, _T], ...] [case testDictWithKeywordArgs] from typing import Dict, Any, List @@ -1005,7 +1005,7 @@ re.subn(bpat, b'', b'')[0] + b'' re.subn(bre, lambda m: b'', b'')[0] + b'' re.subn(bpat, lambda m: b'', b'')[0] + b'' [out] -_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "object" +_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "Sequence[object]" _program.py:9: error: Cannot infer type argument 1 of "search" [case testReModuleString] @@ -1029,7 +1029,7 @@ re.subn(spat, '', '')[0] + '' re.subn(sre, lambda m: '', '')[0] + '' re.subn(spat, lambda m: '', '')[0] + '' [out] -_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "object" +_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "Sequence[object]" _program.py:9: error: Cannot infer type argument 1 of "search" [case testListSetitemTuple] @@ -1085,7 +1085,7 @@ _testTypedDictGet.py:9: note: Revealed type is "builtins.object*" _testTypedDictGet.py:10: error: All overload variants of "get" of "Mapping" require at least one argument _testTypedDictGet.py:10: note: Possible overload variants: _testTypedDictGet.py:10: note: def get(self, key: str) -> object -_testTypedDictGet.py:10: note: def [_T] get(self, key: str, default: object) -> object +_testTypedDictGet.py:10: note: def [_T] get(self, str, object) -> object _testTypedDictGet.py:12: note: Revealed type is "builtins.object*" [case testTypedDictMappingMethods] @@ -1390,6 +1390,32 @@ x = X(a=1, b='s') [out] _testNamedTupleNew.py:12: note: Revealed type is "Tuple[builtins.int, fallback=_testNamedTupleNew.Child]" +[case testNamedTupleTypeInheritanceSpecialCase] +from typing import NamedTuple, Tuple +from collections import namedtuple + +A = NamedTuple('A', [('param', int)]) +B = namedtuple('B', ['param']) + +def accepts_named_tuple(arg: NamedTuple): + reveal_type(arg._asdict()) + reveal_type(arg._fields) + reveal_type(arg._field_defaults) + +a = A(1) +b = B(1) + +accepts_named_tuple(a) +accepts_named_tuple(b) +accepts_named_tuple(1) +accepts_named_tuple((1, 2)) +[out] +_testNamedTupleTypeInheritanceSpecialCase.py:8: note: Revealed type is "collections.OrderedDict[builtins.str, Any]" +_testNamedTupleTypeInheritanceSpecialCase.py:9: note: Revealed type is "builtins.tuple[builtins.str]" +_testNamedTupleTypeInheritanceSpecialCase.py:10: note: Revealed type is "builtins.dict[builtins.str, Any]" +_testNamedTupleTypeInheritanceSpecialCase.py:17: error: Argument 1 to "accepts_named_tuple" has incompatible type "int"; expected "NamedTuple" +_testNamedTupleTypeInheritanceSpecialCase.py:18: error: Argument 1 to "accepts_named_tuple" has incompatible type "Tuple[int, int]"; expected "NamedTuple" + [case testNewAnalyzerBasicTypeshed_newsemanal] from typing import Dict, List, Tuple @@ -1414,7 +1440,7 @@ def thing(stuff: StuffDict) -> int: ... [out] _testNewAnalyzerTypedDictInStub_newsemanal.py:2: note: Revealed type is "def (stuff: TypedDict('stub.StuffDict', {'foo': builtins.str, 'bar': builtins.int})) -> builtins.int" -[case testStrictEqualityWhitelist] +[case testStrictEqualityAllowlist] # mypy: strict-equality {1} == frozenset({1}) frozenset({1}) == {1} @@ -1429,10 +1455,10 @@ frozenset({1}) == [1] # Error {1: 2}.values() == {2} # Error {1: 2}.keys() == [1] # Error [out] -_testStrictEqualityWhitelist.py:5: error: Non-overlapping equality check (left operand type: "FrozenSet[int]", right operand type: "List[int]") -_testStrictEqualityWhitelist.py:11: error: Non-overlapping equality check (left operand type: "KeysView[int]", right operand type: "Set[str]") -_testStrictEqualityWhitelist.py:12: error: Non-overlapping equality check (left operand type: "ValuesView[int]", right operand type: "Set[int]") -_testStrictEqualityWhitelist.py:13: error: Non-overlapping equality check (left operand type: "KeysView[int]", right operand type: "List[int]") +_testStrictEqualityAllowlist.py:5: error: Non-overlapping equality check (left operand type: "FrozenSet[int]", right operand type: "List[int]") +_testStrictEqualityAllowlist.py:11: error: Non-overlapping equality check (left operand type: "dict_keys[int, int]", right operand type: "Set[str]") +_testStrictEqualityAllowlist.py:12: error: Non-overlapping equality check (left operand type: "dict_values[int, int]", right operand type: "Set[int]") +_testStrictEqualityAllowlist.py:13: error: Non-overlapping equality check (left operand type: "dict_keys[int, int]", right operand type: "List[int]") [case testUnreachableWithStdlibContextManagers] # mypy: warn-unreachable, strict-optional @@ -1508,3 +1534,42 @@ x = 0 [out] mypy: "tmp/typing.py" shadows library module "typing" note: A user-defined top-level module with name "typing" is not supported + +[case testIgnoreImportIfNoPython3StubAvailable] +# flags: --ignore-missing-imports +import scribe # No Python 3 stubs available for scribe +from scribe import x +import maxminddb # Python 3 stubs available for maxminddb +import foobar_asdf +[out] +_testIgnoreImportIfNoPython3StubAvailable.py:4: error: Library stubs not installed for "maxminddb" (or incompatible with Python 3.6) +_testIgnoreImportIfNoPython3StubAvailable.py:4: note: Hint: "python3 -m pip install types-maxminddb" +_testIgnoreImportIfNoPython3StubAvailable.py:4: note: (or run "mypy --install-types" to install all missing stub packages) +_testIgnoreImportIfNoPython3StubAvailable.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports + +[case testNoPython3StubAvailable] +import scribe +from scribe import x +import maxminddb +[out] +_testNoPython3StubAvailable.py:1: error: Cannot find implementation or library stub for module named "scribe" +_testNoPython3StubAvailable.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +_testNoPython3StubAvailable.py:3: error: Library stubs not installed for "maxminddb" (or incompatible with Python 3.6) +_testNoPython3StubAvailable.py:3: note: Hint: "python3 -m pip install types-maxminddb" +_testNoPython3StubAvailable.py:3: note: (or run "mypy --install-types" to install all missing stub packages) + + +[case testTypingOrderedDictAlias] +# flags: --python-version 3.7 +from typing import OrderedDict +x: OrderedDict[str, int] = OrderedDict({}) +reveal_type(x) +[out] +_testTypingOrderedDictAlias.py:4: note: Revealed type is "collections.OrderedDict[builtins.str, builtins.int]" + +[case testTypingExtensionsOrderedDictAlias] +from typing_extensions import OrderedDict +x: OrderedDict[str, str] = OrderedDict({}) +reveal_type(x) # Revealed type is "collections.OrderedDict[builtins.str, builtins.int]" +[out] +_testTypingExtensionsOrderedDictAlias.py:3: note: Revealed type is "collections.OrderedDict[builtins.str, builtins.str]" diff --git a/test-data/unit/reports.test b/test-data/unit/reports.test index 5e0da3f07a98..a7ab6d754b2c 100644 --- a/test-data/unit/reports.test +++ b/test-data/unit/reports.test @@ -456,3 +456,41 @@ DisplayToSource = Callable[[int], int] + +[case testHtmlReportOnNamespacePackagesWithExplicitBases] +# cmd: mypy --html-report report -p folder +[file folder/subfolder/something.py] +class Something: + pass +[file folder/main.py] +from .subfolder.something import Something +print(Something()) +[file folder/__init__.py] +[file mypy.ini] +\[mypy] +explicit_package_bases = True +namespace_packages = True + +[file report/mypy-html.css] +[file report/index.html] +[outfile report/html/folder/subfolder/something.py.html] + + + + + + +

folder.subfolder.something

+ + + + + + +
folder/subfolder/something.py
1
+2
+
class Something:
+    pass
+
+ + diff --git a/test-data/unit/semanal-abstractclasses.test b/test-data/unit/semanal-abstractclasses.test index dfd5dee1554a..b0cb00e82106 100644 --- a/test-data/unit/semanal-abstractclasses.test +++ b/test-data/unit/semanal-abstractclasses.test @@ -79,7 +79,7 @@ MypyFile:1( ClassDef:4( A TypeVars( - T) + T`1) Decorator:5( Var(f) FuncDef:6( diff --git a/test-data/unit/semanal-basic.test b/test-data/unit/semanal-basic.test index 22231f067de3..bb829dd9a4c1 100644 --- a/test-data/unit/semanal-basic.test +++ b/test-data/unit/semanal-basic.test @@ -286,7 +286,7 @@ MypyFile:1( NameExpr(x* [l]) NameExpr(None [builtins.None]))))) -[case testGlobalDeclScope] +[case testGlobalDeclScope2] x = None def f(): global x diff --git a/test-data/unit/semanal-classvar.test b/test-data/unit/semanal-classvar.test index 8add559bdd27..a7bcec0324dc 100644 --- a/test-data/unit/semanal-classvar.test +++ b/test-data/unit/semanal-classvar.test @@ -207,3 +207,14 @@ class B: pass [out] main:4: error: ClassVar can only be used for assignments in class body + +[case testClassVarWithTypeVariable] +from typing import ClassVar, TypeVar, Generic, List + +T = TypeVar('T') + +class Some(Generic[T]): + error: ClassVar[T] # E: ClassVar cannot contain type variables + nested: ClassVar[List[List[T]]] # E: ClassVar cannot contain type variables + ok: ClassVar[int] +[out] diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 3a1fad61556a..e5aea483a210 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1030,11 +1030,13 @@ a = TypeVar() # E: Too few arguments for TypeVar() b = TypeVar(x='b') # E: TypeVar() expects a string literal as first argument c = TypeVar(1) # E: TypeVar() expects a string literal as first argument d = TypeVar('D') # E: String argument 1 "D" to TypeVar(...) does not match variable name "d" -e = TypeVar('e', int, str, x=1) # E: Unexpected argument to TypeVar(): "x" +e = TypeVar('e', int, str, x=1) # E: Unexpected argument to "TypeVar()": "x" f = TypeVar('f', (int, str), int) # E: Type expected g = TypeVar('g', int) # E: TypeVar cannot have only a single constraint -h = TypeVar('h', x=(int, str)) # E: Unexpected argument to TypeVar(): "x" +h = TypeVar('h', x=(int, str)) # E: Unexpected argument to "TypeVar()": "x" i = TypeVar('i', bound=1) # E: TypeVar "bound" must be a type +j = TypeVar('j', covariant=None) # E: TypeVar "covariant" may only be a literal bool +k = TypeVar('k', contravariant=1) # E: TypeVar "contravariant" may only be a literal bool [out] [case testMoreInvalidTypevarArguments] @@ -1046,7 +1048,7 @@ S = TypeVar('S', covariant=True, contravariant=True) \ [case testInvalidTypevarValues] from typing import TypeVar -b = TypeVar('b', *[int]) # E: Unexpected argument to TypeVar() +b = TypeVar('b', *[int]) # E: Unexpected argument to "TypeVar()" c = TypeVar('c', int, 2) # E: Invalid type: try using Literal[2] instead? [out] @@ -1426,7 +1428,6 @@ def g() -> None: [out] [case testParamSpec] -# flags: --wip-pep-612 from typing_extensions import ParamSpec TParams = ParamSpec('TParams') diff --git a/test-data/unit/semanal-lambda.test b/test-data/unit/semanal-lambda.test new file mode 100644 index 000000000000..1cde1a794dc2 --- /dev/null +++ b/test-data/unit/semanal-lambda.test @@ -0,0 +1,94 @@ +[case testLambdaInheritsCheckedContextFromFunc] +def g(): + return lambda x: UNDEFINED in x +[out] +MypyFile:1( + FuncDef:1( + g + Block:1( + ReturnStmt:2( + LambdaExpr:2( + Args( + Var(x)) + Block:2( + ReturnStmt:2( + ComparisonExpr:2( + in + NameExpr(UNDEFINED) + NameExpr(x [l]))))))))) + +[case testLambdaInheritsCheckedContextFromFuncForced] +# flags: --check-untyped-defs +def g(): + return lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromTypedFunc] +def g() -> None: + return lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromTypedFuncForced] +# flags: --check-untyped-defs +def g() -> None: + return lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromModule] +g = lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromModuleForce] +# flags: --check-untyped-defs +g = lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromModuleLambdaStack] +g = lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromModuleLambdaStackForce] +# flags: --check-untyped-defs +g = lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromFuncLambdaStack] +def g(): + return lambda: lambda: lambda x: UNDEFINED in x +[out] +MypyFile:1( + FuncDef:1( + g + Block:1( + ReturnStmt:2( + LambdaExpr:2( + Block:2( + ReturnStmt:2( + LambdaExpr:2( + Block:2( + ReturnStmt:2( + LambdaExpr:2( + Args( + Var(x)) + Block:2( + ReturnStmt:2( + ComparisonExpr:2( + in + NameExpr(UNDEFINED) + NameExpr(x [l]))))))))))))))) + +[case testLambdaInheritsCheckedContextFromFuncLambdaStackForce] +# flags: --check-untyped-defs +def g(): + return lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromTypedFuncLambdaStack] +def g() -> None: + return lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromTypedFuncLambdaStackForce] +# flags: --check-untyped-defs +def g() -> None: + return lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromClassLambdaStack] +class A: + g = lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined + +[case testLambdaInheritsCheckedContextFromClassLambdaStackForce] +# flags: --check-untyped-defs +class A: + g = lambda: lambda: lambda x: UNDEFINED in x # E: Name "UNDEFINED" is not defined diff --git a/test-data/unit/semanal-modules.test b/test-data/unit/semanal-modules.test index d81a81c326de..86bb82d7bd69 100644 --- a/test-data/unit/semanal-modules.test +++ b/test-data/unit/semanal-modules.test @@ -206,7 +206,7 @@ MypyFile:1( NameExpr(_n) x [_n.x]))) -[case testAccessingImportedModule] +[case testAccessingImportedModule2] import _m _m._n.x [file _m.py] @@ -385,7 +385,7 @@ MypyFile:1( NameExpr(None [builtins.None]) m._n.c)) -[case testSubmodulesAndTypes] +[case testSubmodulesAndTypes2] from m._n import c x = None # type: c [file m/__init__.py] diff --git a/test-data/unit/semanal-namedtuple.test b/test-data/unit/semanal-namedtuple.test index e018763e7712..df1d5679c892 100644 --- a/test-data/unit/semanal-namedtuple.test +++ b/test-data/unit/semanal-namedtuple.test @@ -145,39 +145,76 @@ MypyFile:1( [case testNamedTupleWithTooFewArguments] from collections import namedtuple -N = namedtuple('N') # E: Too few arguments for namedtuple() +N = namedtuple('N') # E: Too few arguments for "namedtuple()" [builtins fixtures/tuple.pyi] [case testNamedTupleWithInvalidName] from collections import namedtuple -N = namedtuple(1, ['x']) # E: namedtuple() expects a string literal as the first argument +N = namedtuple(1, ['x']) # E: "namedtuple()" expects a string literal as the first argument [builtins fixtures/tuple.pyi] [case testNamedTupleWithInvalidItems] from collections import namedtuple -N = namedtuple('N', 1) # E: List or tuple literal expected as the second argument to namedtuple() +N = namedtuple('N', 1) # E: List or tuple literal expected as the second argument to "namedtuple()" [builtins fixtures/tuple.pyi] [case testNamedTupleWithInvalidItems2] from collections import namedtuple -N = namedtuple('N', ['x', 1]) # E: String literal expected as namedtuple() item +N = namedtuple('N', ['x', 1]) # E: String literal expected as "namedtuple()" item [builtins fixtures/tuple.pyi] [case testNamedTupleWithUnderscoreItemName] from collections import namedtuple -N = namedtuple('N', ['_fallback']) # E: namedtuple() field names cannot start with an underscore: _fallback +N = namedtuple('N', ['_fallback']) # E: "namedtuple()" field names cannot start with an underscore: _fallback [builtins fixtures/tuple.pyi] -- NOTE: The following code works at runtime but is not yet supported by mypy. -- Keyword arguments may potentially be supported in the future. [case testNamedTupleWithNonpositionalArgs] from collections import namedtuple -N = namedtuple(typename='N', field_names=['x']) # E: Unexpected arguments to namedtuple() +N = namedtuple(typename='N', field_names=['x']) # E: Unexpected arguments to "namedtuple()" +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithTooFewArguments] +from typing import NamedTuple +N = NamedTuple('N') # E: Too few arguments for "NamedTuple()" +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithManyArguments] +from typing import NamedTuple +N = NamedTuple('N', [], []) # E: Too many arguments for "NamedTuple()" +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithInvalidName] +from typing import NamedTuple +N = NamedTuple(1, ['x']) # E: "NamedTuple()" expects a string literal as the first argument +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithInvalidItems] +from typing import NamedTuple +N = NamedTuple('N', 1) # E: List or tuple literal expected as the second argument to "NamedTuple()" +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithUnderscoreItemName] +from typing import NamedTuple +N = NamedTuple('N', [('_fallback', int)]) # E: "NamedTuple()" field names cannot start with an underscore: _fallback +[builtins fixtures/tuple.pyi] + +[case testTypingNamedTupleWithUnexpectedNames] +from typing import NamedTuple +N = NamedTuple(name='N', fields=[]) # E: Unexpected arguments to "NamedTuple()" +[builtins fixtures/tuple.pyi] + +-- NOTE: The following code works at runtime but is not yet supported by mypy. +-- Keyword arguments may potentially be supported in the future. +[case testNamedTupleWithNonpositionalArgs2] +from collections import namedtuple +N = namedtuple(typename='N', field_names=['x']) # E: Unexpected arguments to "namedtuple()" [builtins fixtures/tuple.pyi] [case testInvalidNamedTupleBaseClass] from typing import NamedTuple -class A(NamedTuple('N', [1])): pass # E: Tuple expected as NamedTuple() field +class A(NamedTuple('N', [1])): pass # E: Tuple expected as "NamedTuple()" field class B(A): pass [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/semanal-typealiases.test b/test-data/unit/semanal-typealiases.test index 0f16754e0959..debc7ecdf722 100644 --- a/test-data/unit/semanal-typealiases.test +++ b/test-data/unit/semanal-typealiases.test @@ -219,7 +219,7 @@ MypyFile:1( ClassDef:3( G TypeVars( - T) + T`1) PassStmt:3()) AssignmentStmt:4( NameExpr(A* [__main__.A]) diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index 19d2d037e032..772de61b5900 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -188,7 +188,7 @@ MypyFile:1( ClassDef:5( A TypeVars( - t) + t`1) PassStmt:5()) ClassDef:6( B @@ -221,8 +221,8 @@ MypyFile:1( ClassDef:4( A TypeVars( - t - s) + t`1 + s`2) PassStmt:4()) ClassDef:5( B @@ -284,7 +284,7 @@ MypyFile:1( ClassDef:4( d TypeVars( - t) + t`1) PassStmt:4()) ExpressionStmt:5( CastExpr:5( @@ -348,8 +348,8 @@ MypyFile:1( ClassDef:4( C TypeVars( - t - s) + t`1 + s`2) PassStmt:4()) ExpressionStmt:5( CastExpr:5( @@ -450,7 +450,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) FuncDef:4( f @@ -476,7 +476,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) FuncDef:4( f @@ -500,7 +500,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) FuncDef:4( f @@ -524,7 +524,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) FuncDef:4( f @@ -603,7 +603,7 @@ MypyFile:1( ClassDef:5( c TypeVars( - t) + t`1) FuncDef:6( f Args( @@ -632,8 +632,8 @@ MypyFile:1( ClassDef:6( c TypeVars( - t - s) + t`1 + s`2) FuncDef:7( f Args( @@ -657,12 +657,12 @@ MypyFile:1( ClassDef:3( d TypeVars( - t) + t`1) PassStmt:3()) ClassDef:4( c TypeVars( - t) + t`1) BaseType( __main__.d[t`1]) PassStmt:4())) @@ -876,8 +876,8 @@ MypyFile:1( ClassDef:4( A TypeVars( - t - s) + t`1 + s`2) PassStmt:4()) AssignmentStmt:5( NameExpr(x [__main__.x]) @@ -902,12 +902,12 @@ MypyFile:1( ClassDef:4( B TypeVars( - s) + s`1) PassStmt:4()) ClassDef:5( A TypeVars( - t) + t`1) BaseType( __main__.B[Any]) PassStmt:5())) @@ -926,7 +926,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) AssignmentStmt:4( NameExpr(x* [__main__.x]) @@ -955,8 +955,8 @@ MypyFile:1( ClassDef:4( A TypeVars( - t - s) + t`1 + s`2) PassStmt:4()) AssignmentStmt:5( NameExpr(x* [__main__.x]) @@ -1009,7 +1009,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - t) + t`1) PassStmt:3()) ExpressionStmt:4( CallExpr:4( @@ -1051,7 +1051,7 @@ MypyFile:1( ClassDef:4( A TypeVars( - T) + T`1) PassStmt:4())) [case testQualifiedTypevar] @@ -1149,7 +1149,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - T) + T`1) AssignmentStmt:4( NameExpr(y [m]) NameExpr(None [builtins.None]) @@ -1172,7 +1172,7 @@ MypyFile:1( ClassDef:3( A TypeVars( - _m.T) + _m.T`1) AssignmentStmt:4( NameExpr(a [m]) NameExpr(None [builtins.None]) @@ -1284,6 +1284,35 @@ MypyFile:1( builtins.int builtins.str)))) +[case testTypevarWithFalseVariance] +from typing import TypeVar +T1 = TypeVar('T1', covariant=False) +T2 = TypeVar('T2', covariant=False, contravariant=False) +T3 = TypeVar('T3', contravariant=False) +T4 = TypeVar('T4', covariant=True, contravariant=False) +T5 = TypeVar('T5', covariant=False, contravariant=True) +[builtins fixtures/bool.pyi] +[out] +MypyFile:1( + ImportFrom:1(typing, [TypeVar]) + AssignmentStmt:2( + NameExpr(T1* [__main__.T1]) + TypeVarExpr:2()) + AssignmentStmt:3( + NameExpr(T2* [__main__.T2]) + TypeVarExpr:3()) + AssignmentStmt:4( + NameExpr(T3* [__main__.T3]) + TypeVarExpr:4()) + AssignmentStmt:5( + NameExpr(T4* [__main__.T4]) + TypeVarExpr:5( + Variance(COVARIANT))) + AssignmentStmt:6( + NameExpr(T5* [__main__.T5]) + TypeVarExpr:6( + Variance(CONTRAVARIANT)))) + [case testTypevarWithBound] from typing import TypeVar T = TypeVar('T', bound=int) @@ -1332,7 +1361,7 @@ MypyFile:1( ClassDef:3( C TypeVars( - T in (builtins.int, builtins.str)) + T`1) PassStmt:3())) [case testGenericFunctionWithBound] @@ -1368,7 +1397,7 @@ MypyFile:1( ClassDef:3( C TypeVars( - T <: builtins.int) + T`1) PassStmt:3())) [case testSimpleDucktypeDecorator] @@ -1500,12 +1529,11 @@ MypyFile:1( [case testParamSpec] -# flags: --wip-pep-612 from typing import ParamSpec P = ParamSpec("P") [out] MypyFile:1( - ImportFrom:2(typing, [ParamSpec]) - AssignmentStmt:3( + ImportFrom:1(typing, [ParamSpec]) + AssignmentStmt:2( NameExpr(P* [__main__.P]) - ParamSpecExpr:3())) + ParamSpecExpr:2())) diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index cfcd13eb45ad..e20073027db2 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -15,26 +15,22 @@ def f(a, b): def g(arg): pass [out] -from typing import Any - -def f(a: Any, b: Any) -> None: ... -def g(arg: Any) -> None: ... +def f(a, b) -> None: ... +def g(arg) -> None: ... [case testDefaultArgInt] def f(a, b=2): ... def g(b=-1, c=0): ... [out] -from typing import Any - -def f(a: Any, b: int = ...) -> None: ... +def f(a, b: int = ...) -> None: ... def g(b: int = ..., c: int = ...) -> None: ... [case testDefaultArgNone] def f(x=None): ... [out] -from typing import Any, Optional +from typing import Any -def f(x: Optional[Any] = ...) -> None: ... +def f(x: Any | None = ...) -> None: ... [case testDefaultArgBool] def f(x=True, y=False): ... @@ -59,14 +55,33 @@ def f(x: float = ...) -> None: ... [case testDefaultArgOther] def f(x=ord): ... [out] -from typing import Any - -def f(x: Any = ...) -> None: ... +def f(x=...) -> None: ... [case testPreserveFunctionAnnotation] def f(x: Foo) -> Bar: ... +def g(x: Foo = Foo()) -> Bar: ... [out] def f(x: Foo) -> Bar: ... +def g(x: Foo = ...) -> Bar: ... + +[case testPreserveFunctionAnnotationWithArgs] +def f(x: foo['x']) -> bar: ... +def g(x: foo[x]) -> bar: ... +def h(x: foo['x', 'y']) -> bar: ... +def i(x: foo[x, y]) -> bar: ... +def j(x: foo['x', y]) -> bar: ... +def k(x: foo[x, 'y']) -> bar: ... +def lit_str(x: Literal['str']) -> Literal['str']: ... +def lit_int(x: Literal[1]) -> Literal[1]: ... +[out] +def f(x: foo['x']) -> bar: ... +def g(x: foo[x]) -> bar: ... +def h(x: foo['x', 'y']) -> bar: ... +def i(x: foo[x, y]) -> bar: ... +def j(x: foo['x', y]) -> bar: ... +def k(x: foo[x, 'y']) -> bar: ... +def lit_str(x: Literal['str']) -> Literal['str']: ... +def lit_int(x: Literal[1]) -> Literal[1]: ... [case testPreserveVarAnnotation] x: Foo @@ -81,16 +96,12 @@ x: Foo [case testVarArgs] def f(x, *y): ... [out] -from typing import Any - -def f(x: Any, *y: Any) -> None: ... +def f(x, *y) -> None: ... [case testKwVarArgs] def f(x, **y): ... [out] -from typing import Any - -def f(x: Any, **y: Any) -> None: ... +def f(x, **y) -> None: ... [case testVarArgsWithKwVarArgs] def f(a, *b, **c): ... @@ -99,13 +110,11 @@ def h(a, *b, c=1, **d): ... def i(a, *, b=1): ... def j(a, *, b=1, **c): ... [out] -from typing import Any - -def f(a: Any, *b: Any, **c: Any) -> None: ... -def g(a: Any, *b: Any, c: int = ...) -> None: ... -def h(a: Any, *b: Any, c: int = ..., **d: Any) -> None: ... -def i(a: Any, *, b: int = ...) -> None: ... -def j(a: Any, *, b: int = ..., **c: Any) -> None: ... +def f(a, *b, **c) -> None: ... +def g(a, *b, c: int = ...) -> None: ... +def h(a, *b, c: int = ..., **d) -> None: ... +def i(a, *, b: int = ...) -> None: ... +def j(a, *, b: int = ..., **c) -> None: ... [case testClass] class A: @@ -113,10 +122,8 @@ class A: x = 1 def g(): ... [out] -from typing import Any - class A: - def f(self, x: Any) -> None: ... + def f(self, x) -> None: ... def g() -> None: ... @@ -161,7 +168,7 @@ class C: x = 1 [out] class C: - x: int = ... + x: int [case testInitTypeAnnotationPreserved] class C: @@ -178,7 +185,7 @@ class C: x.y = 2 [out] class C: - x: int = ... + x: int def __init__(self) -> None: ... [case testSelfAndClassBodyAssignment] @@ -192,7 +199,7 @@ class C: x: int class C: - x: int = ... + x: int def __init__(self) -> None: ... [case testEmptyClass] @@ -244,7 +251,7 @@ class A: _x: int class A: - _y: int = ... + _y: int [case testSpecialInternalVar] __all__ = [] @@ -263,9 +270,7 @@ class B(A): ... @decorator def foo(x): ... [out] -from typing import Any - -def foo(x: Any) -> None: ... +def foo(x) -> None: ... [case testMultipleAssignment] x, y = 1, 2 @@ -293,10 +298,8 @@ y: Any def f(x, *, y=1): ... def g(x, *, y=1, z=2): ... [out] -from typing import Any - -def f(x: Any, *, y: int = ...) -> None: ... -def g(x: Any, *, y: int = ..., z: int = ...) -> None: ... +def f(x, *, y: int = ...) -> None: ... +def g(x, *, y: int = ..., z: int = ...) -> None: ... [case testProperty] class A: @@ -309,13 +312,11 @@ class A: def h(self): self.f = 1 [out] -from typing import Any - class A: @property def f(self): ... @f.setter - def f(self, x: Any) -> None: ... + def f(self, x) -> None: ... def h(self) -> None: ... [case testStaticMethod] @@ -323,11 +324,9 @@ class A: @staticmethod def f(x): ... [out] -from typing import Any - class A: @staticmethod - def f(x: Any) -> None: ... + def f(x) -> None: ... [case testClassMethod] class A: @@ -390,10 +389,8 @@ class A: def __getstate__(self): ... def __setstate__(self, state): ... [out] -from typing import Any - class A: - def __eq__(self) -> Any: ... + def __eq__(self): ... -- Tests that will perform runtime imports of modules. -- Don't use `_import` suffix if there are unquoted forward references. @@ -438,7 +435,7 @@ class A: def f(self): ... [out] class A: - x: int = ... + x: int def f(self) -> None: ... [case testSkipMultiplePrivateDefs] @@ -486,7 +483,7 @@ import re as re x: int -[case testExportModule_import] +[case testExportModule2_import] import re __all__ = ['re', 'x'] x = 1 @@ -591,18 +588,52 @@ class A: import collections, x X = collections.namedtuple('X', ['a', 'b']) [out] -from collections import namedtuple +from typing import Any, NamedTuple -X = namedtuple('X', ['a', 'b']) +class X(NamedTuple): + a: Any + b: Any + +[case testEmptyNamedtuple] +import collections +X = collections.namedtuple('X', []) +[out] +from typing import NamedTuple + +class X(NamedTuple): ... [case testNamedtupleAltSyntax] from collections import namedtuple, xx X = namedtuple('X', 'a b') xx [out] -from collections import namedtuple +from typing import Any, NamedTuple -X = namedtuple('X', 'a b') +class X(NamedTuple): + a: Any + b: Any + +[case testNamedtupleAltSyntaxUsingComma] +from collections import namedtuple, xx +X = namedtuple('X', 'a, b') +xx +[out] +from typing import Any, NamedTuple + +class X(NamedTuple): + a: Any + b: Any + +[case testNamedtupleAltSyntaxUsingMultipleCommas] +from collections import namedtuple, xx +X = namedtuple('X', 'a,, b') +xx +[out] +from typing import Any, NamedTuple + +class X(NamedTuple): + a: Any + b: Any [case testNamedtupleWithUnderscore] from collections import namedtuple as _namedtuple @@ -610,11 +641,13 @@ def f(): ... X = _namedtuple('X', 'a b') def g(): ... [out] -from collections import namedtuple +from typing import Any, NamedTuple def f() -> None: ... -X = namedtuple('X', 'a b') +class X(NamedTuple): + a: Any + b: Any def g() -> None: ... @@ -623,9 +656,11 @@ import collections, x _X = collections.namedtuple('_X', ['a', 'b']) class Y(_X): ... [out] -from collections import namedtuple +from typing import Any, NamedTuple -_X = namedtuple('_X', ['a', 'b']) +class _X(NamedTuple): + a: Any + b: Any class Y(_X): ... @@ -636,13 +671,19 @@ Y = namedtuple('Y', ('a',)) Z = namedtuple('Z', ('a', 'b', 'c', 'd', 'e')) xx [out] -from collections import namedtuple +from typing import Any, NamedTuple -X = namedtuple('X', []) +class X(NamedTuple): ... -Y = namedtuple('Y', ['a']) +class Y(NamedTuple): + a: Any -Z = namedtuple('Z', ['a', 'b', 'c', 'd', 'e']) +class Z(NamedTuple): + a: Any + b: Any + c: Any + d: Any + e: Any [case testDynamicNamedTuple] from collections import namedtuple @@ -660,7 +701,7 @@ import x class D(x.C): ... -[case testArbitraryBaseClass] +[case testArbitraryBaseClass2] import x.y class D(x.y.C): ... [out] @@ -720,7 +761,7 @@ class A: [out] class A: class B: - x: int = ... + x: int def f(self) -> None: ... def g(self) -> None: ... @@ -752,17 +793,13 @@ class A(X): ... def syslog(a): pass def syslog(a): pass [out] -from typing import Any - -def syslog(a: Any) -> None: ... +def syslog(a) -> None: ... [case testAsyncAwait_fast_parser] async def f(a): x = await y [out] -from typing import Any - -async def f(a: Any) -> None: ... +async def f(a) -> None: ... [case testInferOptionalOnlyFunc] class A: @@ -772,12 +809,12 @@ class A: def method(self, a=None): self.x = [] [out] -from typing import Any, Optional +from typing import Any class A: - x: Any = ... - def __init__(self, a: Optional[Any] = ...) -> None: ... - def method(self, a: Optional[Any] = ...) -> None: ... + x: Any + def __init__(self, a: Any | None = ...) -> None: ... + def method(self, a: Any | None = ...) -> None: ... [case testAnnotationImportsFrom] import foo @@ -800,7 +837,7 @@ import collections x: collections.defaultdict -[case testAnnotationImports] +[case testAnnotationImports2] from typing import List import collections x: List[collections.defaultdict] @@ -911,7 +948,7 @@ class Foo: from typing import Any class Foo: - alias: Any = ... + alias: Any [case testAliasExceptions] noalias1 = None @@ -948,6 +985,56 @@ def f(): ... [out] def f() -> None: ... +[case testFunctionYields] +def f(): + yield 123 +def g(): + x = yield +def h1(): + yield + return +def h2(): + yield + return "abc" +def all(): + x = yield 123 + return "abc" +[out] +from collections.abc import Generator +from typing import Any + +def f() -> Generator[Any, None, None]: ... +def g() -> Generator[None, Any, None]: ... +def h1() -> Generator[None, None, None]: ... +def h2() -> Generator[None, None, Any]: ... +def all() -> Generator[Any, Any, Any]: ... + +[case testFunctionYieldsNone] +def f(): + yield +def g(): + yield None + +[out] +from collections.abc import Generator + +def f() -> Generator[None, None, None]: ... +def g() -> Generator[None, None, None]: ... + +[case testGeneratorAlreadyDefined] +class Generator: + pass + +def f(): + yield 123 +[out] +from collections.abc import Generator as _Generator +from typing import Any + +class Generator: ... + +def f() -> _Generator[Any, None, None]: ... + [case testCallable] from typing import Callable @@ -1505,11 +1592,10 @@ class Base(metaclass=ABCMeta): import abc from abc import abstractmethod from base import Base -from typing import Any class C(Base, metaclass=abc.ABCMeta): @abstractmethod - def other(self) -> Any: ... + def other(self): ... [case testInvalidNumberOfArgsInAnnotation] def f(x): @@ -1517,9 +1603,7 @@ def f(x): return '' [out] -from typing import Any - -def f(x: Any): ... +def f(x): ... [case testFunctionPartiallyAnnotated] def f(x) -> None: @@ -1533,13 +1617,45 @@ class A: pass [out] +def f(x) -> None: ... +def g(x, y: str): ... + +class A: + def f(self, x) -> None: ... + +[case testExplicitAnyArg] from typing import Any -def f(x: Any) -> None: ... -def g(x: Any, y: str) -> Any: ... +def f(x: Any): + pass +def g(x, y: Any) -> str: + pass +def h(x: Any) -> str: + pass -class A: - def f(self, x: Any) -> None: ... +[out] +from typing import Any + +def f(x: Any): ... +def g(x, y: Any) -> str: ... +def h(x: Any) -> str: ... + +[case testExplicitReturnedAny] +from typing import Any + +def f(x: str) -> Any: + pass +def g(x, y: str) -> Any: + pass +def h(x) -> Any: + pass + +[out] +from typing import Any + +def f(x: str) -> Any: ... +def g(x, y: str) -> Any: ... +def h(x) -> Any: ... [case testPlacementOfDecorators] class A: @@ -1558,19 +1674,17 @@ class B: self.y = 'y' [out] -from typing import Any - class A: - y: str = ... + y: str @property def x(self): ... class B: @property def x(self): ... - y: str = ... + y: str @x.setter - def x(self, value: Any) -> None: ... + def x(self, value) -> None: ... [case testMisplacedTypeComment] def f(): @@ -1644,12 +1758,11 @@ class A: [out] import abc -from typing import Any class A(metaclass=abc.ABCMeta): @property @abc.abstractmethod - def x(self) -> Any: ... + def x(self): ... [case testAbstractProperty2_semanal] import other @@ -1661,12 +1774,11 @@ class A: [out] import abc -from typing import Any class A(metaclass=abc.ABCMeta): @property @abc.abstractmethod - def x(self) -> Any: ... + def x(self): ... [case testAbstractProperty3_semanal] import other @@ -1678,16 +1790,14 @@ class A: [out] import abc -from typing import Any class A(metaclass=abc.ABCMeta): @property @abc.abstractmethod - def x(self) -> Any: ... + def x(self): ... [case testClassWithNameAnyOrOptional] -def f(x=object()): - return 1 +Y = object() def g(x=None): pass @@ -1700,10 +1810,11 @@ def Optional(): return 0 [out] -from typing import Any as _Any, Optional as _Optional +from typing import Any as _Any -def f(x: _Any = ...): ... -def g(x: _Optional[_Any] = ...) -> None: ... +Y: _Any + +def g(x: _Any | None = ...) -> None: ... x: _Any @@ -1836,9 +1947,7 @@ def g() -> None: ... def f(x, y): pass [out] -from typing import Any - -def f(x: Any, y: Any) -> None: ... +def f(x, y) -> None: ... [case testImportedModuleExits_import] # modules: a b c @@ -2174,12 +2283,12 @@ class C: from typing import Any class C: - x: Any = ... - def __init__(self, x: Any) -> None: ... - def __lt__(self, other: Any) -> Any: ... - def __le__(self, other: Any) -> Any: ... - def __gt__(self, other: Any) -> Any: ... - def __ge__(self, other: Any) -> Any: ... + x: Any + def __init__(self, x) -> None: ... + def __lt__(self, other): ... + def __le__(self, other): ... + def __gt__(self, other): ... + def __ge__(self, other): ... [case testNamedTupleInClass] from collections import namedtuple @@ -2187,10 +2296,12 @@ from collections import namedtuple class C: N = namedtuple('N', ['x', 'y']) [out] -from collections import namedtuple +from typing import Any, NamedTuple class C: - N = namedtuple('N', ['x', 'y']) + class N(NamedTuple): + x: Any + y: Any [case testImports_directImportsWithAlias] import p.a as a diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index deb43f6d316f..7a0115f17e9c 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -247,7 +247,7 @@ elif not a: [out] NameExpr(3) : builtins.bool IntExpr(4) : Literal[1]? -NameExpr(5) : builtins.bool +NameExpr(5) : Literal[False] UnaryExpr(5) : builtins.bool IntExpr(6) : Literal[1]? @@ -259,7 +259,7 @@ while a: [builtins fixtures/bool.pyi] [out] NameExpr(3) : builtins.bool -NameExpr(4) : builtins.bool +NameExpr(4) : Literal[True] -- Simple type inference @@ -727,7 +727,7 @@ f = lambda: [1] LambdaExpr(3) : def () -> builtins.list[builtins.int] NameExpr(3) : def () -> builtins.list[builtins.int] -[case testLambdaWithInferredType2] +[case testLambdaWithInferredType3] from typing import List, Callable f = lambda x: [] # type: Callable[[B], List[A]] class A: pass diff --git a/test-requirements.txt b/test-requirements.txt index 2d83221c2f7a..c5db79ada816 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,18 +1,17 @@ -r mypy-requirements.txt -r build-requirements.txt attrs>=18.0 -flake8>=3.8.1 -flake8-bugbear; python_version >= '3.5' -flake8-pyi>=20.5; python_version >= '3.6' +flake8==3.9.2 +flake8-bugbear +flake8-pyi>=20.5 lxml>=4.4.0 psutil>=4.0 -# pytest 6.2 does not support Python 3.5 -pytest>=6.1.0,<6.2.0 +pytest>=6.2.0,<7.0.0 pytest-xdist>=1.34.0,<2.0.0 pytest-forked>=1.3.0,<2.0.0 pytest-cov>=2.10.0,<3.0.0 -typing>=3.5.2; python_version < '3.5' py>=1.5.2 -virtualenv<20 +typed_ast>=1.4.0,<2; python_version>='3.8' +virtualenv>=20.6.0 setuptools!=50 -importlib-metadata==0.20 +importlib-metadata>=4.6.1,<5.0.0 diff --git a/tox.ini b/tox.ini index ac7cdc72fdb7..44334688b0ad 100644 --- a/tox.ini +++ b/tox.ini @@ -51,7 +51,7 @@ description = type check ourselves basepython = python3.7 commands = python -m mypy --config-file mypy_self_check.ini -p mypy -p mypyc - python -m mypy --config-file mypy_self_check.ini misc/proper_plugin.py scripts/mypyc + python -m mypy --config-file mypy_self_check.ini misc/proper_plugin.py [testenv:docs] description = invoke sphinx-build to build the HTML docs