Git Product home page Git Product logo

typeshed's Introduction

typeshed

Tests Chat at https://gitter.im/python/typing Pull Requests Welcome

About

Typeshed contains external type annotations for the Python standard library and Python builtins, as well as third party packages as contributed by people external to those projects.

This data can e.g. be used for static analysis, type checking, type inference, and autocompletion.

For information on how to use typeshed, read below. Information for contributors can be found in CONTRIBUTING.md. Please read it before submitting pull requests; do not report issues with annotations to the project the stubs are for, but instead report them here to typeshed.

Further documentation on stub files, typeshed, and Python's typing system in general, can also be found at https://typing.readthedocs.io/en/latest/.

Typeshed supports Python versions 3.8 and up.

Using

If you're just using a type checker (mypy, pyright, pytype, PyCharm, ...), as opposed to developing it, you don't need to interact with the typeshed repo at all: a copy of standard library part of typeshed is bundled with type checkers. And type stubs for third party packages and modules you are using can be installed from PyPI. For example, if you are using html5lib and requests, you can install the type stubs using

$ pip install types-html5lib types-requests

These PyPI packages follow PEP 561 and are automatically released (up to once a day) by typeshed internal machinery.

Type checkers should be able to use these stub packages when installed. For more details, see the documentation for your type checker.

Package versioning for third-party stubs

Version numbers of third-party stub packages consist of at least four parts. All parts of the stub version, except for the last part, correspond to the version of the runtime package being stubbed. For example, if the types-foo package has version 1.2.0.20240309, this guarantees that the types-foo package contains stubs targeted against foo==1.2.* and tested against the latest version of foo matching that specifier. In this example, the final element of the version number (20240309) indicates that the stub package was pushed on March 9, 2024.

At typeshed, we try to keep breaking changes to a minimum. However, due to the nature of stubs, any version bump can introduce changes that might make your code fail to type check.

There are several strategies available for specifying the version of a stubs package you're using, each with its own tradeoffs:

  1. Use the same bounds that you use for the package being stubbed. For example, if you use requests>=2.30.0,<2.32, you can use types-requests>=2.30.0,<2.32. This ensures that the stubs are compatible with the package you are using, but it carries a small risk of breaking type checking due to changes in the stubs.

    Another risk of this strategy is that stubs often lag behind the package being stubbed. You might want to force the package being stubbed to a certain minimum version because it fixes a critical bug, but if correspondingly updated stubs have not been released, your type checking results may not be fully accurate.

  2. Pin the stubs to a known good version and update the pin from time to time (either manually, or using a tool such as dependabot or renovate).

    For example, if you use types-requests==2.31.0.1, you can have confidence that upgrading dependencies will not break type checking. However, you will miss out on improvements in the stubs that could potentially improve type checking until you update the pin. This strategy also has the risk that the stubs you are using might become incompatible with the package being stubbed.

  3. Don't pin the stubs. This is the option that demands the least work from you when it comes to updating version pins, and has the advantage that you will automatically benefit from improved stubs whenever a new version of the stubs package is released. However, it carries the risk that the stubs become incompatible with the package being stubbed.

    For example, if a new major version of the package is released, there's a chance the stubs might be updated to reflect the new version of the runtime package before you update the package being stubbed.

You can also switch between the different strategies as needed. For example, you could default to strategy (1), but fall back to strategy (2) when a problem arises that can't easily be fixed.

The _typeshed package

typeshed includes a package _typeshed as part of the standard library. This package and its submodules contain utility types, but are not available at runtime. For more information about how to use this package, see the stdlib/_typeshed directory.

Discussion

If you've run into behavior in the type checker that suggests the type stubs for a given library are incorrect or incomplete, we want to hear from you!

Our main forum for discussion is the project's GitHub issue tracker. This is the right place to start a discussion of any of the above or most any other topic concerning the project.

If you have general questions about typing with Python, or you need a review of your type annotations or stubs outside of typeshed, head over to our discussion forum. For less formal discussion, try the typing chat room on gitter.im. Some typeshed maintainers 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.

typeshed's People

Contributors

adamtheturtle avatar akuli avatar alexwaygood avatar alvarocaceres avatar asottile avatar avasam avatar craftspider avatar erictraut avatar euresti avatar github-actions[bot] avatar gruebel avatar gvanrossum avatar hamdanal avatar hatal175 avatar hauntsaninja avatar ilevkivskyi avatar ismail-s avatar jellezijlstra avatar jukkal avatar kasium avatar matthiaskramm avatar michael0x2a avatar msullivan avatar nipunn1313 avatar rchen152 avatar sobolevn avatar sproshev avatar srittau avatar tharvik avatar timabbott avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typeshed's Issues

Tornado module for Python 2.7 broken locally in tests

Running with Python 3.5.1 on OS X, I get:

$ python3 runtests.py
running mypy --python-version 3.5 # with 243 files
running mypy --python-version 3.4 # with 243 files
running mypy --python-version 3.3 # with 229 files
running mypy --python-version 3.2 # with 228 files
running mypy --python-version 2.7 # with 330 files
third_party/2.7/sqlalchemy/sql/base.pyi:4: note: In module imported here,
third_party/2.7/sqlalchemy/engine/strategies.pyi:6: note: ... from here:
third_party/2.7/tornado/util.pyi:1: error: Duplicate module named '.util'
--- exit status 1 ---

Stub versioning

Several people have expressed interest in versioning stub files.

Here are some reasons:

  • A library maintainer is worried that stubs maintained by 3rd parties for his or her library will get out of date, and people will complain to the library maintainer instead of the one who maintains the stubs.
  • A new version of a library breaks compatibility with earlier versions and it's no longer possible to use the same stub with all version of the library in any meaningful way.

Support partial/incomplete stubs

Maybe we should have a way of specifying a stub as (potentially) incomplete for libraries that are changing rapidly and there is no dedicated maintainer for the stub. In cases like this a type checker / inferencer would either treat all names as implicitly defined in the module (with type Any), or it could parse the actual main Python implementation and merge the annotations from the stubs to the full module AST.

What if some versions of a library have inline stubs?

Tornado is considering the release of a version of Tornado with inline annotations. That's great! But because the rule for type checkers is to prefer stubs over .py files, those inline annotations won't be used when type-checking applications using typeshed, because typeshed has its own Tornado stubs.

It would be good to create a convention for this, but I don't know how. Maybe we could solve it with some path magic?

Specify how to annotate variable types

We should probably have a single convention for attribute and module-level variable annotations that would at least be recommended (even if other ways would also work).

Here are some potential approaches:

  • x = 0, x = '', etc. (at least for built-in types)
  • x = Undefined(int)
  • x = Undefined # type: int
  • # var x: int (a proposal for PEP 484, still under discussion)
  • x = ClassName()

os.path should use AnyStr, not unicode

os.path currently defines everything as using unicode. But most functions accept both str and unicode.
E.g. os.path.isdir uses os.stat() underneath, which does PyArg_ParseTuple(args, "et"). Hence it supports str and unicode. (And character buffer objects, for that matter)

os.path should use AnyStr.

how to type check the xml element class

I have been adding type hints to the xml module on this branch. Now, the Element class has one mandatory param which shoud be a str or bytes. But at in the Comment function the Comment function itself is passed in instead, and then this is used later on to identify that an element is a comment. An interesting way of checking this imo, but is there any way of dealing with thisʔ Atm, this will just mean the xml module will fail its own type check.

Also, if this issue should have been raised elsewhere, let me know.

Potentially merge Python 2 and 3 stubs for many modules

We'd need to add aliases for string-like types such as str/bytes/unicode, and these would be different between Python 2 and 3. We'd need to decide where to define the type aliases, either in the stub of the module that uses them or in a shared typeshed-related (?) module that is only available as a stub.

Add Generator to typing.pyi

PEP 484 defines Generator, a subclass of Iterator that can be used as the return type for generators for which you want to use send() and/or get a return value (with yield from). This needs to be added to the typing.pyi stubs. I'm not 100% sure that this won't require changes to mypy, for which I added python/mypy#1011.

runtests.py trips over sqlalchemy

Running runtests.py locally using python3 runtests.py, I get:

running mypy --python-version 3.5 # with 250 files
running mypy --python-version 3.4 # with 250 files
running mypy --python-version 3.3 # with 236 files
running mypy --python-version 3.2 # with 235 files
running mypy --python-version 2.7 # with 334 files
third_party/2.7/sqlalchemy/engine/url.pyi:8: error: "module" has no attribute "registry"
third_party/2.7/sqlalchemy/orm/__init__.pyi:6: error: Module has no attribute 'mapper'
third_party/2.7/sqlalchemy/orm/__init__.pyi:7: error: Module has no attribute 'interfaces'
third_party/2.7/sqlalchemy/orm/__init__.pyi:8: error: Module has no attribute 'deprecated_i
nterfaces'
third_party/2.7/sqlalchemy/orm/__init__.pyi:9: error: Module has no attribute 'util'
third_party/2.7/sqlalchemy/orm/__init__.pyi:10: error: Module has no attribute 'properties'
third_party/2.7/sqlalchemy/orm/__init__.pyi:11: error: Module has no attribute 'relationshi
ps'
third_party/2.7/sqlalchemy/orm/__init__.pyi:12: error: Module has no attribute 'descriptor_
props'
third_party/2.7/sqlalchemy/orm/__init__.pyi:14: error: Module has no attribute 'scoping'
third_party/2.7/sqlalchemy/orm/__init__.pyi:15: error: Module has no attribute 'query'
third_party/2.7/sqlalchemy/orm/__init__.pyi:17: error: Module has no attribute 'strategy_op
tions'
third_party/2.7/sqlalchemy/orm/__init__.pyi:46: error: "module" has no attribute "object_se
ssion"
third_party/2.7/sqlalchemy/orm/__init__.pyi:48: error: "module" has no attribute "make_tran
sient"
third_party/2.7/sqlalchemy/orm/__init__.pyi:49: error: "module" has no attribute "make_tran
sient_to_detached"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:12: error: "module" has no attribute "co
mpiler"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:13: error: "module" has no attribute "re
flection"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:14: error: "module" has no attribute "de
fault"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:15: error: "module" has no attribute "to
pological"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:31: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:35: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:39: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:47: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:50: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:54: error: Invalid type "sqlalc[33/9160]
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:62: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:66: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:71: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:75: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:87: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:91: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:97: error: Invalid type "sqlalchemy.dial
ects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:103: error: Invalid type "sqlalchemy.dia
lects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:108: error: Invalid type "sqlalchemy.dia
lects.mysql.base.sqltypes"
third_party/2.7/sqlalchemy/dialects/mysql/base.pyi:113: error: Invalid type "sqlalchemy.dia
lects.mysql.base.sqltypes"
[...]
third_party/2.7/sqlalchemy/dialects/mysql/__init__.pyi:40: error: "module" has no attribute "dialect"

Is sqlalchemy still broken, like #14 seems to imply? How come Travis isn't yelling at us?

class instance has `__dict__`

class A:
    pass
A().__dict__

is a valid python3 statement but mypy (more a typeshed issue I guess) gives me

file:4: error: "A" has no attribute "__dict__"

So I modified added, in object, __dict__ = ... # type: Dict[str, Any] to stdlib/3/builtins.pyi which indeed make it warning-less.

But, it is wrong, as

object().__dict__

fail with an AttributeError.

Is there a better place to put this __dict__? Or is it a mypy issue?

json's stubs are incomplete

I just noticed that the stubs for json.dump and json.dumps do not include some of the keyword arguments, like indent.

OOT until Nov 30th

I'll be out of town until after Thanksgiving. I'll look at any new pull requests and/or issues once I get back.

Migrating stubs from other repositories

These may include sources like PyCharm, mypy, pytypedecl, etc. We may also want to formally review at least some of the stubs before committing to make sure that they conform to the typeshed conventions.

If the same stubs is available from multiple sources, we'd probably want to start with the most complete/precise ones. We also want to keep Python 2 and 3 stubs for each module reasonably similar, but this is not absolutely necessary.

invalid syntax in builtins

The PEP 484 section on stub files says that stub files have the same syntax as Python files. Typeshed conforms to this spec except in one place in builtins.pyi:

True = ...  # type: bool
False = ...  # type: bool
__debug__ = False

This is a "can't assign to keyword" syntax error.

I propose we remove these three lines from typeshed to make it PEP 484 compliant. This means that type checkers will have to hard code their knowledge that True, False, and __debug__ are bools, which seems reasonable.

Complete six.moves

There are a bunch of six.moves submodules (and other things) that aren't supported yet because there are no stubs yet for the module to which they refer. We should remember to update six.moves whenever we add stubs for such a module.

References:

  • Unmerged PR that added everything: #21
  • Merged PR that added only those items that work: #61
  • Issue with a list of things to do: #22
  • Tool that generated the initial PR (I think): https://github.com/o11c/stubtool

argparse.Namespace is more complicated than it seems

The argparse.Namespace class stub doesn't reflect its actual complexity -- it has dynamically created attributes based on the parser specification. For example:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--database', type=str, default='data.db')
def foo(args: argparse.Namespace):
    print(args.database)
def main():
    args = parser.parse_args()
    assert args.__class__ is argparse.Namespace
    foo(args)

This gives these errors:

t.py: note: In function "foo":
t.py:5: error: "Namespace" has no attribute "database"

Now, ideally there would be some kind of plugin that understands the parser specification. But I'd be happy if it just didn't complain about using unknown attributes of Namespace objects, while still verifying that the caller indeed passes something of that type (so I don't want to just use Any).

Types that don't exist under their inspected name

Some classes don't exist under their inspected name. I define inspected name as __module__.__qualname__, but only if __qualname__ ends with __name__, else __module__.__name__.

There are several (overlapping) cases:

  • The class comes from C and was never exported.
  • The class comes from Python but was explicitly deleted (or overwritten? Don't Python-originated types get GC'ed if unused nowadays?).
  • The class is available under some other name, e.g. under types.
  • The class can only have a single instance.
  • The class is created local to some function (has .<locals>. in __qualname__), and may be created more than once.
  • There is more than one competing implementation and they share the same name.
  • There is an artificial base class that shares the same name as the subclass.
  • The class is intended to be used as a duck implementation of some interface.

In some cases, later python versions do add a name for the type, but since we need to support all of them, we can't rely on that.

Note that _builtin() means either __builtin__ or builtins, and _collections_abc means either _collections_abc, collections.abc, or _abccoll depending on Python version.

Here is my initial mapping, based on importing every module (except test modules and dummy implementations, and being careful with a few modules that can't be imported in the wrong order) in the standard library (for CPython 2.7 and 3.2 though 3.5), checking every module for top-level attributes, and then finally checking object.__subclasses__. This is actually quite fast, just a few seconds.

type_rename = {
    '<AttributeError>.xxlimited.Null': 'xxlimited.Null',
    '<AttributeError>.xxlimited.Str': 'xxlimited.Str',
    '<AttributeError>.xxlimited.Xxo': '',
    '<unknown>.Purpose': 'ssl.Purpose',
    '__builtin__.BlockingIOError': '_io.BlockingIOError',
    '__builtin__.CArgObject': '',
    '__builtin__.DB': '',
    '__builtin__.DBCursor': '',
    '__builtin__.DBEnv': '',
    '__builtin__.DBLock': '',
    '__builtin__.DBLogCursor': '',
    '__builtin__.DBSequence': '',
    '__builtin__.DBSite': '',
    '__builtin__.DBTxn': '',
    '__builtin__.Element': '',
    '__builtin__.ElementTree': '_elementtree.ElementTree',
    '__builtin__.EncodingMap': '',
    '__builtin__.MultibyteCodec': '',
    '__builtin__.MultibyteIncrementalDecoder': '_multibytecodec.MultibyteIncrementalDecoder',
    '__builtin__.MultibyteIncrementalEncoder': '_multibytecodec.MultibyteIncrementalEncoder',
    '__builtin__.MultibyteStreamReader': '_multibytecodec.MultibyteStreamReader',
    '__builtin__.MultibyteStreamWriter': '_multibytecodec.MultibyteStreamWriter',
    '__builtin__.NoneType': 'types.NoneType',
    '__builtin__.NotImplementedType': 'types.NotImplementedType',
    '__builtin__.PyCapsule': '',
    '__builtin__.StgDict': '',
    '__builtin__.Struct': '_struct.Struct',
    '__builtin__.builtin_function_or_method': 'types.BuiltinFunctionType',
    '__builtin__.callable-iterator': '',
    '__builtin__.cell': '',
    '__builtin__.classobj': 'types.ClassType',
    '__builtin__.code': 'types.CodeType',
    '__builtin__.deque_iterator': '',
    '__builtin__.deque_reverse_iterator': '',
    '__builtin__.dict_items': '',
    '__builtin__.dict_keys': '',
    '__builtin__.dict_values': '',
    '__builtin__.dictionary-keyiterator': '',
    '__builtin__.dictproxy': 'types.DictProxyType',
    '__builtin__.ellipsis': 'types.EllipsisType',
    '__builtin__.fieldnameiterator': '',
    '__builtin__.formatteriterator': '',
    '__builtin__.frame': 'types.FrameType',
    '__builtin__.function': 'types.FunctionType',
    '__builtin__.generator': 'types.GeneratorType',
    '__builtin__.getset_descriptor': 'types.GetSetDescriptorType',
    '__builtin__.instance': 'types.InstanceType',
    '__builtin__.instancemethod': 'types.MethodType',
    '__builtin__.iterator': '',
    '__builtin__.iterparse': '_elementtree.iterparse',
    '__builtin__.member_descriptor': 'types.MemberDescriptorType',
    '__builtin__.method-wrapper': '',
    '__builtin__.method_descriptor': '',
    '__builtin__.module': 'types.ModuleType',
    '__builtin__.sqlite3Node': '',
    '__builtin__.symtable entry': '',
    '__builtin__.test_structmembersType': '_testcapi._test_structmembersType',
    '__builtin__.tkapp': '_tkinter.TkappType',
    '__builtin__.tktimertoken': '_tkinter.TkttType',
    '__builtin__.traceback': 'types.TracebackType',
    '__builtin__.weakcallableproxy': '_weakref.CallableProxyType',
    '__builtin__.weakproxy': '_weakref.ProxyType',
    '__builtin__.weakref': '_weakref.ReferenceType',
    '__builtin__.wrapper_descriptor': '',
    '_csv.reader': '',
    '_csv.writer': '',
    '_ctypes.CField': '',
    '_ctypes.CThunkObject': '',
    '_ctypes.DictRemover': '',
    '_ctypes.PyCArrayType': '_ctypes.Array.__class__',
    '_ctypes.PyCFuncPtr': '_ctypes.CFuncPtr',
    '_ctypes.PyCFuncPtrType': '_ctypes.CFuncPtr.__class__',
    '_ctypes.PyCPointerType': '_ctypes._Pointer.__class__',
    '_ctypes.PyCSimpleType': '_ctypes._SimpleCData.__class__',
    '_ctypes.PyCStructType': '_ctypes.Structure.__class__',
    '_ctypes.UnionType': '_ctypes.Union.__class__',
    '_ctypes._CData': '',
    '_curses.curses window': '',
    '_curses_panel.curses panel': '',
    '_dbm.dbm': '',
    '_elementtree._element_iterator': '',
    '_gdbm.gdbm': '',
    '_hashlib.HASH': '',
    '_io._BytesIOBuffer': '',
    '_json.Encoder': '_json.make_encoder',
    '_json.Scanner': '_json.make_scanner',
    '_pickle.Pdata': '',
    '_pickle.PicklerMemoProxy': '',
    '_pickle.UnpicklerMemoProxy': '',
    '_sre.SRE_Match': '',
    '_sre.SRE_Pattern': 're._pattern_type',
    '_sre.SRE_Scanner': '',
    '_thread._localdummy': '',
    '_thread.lock': '_thread.LockType',
    '_tkinter.tkapp': '_tkinter.TkappType',
    '_tkinter.tktimertoken': '_tkinter.TkttType',
    'abc.SignalDict': '',
    'anydbm.error': '',
    'argparse._ChoicesPseudoAction': '',
    'argparse._Section': '',
    'builtins.BlockingIOError': '_io.BlockingIOError',
    'builtins.CArgObject': '',
    'builtins.CommentProxy': '',
    'builtins.Element': '',
    'builtins.ElementTree': '_elementtree.ElementTree',
    'builtins.EncodingMap': '',
    'builtins.MultibyteCodec': '',
    'builtins.MultibyteIncrementalDecoder': '_multibytecodec.MultibyteIncrementalDecoder',
    'builtins.MultibyteIncrementalEncoder': '_multibytecodec.MultibyteIncrementalEncoder',
    'builtins.MultibyteStreamReader': '_multibytecodec.MultibyteStreamReader',
    'builtins.MultibyteStreamWriter': '_multibytecodec.MultibyteStreamWriter',
    'builtins.NoneType': 'builtins.None.__class__',
    'builtins.NotImplementedType': 'builtins.NotImplemented.__class__',
    'builtins.PIProxy': '',
    'builtins.PyCapsule': '',
    'builtins.StgDict': '',
    'builtins.Struct': '_struct.Struct',
    'builtins.TreeBuilder': '',
    'builtins.XMLParser': '',
    'builtins.builtin_function_or_method': 'types.BuiltinFunctionType',
    'builtins.bytearray_iterator': _collections_abc('bytearray_iterator'),
    'builtins.bytes_iterator': _collections_abc('bytes_iterator'),
    'builtins.callable_iterator': '',
    'builtins.cell': '',
    'builtins.classmethod_descriptor': '', # inspect._ClassMethodWrapper
    'builtins.code': 'types.CodeType',
    'builtins.coroutine': 'types.CoroutineType',
    'builtins.coroutine_wrapper': '',
    'builtins.deque_iterator': '',
    'builtins.deque_reverse_iterator': '',
    'builtins.dict_itemiterator': _collections_abc('dict_itemiterator'),
    'builtins.dict_items': _collections_abc('dict_items'),
    'builtins.dict_keyiterator': _collections_abc('dict_keyiterator'),
    'builtins.dict_keys': _collections_abc('dict_keys'),
    'builtins.dict_proxy': '_abcoll.dict_proxy',
    'builtins.dict_valueiterator': _collections_abc('dict_valueiterator'),
    'builtins.dict_values': _collections_abc('dict_values'),
    'builtins.ellipsis': 'builtins.Ellipsis.__class__',
    'builtins.fieldnameiterator': '',
    'builtins.formatteriterator': '',
    'builtins.frame': 'types.FrameType',
    'builtins.function': 'types.FunctionType',
    'builtins.generator': 'types.GeneratorType',
    'builtins.getset_descriptor': 'types.GetSetDescriptorType',
    'builtins.instancemethod': '',
    'builtins.iterator': '',
    'builtins.iterparse': '_elementtree.iterparse',
    'builtins.list_iterator': _collections_abc('list_iterator'),
    'builtins.list_reverseiterator': _collections_abc('list_reverseiterator'),
    'builtins.longrange_iterator': '',
    'builtins.managedbuffer': '',
    'builtins.mappingproxy': 'types.MappingProxyType',
    'builtins.member_descriptor': 'types.MemberDescriptorType',
    'builtins.method': 'types.MethodType',
    'builtins.method-wrapper': '', # later 'inspect._MethodWrapper'
    'builtins.method_descriptor': '',
    'builtins.module': 'types.ModuleType',
    'builtins.moduledef': '',
    'builtins.namespace': 'types.SimpleNamespace',
    'builtins.odict_items': '',
    'builtins.odict_iterator': '',
    'builtins.odict_keys': '',
    'builtins.odict_values': '',
    'builtins.range_iterator': _collections_abc('range_iterator'),
    'builtins.set_iterator': _collections_abc('set_iterator'),
    'builtins.sqlite3Node': '',
    'builtins.stderrprinter': '',
    'builtins.str_iterator': _collections_abc('str_iterator'),
    'builtins.symtable entry': '',
    'builtins.traceback': 'types.TracebackType',
    'builtins.tuple_iterator': _collections_abc('tuple_iterator'),
    'builtins.weakcallableproxy': '_weakref.CallableProxyType',
    'builtins.weakproxy': '_weakref.ProxyType',
    'builtins.weakref': '_weakref.ReferenceType',
    'builtins.wrapper_descriptor': '', # later 'inspect._WrapperDescriptor'
    'cElementTree.ParseError': '_elementtree.ParseError',
    'cPickle.Pickler': '',
    'cPickle.Unpickler': '',
    'cStringIO.StringI': 'cStringIO.InputType',
    'cStringIO.StringO': 'cStringIO.OutputType',
    'crypt._Method': '',
    'ctypes.CDLL.__init__.<locals>._FuncPtr': '',
    'ctypes.CFUNCTYPE.<locals>.CFunctionType': '',
    'ctypes.CFunctionType': '',
    'ctypes.LP_c_char': '',
    'ctypes.LP_c_wchar': '',
    'ctypes.PYFUNCTYPE.<locals>.CFunctionType': '',
    'ctypes._FuncPtr': '',
    'ctypes.c_double_be': '',
    'ctypes.c_float_be': '',
    'ctypes.c_int_be': '',
    'ctypes.c_long_be': '',
    'ctypes.c_short_be': '',
    'ctypes.c_uint_be': '',
    'ctypes.c_ulong_be': '',
    'ctypes.c_ushort_be': '',
    'datetime.date': '',
    'datetime.datetime': '',
    'datetime.timedelta': '',
    'datetime.timezone': '',
    'datetime.tzinfo': '',
    'dbm.error': '',
    'decimal.ContextManager': '',
    'decimal.SignalDictMixin': '',
    'functools.CacheInfo': 'functools._CacheInfo',
    'imaplib.abort': '',
    'imaplib.error': '',
    'imaplib.readonly': '',
    'importlib._bootstrap.DecimalTuple': '_decimal.DecimalTuple',
    'itertools._grouper': '',
    'itertools.tee': '',
    'itertools.tee_dataobject': '',
    'multiprocessing.managers.PoolProxy': '',  # base class
    'multiprocessing.process._MainProcess': 'multiprocessing.process._current_process.__class__',
    'ossaudiodev.oss_audio_device': '',
    'ossaudiodev.oss_mixer_device': '',
    'parser.st': 'parser.ASTType' if PY2 else 'parser.STType',
    'pkg_resources._vendor.packaging._structures.Infinity': 'pkg_resources._vendor.packaging._structures.Infinity.__class__',
    'pkg_resources._vendor.packaging._structures.NegativeInfinity': 'pkg_resources._vendor.packaging._structures.NegativeInfinity.__class__',
    'pkg_resources.manifest_mod': '',
    'posix.DirEntry': '',
    'posix.ScandirIterator': '',
    'profile.fake_code': '',
    'profile.fake_frame': '',
    'pyexpat.xmlparser': 'pyexpat.XMLParserType',
    'sched.Event': '',
    'select.poll': '',
    'shutil.usage': 'shutil._ntuple_diskusage',
    'site.Quitter': _builtin('exit.__class__'),
    'site.setquit.<locals>.Quitter': 'builtins.exit.__class__',
    'ssl._ASN1Object': '',
    'sys.flags': 'sys.flags.__class__',
    'sys.float_info': 'sys.float_info.__class__',
    'sys.hash_info': 'sys.hash_info.__class__',
    'sys.int_info': 'sys.int_info.__class__',
    'sys.long_info': 'sys.long_info.__class__',
    'sys.thread_info': 'sys.thread_info.__class__',
    'sys.version_info': 'sys.version_info.__class__',
    'thread.lock': 'thread.LockType',
    'tokenize.TokenInfo': '',
    'typing.typing.io': 'typing.io',
    'typing.typing.re': 'typing.re',
    'unittest.util.Mismatch': 'unittest.util._Mismatch',
    'urllib.parse.DefragResult': '',  # base class
    'urllib.parse.ParseResult': '',  # base class
    'urllib.parse.SplitResult': '',  # base class
    'urlparse.ParseResult': '',  # base class
    'urlparse.SplitResult': '',  # base class
    'xml.dom.xmlbuilder._AsyncDeprecatedProperty': '',
    'xml.etree.ElementTree.Element': '',  # multiple implementations
    'xml.etree.ElementTree.ElementTree': '',
    'xxlimited.Xxo': '',
    'zlib.Compress': '',
    'zlib.Decompress': '',
}

Notes:

  • Python2 and Python3 module names were deliberately not collapsed in keys, since we might have to take different strategies.
  • Some of the values might represent internal names, so we should treat them as not existing.
  • If a class is not present, that means either it's not in the standard library, or else it is available under its declared name. Classes in well-known third-party packages should be added to the list.
  • If there is a simple key-value pair, that means the real name was always found.
  • If the value ends with .__class__, that means that there is a single canonical instance.
  • If the value is '' and there is a comment, see it.
  • If the value is '' otherwise, I could not locate a canonical location for the class.

My thought is to add a stubtool.types module similar to types and ask people to use it where appropriate. I think we do need to supply classes like bytearray_iterator, even if most stubs will just use Iterator[int] (though we do need to do something about __length_hint__() in general).

Feedback?

print's flush argument is missing from builtins, I'd like to add it

In Python 3.3 and later, I can write this code:

"""
    Printing ten dots one by one in a single line.
"""

import time

if __name__ == '__main__':
    for _ in range(10):
        print('.', end='', flush=True)
        time.sleep(1 / 10)
    print()

docs: https://docs.python.org/3/library/functions.html#print

I'm familiar with doing pull requests, and I'd like to add information about new print signature to typeshed. However, before I do, I'd like to learn how to contribute. Currently there is this file: /builtins/3/builtins.pyi

So from what I understand, I would be creating /builtins/3.3/builtins.pyi and in there I would add:

def print(*values: Any, sep: str = ' ', end: str = '\n', file: IO[str] = None, flush: bool=False) -> None: ...

in place of the old one:

def print(*values: Any, sep: str = ' ', end: str = '\n', file: IO[str] = None) -> None: ...

... but what about everything else? Should I add all other updates to builtins.pyi between 3 and 3.3 before I request a pull?

Come up with a way for a module to say "I don't exist"

While tooling support isn't there yet, there is a way for stubs to indicate "the module only contains this function on this platform/version/implementation", using if branches like:

# Stubs for gc
if platform.python_implementation() == 'CPython':
    def get_count(o: object) -> int: ...

There is also a fairly obvious extension for try ... except ImportError

However, there is no way to indicate the complete absence of a module based on such a condition.

This is needed for tools to be able to correctly handle code like:

try:
    import msvcrt
except ImportError:
    msvcrt = None

i.e. only import the msvcrt stub if it is supposed to exist on the platform that is currently being checked-for, and otherwise assign the variable to have type NoneType, so that it can propogate constant checks for is [not] None later.

While it would be possible to add an entirely new set of directories for platform and also for implementation, this would grow quite quickly

Let stubs files indicate their builtin nature.

Builtin modules have some differences from normal modules. For example, they do not expose __builtins__ or __cached__, and don't expose __file__ unless it comes from a shared library.

The current builtins vs stdlib distinction is not useful for checking purposes, only for stub-maintenance purposes. Though even for that purpose, it is lacking for third-party modules, and also for modules within a package (example: lxml is a pure-python package, but lxml.etree is implemented in C. I'm not sure if there are any stdlib builtin modules within a package though).

This should support the usual version and implementation checks (e.g. PyPy uses pure-python modules for many of CPython's builtin modules).

stubs for 3rd party modules

  • Is it intended for stubs for third party modules to come from their respective developers or just from the community as a whole?

I'd like to look into creating some stubs for various projects not owned by me. I know in PEP-0484 it says:

Note that stubs for a given package will not be included here without the explicit consent of the package owner.

I'm just looking for clarification about whether that specifically means that such stubs will only come from the package owner or if I (for example) would have to work it out with the package owner and then have the owner communicate that to Boss Of Typeshed.

  • What should pull requests for third party modules look like?

Take a library that has multiple modules and packages. Should our pull request put all the stubs in a package named after the third party library and then have a structure in that package mirroring the structure of that third party library?

Probably fodder for an updated README.md as mentioned in #1 ...

Help wanted: stubs needed for `six.moves`

Some of these might be implemented for the opposite python version, or located in the wrong module for the given version.

Python2:

  • attribute urllib.proxy_bypass
  • module BaseHTTPServer
  • module CGIHTTPServer
  • module ConfigParser
  • module Cookie
  • module Dialog
  • module FileDialog
  • module HTMLParser
  • module ScrolledText
  • module SimpleDialog
  • module SimpleHTTPServer
  • module SimpleXMLRPCServer
  • module SocketServer
  • module Tix
  • module Tkconstants
  • module Tkdnd
  • module Tkinter
  • module UserList
  • module UserString
  • module cookielib
  • module copy_reg
  • module dummy_thread
  • module email.MIMEBase
  • module email.MIMEMultipart
  • module email.MIMENonMultipart
  • module gdbm
  • module repr
  • module robotparser
  • module tkColorChooser
  • module tkCommonDialog
  • module tkFileDialog
  • module tkFont
  • module tkMessageBox
  • module tkSimpleDialog
  • module ttk
  • module urllib2
  • module xmlrpclib

Python3:

  • attribute urllib.request.AbstractBasicAuthHandler
  • attribute urllib.request.AbstractDigestAuthHandler
  • attribute urllib.request.CacheFTPHandler
  • attribute urllib.error.ContentTooShortError
  • attribute urllib.request.FTPHandler
  • attribute urllib.request.FancyURLopener
  • attribute urllib.request.FileHandler
  • attribute urllib.request.HTTPBasicAuthHandler
  • attribute urllib.request.HTTPCookieProcessor
  • attribute urllib.request.HTTPDefaultErrorHandler
  • attribute urllib.request.HTTPDigestAuthHandler
  • attribute urllib.request.HTTPErrorProcessor
  • attribute urllib.request.HTTPHandler
  • attribute urllib.request.HTTPPasswordMgr
  • attribute urllib.request.HTTPPasswordMgrWithDefaultRealm
  • attribute urllib.request.HTTPSHandler
  • attribute urllib.request.ProxyBasicAuthHandler
  • attribute urllib.request.ProxyDigestAuthHandler
  • attribute urllib.request.ProxyHandler
  • attribute urllib.request.Request
  • attribute urllib.request.URLopener
  • attribute urllib.request.UnknownHandler
  • attribute urllib.request.getproxies
  • attribute urllib.request.pathname2url
  • attribute urllib.request.proxy_bypass
  • attribute urllib.request.url2pathname
  • attribute urllib.request.urlcleanup
  • attribute urllib.request.urlopen
  • attribute urllib.request.urlretrieve
  • module configparser
  • module copyreg
  • module dbm.gnu
  • module html.entities
  • module html.parser
  • module http.cookies
  • module http.server
  • module reprlib
  • module tkinter
  • module tkinter.colorchooser
  • module tkinter.commondialog
  • module tkinter.constants
  • module tkinter.dialog
  • module tkinter.dnd
  • module tkinter.filedialog
  • module tkinter.font
  • module tkinter.messagebox
  • module tkinter.scrolledtext
  • module tkinter.simpledialog
  • module tkinter.tix
  • module tkinter.ttk
  • module urllib.response
  • module urllib.robotparser
  • module xmlrpc.client
  • module xmlrpc.server

No stubs for mysql

⌁ [juke:~/minimysqconnector] 1 % cat mini.py                              
from mysql.connector import connect
⌁ [juke:~/minimysqconnector] % mypy mini.py               
mini.py:1: error: Cannot find module named 'mysql.connector'
mini.py:1: note: (Perhaps setting MYPYPATH would help)

How to specify constants of type NoneType?

PEP 484 says "By default, None is an invalid value for any type". However, in the Python standard library there are class-level and module-level constants that are legitimately None.

Examples:

  formatter.py.AS_IS
  hmac.digest_size
  cgi.FieldStorage.FieldStorageClass
  copy.PyStringMap

Should we allow these to be declared using e.g. something like

  AS_IS = Undefined(NoneType)

?

miniunittest.py:9: error: "unittest" has no attribute "assertListEqual"

⌁ [juke:~/mypytest] 1 % cat miniunittest.py 
from unittest import TestCase
from typing import List


class MyTest(TestCase):
    def test_assert_list(self):
        list1 = list()  # type: List[None]
        list2 = list()  # type: List[None]
        self.assertListEqual(list1, list2)
⌁ [juke:~/mypytest] % mypy --implicit-any miniunittest.py
miniunittest.py: note: In member "test_assert_list" of class "MyTest":
miniunittest.py:9: error: "MyTest" has no attribute "assertListEqual"

Document version/system/implementation checks that tools might want to support

A tool takes as input a python version, host system, python implementation, and body of python code, and returns a set of errors. Some tools may also support querying the type of an expression (e.g. for autocompletion of its attributes in an IDE).

How many and how finely it supports the platform checks, and whether it allows running checks for platforms other than the one it is currently running (simultaneously or in a separate run), is a QoI issue - this document nearly. However, tools should not make it impossible to check Windows-specific code from a Linux host.

At the very least, most tools will want to support python2 vs python3 detection.

Here's my list of branches that should be followed:

  • assert and if statements with comparisons (==, !=, <, >, <=, >=; possibly chained like x < y < z), and and, not, and or expressions containing only comparisons, which contain only literals (of type str, int, or tuple of literals) and the following:
    • platform.python_version()
    • platform.python_version_tuple()
    • sys.version
    • sys.version_info
    • indexing and slices of the above
    • sys.hexversion
    • platform.python_implementation()
    • platform.system()
    • sys.platform maybe? (icky for e.g. linux2 vs linux)
    • Some way to specify that a value exported really is supposed to be constant.
      • "Anything that is not initialized to ..." would require changing many stubs that currently use x = ('', 0) as a short form of x = ... # type: Tuple[str, int].
      • Use this to implement a six stub via the above.
  • else and elif branches following the above (not that elif need not have such an expression)
  • Other:
    • if string_literal [not] in sys.modules maybe? Needs justification.
    • try ... except ImportError
    • try ... except AttributeError where the object is a module.
    • try ... except NameError for builtins e.g. unicode and long.

Why does mypy not treat DictReader as iterable?

I have cloned the latest git on mypy and I'm on master
Python 3.5.1

with open(billto_shipto_file) as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                 ...

mypy says: error: Iterable expected in the 'for row in reader' line.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.