aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/PySide2/support
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2/PySide2/support')
-rw-r--r--sources/pyside2/PySide2/support/__init__.py10
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py351
-rw-r--r--sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt43
-rw-r--r--sources/pyside2/PySide2/support/signature/__init__.py8
-rw-r--r--sources/pyside2/PySide2/support/signature/backport_inspect.py956
-rw-r--r--sources/pyside2/PySide2/support/signature/layout.py (renamed from sources/pyside2/PySide2/support/signature/fix-complaints.py)53
-rw-r--r--sources/pyside2/PySide2/support/signature/lib/__init__.py40
-rw-r--r--sources/pyside2/PySide2/support/signature/lib/enum_sig.py42
-rw-r--r--sources/pyside2/PySide2/support/signature/loader.py110
-rw-r--r--sources/pyside2/PySide2/support/signature/mapping.py159
-rw-r--r--sources/pyside2/PySide2/support/signature/parser.py245
-rw-r--r--sources/pyside2/PySide2/support/signature/qt_attribution.json13
-rw-r--r--sources/pyside2/PySide2/support/signature/typing.py42
-rw-r--r--sources/pyside2/PySide2/support/signature/typing27.py2288
14 files changed, 531 insertions, 3829 deletions
diff --git a/sources/pyside2/PySide2/support/__init__.py b/sources/pyside2/PySide2/support/__init__.py
index 18abd9d0e..dda01474d 100644
--- a/sources/pyside2/PySide2/support/__init__.py
+++ b/sources/pyside2/PySide2/support/__init__.py
@@ -37,12 +37,4 @@
##
#############################################################################
-# Import VoidPtr type to expose it under PySide2.support.VoidPtr
-try:
- # The normal import statement when PySide2 is installed.
- from PySide2.shiboken2 import VoidPtr
-except ImportError:
- # When running make test in shiboken build dir, or when running testrunner.py,
- # shiboken2 is not part of the PySide2 module, so it needs to be imported as a standalone
- # module.
- from shiboken2 import VoidPtr
+from shiboken2 import VoidPtr
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
new file mode 100644
index 000000000..bd3e7500a
--- /dev/null
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -0,0 +1,351 @@
+# This Python file uses the following encoding: utf-8
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import, unicode_literals
+
+"""
+generate_pyi.py
+
+This script generates the .pyi files for all PySide modules.
+"""
+
+import sys
+import os
+import io
+import re
+import subprocess
+import argparse
+from contextlib import contextmanager
+from textwrap import dedent
+
+
+import logging
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger("generate_pyi")
+
+
+# Make sure not to get .pyc in Python2.
+sourcepath = os.path.splitext(__file__)[0] + ".py"
+
+# Can we use forward references?
+USE_PEP563 = sys.version_info[:2] >= (3, 7)
+
+indent = " " * 4
+
+class Writer(object):
+ def __init__(self, outfile):
+ self.outfile = outfile
+ self.history = [True, True]
+
+ def print(self, *args, **kw):
+ # controlling too much blank lines
+ if self.outfile:
+ if args == () or args == ("",):
+ # Python 2.7 glitch: Empty tuples have wrong encoding.
+ # But we use that to skip too many blank lines:
+ if self.history[-2:] == [True, True]:
+ return
+ print("", file=self.outfile, **kw)
+ self.history.append(True)
+ else:
+ print(*args, file=self.outfile, **kw)
+ self.history.append(False)
+
+
+class Formatter(Writer):
+ """
+ Formatter is formatting the signature listing of an enumerator.
+
+ It is written as context managers in order to avoid many callbacks.
+ The separation in formatter and enumerator is done to keep the
+ unrelated tasks of enumeration and formatting apart.
+ """
+ @contextmanager
+ def module(self, mod_name):
+ self.mod_name = mod_name
+ self.print("# Module", mod_name)
+ self.print("import shiboken2 as Shiboken")
+ from PySide2.support.signature import typing
+ self.print("from PySide2.support.signature import typing")
+ self.print("from PySide2.support.signature.mapping import (")
+ self.print(" Virtual, Missing, Invalid, Default, Instance)")
+ self.print()
+ self.print("class Object(object): pass")
+ self.print()
+ self.print("Shiboken.Object = Object")
+ self.print()
+ # This line will be replaced by the missing imports.
+ self.print("IMPORTS")
+ yield
+
+ @contextmanager
+ def klass(self, class_name, class_str):
+ self.class_name = class_name
+ spaces = ""
+ while "." in class_name:
+ spaces += indent
+ class_name = class_name.split(".", 1)[-1]
+ class_str = class_str.split(".", 1)[-1]
+ self.print()
+ if not spaces:
+ self.print()
+ here = self.outfile.tell()
+ self.print("{spaces}class {class_str}:".format(**locals()))
+ self.print()
+ pos = self.outfile.tell()
+ self.spaces = spaces
+ yield
+ if pos == self.outfile.tell():
+ # we have not written any function
+ self.outfile.seek(here)
+ self.outfile.truncate()
+ # Note: we cannot use class_str when we have no body.
+ self.print("{spaces}class {class_name}: ...".format(**locals()))
+ if "<" in class_name:
+ # This is happening in QtQuick for some reason:
+ ## class QSharedPointer<QQuickItemGrabResult >:
+ # We simply skip over this class.
+ self.outfile.seek(here)
+ self.outfile.truncate()
+
+ @contextmanager
+ def function(self, func_name, signature):
+ key = func_name
+ spaces = indent + self.spaces if self.class_name else ""
+ if type(signature) == type([]):
+ for sig in signature:
+ self.print('{spaces}@typing.overload'.format(**locals()))
+ self._function(func_name, sig, spaces)
+ else:
+ self._function(func_name, signature, spaces)
+ yield key
+
+ def _function(self, func_name, signature, spaces):
+ # this would be nicer to get somehow together with the signature
+ is_meth = re.match(r"\((\w*)", str(signature)).group(1) == "self"
+ if self.class_name and not is_meth:
+ self.print('{spaces}@staticmethod'.format(**locals()))
+ self.print('{spaces}def {func_name}{signature}: ...'.format(**locals()))
+
+
+def get_license_text():
+ with io.open(sourcepath) as f:
+ lines = f.readlines()
+ license_line = next((lno for lno, line in enumerate(lines)
+ if "$QT_END_LICENSE$" in line))
+ return "".join(lines[:license_line + 3])
+
+
+def find_imports(text):
+ return [imp for imp in PySide2.__all__ if imp + "." in text]
+
+
+def safe_create(filename):
+ pid = os.getpid()
+ locname = "{filename}.{pid}".format(**locals())
+ f = io.open(locname, "w") # do not close for atomic rename on Linux
+ if sys.platform == "win32":
+ f.close()
+ try:
+ os.rename(locname, filename)
+ logger.debug("{pid}:File {filename} created".format(**locals()))
+ if sys.platform == "win32":
+ f = io.open(filename, "w")
+ return f
+ except OSError:
+ logger.debug("{pid}:Could not rename {locname} to {filename}"
+ .format(**locals()))
+ try:
+ os.remove(locname)
+ except OSError as e:
+ logger.warning("{pid}: unexpected os.remove error in safe_create: {e}"
+ .format(**locals()))
+ return None
+
+
+def generate_pyi(import_name, outpath, options):
+ """
+ Generates a .pyi file.
+
+ Returns 1 If the result is valid, else 0.
+ """
+ pid = os.getpid()
+ plainname = import_name.split(".")[-1]
+ if not outpath:
+ outpath = os.path.dirname(PySide2.__file__)
+ outfilepath = os.path.join(outpath, plainname + ".pyi")
+ if options.skip and os.path.exists(outfilepath):
+ logger.debug("{pid}:Skipped existing: {outfilepath}".format(**locals()))
+ return 1
+ workpath = outfilepath + ".working"
+ if os.path.exists(workpath):
+ return 0
+ realfile = safe_create(workpath)
+ if not realfile:
+ return 0
+
+ try:
+ top = __import__(import_name)
+ obj = getattr(top, plainname)
+ if not getattr(obj, "__file__", None) or os.path.isdir(obj.__file__):
+ raise ImportError("We do not accept a namespace as module {plainname}"
+ .format(**locals()))
+ module = sys.modules[import_name]
+
+ outfile = io.StringIO()
+ fmt = Formatter(outfile)
+ enu = HintingEnumerator(fmt)
+ fmt.print(get_license_text()) # which has encoding, already
+ need_imports = not USE_PEP563
+ if USE_PEP563:
+ fmt.print("from __future__ import annotations")
+ fmt.print()
+ fmt.print(dedent('''\
+ """
+ This file contains the exact signatures for all functions in module
+ {import_name}, except for defaults which are replaced by "...".
+ """
+ '''.format(**locals())))
+ enu.module(import_name)
+ fmt.print()
+ fmt.print("# eof")
+
+ except ImportError as e:
+ logger.debug("{pid}:Import problem with module {plainname}: {e}".format(**locals()))
+ try:
+ os.remove(workpath)
+ except OSError as e:
+ logger.warning("{pid}: unexpected os.remove error in generate_pyi: {e}"
+ .format(**locals()))
+ return 0
+
+ wr = Writer(realfile)
+ outfile.seek(0)
+ while True:
+ line = outfile.readline()
+ if not line:
+ break
+ line = line.rstrip()
+ # we remove the IMPORTS marker and insert imports if needed
+ if line == "IMPORTS":
+ if need_imports:
+ for mod_name in find_imports(outfile.getvalue()):
+ imp = "PySide2." + mod_name
+ if imp != import_name:
+ wr.print("import " + imp)
+ wr.print("import " + import_name)
+ wr.print()
+ wr.print()
+ else:
+ wr.print(line)
+ realfile.close()
+
+ if os.path.exists(outfilepath):
+ os.remove(outfilepath)
+ try:
+ os.rename(workpath, outfilepath)
+ except OSError:
+ logger.warning("{pid}: probable duplicate generated: {outfilepath}"#
+ .format(**locals()))
+ return 0
+ logger.info("Generated: {outfilepath}".format(**locals()))
+ if sys.version_info[0] == 3:
+ # Python 3: We can check the file directly if the syntax is ok.
+ subprocess.check_output([sys.executable, outfilepath])
+ return 1
+
+
+def generate_all_pyi(outpath, options):
+ ps = os.pathsep
+ if options.sys_path:
+ # make sure to propagate the paths from sys_path to subprocesses
+ sys_path = [os.path.normpath(_) for _ in options.sys_path]
+ sys.path[0:0] = sys_path
+ pypath = ps.join(sys_path)
+ os.environ["PYTHONPATH"] = pypath
+ if options.lib_path:
+ # the path changes are automatically propagated to subprocesses
+ ospath_var = "PATH" if sys.platform == "win32" else "LD_LIBRARY_PATH"
+ old_val = os.environ.get(ospath_var, "")
+ lib_path = [os.path.normpath(_) for _ in options.lib_path]
+ ospath = ps.join(lib_path + old_val.split(ps))
+ os.environ[ospath_var] = ospath
+
+ # now we can import
+ global PySide2, inspect, HintingEnumerator
+ import PySide2
+ from PySide2.support.signature import inspect
+ from PySide2.support.signature.lib.enum_sig import HintingEnumerator
+
+ valid = 0
+ for mod_name in PySide2.__all__:
+ import_name = "PySide2." + mod_name
+ valid += generate_pyi(import_name, outpath, options)
+
+ npyi = len(PySide2.__all__)
+ if valid == npyi:
+ logger.info("+++ All {npyi} .pyi files have been created.".format(**locals()))
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(dest="command")
+ # create the parser for the "run" command
+ parser_run = subparsers.add_parser("run",
+ help="run the generation",
+ description="This script generates the .pyi file for all PySide modules.")
+ parser_run.add_argument("--skip", action="store_true",
+ help="skip existing files")
+ parser_run.add_argument("--outpath",
+ help="the output directory (default = binary location)")
+ parser_run.add_argument("--sys-path", nargs="+",
+ help="a list of strings prepended to sys.path")
+ parser_run.add_argument("--lib-path", nargs="+",
+ help="a list of strings prepended to LD_LIBRARY_PATH (unix) or PATH (windows)")
+ options = parser.parse_args()
+ if options.command == "run":
+ outpath = options.outpath
+ if outpath and not os.path.exists(outpath):
+ os.makedirs(outpath)
+ logger.info("+++ Created path {outpath}".format(**locals()))
+ generate_all_pyi(outpath, options=options)
+ else:
+ parser_run.print_help()
+ sys.exit(1)
diff --git a/sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt b/sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt
deleted file mode 100644
index be42010dd..000000000
--- a/sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-PSF LICENSE AGREEMENT FOR PYTHON 3.7.0
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 3.7.0 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 3.7.0 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights
- Reserved" are retained in Python 3.7.0 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 3.7.0 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 3.7.0.
-
-4. PSF is making Python 3.7.0 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 3.7.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.0
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.0, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 3.7.0, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
diff --git a/sources/pyside2/PySide2/support/signature/__init__.py b/sources/pyside2/PySide2/support/signature/__init__.py
index 0ff9ec7e9..5a87a814a 100644
--- a/sources/pyside2/PySide2/support/signature/__init__.py
+++ b/sources/pyside2/PySide2/support/signature/__init__.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2017 The Qt Company Ltd.
+## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -39,4 +39,8 @@
from __future__ import print_function, absolute_import
-from .loader import inspect
+# Trigger initialization phase 2.
+_ = type.__signature__
+from signature_loader import get_signature, inspect, typing
+
+__all__ = "get_signature inspect typing layout mapping lib".split()
diff --git a/sources/pyside2/PySide2/support/signature/backport_inspect.py b/sources/pyside2/PySide2/support/signature/backport_inspect.py
deleted file mode 100644
index 0eafe9caa..000000000
--- a/sources/pyside2/PySide2/support/signature/backport_inspect.py
+++ /dev/null
@@ -1,956 +0,0 @@
-# This Python file uses the following encoding: utf-8
-# It has been edited by fix-complaints.py .
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-from __future__ import print_function
-
-"""
-PSF LICENSE AGREEMENT FOR PYTHON 3.7.0
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 3.7.0 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 3.7.0 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights
- Reserved" are retained in Python 3.7.0 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 3.7.0 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 3.7.0.
-
-4. PSF is making Python 3.7.0 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 3.7.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.0
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.0, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 3.7.0, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
-"""
-
-__doc__ = """
- signature() - get a Signature object for the callable
-"""
-
-import sys
-from collections import OrderedDict
-
-CO_OPTIMIZED = 0x0001
-CO_NEWLOCALS = 0x0002
-CO_VARARGS = 0x0004
-CO_VARKEYWORDS = 0x0008
-CO_NESTED = 0x0010
-CO_GENERATOR = 0x0020
-CO_NOFREE = 0x0040
-
-
-###############################################################################
-### Function Signature Object (PEP 362)
-###############################################################################
-
-
-# This function was changed: 'builtins' and 'qualname' don't exist.
-# We use '__builtin__' and '__name__' instead.
-# It is further changed because we use a local copy of typing
-def formatannotation(annotation, base_module=None):
- if getattr(annotation, '__module__', None) == 'PySide2.support.signature.typing':
- return repr(annotation).replace('PySide2.support.signature.typing.', '')
- if isinstance(annotation, type):
- if annotation.__module__ in ('__builtin__', base_module):
- return annotation.__name__
- return annotation.__module__+'.'+annotation.__name__
- return repr(annotation)
-
-
-def _signature_is_functionlike(obj):
- """Private helper to test if `obj` is a duck type of FunctionType.
- A good example of such objects are functions compiled with
- Cython, which have all attributes that a pure Python function
- would have, but have their code statically compiled.
- """
-
- if not callable(obj) or isclass(obj):
- # All function-like objects are obviously callables,
- # and not classes.
- return False
-
- name = getattr(obj, '__name__', None)
- code = getattr(obj, '__code__', None)
- defaults = getattr(obj, '__defaults__', _void) # Important to use _void ...
- kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here
- annotations = getattr(obj, '__annotations__', None)
-
- return (isinstance(code, types.CodeType) and
- isinstance(name, str) and
- (defaults is None or isinstance(defaults, tuple)) and
- (kwdefaults is None or isinstance(kwdefaults, dict)) and
- isinstance(annotations, dict))
-
-
-
-def _signature_from_function(cls, func):
- """Private helper: constructs Signature for the given python function."""
-
- is_duck_function = False
- if not isfunction(func):
- if _signature_is_functionlike(func):
- is_duck_function = True
- else:
- # If it's not a pure Python function, and not a duck type
- # of pure function:
- raise TypeError('{!r} is not a Python function'.format(func))
-
- Parameter = cls._parameter_cls
-
- # Parameter information.
- func_code = func.__code__
- pos_count = func_code.co_argcount
- arg_names = func_code.co_varnames
- positional = tuple(arg_names[:pos_count])
- keyword_only_count = 0 # func_code.co_kwonlyargcount
- keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)]
- annotations = func.__annotations__
- defaults = func.__defaults__
- kwdefaults = func.__kwdefaults__
-
- if defaults:
- pos_default_count = len(defaults)
- else:
- pos_default_count = 0
-
- parameters = []
-
- # Non-keyword-only parameters w/o defaults.
- non_default_count = pos_count - pos_default_count
- for name in positional[:non_default_count]:
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_POSITIONAL_OR_KEYWORD))
-
- # ... w/ defaults.
- for offset, name in enumerate(positional[non_default_count:]):
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_POSITIONAL_OR_KEYWORD,
- default=defaults[offset]))
-
- # *args
- if func_code.co_flags & CO_VARARGS:
- name = arg_names[pos_count + keyword_only_count]
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_VAR_POSITIONAL))
-
- # Keyword-only parameters.
- for name in keyword_only:
- default = _empty
- if kwdefaults is not None:
- default = kwdefaults.get(name, _empty)
-
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_KEYWORD_ONLY,
- default=default))
- # **kwargs
- if func_code.co_flags & CO_VARKEYWORDS:
- index = pos_count + keyword_only_count
- if func_code.co_flags & CO_VARARGS:
- index += 1
-
- name = arg_names[index]
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_VAR_KEYWORD))
-
- # Is 'func' is a pure Python function - don't validate the
- # parameters list (for correct order and defaults), it should be OK.
- return cls(parameters,
- return_annotation=annotations.get('return', _empty),
- __validate_parameters__=is_duck_function)
-
-
-
-
-class _void(object):
- """A private marker - used in Parameter & Signature."""
-
-
-class _empty(object):
- """Marker object for Signature.empty and Parameter.empty."""
-
-
-class _ParameterKind(object): # (enum.IntEnum):
- POSITIONAL_ONLY = 0
- POSITIONAL_OR_KEYWORD = 1
- VAR_POSITIONAL = 2
- KEYWORD_ONLY = 3
- VAR_KEYWORD = 4
-
- def __str__(self):
- return self._name_
-
-
-_POSITIONAL_ONLY = _ParameterKind.POSITIONAL_ONLY
-_POSITIONAL_OR_KEYWORD = _ParameterKind.POSITIONAL_OR_KEYWORD
-_VAR_POSITIONAL = _ParameterKind.VAR_POSITIONAL
-_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY
-_VAR_KEYWORD = _ParameterKind.VAR_KEYWORD
-
-
-class Parameter(object):
- """Represents a parameter in a function signature.
-
- Has the following public attributes:
-
- * name : str
- The name of the parameter as a string.
- * default : object
- The default value for the parameter if specified. If the
- parameter has no default value, this attribute is set to
- `Parameter.empty`.
- * annotation
- The annotation for the parameter if specified. If the
- parameter has no annotation, this attribute is set to
- `Parameter.empty`.
- * kind : str
- Describes how argument values are bound to the parameter.
- Possible values: `Parameter.POSITIONAL_ONLY`,
- `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`,
- `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`.
- """
-
- __slots__ = ('_name', '_kind', '_default', '_annotation')
-
- POSITIONAL_ONLY = _POSITIONAL_ONLY
- POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD
- VAR_POSITIONAL = _VAR_POSITIONAL
- KEYWORD_ONLY = _KEYWORD_ONLY
- VAR_KEYWORD = _VAR_KEYWORD
-
- empty = _empty
-
- def __init__(self, name, kind, default=_empty, annotation=_empty):
-
- if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD,
- _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD):
- raise ValueError("invalid value for 'Parameter.kind' attribute")
- self._kind = kind
-
- if default is not _empty:
- if kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
- msg = '{} parameters cannot have default values'.format(kind)
- raise ValueError(msg)
- self._default = default
- self._annotation = annotation
-
- if name is _empty:
- raise ValueError('name is a required attribute for Parameter')
-
- if not isinstance(name, str):
- raise TypeError("name must be a str, not a {!r}".format(name))
-
- if name[0] == '.' and name[1:].isdigit():
- # These are implicit arguments generated by comprehensions. In
- # order to provide a friendlier interface to users, we recast
- # their name as "implicitN" and treat them as positional-only.
- # See issue 19611.
- if kind != _POSITIONAL_OR_KEYWORD:
- raise ValueError(
- 'implicit arguments must be passed in as {}'.format(
- _POSITIONAL_OR_KEYWORD
- )
- )
- self._kind = _POSITIONAL_ONLY
- name = 'implicit{}'.format(name[1:])
-
- if not True: # name.isidentifier():
- raise ValueError('{!r} is not a valid parameter name'.format(name))
-
- self._name = name
-
- def __reduce__(self):
- return (type(self),
- (self._name, self._kind),
- {'_default': self._default,
- '_annotation': self._annotation})
-
- def __setstate__(self, state):
- self._default = state['_default']
- self._annotation = state['_annotation']
-
- @property
- def name(self):
- return self._name
-
- @property
- def default(self):
- return self._default
-
- @property
- def annotation(self):
- return self._annotation
-
- @property
- def kind(self):
- return self._kind
-
- def replace(self, name=_void, kind=_void,
- annotation=_void, default=_void):
- """Creates a customized copy of the Parameter."""
-
- if name is _void:
- name = self._name
-
- if kind is _void:
- kind = self._kind
-
- if annotation is _void:
- annotation = self._annotation
-
- if default is _void:
- default = self._default
-
- return type(self)(name, kind, default=default, annotation=annotation)
-
- def __str__(self):
- kind = self.kind
- formatted = self._name
-
- # Add annotation and default value
- if self._annotation is not _empty:
- formatted = '{}:{}'.format(formatted,
- formatannotation(self._annotation))
-
- if self._default is not _empty:
- formatted = '{}={}'.format(formatted, repr(self._default))
-
- if kind == _VAR_POSITIONAL:
- formatted = '*' + formatted
- elif kind == _VAR_KEYWORD:
- formatted = '**' + formatted
-
- return formatted
-
- def __repr__(self):
- return '<{} "{}">'.format(self.__class__.__name__, self)
-
- def __hash__(self):
- return hash((self.name, self.kind, self.annotation, self.default))
-
- def __eq__(self, other):
- if self is other:
- return True
- if not isinstance(other, Parameter):
- return NotImplemented
- return (self._name == other._name and
- self._kind == other._kind and
- self._default == other._default and
- self._annotation == other._annotation)
-
-
-class BoundArguments(object):
- """Result of `Signature.bind` call. Holds the mapping of arguments
- to the function's parameters.
-
- Has the following public attributes:
-
- * arguments : OrderedDict
- An ordered mutable mapping of parameters' names to arguments' values.
- Does not contain arguments' default values.
- * signature : Signature
- The Signature object that created this instance.
- * args : tuple
- Tuple of positional arguments values.
- * kwargs : dict
- Dict of keyword arguments values.
- """
-
- __slots__ = ('arguments', '_signature', '__weakref__')
-
- def __init__(self, signature, arguments):
- self.arguments = arguments
- self._signature = signature
-
- @property
- def signature(self):
- return self._signature
-
- @property
- def args(self):
- args = []
- for param_name, param in self._signature.parameters.items():
- if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
- break
-
- try:
- arg = self.arguments[param_name]
- except KeyError:
- # We're done here. Other arguments
- # will be mapped in 'BoundArguments.kwargs'
- break
- else:
- if param.kind == _VAR_POSITIONAL:
- # *args
- args.extend(arg)
- else:
- # plain argument
- args.append(arg)
-
- return tuple(args)
-
- @property
- def kwargs(self):
- kwargs = {}
- kwargs_started = False
- for param_name, param in self._signature.parameters.items():
- if not kwargs_started:
- if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
- kwargs_started = True
- else:
- if param_name not in self.arguments:
- kwargs_started = True
- continue
-
- if not kwargs_started:
- continue
-
- try:
- arg = self.arguments[param_name]
- except KeyError:
- pass
- else:
- if param.kind == _VAR_KEYWORD:
- # **kwargs
- kwargs.update(arg)
- else:
- # plain keyword argument
- kwargs[param_name] = arg
-
- return kwargs
-
- def apply_defaults(self):
- """Set default values for missing arguments.
-
- For variable-positional arguments (*args) the default is an
- empty tuple.
-
- For variable-keyword arguments (**kwargs) the default is an
- empty dict.
- """
- arguments = self.arguments
- new_arguments = []
- for name, param in self._signature.parameters.items():
- try:
- new_arguments.append((name, arguments[name]))
- except KeyError:
- if param.default is not _empty:
- val = param.default
- elif param.kind is _VAR_POSITIONAL:
- val = ()
- elif param.kind is _VAR_KEYWORD:
- val = {}
- else:
- # This BoundArguments was likely produced by
- # Signature.bind_partial().
- continue
- new_arguments.append((name, val))
- self.arguments = OrderedDict(new_arguments)
-
- def __eq__(self, other):
- if self is other:
- return True
- if not isinstance(other, BoundArguments):
- return NotImplemented
- return (self.signature == other.signature and
- self.arguments == other.arguments)
-
- def __setstate__(self, state):
- self._signature = state['_signature']
- self.arguments = state['arguments']
-
- def __getstate__(self):
- return {'_signature': self._signature, 'arguments': self.arguments}
-
- def __repr__(self):
- args = []
- for arg, value in self.arguments.items():
- args.append('{}={!r}'.format(arg, value))
- return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args))
-
-
-class Signature(object):
- """A Signature object represents the overall signature of a function.
- It stores a Parameter object for each parameter accepted by the
- function, as well as information specific to the function itself.
-
- A Signature object has the following public attributes and methods:
-
- * parameters : OrderedDict
- An ordered mapping of parameters' names to the corresponding
- Parameter objects (keyword-only arguments are in the same order
- as listed in `code.co_varnames`).
- * return_annotation : object
- The annotation for the return type of the function if specified.
- If the function has no annotation for its return type, this
- attribute is set to `Signature.empty`.
- * bind(*args, **kwargs) -> BoundArguments
- Creates a mapping from positional and keyword arguments to
- parameters.
- * bind_partial(*args, **kwargs) -> BoundArguments
- Creates a partial mapping from positional and keyword arguments
- to parameters (simulating 'functools.partial' behavior.)
- """
-
- __slots__ = ('_return_annotation', '_parameters')
-
- _parameter_cls = Parameter
- _bound_arguments_cls = BoundArguments
-
- empty = _empty
-
- def __init__(self, parameters=None, return_annotation=_empty,
- __validate_parameters__=True):
- """Constructs Signature from the given list of Parameter
- objects and 'return_annotation'. All arguments are optional.
- """
-
- if parameters is None:
- params = OrderedDict()
- else:
- if __validate_parameters__:
- params = OrderedDict()
- top_kind = _POSITIONAL_ONLY
- kind_defaults = False
-
- for idx, param in enumerate(parameters):
- kind = param.kind
- name = param.name
-
- if kind < top_kind:
- msg = 'wrong parameter order: {!r} before {!r}'
- msg = msg.format(top_kind, kind)
- raise ValueError(msg)
- elif kind > top_kind:
- kind_defaults = False
- top_kind = kind
-
- if kind in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD):
- if param.default is _empty:
- if kind_defaults:
- # No default for this parameter, but the
- # previous parameter of the same kind had
- # a default
- msg = 'non-default argument follows default ' \
- 'argument'
- raise ValueError(msg)
- else:
- # There is a default for this parameter.
- kind_defaults = True
-
- if name in params:
- msg = 'duplicate parameter name: {!r}'.format(name)
- raise ValueError(msg)
-
- params[name] = param
- else:
- params = OrderedDict(((param.name, param)
- for param in parameters))
-
- self._parameters = params # types.MappingProxyType(params)
- self._return_annotation = return_annotation
-
- @classmethod
- def from_function(cls, func):
- """Constructs Signature for the given python function."""
-
- warnings.warn("inspect.Signature.from_function() is deprecated, "
- "use Signature.from_callable()",
- DeprecationWarning, stacklevel=2)
- return _signature_from_function(cls, func)
-
- @classmethod
- def from_builtin(cls, func):
- """Constructs Signature for the given builtin function."""
-
- warnings.warn("inspect.Signature.from_builtin() is deprecated, "
- "use Signature.from_callable()",
- DeprecationWarning, stacklevel=2)
- return _signature_from_builtin(cls, func)
-
- @classmethod
- def from_callable(cls, obj, follow_wrapped=True):
- """Constructs Signature for the given callable object."""
- return _signature_from_callable(obj, sigcls=cls,
- follow_wrapper_chains=follow_wrapped)
-
- @property
- def parameters(self):
- return self._parameters
-
- @property
- def return_annotation(self):
- return self._return_annotation
-
- def replace(self, parameters=_void, return_annotation=_void):
- """Creates a customized copy of the Signature.
- Pass 'parameters' and/or 'return_annotation' arguments
- to override them in the new copy.
- """
-
- if parameters is _void:
- parameters = self.parameters.values()
-
- if return_annotation is _void:
- return_annotation = self._return_annotation
-
- return type(self)(parameters,
- return_annotation=return_annotation)
-
- def _hash_basis(self):
- params = tuple(param for param in self.parameters.values()
- if param.kind != _KEYWORD_ONLY)
-
- kwo_params = {param.name: param for param in self.parameters.values()
- if param.kind == _KEYWORD_ONLY}
-
- return params, kwo_params, self.return_annotation
-
- def __hash__(self):
- params, kwo_params, return_annotation = self._hash_basis()
- kwo_params = frozenset(kwo_params.values())
- return hash((params, kwo_params, return_annotation))
-
- def __eq__(self, other):
- if self is other:
- return True
- if not isinstance(other, Signature):
- return NotImplemented
- return self._hash_basis() == other._hash_basis()
-
- def _bind(self, args, kwargs, partial=False):
- """Private method. Don't use directly."""
-
- arguments = OrderedDict()
-
- parameters = iter(self.parameters.values())
- parameters_ex = ()
- arg_vals = iter(args)
-
- while True:
- # Let's iterate through the positional arguments and corresponding
- # parameters
- try:
- arg_val = next(arg_vals)
- except StopIteration:
- # No more positional arguments
- try:
- param = next(parameters)
- except StopIteration:
- # No more parameters. That's it. Just need to check that
- # we have no `kwargs` after this while loop
- break
- else:
- if param.kind == _VAR_POSITIONAL:
- # That's OK, just empty *args. Let's start parsing
- # kwargs
- break
- elif param.name in kwargs:
- if param.kind == _POSITIONAL_ONLY:
- msg = '{arg!r} parameter is positional only, ' \
- 'but was passed as a keyword'
- msg = msg.format(arg=param.name)
- raise TypeError(msg)# from None
- parameters_ex = (param,)
- break
- elif (param.kind == _VAR_KEYWORD or
- param.default is not _empty):
- # That's fine too - we have a default value for this
- # parameter. So, lets start parsing `kwargs`, starting
- # with the current parameter
- parameters_ex = (param,)
- break
- else:
- # No default, not VAR_KEYWORD, not VAR_POSITIONAL,
- # not in `kwargs`
- if partial:
- parameters_ex = (param,)
- break
- else:
- msg = 'missing a required argument: {arg!r}'
- msg = msg.format(arg=param.name)
- raise TypeError(msg)# from None
- else:
- # We have a positional argument to process
- try:
- param = next(parameters)
- except StopIteration:
- raise TypeError('too many positional arguments')# from None
- else:
- if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
- # Looks like we have no parameter for this positional
- # argument
- raise TypeError(
- 'too many positional arguments')# from None
-
- if param.kind == _VAR_POSITIONAL:
- # We have an '*args'-like argument, let's fill it with
- # all positional arguments we have left and move on to
- # the next phase
- values = [arg_val]
- values.extend(arg_vals)
- arguments[param.name] = tuple(values)
- break
-
- if param.name in kwargs:
- raise TypeError(
- 'multiple values for argument {arg!r}'.format(
- arg=param.name))# from None
-
- arguments[param.name] = arg_val
-
- # Now, we iterate through the remaining parameters to process
- # keyword arguments
- kwargs_param = None
- for param in itertools.chain(parameters_ex, parameters):
- if param.kind == _VAR_KEYWORD:
- # Memorize that we have a '**kwargs'-like parameter
- kwargs_param = param
- continue
-
- if param.kind == _VAR_POSITIONAL:
- # Named arguments don't refer to '*args'-like parameters.
- # We only arrive here if the positional arguments ended
- # before reaching the last parameter before *args.
- continue
-
- param_name = param.name
- try:
- arg_val = kwargs.pop(param_name)
- except KeyError:
- # We have no value for this parameter. It's fine though,
- # if it has a default value, or it is an '*args'-like
- # parameter, left alone by the processing of positional
- # arguments.
- if (not partial and param.kind != _VAR_POSITIONAL and
- param.default is _empty):
- raise TypeError('missing a required argument: {arg!r}'. \
- format(arg=param_name))# from None
-
- else:
- if param.kind == _POSITIONAL_ONLY:
- # This should never happen in case of a properly built
- # Signature object (but let's have this check here
- # to ensure correct behavior just in case)
- raise TypeError('{arg!r} parameter is positional only, '
- 'but was passed as a keyword'. \
- format(arg=param.name))
-
- arguments[param_name] = arg_val
-
- if kwargs:
- if kwargs_param is not None:
- # Process our '**kwargs'-like parameter
- arguments[kwargs_param.name] = kwargs
- else:
- raise TypeError(
- 'got an unexpected keyword argument {arg!r}'.format(
- arg=next(iter(kwargs))))
-
- return self._bound_arguments_cls(self, arguments)
-
- def bind(*args, **kwargs):
- """Get a BoundArguments object, that maps the passed `args`
- and `kwargs` to the function's signature. Raises `TypeError`
- if the passed arguments can not be bound.
- """
- return args[0]._bind(args[1:], kwargs)
-
- def bind_partial(*args, **kwargs):
- """Get a BoundArguments object, that partially maps the
- passed `args` and `kwargs` to the function's signature.
- Raises `TypeError` if the passed arguments can not be bound.
- """
- return args[0]._bind(args[1:], kwargs, partial=True)
-
- def __reduce__(self):
- return (type(self),
- (tuple(self._parameters.values()),),
- {'_return_annotation': self._return_annotation})
-
- def __setstate__(self, state):
- self._return_annotation = state['_return_annotation']
-
- def __repr__(self):
- return '<{} {}>'.format(self.__class__.__name__, self)
-
- def __str__(self):
- result = []
- render_pos_only_separator = False
- render_kw_only_separator = True
- for param in self.parameters.values():
- formatted = str(param)
-
- kind = param.kind
-
- if kind == _POSITIONAL_ONLY:
- render_pos_only_separator = True
- elif render_pos_only_separator:
- # It's not a positional-only parameter, and the flag
- # is set to 'True' (there were pos-only params before.)
- result.append('/')
- render_pos_only_separator = False
-
- if kind == _VAR_POSITIONAL:
- # OK, we have an '*args'-like parameter, so we won't need
- # a '*' to separate keyword-only arguments
- render_kw_only_separator = False
- elif kind == _KEYWORD_ONLY and render_kw_only_separator:
- # We have a keyword-only parameter to render and we haven't
- # rendered an '*args'-like parameter before, so add a '*'
- # separator to the parameters list ("foo(arg1, *, arg2)" case)
- result.append('*')
- # This condition should be only triggered once, so
- # reset the flag
- render_kw_only_separator = False
-
- result.append(formatted)
-
- if render_pos_only_separator:
- # There were only positional-only parameters, hence the
- # flag was not reset to 'False'
- result.append('/')
-
- rendered = '({})'.format(', '.join(result))
-
- if self.return_annotation is not _empty:
- anno = formatannotation(self.return_annotation)
- rendered += ' -> {}'.format(anno)
-
- return rendered
-
-
-def signature(obj, follow_wrapped=True):
- """Get a signature object for the passed callable."""
- return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
-
-
-def _main():
- """ Logic for inspecting an object given at command line """
- import argparse
- import importlib
-
- parser = argparse.ArgumentParser()
- parser.add_argument(
- 'object',
- help="The object to be analysed. "
- "It supports the 'module:qualname' syntax")
- parser.add_argument(
- '-d', '--details', action='store_true',
- help='Display info about the module rather than its source code')
-
- args = parser.parse_args()
-
- target = args.object
- mod_name, has_attrs, attrs = target.partition(":")
- try:
- obj = module = importlib.import_module(mod_name)
- except Exception as exc:
- msg = "Failed to import {} ({}: {})".format(mod_name,
- type(exc).__name__,
- exc)
- print(msg, file=sys.stderr)
- exit(2)
-
- if has_attrs:
- parts = attrs.split(".")
- obj = module
- for part in parts:
- obj = getattr(obj, part)
-
- if module.__name__ in sys.builtin_module_names:
- print("Can't get info for builtin modules.", file=sys.stderr)
- exit(1)
-
- if args.details:
- print('Target: {}'.format(target))
- print('Origin: {}'.format(getsourcefile(module)))
- print('Cached: {}'.format(module.__cached__))
- if obj is module:
- print('Loader: {}'.format(repr(module.__loader__)))
- if hasattr(module, '__path__'):
- print('Submodule search path: {}'.format(module.__path__))
- else:
- try:
- __, lineno = findsource(obj)
- except Exception:
- pass
- else:
- print('Line: {}'.format(lineno))
-
- print('\n')
- else:
- print(getsource(obj))
-
-
-if __name__ == "__main__":
- _main()
diff --git a/sources/pyside2/PySide2/support/signature/fix-complaints.py b/sources/pyside2/PySide2/support/signature/layout.py
index fa2b44420..c8a4062cb 100644
--- a/sources/pyside2/PySide2/support/signature/fix-complaints.py
+++ b/sources/pyside2/PySide2/support/signature/layout.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2017 The Qt Company Ltd.
+## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -39,53 +39,4 @@
from __future__ import print_function, absolute_import
-"""
-fix-complaints.py
-
-This module fixes the buildbot messages of external python modules.
-Run it once after copying a new version. It is idem-potent, unless
-you are changing messages (what I did, of course :-) .
-"""
-
-import os
-
-patched_modules = "backport_inspect typing27"
-
-offending_words = {
- "behavio""ur": "behavior",
- "at""least": "at_least",
- "reali""sed": "realized",
-}
-
-utf8_line = "# This Python file uses the following encoding: utf-8\n"
-marker_line = "# It has been edited by {} .\n".format(
- os.path.basename(__file__))
-
-def patch_file(fname):
- with open(fname) as f:
- lines = f.readlines()
- dup = lines[:]
- for idx, line in enumerate(lines):
- for word, repl in offending_words.items():
- if word in line:
- lines[idx] = line.replace(word, repl)
- print("line:{!r} {!r}->{!r}".format(line, word, repl))
- if lines[0].strip() != utf8_line.strip():
- lines[:0] = [utf8_line, "\n"]
- if lines[1] != marker_line:
- lines[1:1] = marker_line
- if lines != dup:
- with open(fname, "w") as f:
- f.write("".join(lines))
-
-def doit():
- dir = os.path.dirname(__file__)
- for name in patched_modules.split():
- fname = os.path.join(dir, name + ".py")
- print("Working on", fname)
- patch_file(fname)
-
-if __name__ == "__main__":
- doit()
-
-# end of file
+from signature_loader.layout import *
diff --git a/sources/pyside2/PySide2/support/signature/lib/__init__.py b/sources/pyside2/PySide2/support/signature/lib/__init__.py
new file mode 100644
index 000000000..2d640cb89
--- /dev/null
+++ b/sources/pyside2/PySide2/support/signature/lib/__init__.py
@@ -0,0 +1,40 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# this file intentionally left blank
diff --git a/sources/pyside2/PySide2/support/signature/lib/enum_sig.py b/sources/pyside2/PySide2/support/signature/lib/enum_sig.py
new file mode 100644
index 000000000..1d19ad5e4
--- /dev/null
+++ b/sources/pyside2/PySide2/support/signature/lib/enum_sig.py
@@ -0,0 +1,42 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+from signature_loader.enum_sig import *
diff --git a/sources/pyside2/PySide2/support/signature/loader.py b/sources/pyside2/PySide2/support/signature/loader.py
deleted file mode 100644
index f51bafe79..000000000
--- a/sources/pyside2/PySide2/support/signature/loader.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#############################################################################
-##
-## Copyright (C) 2017 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-from __future__ import print_function, absolute_import
-
-"""
-loader.py
-
-The loader has to lazy-load the signature module and also provides a few
-Python modules to support Python 2.7 .
-
-This file was originally directly embedded into the C source.
-After it grew more and more, I now prefer to have it as Python file.
-The remaining stub loader in the C source is now only a short string.
-
-This version does no longer use an embedded .zip file but is a package.
-The old code without a package but with zip compression can still be found
-at https://codereview.qt-project.org/#/c/203533/ for reference.
-"""
-
-import sys
-import os
-
-# Make sure that we always have the PySide containing package first.
-# This is crucial for the mapping during reload in the tests.
-package_dir = __file__
-for _ in "four":
- package_dir = os.path.dirname(package_dir)
-sys.path.insert(0, package_dir)
-if sys.version_info >= (3,):
- import inspect
-else:
- import inspect
- namespace = inspect.__dict__
- from PySide2.support.signature import backport_inspect as inspect
- _doc = inspect.__doc__
- inspect.__dict__.update(namespace)
- inspect.__doc__ += _doc
- # force inspect to find all attributes. See "heuristic" in pydoc.py!
- inspect.__all__ = list(x for x in dir(inspect) if not x.startswith("_"))
-
-# name used in signature.cpp
-from PySide2.support.signature.parser import pyside_type_init
-sys.path.pop(0)
-# Note also that during the tests we have a different encoding that would
-# break the Python license decorated files without an encoding line.
-
-# name used in signature.cpp
-def create_signature(props, sig_kind):
- if not props:
- # empty signatures string
- return
- if isinstance(props["multi"], list):
- return list(create_signature(elem, sig_kind)
- for elem in props["multi"])
- varnames = props["varnames"]
- if sig_kind == "method":
- varnames = ("self",) + varnames
- elif sig_kind == "staticmethod":
- pass
- elif sig_kind == "classmethod":
- varnames = ("klass",) + varnames
- else:
- raise SystemError("Methods must be normal, staticmethod or "
- "classmethod")
- argstr = ", ".join(varnames)
- fakefunc = eval("lambda {}: None".format(argstr))
- fakefunc.__name__ = props["name"]
- fakefunc.__defaults__ = props["defaults"]
- fakefunc.__kwdefaults__ = props["kwdefaults"]
- fakefunc.__annotations__ = props["annotations"]
- return inspect._signature_from_function(inspect.Signature, fakefunc)
-
-# end of file
diff --git a/sources/pyside2/PySide2/support/signature/mapping.py b/sources/pyside2/PySide2/support/signature/mapping.py
index dd3df0988..1a769484d 100644
--- a/sources/pyside2/PySide2/support/signature/mapping.py
+++ b/sources/pyside2/PySide2/support/signature/mapping.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2017 The Qt Company Ltd.
+## Copyright (C) 2018 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -46,114 +46,28 @@ This module has the mapping from the pyside C-modules view of signatures
to the Python representation.
The PySide modules are not loaded in advance, but only after they appear
-in sys.modules. This minimises the loading overhead.
-In principle, we need to re-load the module, when the imports change.
-But it is much easier to do it on demand, when we get an exception.
-See _resolve_value() in singature.py
+in sys.modules. This minimizes the loading overhead.
"""
-import sys
-import struct
import PySide2
-try:
- from . import typing
-except ImportError:
- import typing
-
-ellipsis = "..."
-Char = typing.Union[str, int] # how do I model the limitation to 1 char?
-StringList = typing.List[str]
-IntList = typing.List[int]
-Variant = typing.Any
-ModelIndexList = typing.List[int]
-QImageCleanupFunction = typing.Callable
-FloatMatrix = typing.List[typing.List[float]]
-# Pair could be more specific, but we loose the info in the generator.
-Pair = typing.Tuple[typing.Any, typing.Any]
-MultiMap = typing.DefaultDict[str, typing.List[str]]
-Text = typing.Text
-
-# ulong_max is only 32 bit on windows.
-ulong_max = 2*sys.maxsize+1 if len(struct.pack("L", 1)) != 4 else 0xffffffff
-ushort_max = 0xffff
-
-GL_COLOR_BUFFER_BIT = 0x00004000
-GL_NEAREST = 0x2600
-
-WId = int
-# from 5.9
-GL_TEXTURE_2D = 0x0DE1
-GL_RGBA = 0x1908
-
-class _NotCalled(str):
- """
- Wrap some text with semantics
-
- This class is wrapped around text in order to avoid calling it.
- There are three reasons for this:
-
- - some instances cannot be created since they are abstract,
- - some can only be created after qApp was created,
- - some have an ugly __repr__ with angle brackets in it.
-
- By using derived classes, good looking instances can be created
- which can be used to generate source code or .pyi files. When the
- real object is needed, the wrapper can simply be called.
- """
- def __repr__(self):
- suppress = "PySide2.support.signature.typing."
- text = self[len(suppress):] if self.startswith(suppress) else self
- return "{}({})".format(type(self).__name__, text)
-
- def __call__(self):
- from .mapping import __dict__ as namespace
- text = self if self.endswith(")") else self + "()"
- return eval(text, namespace)
-
-# Some types are abstract. They just show their name.
-class Virtual(_NotCalled):
- pass
-
-# Other types I simply could not find.
-class Missing(_NotCalled):
- pass
+from signature_loader.sbk_mapping import *
-class Invalid(_NotCalled):
- pass
+Sbk_Reloader = Reloader
-# Helper types
-class Default(_NotCalled):
- pass
-
-class Instance(_NotCalled):
- pass
-
-
-class Reloader(object):
- def __init__(self):
- self.sys_module_count = 0
- self.uninitialized = PySide2.__all__[:]
+class Reloader(Sbk_Reloader):
+ _uninitialized = Sbk_Reloader._uninitialized + PySide2.__all__
+ _prefixes = Sbk_Reloader._prefixes + ["PySide2."]
def update(self):
- if self.sys_module_count == len(sys.modules):
- return
- self.sys_module_count = len(sys.modules)
- g = globals()
- for mod_name in self.uninitialized[:]:
- if "PySide2." + mod_name in sys.modules:
- self.uninitialized.remove(mod_name)
- proc_name = "init_" + mod_name
- if proc_name in g:
- g.update(g[proc_name]())
-
+ Sbk_Reloader.update(self, globals())
update_mapping = Reloader().update
-type_map = {}
+
def init_QtCore():
import PySide2.QtCore
- from PySide2.QtCore import Qt, QUrl, QDir, QGenericArgument
+ from PySide2.QtCore import Qt, QUrl, QDir
from PySide2.QtCore import QRect, QSize, QPoint, QLocale, QByteArray
from PySide2.QtCore import QMarginsF # 5.9
try:
@@ -201,9 +115,8 @@ def init_QtCore():
"ULONG_MAX": ulong_max,
"quintptr": int,
"PyCallable": typing.Callable,
- "...": ellipsis, # no idea how this should be translated... maybe so?
"PyTypeObject": type,
- "PySequence": typing.Sequence,
+ "PySequence": typing.Iterable, # important for numpy
"qptrdiff": int,
"true": True,
"Qt.HANDLE": int, # be more explicit with some consts?
@@ -242,7 +155,7 @@ def init_QtCore():
"QDir.SortFlags(QDir.Name | QDir.IgnoreCase)"),
"PyBytes": bytes,
"PyByteArray": bytearray,
- "PyUnicode": Text,
+ "PyUnicode": typing.Text,
"signed long": int,
"PySide2.QtCore.int": int,
"PySide2.QtCore.char": StringList, # A 'char **' is a list of strings.
@@ -259,13 +172,13 @@ def init_QtCore():
"float[][]": FloatMatrix, # 5.9
"PySide2.QtCore.unsigned int": int, # 5.9 Ubuntu
"PySide2.QtCore.long long": int, # 5.9, MSVC 15
- "QGenericArgument(nullptr)": QGenericArgument(None), # 5.10
+ "QGenericArgument(nullptr)": ellipsis, # 5.10
"QModelIndex()": Invalid("PySide2.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
- "QGenericArgument((0))": None, # 5.6, RHEL 6.6. Is that ok?
- "QGenericArgument()": None,
- "QGenericArgument(0)": None,
- "QGenericArgument(NULL)": None, # 5.6, MSVC
- "QGenericArgument(Q_NULLPTR)": None,
+ "QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
+ "QGenericArgument()": ellipsis,
+ "QGenericArgument(0)": ellipsis,
+ "QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
+ "QGenericArgument(Q_NULLPTR)": ellipsis,
"zero(PySide2.QtCore.QObject)": None,
"zero(PySide2.QtCore.QThread)": None,
"zero(quintptr)": 0,
@@ -289,6 +202,9 @@ def init_QtCore():
"zero(PySide2.QtCore.QEvent.Type)": None,
"CheckIndexOption.NoOption": Instance(
"PySide2.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
+ "QVariantMap": dict,
+ "PySide2.QtCore.QCborStreamReader.StringResult": typing.AnyStr,
+ "PySide2.QtCore.double": float,
})
try:
type_map.update({
@@ -299,9 +215,10 @@ def init_QtCore():
pass
return locals()
+
def init_QtGui():
import PySide2.QtGui
- from PySide2.QtGui import QPageLayout, QPageSize # 5.9
+ from PySide2.QtGui import QPageLayout, QPageSize # 5.12 macOS
type_map.update({
"QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
"USHRT_MAX": ushort_max,
@@ -313,7 +230,7 @@ def init_QtGui():
"GL_COLOR_BUFFER_BIT": GL_COLOR_BUFFER_BIT,
"GL_NEAREST": GL_NEAREST,
"WId": WId,
- "PySide2.QtGui.QPlatformSurface": Virtual("PySide2.QtGui.QPlatformSurface"), # hmm...
+ "PySide2.QtGui.QPlatformSurface": int, # a handle
"QList< QTouchEvent.TouchPoint >()": [], # XXX improve?
"QPixmap()": Default("PySide2.QtGui.QPixmap"), # can't create without qApp
"PySide2.QtCore.uint8_t": int, # macOS 5.9
@@ -325,9 +242,11 @@ def init_QtGui():
"zero(PySide2.QtGui.QTextLayout.FormatRange)": None,
"zero(PySide2.QtGui.QTouchDevice)": None,
"zero(PySide2.QtGui.QScreen)": None,
+ "PySide2.QtGui.QGenericMatrix": Missing("PySide2.QtGui.QGenericMatrix"),
})
return locals()
+
def init_QtWidgets():
import PySide2.QtWidgets
from PySide2.QtWidgets import QWidget, QMessageBox, QStyleOption, QStyleHintReturn, QStyleOptionComplex
@@ -364,6 +283,7 @@ def init_QtWidgets():
})
return locals()
+
def init_QtSql():
import PySide2.QtSql
from PySide2.QtSql import QSqlDatabase
@@ -373,6 +293,7 @@ def init_QtSql():
})
return locals()
+
def init_QtNetwork():
import PySide2.QtNetwork
type_map.update({
@@ -383,6 +304,7 @@ def init_QtNetwork():
})
return locals()
+
def init_QtXmlPatterns():
import PySide2.QtXmlPatterns
from PySide2.QtXmlPatterns import QXmlName
@@ -392,16 +314,16 @@ def init_QtXmlPatterns():
})
return locals()
-def init_QtMultimedia():
- import PySide2.QtMultimedia
+
+def init_QtMultimediaWidgets():
import PySide2.QtMultimediaWidgets
type_map.update({
- "QVariantMap": dict,
"QGraphicsVideoItem": PySide2.QtMultimediaWidgets.QGraphicsVideoItem,
"QVideoWidget": PySide2.QtMultimediaWidgets.QVideoWidget,
})
return locals()
+
def init_QtOpenGL():
import PySide2.QtOpenGL
type_map.update({
@@ -418,6 +340,7 @@ def init_QtOpenGL():
})
return locals()
+
def init_QtQml():
import PySide2.QtQml
type_map.update({
@@ -430,6 +353,7 @@ def init_QtQml():
})
return locals()
+
def init_QtQuick():
import PySide2.QtQuick
type_map.update({
@@ -441,6 +365,7 @@ def init_QtQuick():
})
return locals()
+
def init_QtScript():
import PySide2.QtScript
type_map.update({
@@ -448,6 +373,7 @@ def init_QtScript():
})
return locals()
+
def init_QtTest():
import PySide2.QtTest
type_map.update({
@@ -459,7 +385,6 @@ def init_QtTest():
def init_QtWebEngineWidgets():
import PySide2.QtWebEngineWidgets
type_map.update({
- "PySide2.QtTest.QTouchEventSequence": PySide2.QtTest.QTest.QTouchEventSequence,
"zero(PySide2.QtWebEngineWidgets.QWebEnginePage.FindFlags)": 0,
})
return locals()
@@ -472,6 +397,16 @@ def init_QtWinExtras():
})
return locals()
-# Here was testbinding, actually the source of all evil.
+# from 5.12, macOS
+def init_QtDataVisualization():
+ from PySide2.QtDataVisualization import QtDataVisualization
+ QtDataVisualization.QBarDataRow = typing.List[QtDataVisualization.QBarDataItem]
+ QtDataVisualization.QBarDataArray = typing.List[QtDataVisualization.QBarDataRow]
+ QtDataVisualization.QSurfaceDataRow = typing.List[QtDataVisualization.QSurfaceDataItem]
+ QtDataVisualization.QSurfaceDataArray = typing.List[QtDataVisualization.QSurfaceDataRow]
+ type_map.update({
+ "100.0f": 100.0,
+ })
+ return locals()
# end of file
diff --git a/sources/pyside2/PySide2/support/signature/parser.py b/sources/pyside2/PySide2/support/signature/parser.py
deleted file mode 100644
index 9313fb540..000000000
--- a/sources/pyside2/PySide2/support/signature/parser.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#############################################################################
-##
-## Copyright (C) 2017 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-from __future__ import print_function, absolute_import
-
-import sys
-import re
-import warnings
-import types
-import keyword
-import functools
-from .mapping import type_map, update_mapping, __dict__ as namespace
-
-_DEBUG = False
-
-"""
-parser.py
-
-This module parses the signature text and creates properties for the
-signature objects.
-
-PySide has a new function 'CppGenerator::writeSignatureInfo()'
-that extracts the gathered information about the function arguments
-and defaults as good as it can. But what PySide generates is still
-very C-ish and has many constants that Python doesn't understand.
-
-The function 'try_to_guess()' below understands a lot of PySide's
-peculiar way to assume local context. If it is able to do the guess,
-then the result is inserted into the dict, so the search happens
-not again. For everything that is not covered by these automatic
-guesses, we provide an entry in 'type_map' that resolves it.
-
-In effect, 'type_map' maps text to real Python objects.
-"""
-
-def dprint(*args, **kw):
- if _DEBUG:
- import pprint
- for arg in args:
- pprint.pprint(arg)
-
-def _parse_line(line):
- line_re = r"""
- ((?P<multi> ([0-9]+)) : )? # the optional multi-index
- (?P<funcname> \w+(\.\w+)*) # the function name
- \( (?P<arglist> .*?) \) # the argument list
- ( -> (?P<returntype> .*) )? # the optional return type
- $
- """
- ret = re.match(line_re, line, re.VERBOSE).groupdict()
- arglist = ret["arglist"]
- # The following is a split re. The string is broken into pieces which are
- # between the recognized strings. Because the re has groups, both the
- # strings and the delimiters are returned, where the strings are not
- # interesting at all: They are just the commata.
- # Note that it is necessary to put the characters with special handling in
- # the first group (comma, brace, angle bracket).
- # Then they are not recognized there, and we can handle them differently
- # in the following expressions.
- arglist = list(x.strip() for x in re.split(r"""
- (
- (?: # inner group is not capturing
- [^,()<>] # no commas or braces or angle brackets
- |
- \(
- (?:
- [^()]* # or one brace pair
- |
- \(
- [^()]* # or doubls nested pair
- \)
- )*
- \)
- |
- < # or one angle bracket pair
- [^<>]*
- >
- )+ # longest possible span
- ) # this list is interspersed with "," and surrounded by ""
- """, arglist, flags=re.VERBOSE)
- if x.strip() not in ("", ","))
- args = []
- for arg in arglist:
- name, ann = arg.split(":")
- if name in keyword.kwlist:
- name = name + "_"
- if "=" in ann:
- ann, default = ann.split("=")
- tup = name, ann, default
- else:
- tup = name, ann
- args.append(tup)
- ret["arglist"] = args
- multi = ret["multi"]
- if multi is not None:
- ret["multi"] = int(multi)
- return ret
-
-def make_good_value(thing, valtype):
- try:
- if thing.endswith("()"):
- thing = 'Default("{}")'.format(thing[:-2])
- else:
- ret = eval(thing, namespace)
- if valtype and repr(ret).startswith("<"):
- thing = 'Instance("{}")'.format(thing)
- return eval(thing, namespace)
- except Exception:
- pass
-
-def try_to_guess(thing, valtype):
- if "." not in thing and "(" not in thing:
- text = "{}.{}".format(valtype, thing)
- ret = make_good_value(text, valtype)
- if ret is not None:
- return ret
- typewords = valtype.split(".")
- valwords = thing.split(".")
- braceless = valwords[0] # Yes, not -1. Relevant is the overlapped word.
- if "(" in braceless:
- braceless = braceless[:braceless.index("(")]
- for idx, w in enumerate(typewords):
- if w == braceless:
- text = ".".join(typewords[:idx] + valwords)
- ret = make_good_value(text, valtype)
- if ret is not None:
- return ret
- return None
-
-def _resolve_value(thing, valtype, line):
- if thing in ("0", "None") and valtype:
- thing = "zero({})".format(valtype)
- if thing in type_map:
- return type_map[thing]
- res = make_good_value(thing, valtype)
- if res is not None:
- type_map[thing] = res
- return res
- res = try_to_guess(thing, valtype) if valtype else None
- if res is not None:
- type_map[thing] = res
- return res
- warnings.warn("""pyside_type_init:
-
- UNRECOGNIZED: {!r}
- OFFENDING LINE: {!r}
- """.format(thing, line), RuntimeWarning)
- return thing
-
-def _resolve_type(thing, line):
- return _resolve_value(thing, None, line)
-
-def calculate_props(line):
- line = line.strip()
- res = _parse_line(line)
- arglist = res["arglist"]
- annotations = {}
- _defaults = []
- for tup in arglist:
- name, ann = tup[:2]
- annotations[name] = _resolve_type(ann, line)
- if len(tup) == 3:
- default = _resolve_value(tup[2], ann, line)
- _defaults.append(default)
- defaults = tuple(_defaults)
- returntype = res["returntype"]
- if returntype is not None:
- annotations["return"] = _resolve_type(returntype, line)
- props = {}
- props["defaults"] = defaults
- props["kwdefaults"] = {}
- props["annotations"] = annotations
- props["varnames"] = varnames = tuple(tup[0] for tup in arglist)
- funcname = res["funcname"]
- props["fullname"] = funcname
- shortname = funcname[funcname.rindex(".")+1:]
- props["name"] = shortname
- props["multi"] = res["multi"]
- return props
-
-def pyside_type_init(typemod, sig_str):
- dprint()
- if type(typemod) is types.ModuleType:
- dprint("Initialization of module '{}'".format(typemod.__name__))
- else:
- dprint("Initialization of type '{}.{}'".format(typemod.__module__,
- typemod.__name__))
- update_mapping()
- ret = {}
- multi_props = []
- for line in sig_str.strip().splitlines():
- props = calculate_props(line)
- shortname = props["name"]
- multi = props["multi"]
- if multi is None:
- ret[shortname] = props
- dprint(props)
- else:
- fullname = props.pop("fullname")
- multi_props.append(props)
- if multi > 0:
- continue
- multi_props = {"multi": multi_props, "fullname": fullname}
- ret[shortname] = multi_props
- dprint(multi_props)
- multi_props = []
- return ret
-
-# end of file
diff --git a/sources/pyside2/PySide2/support/signature/qt_attribution.json b/sources/pyside2/PySide2/support/signature/qt_attribution.json
deleted file mode 100644
index 491ae8054..000000000
--- a/sources/pyside2/PySide2/support/signature/qt_attribution.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "Id": "python",
- "Name": "Python",
- "QDocModule": "QtForPython",
- "QtUsage": "Used for Qt for Python in the signature extension.",
- "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files (backport_inspect.py, typing27.py). See the folder sources/pyside2/PySide2/support/signature .",
- "Homepage": "http://www.python.org/",
- "Version": "3.7.0",
- "LicenseId": "Python-2.0",
- "License": "Python License 2.0",
- "LicenseFile": "PSF-3.7.0.txt",
- "Copyright": "© Copyright 2001-2018, Python Software Foundation."
-}
diff --git a/sources/pyside2/PySide2/support/signature/typing.py b/sources/pyside2/PySide2/support/signature/typing.py
new file mode 100644
index 000000000..dd52a2c45
--- /dev/null
+++ b/sources/pyside2/PySide2/support/signature/typing.py
@@ -0,0 +1,42 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+from signature_loader.typing import *
diff --git a/sources/pyside2/PySide2/support/signature/typing27.py b/sources/pyside2/PySide2/support/signature/typing27.py
deleted file mode 100644
index ae1d6ba27..000000000
--- a/sources/pyside2/PySide2/support/signature/typing27.py
+++ /dev/null
@@ -1,2288 +0,0 @@
-# This Python file uses the following encoding: utf-8
-# It has been edited by fix-complaints.py .
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""
-PSF LICENSE AGREEMENT FOR PYTHON 3.7.0
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 3.7.0 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 3.7.0 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights
- Reserved" are retained in Python 3.7.0 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 3.7.0 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 3.7.0.
-
-4. PSF is making Python 3.7.0 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 3.7.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.0
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.0, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 3.7.0, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
-"""
-
-from __future__ import absolute_import, unicode_literals
-
-import abc
-from abc import abstractmethod, abstractproperty
-import collections
-import functools
-import re as stdlib_re # Avoid confusion with the re we export.
-import sys
-import types
-try:
- import collections.abc as collections_abc
-except ImportError:
- import collections as collections_abc # Fallback for PY3.2.
-
-
-# Please keep __all__ alphabetized within each category.
-__all__ = [
- # Super-special typing primitives.
- 'Any',
- 'Callable',
- 'ClassVar',
- 'Generic',
- 'Optional',
- 'Tuple',
- 'Type',
- 'TypeVar',
- 'Union',
-
- # ABCs (from collections.abc).
- 'AbstractSet', # collections.abc.Set.
- 'GenericMeta', # subclass of abc.ABCMeta and a metaclass
- # for 'Generic' and ABCs below.
- 'ByteString',
- 'Container',
- 'ContextManager',
- 'Hashable',
- 'ItemsView',
- 'Iterable',
- 'Iterator',
- 'KeysView',
- 'Mapping',
- 'MappingView',
- 'MutableMapping',
- 'MutableSequence',
- 'MutableSet',
- 'Sequence',
- 'Sized',
- 'ValuesView',
-
- # Structural checks, a.k.a. protocols.
- 'Reversible',
- 'SupportsAbs',
- 'SupportsComplex',
- 'SupportsFloat',
- 'SupportsInt',
-
- # Concrete collection types.
- 'Counter',
- 'Deque',
- 'Dict',
- 'DefaultDict',
- 'List',
- 'Set',
- 'FrozenSet',
- 'NamedTuple', # Not really a type.
- 'Generator',
-
- # One-off things.
- 'AnyStr',
- 'cast',
- 'get_type_hints',
- 'NewType',
- 'no_type_check',
- 'no_type_check_decorator',
- 'overload',
- 'Text',
- 'TYPE_CHECKING',
-]
-
-# The pseudo-submodules 're' and 'io' are part of the public
-# namespace, but excluded from __all__ because they might stomp on
-# legitimate imports of those modules.
-
-
-def _qualname(x):
- if sys.version_info[:2] >= (3, 3):
- return x.__qualname__
- else:
- # Fall back to just name.
- return x.__name__
-
-
-def _trim_name(nm):
- whitelist = ('_TypeAlias', '_ForwardRef', '_TypingBase', '_FinalTypingBase')
- if nm.startswith('_') and nm not in whitelist:
- nm = nm[1:]
- return nm
-
-
-class TypingMeta(type):
- """Metaclass for most types defined in typing module
- (not a part of public API).
-
- This also defines a dummy constructor (all the work for most typing
- constructs is done in __new__) and a nicer repr().
- """
-
- _is_protocol = False
-
- def __new__(cls, name, bases, namespace):
- return super(TypingMeta, cls).__new__(cls, str(name), bases, namespace)
-
- @classmethod
- def assert_no_subclassing(cls, bases):
- for base in bases:
- if isinstance(base, cls):
- raise TypeError("Cannot subclass %s" %
- (', '.join(map(_type_repr, bases)) or '()'))
-
- def __init__(self, *args, **kwds):
- pass
-
- def _eval_type(self, globalns, localns):
- """Override this in subclasses to interpret forward references.
-
- For example, List['C'] is internally stored as
- List[_ForwardRef('C')], which should evaluate to List[C],
- where C is an object found in globalns or localns (searching
- localns first, of course).
- """
- return self
-
- def _get_type_vars(self, tvars):
- pass
-
- def __repr__(self):
- qname = _trim_name(_qualname(self))
- return '%s.%s' % (self.__module__, qname)
-
-
-class _TypingBase(object):
- """Internal indicator of special typing constructs."""
- __metaclass__ = TypingMeta
- __slots__ = ('__weakref__',)
-
- def __init__(self, *args, **kwds):
- pass
-
- def __new__(cls, *args, **kwds):
- """Constructor.
-
- This only exists to give a better error message in case
- someone tries to subclass a special typing object (not a good idea).
- """
- if (len(args) == 3 and
- isinstance(args[0], str) and
- isinstance(args[1], tuple)):
- # Close enough.
- raise TypeError("Cannot subclass %r" % cls)
- return super(_TypingBase, cls).__new__(cls)
-
- # Things that are not classes also need these.
- def _eval_type(self, globalns, localns):
- return self
-
- def _get_type_vars(self, tvars):
- pass
-
- def __repr__(self):
- cls = type(self)
- qname = _trim_name(_qualname(cls))
- return '%s.%s' % (cls.__module__, qname)
-
- def __call__(self, *args, **kwds):
- raise TypeError("Cannot instantiate %r" % type(self))
-
-
-class _FinalTypingBase(_TypingBase):
- """Internal mix-in class to prevent instantiation.
-
- Prevents instantiation unless _root=True is given in class call.
- It is used to create pseudo-singleton instances Any, Union, Optional, etc.
- """
-
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- self = super(_FinalTypingBase, cls).__new__(cls, *args, **kwds)
- if '_root' in kwds and kwds['_root'] is True:
- return self
- raise TypeError("Cannot instantiate %r" % cls)
-
- def __reduce__(self):
- return _trim_name(type(self).__name__)
-
-
-class _ForwardRef(_TypingBase):
- """Internal wrapper to hold a forward reference."""
-
- __slots__ = ('__forward_arg__', '__forward_code__',
- '__forward_evaluated__', '__forward_value__')
-
- def __init__(self, arg):
- super(_ForwardRef, self).__init__(arg)
- if not isinstance(arg, basestring):
- raise TypeError('Forward reference must be a string -- got %r' % (arg,))
- try:
- code = compile(arg, '<string>', 'eval')
- except SyntaxError:
- raise SyntaxError('Forward reference must be an expression -- got %r' %
- (arg,))
- self.__forward_arg__ = arg
- self.__forward_code__ = code
- self.__forward_evaluated__ = False
- self.__forward_value__ = None
-
- def _eval_type(self, globalns, localns):
- if not self.__forward_evaluated__ or localns is not globalns:
- if globalns is None and localns is None:
- globalns = localns = {}
- elif globalns is None:
- globalns = localns
- elif localns is None:
- localns = globalns
- self.__forward_value__ = _type_check(
- eval(self.__forward_code__, globalns, localns),
- "Forward references must evaluate to types.")
- self.__forward_evaluated__ = True
- return self.__forward_value__
-
- def __eq__(self, other):
- if not isinstance(other, _ForwardRef):
- return NotImplemented
- return (self.__forward_arg__ == other.__forward_arg__ and
- self.__forward_value__ == other.__forward_value__)
-
- def __hash__(self):
- return hash((self.__forward_arg__, self.__forward_value__))
-
- def __instancecheck__(self, obj):
- raise TypeError("Forward references cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("Forward references cannot be used with issubclass().")
-
- def __repr__(self):
- return '_ForwardRef(%r)' % (self.__forward_arg__,)
-
-
-class _TypeAlias(_TypingBase):
- """Internal helper class for defining generic variants of concrete types.
-
- Note that this is not a type; let's call it a pseudo-type. It cannot
- be used in instance and subclass checks in parameterized form, i.e.
- ``isinstance(42, Match[str])`` raises ``TypeError`` instead of returning
- ``False``.
- """
-
- __slots__ = ('name', 'type_var', 'impl_type', 'type_checker')
-
- def __init__(self, name, type_var, impl_type, type_checker):
- """Initializer.
-
- Args:
- name: The name, e.g. 'Pattern'.
- type_var: The type parameter, e.g. AnyStr, or the
- specific type, e.g. str.
- impl_type: The implementation type.
- type_checker: Function that takes an impl_type instance.
- and returns a value that should be a type_var instance.
- """
- assert isinstance(name, basestring), repr(name)
- assert isinstance(impl_type, type), repr(impl_type)
- assert not isinstance(impl_type, TypingMeta), repr(impl_type)
- assert isinstance(type_var, (type, _TypingBase)), repr(type_var)
- self.name = name
- self.type_var = type_var
- self.impl_type = impl_type
- self.type_checker = type_checker
-
- def __repr__(self):
- return "%s[%s]" % (self.name, _type_repr(self.type_var))
-
- def __getitem__(self, parameter):
- if not isinstance(self.type_var, TypeVar):
- raise TypeError("%s cannot be further parameterized." % self)
- if self.type_var.__constraints__ and isinstance(parameter, type):
- if not issubclass(parameter, self.type_var.__constraints__):
- raise TypeError("%s is not a valid substitution for %s." %
- (parameter, self.type_var))
- if isinstance(parameter, TypeVar) and parameter is not self.type_var:
- raise TypeError("%s cannot be re-parameterized." % self)
- return self.__class__(self.name, parameter,
- self.impl_type, self.type_checker)
-
- def __eq__(self, other):
- if not isinstance(other, _TypeAlias):
- return NotImplemented
- return self.name == other.name and self.type_var == other.type_var
-
- def __hash__(self):
- return hash((self.name, self.type_var))
-
- def __instancecheck__(self, obj):
- if not isinstance(self.type_var, TypeVar):
- raise TypeError("Parameterized type aliases cannot be used "
- "with isinstance().")
- return isinstance(obj, self.impl_type)
-
- def __subclasscheck__(self, cls):
- if not isinstance(self.type_var, TypeVar):
- raise TypeError("Parameterized type aliases cannot be used "
- "with issubclass().")
- return issubclass(cls, self.impl_type)
-
-
-def _get_type_vars(types, tvars):
- for t in types:
- if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
- t._get_type_vars(tvars)
-
-
-def _type_vars(types):
- tvars = []
- _get_type_vars(types, tvars)
- return tuple(tvars)
-
-
-def _eval_type(t, globalns, localns):
- if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
- return t._eval_type(globalns, localns)
- return t
-
-
-def _type_check(arg, msg):
- """Check that the argument is a type, and return it (internal helper).
-
- As a special case, accept None and return type(None) instead.
- Also, _TypeAlias instances (e.g. Match, Pattern) are acceptable.
-
- The msg argument is a human-readable error message, e.g.
-
- "Union[arg, ...]: arg should be a type."
-
- We append the repr() of the actual value (truncated to 100 chars).
- """
- if arg is None:
- return type(None)
- if isinstance(arg, basestring):
- arg = _ForwardRef(arg)
- if (
- isinstance(arg, _TypingBase) and type(arg).__name__ == '_ClassVar' or
- not isinstance(arg, (type, _TypingBase)) and not callable(arg)
- ):
- raise TypeError(msg + " Got %.100r." % (arg,))
- # Bare Union etc. are not valid as type arguments
- if (
- type(arg).__name__ in ('_Union', '_Optional') and
- not getattr(arg, '__origin__', None) or
- isinstance(arg, TypingMeta) and _gorg(arg) in (Generic, _Protocol)
- ):
- raise TypeError("Plain %s is not valid as type argument" % arg)
- return arg
-
-
-def _type_repr(obj):
- """Return the repr() of an object, special-casing types (internal helper).
-
- If obj is a type, we return a shorter version than the default
- type.__repr__, based on the module and qualified name, which is
- typically enough to uniquely identify a type. For everything
- else, we fall back on repr(obj).
- """
- if isinstance(obj, type) and not isinstance(obj, TypingMeta):
- if obj.__module__ == '__builtin__':
- return _qualname(obj)
- return '%s.%s' % (obj.__module__, _qualname(obj))
- if obj is Ellipsis:
- return('...')
- if isinstance(obj, types.FunctionType):
- return obj.__name__
- return repr(obj)
-
-
-class ClassVarMeta(TypingMeta):
- """Metaclass for _ClassVar"""
-
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- self = super(ClassVarMeta, cls).__new__(cls, name, bases, namespace)
- return self
-
-
-class _ClassVar(_FinalTypingBase):
- """Special type construct to mark class variables.
-
- An annotation wrapped in ClassVar indicates that a given
- attribute is intended to be used as a class variable and
- should not be set on instances of that class. Usage::
-
- class Starship:
- stats = {} # type: ClassVar[Dict[str, int]] # class variable
- damage = 10 # type: int # instance variable
-
- ClassVar accepts only types and cannot be further subscribed.
-
- Note that ClassVar is not a class itself, and should not
- be used with isinstance() or issubclass().
- """
-
- __metaclass__ = ClassVarMeta
- __slots__ = ('__type__',)
-
- def __init__(self, tp=None, _root=False):
- self.__type__ = tp
-
- def __getitem__(self, item):
- cls = type(self)
- if self.__type__ is None:
- return cls(_type_check(item,
- '{} accepts only types.'.format(cls.__name__[1:])),
- _root=True)
- raise TypeError('{} cannot be further subscripted'
- .format(cls.__name__[1:]))
-
- def _eval_type(self, globalns, localns):
- return type(self)(_eval_type(self.__type__, globalns, localns),
- _root=True)
-
- def __repr__(self):
- r = super(_ClassVar, self).__repr__()
- if self.__type__ is not None:
- r += '[{}]'.format(_type_repr(self.__type__))
- return r
-
- def __hash__(self):
- return hash((type(self).__name__, self.__type__))
-
- def __eq__(self, other):
- if not isinstance(other, _ClassVar):
- return NotImplemented
- if self.__type__ is not None:
- return self.__type__ == other.__type__
- return self is other
-
-
-ClassVar = _ClassVar(_root=True)
-
-
-class AnyMeta(TypingMeta):
- """Metaclass for Any."""
-
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- self = super(AnyMeta, cls).__new__(cls, name, bases, namespace)
- return self
-
-
-class _Any(_FinalTypingBase):
- """Special type indicating an unconstrained type.
-
- - Any is compatible with every type.
- - Any assumed to have all methods.
- - All values assumed to be instances of Any.
-
- Note that all the above statements are true from the point of view of
- static type checkers. At runtime, Any should not be used with instance
- or class checks.
- """
- __metaclass__ = AnyMeta
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError("Any cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("Any cannot be used with issubclass().")
-
-
-Any = _Any(_root=True)
-
-
-class NoReturnMeta(TypingMeta):
- """Metaclass for NoReturn."""
-
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- self = super(NoReturnMeta, cls).__new__(cls, name, bases, namespace)
- return self
-
-
-class _NoReturn(_FinalTypingBase):
- """Special type indicating functions that never return.
- Example::
-
- from typing import NoReturn
-
- def stop() -> NoReturn:
- raise Exception('no way')
-
- This type is invalid in other positions, e.g., ``List[NoReturn]``
- will fail in static type checkers.
- """
- __metaclass__ = NoReturnMeta
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError("NoReturn cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("NoReturn cannot be used with issubclass().")
-
-
-NoReturn = _NoReturn(_root=True)
-
-
-class TypeVarMeta(TypingMeta):
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- return super(TypeVarMeta, cls).__new__(cls, name, bases, namespace)
-
-
-class TypeVar(_TypingBase):
- """Type variable.
-
- Usage::
-
- T = TypeVar('T') # Can be anything
- A = TypeVar('A', str, bytes) # Must be str or bytes
-
- Type variables exist primarily for the benefit of static type
- checkers. They serve as the parameters for generic types as well
- as for generic function definitions. See class Generic for more
- information on generic types. Generic functions work as follows:
-
- def repeat(x: T, n: int) -> List[T]:
- '''Return a list containing n references to x.'''
- return [x]*n
-
- def longest(x: A, y: A) -> A:
- '''Return the longest of two strings.'''
- return x if len(x) >= len(y) else y
-
- The latter example's signature is essentially the overloading
- of (str, str) -> str and (bytes, bytes) -> bytes. Also note
- that if the arguments are instances of some subclass of str,
- the return type is still plain str.
-
- At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.
-
- Type variables defined with covariant=True or contravariant=True
- can be used do declare covariant or contravariant generic types.
- See PEP 484 for more details. By default generic types are invariant
- in all type variables.
-
- Type variables can be introspected. e.g.:
-
- T.__name__ == 'T'
- T.__constraints__ == ()
- T.__covariant__ == False
- T.__contravariant__ = False
- A.__constraints__ == (str, bytes)
- """
-
- __metaclass__ = TypeVarMeta
- __slots__ = ('__name__', '__bound__', '__constraints__',
- '__covariant__', '__contravariant__')
-
- def __init__(self, name, *constraints, **kwargs):
- super(TypeVar, self).__init__(name, *constraints, **kwargs)
- bound = kwargs.get('bound', None)
- covariant = kwargs.get('covariant', False)
- contravariant = kwargs.get('contravariant', False)
- self.__name__ = name
- if covariant and contravariant:
- raise ValueError("Bivariant types are not supported.")
- self.__covariant__ = bool(covariant)
- self.__contravariant__ = bool(contravariant)
- if constraints and bound is not None:
- raise TypeError("Constraints cannot be combined with bound=...")
- if constraints and len(constraints) == 1:
- raise TypeError("A single constraint is not allowed")
- msg = "TypeVar(name, constraint, ...): constraints must be types."
- self.__constraints__ = tuple(_type_check(t, msg) for t in constraints)
- if bound:
- self.__bound__ = _type_check(bound, "Bound must be a type.")
- else:
- self.__bound__ = None
-
- def _get_type_vars(self, tvars):
- if self not in tvars:
- tvars.append(self)
-
- def __repr__(self):
- if self.__covariant__:
- prefix = '+'
- elif self.__contravariant__:
- prefix = '-'
- else:
- prefix = '~'
- return prefix + self.__name__
-
- def __instancecheck__(self, instance):
- raise TypeError("Type variables cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("Type variables cannot be used with issubclass().")
-
-
-# Some unconstrained type variables. These are used by the container types.
-# (These are not for export.)
-T = TypeVar('T') # Any type.
-KT = TypeVar('KT') # Key type.
-VT = TypeVar('VT') # Value type.
-T_co = TypeVar('T_co', covariant=True) # Any type covariant containers.
-V_co = TypeVar('V_co', covariant=True) # Any type covariant containers.
-VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers.
-T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
-
-# A useful type variable with constraints. This represents string types.
-# (This one *is* for export!)
-AnyStr = TypeVar('AnyStr', bytes, unicode)
-
-
-def _replace_arg(arg, tvars, args):
- """An internal helper function: replace arg if it is a type variable
- found in tvars with corresponding substitution from args or
- with corresponding substitution sub-tree if arg is a generic type.
- """
-
- if tvars is None:
- tvars = []
- if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)):
- return arg._subs_tree(tvars, args)
- if isinstance(arg, TypeVar):
- for i, tvar in enumerate(tvars):
- if arg == tvar:
- return args[i]
- return arg
-
-
-# Special typing constructs Union, Optional, Generic, Callable and Tuple
-# use three special attributes for internal bookkeeping of generic types:
-# * __parameters__ is a tuple of unique free type parameters of a generic
-# type, for example, Dict[T, T].__parameters__ == (T,);
-# * __origin__ keeps a reference to a type that was subscripted,
-# e.g., Union[T, int].__origin__ == Union;
-# * __args__ is a tuple of all arguments used in subscripting,
-# e.g., Dict[T, int].__args__ == (T, int).
-
-
-def _subs_tree(cls, tvars=None, args=None):
- """An internal helper function: calculate substitution tree
- for generic cls after replacing its type parameters with
- substitutions in tvars -> args (if any).
- Repeat the same following __origin__'s.
-
- Return a list of arguments with all possible substitutions
- performed. Arguments that are generic classes themselves are represented
- as tuples (so that no new classes are created by this function).
- For example: _subs_tree(List[Tuple[int, T]][str]) == [(Tuple, int, str)]
- """
-
- if cls.__origin__ is None:
- return cls
- # Make of chain of origins (i.e. cls -> cls.__origin__)
- current = cls.__origin__
- orig_chain = []
- while current.__origin__ is not None:
- orig_chain.append(current)
- current = current.__origin__
- # Replace type variables in __args__ if asked ...
- tree_args = []
- for arg in cls.__args__:
- tree_args.append(_replace_arg(arg, tvars, args))
- # ... then continue replacing down the origin chain.
- for ocls in orig_chain:
- new_tree_args = []
- for arg in ocls.__args__:
- new_tree_args.append(_replace_arg(arg, ocls.__parameters__, tree_args))
- tree_args = new_tree_args
- return tree_args
-
-
-def _remove_dups_flatten(parameters):
- """An internal helper for Union creation and substitution: flatten Union's
- among parameters, then remove duplicates and strict subclasses.
- """
-
- # Flatten out Union[Union[...], ...].
- params = []
- for p in parameters:
- if isinstance(p, _Union) and p.__origin__ is Union:
- params.extend(p.__args__)
- elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union:
- params.extend(p[1:])
- else:
- params.append(p)
- # Weed out strict duplicates, preserving the first of each occurrence.
- all_params = set(params)
- if len(all_params) < len(params):
- new_params = []
- for t in params:
- if t in all_params:
- new_params.append(t)
- all_params.remove(t)
- params = new_params
- assert not all_params, all_params
- # Weed out subclasses.
- # E.g. Union[int, Employee, Manager] == Union[int, Employee].
- # If object is present it will be sole survivor among proper classes.
- # Never discard type variables.
- # (In particular, Union[str, AnyStr] != AnyStr.)
- all_params = set(params)
- for t1 in params:
- if not isinstance(t1, type):
- continue
- if any(isinstance(t2, type) and issubclass(t1, t2)
- for t2 in all_params - {t1}
- if not (isinstance(t2, GenericMeta) and
- t2.__origin__ is not None)):
- all_params.remove(t1)
- return tuple(t for t in params if t in all_params)
-
-
-def _check_generic(cls, parameters):
- # Check correct count for parameters of a generic cls (internal helper).
- if not cls.__parameters__:
- raise TypeError("%s is not a generic class" % repr(cls))
- alen = len(parameters)
- elen = len(cls.__parameters__)
- if alen != elen:
- raise TypeError("Too %s parameters for %s; actual %s, expected %s" %
- ("many" if alen > elen else "few", repr(cls), alen, elen))
-
-
-_cleanups = []
-
-
-def _tp_cache(func):
- maxsize = 128
- cache = {}
- _cleanups.append(cache.clear)
-
- @functools.wraps(func)
- def inner(*args):
- key = args
- try:
- return cache[key]
- except TypeError:
- # Assume it's an unhashable argument.
- return func(*args)
- except KeyError:
- value = func(*args)
- if len(cache) >= maxsize:
- # If the cache grows too much, just start over.
- cache.clear()
- cache[key] = value
- return value
-
- return inner
-
-
-class UnionMeta(TypingMeta):
- """Metaclass for Union."""
-
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- return super(UnionMeta, cls).__new__(cls, name, bases, namespace)
-
-
-class _Union(_FinalTypingBase):
- """Union type; Union[X, Y] means either X or Y.
-
- To define a union, use e.g. Union[int, str]. Details:
-
- - The arguments must be types and there must be at least one.
-
- - None as an argument is a special case and is replaced by
- type(None).
-
- - Unions of unions are flattened, e.g.::
-
- Union[Union[int, str], float] == Union[int, str, float]
-
- - Unions of a single argument vanish, e.g.::
-
- Union[int] == int # The constructor actually returns int
-
- - Redundant arguments are skipped, e.g.::
-
- Union[int, str, int] == Union[int, str]
-
- - When comparing unions, the argument order is ignored, e.g.::
-
- Union[int, str] == Union[str, int]
-
- - When two arguments have a subclass relationship, the least
- derived argument is kept, e.g.::
-
- class Employee: pass
- class Manager(Employee): pass
- Union[int, Employee, Manager] == Union[int, Employee]
- Union[Manager, int, Employee] == Union[int, Employee]
- Union[Employee, Manager] == Employee
-
- - Similar for object::
-
- Union[int, object] == object
-
- - You cannot subclass or instantiate a union.
-
- - You can use Optional[X] as a shorthand for Union[X, None].
- """
-
- __metaclass__ = UnionMeta
- __slots__ = ('__parameters__', '__args__', '__origin__', '__tree_hash__')
-
- def __new__(cls, parameters=None, origin=None, *args, **kwds):
- self = super(_Union, cls).__new__(cls, parameters, origin, *args, **kwds)
- if origin is None:
- self.__parameters__ = None
- self.__args__ = None
- self.__origin__ = None
- self.__tree_hash__ = hash(frozenset(('Union',)))
- return self
- if not isinstance(parameters, tuple):
- raise TypeError("Expected parameters=<tuple>")
- if origin is Union:
- parameters = _remove_dups_flatten(parameters)
- # It's not a union if there's only one type left.
- if len(parameters) == 1:
- return parameters[0]
- self.__parameters__ = _type_vars(parameters)
- self.__args__ = parameters
- self.__origin__ = origin
- # Pre-calculate the __hash__ on instantiation.
- # This improves speed for complex substitutions.
- subs_tree = self._subs_tree()
- if isinstance(subs_tree, tuple):
- self.__tree_hash__ = hash(frozenset(subs_tree))
- else:
- self.__tree_hash__ = hash(subs_tree)
- return self
-
- def _eval_type(self, globalns, localns):
- if self.__args__ is None:
- return self
- ev_args = tuple(_eval_type(t, globalns, localns) for t in self.__args__)
- ev_origin = _eval_type(self.__origin__, globalns, localns)
- if ev_args == self.__args__ and ev_origin == self.__origin__:
- # Everything is already evaluated.
- return self
- return self.__class__(ev_args, ev_origin, _root=True)
-
- def _get_type_vars(self, tvars):
- if self.__origin__ and self.__parameters__:
- _get_type_vars(self.__parameters__, tvars)
-
- def __repr__(self):
- if self.__origin__ is None:
- return super(_Union, self).__repr__()
- tree = self._subs_tree()
- if not isinstance(tree, tuple):
- return repr(tree)
- return tree[0]._tree_repr(tree)
-
- def _tree_repr(self, tree):
- arg_list = []
- for arg in tree[1:]:
- if not isinstance(arg, tuple):
- arg_list.append(_type_repr(arg))
- else:
- arg_list.append(arg[0]._tree_repr(arg))
- return super(_Union, self).__repr__() + '[%s]' % ', '.join(arg_list)
-
- @_tp_cache
- def __getitem__(self, parameters):
- if parameters == ():
- raise TypeError("Cannot take a Union of no types.")
- if not isinstance(parameters, tuple):
- parameters = (parameters,)
- if self.__origin__ is None:
- msg = "Union[arg, ...]: each arg must be a type."
- else:
- msg = "Parameters to generic types must be types."
- parameters = tuple(_type_check(p, msg) for p in parameters)
- if self is not Union:
- _check_generic(self, parameters)
- return self.__class__(parameters, origin=self, _root=True)
-
- def _subs_tree(self, tvars=None, args=None):
- if self is Union:
- return Union # Nothing to substitute
- tree_args = _subs_tree(self, tvars, args)
- tree_args = _remove_dups_flatten(tree_args)
- if len(tree_args) == 1:
- return tree_args[0] # Union of a single type is that type
- return (Union,) + tree_args
-
- def __eq__(self, other):
- if isinstance(other, _Union):
- return self.__tree_hash__ == other.__tree_hash__
- elif self is not Union:
- return self._subs_tree() == other
- else:
- return self is other
-
- def __hash__(self):
- return self.__tree_hash__
-
- def __instancecheck__(self, obj):
- raise TypeError("Unions cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("Unions cannot be used with issubclass().")
-
-
-Union = _Union(_root=True)
-
-
-class OptionalMeta(TypingMeta):
- """Metaclass for Optional."""
-
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- return super(OptionalMeta, cls).__new__(cls, name, bases, namespace)
-
-
-class _Optional(_FinalTypingBase):
- """Optional type.
-
- Optional[X] is equivalent to Union[X, None].
- """
-
- __metaclass__ = OptionalMeta
- __slots__ = ()
-
- @_tp_cache
- def __getitem__(self, arg):
- arg = _type_check(arg, "Optional[t] requires a single type.")
- return Union[arg, type(None)]
-
-
-Optional = _Optional(_root=True)
-
-
-def _gorg(a):
- """Return the farthest origin of a generic class (internal helper)."""
- assert isinstance(a, GenericMeta)
- while a.__origin__ is not None:
- a = a.__origin__
- return a
-
-
-def _geqv(a, b):
- """Return whether two generic classes are equivalent (internal helper).
-
- The intention is to consider generic class X and any of its
- parameterized forms (X[T], X[int], etc.) as equivalent.
-
- However, X is not equivalent to a subclass of X.
-
- The relation is reflexive, symmetric and transitive.
- """
- assert isinstance(a, GenericMeta) and isinstance(b, GenericMeta)
- # Reduce each to its origin.
- return _gorg(a) is _gorg(b)
-
-
-def _next_in_mro(cls):
- """Helper for Generic.__new__.
-
- Returns the class after the last occurrence of Generic or
- Generic[...] in cls.__mro__.
- """
- next_in_mro = object
- # Look for the last occurrence of Generic or Generic[...].
- for i, c in enumerate(cls.__mro__[:-1]):
- if isinstance(c, GenericMeta) and _gorg(c) is Generic:
- next_in_mro = cls.__mro__[i + 1]
- return next_in_mro
-
-
-def _make_subclasshook(cls):
- """Construct a __subclasshook__ callable that incorporates
- the associated __extra__ class in subclass checks performed
- against cls.
- """
- if isinstance(cls.__extra__, abc.ABCMeta):
- # The logic mirrors that of ABCMeta.__subclasscheck__.
- # Registered classes need not be checked here because
- # cls and its extra share the same _abc_registry.
- def __extrahook__(cls, subclass):
- res = cls.__extra__.__subclasshook__(subclass)
- if res is not NotImplemented:
- return res
- if cls.__extra__ in getattr(subclass, '__mro__', ()):
- return True
- for scls in cls.__extra__.__subclasses__():
- if isinstance(scls, GenericMeta):
- continue
- if issubclass(subclass, scls):
- return True
- return NotImplemented
- else:
- # For non-ABC extras we'll just call issubclass().
- def __extrahook__(cls, subclass):
- if cls.__extra__ and issubclass(subclass, cls.__extra__):
- return True
- return NotImplemented
- return classmethod(__extrahook__)
-
-
-class GenericMeta(TypingMeta, abc.ABCMeta):
- """Metaclass for generic types.
-
- This is a metaclass for typing.Generic and generic ABCs defined in
- typing module. User defined subclasses of GenericMeta can override
- __new__ and invoke super().__new__. Note that GenericMeta.__new__
- has strict rules on what is allowed in its bases argument:
- * plain Generic is disallowed in bases;
- * Generic[...] should appear in bases at most once;
- * if Generic[...] is present, then it should list all type variables
- that appear in other bases.
- In addition, type of all generic bases is erased, e.g., C[int] is
- stripped to plain C.
- """
-
- def __new__(cls, name, bases, namespace,
- tvars=None, args=None, origin=None, extra=None, orig_bases=None):
- """Create a new generic class. GenericMeta.__new__ accepts
- keyword arguments that are used for internal bookkeeping, therefore
- an override should pass unused keyword arguments to super().
- """
- if tvars is not None:
- # Called from __getitem__() below.
- assert origin is not None
- assert all(isinstance(t, TypeVar) for t in tvars), tvars
- else:
- # Called from class statement.
- assert tvars is None, tvars
- assert args is None, args
- assert origin is None, origin
-
- # Get the full set of tvars from the bases.
- tvars = _type_vars(bases)
- # Look for Generic[T1, ..., Tn].
- # If found, tvars must be a subset of it.
- # If not found, tvars is it.
- # Also check for and reject plain Generic,
- # and reject multiple Generic[...].
- gvars = None
- for base in bases:
- if base is Generic:
- raise TypeError("Cannot inherit from plain Generic")
- if (isinstance(base, GenericMeta) and
- base.__origin__ is Generic):
- if gvars is not None:
- raise TypeError(
- "Cannot inherit from Generic[...] multiple types.")
- gvars = base.__parameters__
- if gvars is None:
- gvars = tvars
- else:
- tvarset = set(tvars)
- gvarset = set(gvars)
- if not tvarset <= gvarset:
- raise TypeError(
- "Some type variables (%s) "
- "are not listed in Generic[%s]" %
- (", ".join(str(t) for t in tvars if t not in gvarset),
- ", ".join(str(g) for g in gvars)))
- tvars = gvars
-
- initial_bases = bases
- if extra is None:
- extra = namespace.get('__extra__')
- if extra is not None and type(extra) is abc.ABCMeta and extra not in bases:
- bases = (extra,) + bases
- bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b for b in bases)
-
- # remove bare Generic from bases if there are other generic bases
- if any(isinstance(b, GenericMeta) and b is not Generic for b in bases):
- bases = tuple(b for b in bases if b is not Generic)
- namespace.update({'__origin__': origin, '__extra__': extra})
- self = super(GenericMeta, cls).__new__(cls, name, bases, namespace)
-
- self.__parameters__ = tvars
- # Be prepared that GenericMeta will be subclassed by TupleMeta
- # and CallableMeta, those two allow ..., (), or [] in __args___.
- self.__args__ = tuple(Ellipsis if a is _TypingEllipsis else
- () if a is _TypingEmpty else
- a for a in args) if args else None
- # Speed hack (https://github.com/python/typing/issues/196).
- self.__next_in_mro__ = _next_in_mro(self)
- # Preserve base classes on subclassing (__bases__ are type erased now).
- if orig_bases is None:
- self.__orig_bases__ = initial_bases
-
- # This allows unparameterized generic collections to be used
- # with issubclass() and isinstance() in the same way as their
- # collections.abc counterparts (e.g., isinstance([], Iterable)).
- if (
- '__subclasshook__' not in namespace and extra or
- # allow overriding
- getattr(self.__subclasshook__, '__name__', '') == '__extrahook__'
- ):
- self.__subclasshook__ = _make_subclasshook(self)
-
- if origin and hasattr(origin, '__qualname__'): # Fix for Python 3.2.
- self.__qualname__ = origin.__qualname__
- self.__tree_hash__ = (hash(self._subs_tree()) if origin else
- super(GenericMeta, self).__hash__())
- return self
-
- def __init__(self, *args, **kwargs):
- super(GenericMeta, self).__init__(*args, **kwargs)
- if isinstance(self.__extra__, abc.ABCMeta):
- self._abc_registry = self.__extra__._abc_registry
- self._abc_cache = self.__extra__._abc_cache
- elif self.__origin__ is not None:
- self._abc_registry = self.__origin__._abc_registry
- self._abc_cache = self.__origin__._abc_cache
-
- # _abc_negative_cache and _abc_negative_cache_version
- # realized as descriptors, since GenClass[t1, t2, ...] always
- # share subclass info with GenClass.
- # This is an important memory optimization.
- @property
- def _abc_negative_cache(self):
- if isinstance(self.__extra__, abc.ABCMeta):
- return self.__extra__._abc_negative_cache
- return _gorg(self)._abc_generic_negative_cache
-
- @_abc_negative_cache.setter
- def _abc_negative_cache(self, value):
- if self.__origin__ is None:
- if isinstance(self.__extra__, abc.ABCMeta):
- self.__extra__._abc_negative_cache = value
- else:
- self._abc_generic_negative_cache = value
-
- @property
- def _abc_negative_cache_version(self):
- if isinstance(self.__extra__, abc.ABCMeta):
- return self.__extra__._abc_negative_cache_version
- return _gorg(self)._abc_generic_negative_cache_version
-
- @_abc_negative_cache_version.setter
- def _abc_negative_cache_version(self, value):
- if self.__origin__ is None:
- if isinstance(self.__extra__, abc.ABCMeta):
- self.__extra__._abc_negative_cache_version = value
- else:
- self._abc_generic_negative_cache_version = value
-
- def _get_type_vars(self, tvars):
- if self.__origin__ and self.__parameters__:
- _get_type_vars(self.__parameters__, tvars)
-
- def _eval_type(self, globalns, localns):
- ev_origin = (self.__origin__._eval_type(globalns, localns)
- if self.__origin__ else None)
- ev_args = tuple(_eval_type(a, globalns, localns) for a
- in self.__args__) if self.__args__ else None
- if ev_origin == self.__origin__ and ev_args == self.__args__:
- return self
- return self.__class__(self.__name__,
- self.__bases__,
- dict(self.__dict__),
- tvars=_type_vars(ev_args) if ev_args else None,
- args=ev_args,
- origin=ev_origin,
- extra=self.__extra__,
- orig_bases=self.__orig_bases__)
-
- def __repr__(self):
- if self.__origin__ is None:
- return super(GenericMeta, self).__repr__()
- return self._tree_repr(self._subs_tree())
-
- def _tree_repr(self, tree):
- arg_list = []
- for arg in tree[1:]:
- if arg == ():
- arg_list.append('()')
- elif not isinstance(arg, tuple):
- arg_list.append(_type_repr(arg))
- else:
- arg_list.append(arg[0]._tree_repr(arg))
- return super(GenericMeta, self).__repr__() + '[%s]' % ', '.join(arg_list)
-
- def _subs_tree(self, tvars=None, args=None):
- if self.__origin__ is None:
- return self
- tree_args = _subs_tree(self, tvars, args)
- return (_gorg(self),) + tuple(tree_args)
-
- def __eq__(self, other):
- if not isinstance(other, GenericMeta):
- return NotImplemented
- if self.__origin__ is None or other.__origin__ is None:
- return self is other
- return self.__tree_hash__ == other.__tree_hash__
-
- def __hash__(self):
- return self.__tree_hash__
-
- @_tp_cache
- def __getitem__(self, params):
- if not isinstance(params, tuple):
- params = (params,)
- if not params and not _gorg(self) is Tuple:
- raise TypeError(
- "Parameter list to %s[...] cannot be empty" % _qualname(self))
- msg = "Parameters to generic types must be types."
- params = tuple(_type_check(p, msg) for p in params)
- if self is Generic:
- # Generic can only be subscripted with unique type variables.
- if not all(isinstance(p, TypeVar) for p in params):
- raise TypeError(
- "Parameters to Generic[...] must all be type variables")
- if len(set(params)) != len(params):
- raise TypeError(
- "Parameters to Generic[...] must all be unique")
- tvars = params
- args = params
- elif self in (Tuple, Callable):
- tvars = _type_vars(params)
- args = params
- elif self is _Protocol:
- # _Protocol is internal, don't check anything.
- tvars = params
- args = params
- elif self.__origin__ in (Generic, _Protocol):
- # Can't subscript Generic[...] or _Protocol[...].
- raise TypeError("Cannot subscript already-subscripted %s" %
- repr(self))
- else:
- # Subscripting a regular Generic subclass.
- _check_generic(self, params)
- tvars = _type_vars(params)
- args = params
-
- prepend = (self,) if self.__origin__ is None else ()
- return self.__class__(self.__name__,
- prepend + self.__bases__,
- dict(self.__dict__),
- tvars=tvars,
- args=args,
- origin=self,
- extra=self.__extra__,
- orig_bases=self.__orig_bases__)
-
- def __subclasscheck__(self, cls):
- if self.__origin__ is not None:
- if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
- raise TypeError("Parameterized generics cannot be used with class "
- "or instance checks")
- return False
- if self is Generic:
- raise TypeError("Class %r cannot be used with class "
- "or instance checks" % self)
- return super(GenericMeta, self).__subclasscheck__(cls)
-
- def __instancecheck__(self, instance):
- # Since we extend ABC.__subclasscheck__ and
- # ABC.__instancecheck__ inlines the cache checking done by the
- # latter, we must extend __instancecheck__ too. For simplicity
- # we just skip the cache check -- instance checks for generic
- # classes are supposed to be rare anyways.
- if not isinstance(instance, type):
- return issubclass(instance.__class__, self)
- return False
-
- def __copy__(self):
- return self.__class__(self.__name__, self.__bases__, dict(self.__dict__),
- self.__parameters__, self.__args__, self.__origin__,
- self.__extra__, self.__orig_bases__)
-
- def __setattr__(self, attr, value):
- # We consider all the subscripted genrics as proxies for original class
- if (
- attr.startswith('__') and attr.endswith('__') or
- attr.startswith('_abc_')
- ):
- super(GenericMeta, self).__setattr__(attr, value)
- else:
- super(GenericMeta, _gorg(self)).__setattr__(attr, value)
-
-
-# Prevent checks for Generic to crash when defining Generic.
-Generic = None
-
-
-def _generic_new(base_cls, cls, *args, **kwds):
- # Assure type is erased on instantiation,
- # but attempt to store it in __orig_class__
- if cls.__origin__ is None:
- return base_cls.__new__(cls)
- else:
- origin = _gorg(cls)
- obj = base_cls.__new__(origin)
- try:
- obj.__orig_class__ = cls
- except AttributeError:
- pass
- obj.__init__(*args, **kwds)
- return obj
-
-
-class Generic(object):
- """Abstract base class for generic types.
-
- A generic type is typically declared by inheriting from
- this class parameterized with one or more type variables.
- For example, a generic mapping type might be defined as::
-
- class Mapping(Generic[KT, VT]):
- def __getitem__(self, key: KT) -> VT:
- ...
- # Etc.
-
- This class can then be used as follows::
-
- def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
- try:
- return mapping[key]
- except KeyError:
- return default
- """
-
- __metaclass__ = GenericMeta
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Generic):
- raise TypeError("Type Generic cannot be instantiated; "
- "it can be used only as a base class")
- return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
-
-
-class _TypingEmpty(object):
- """Internal placeholder for () or []. Used by TupleMeta and CallableMeta
- to allow empty list/tuple in specific places, without allowing them
- to sneak in where prohibited.
- """
-
-
-class _TypingEllipsis(object):
- """Internal placeholder for ... (ellipsis)."""
-
-
-class TupleMeta(GenericMeta):
- """Metaclass for Tuple (internal)."""
-
- @_tp_cache
- def __getitem__(self, parameters):
- if self.__origin__ is not None or not _geqv(self, Tuple):
- # Normal generic rules apply if this is not the first subscription
- # or a subscription of a subclass.
- return super(TupleMeta, self).__getitem__(parameters)
- if parameters == ():
- return super(TupleMeta, self).__getitem__((_TypingEmpty,))
- if not isinstance(parameters, tuple):
- parameters = (parameters,)
- if len(parameters) == 2 and parameters[1] is Ellipsis:
- msg = "Tuple[t, ...]: t must be a type."
- p = _type_check(parameters[0], msg)
- return super(TupleMeta, self).__getitem__((p, _TypingEllipsis))
- msg = "Tuple[t0, t1, ...]: each t must be a type."
- parameters = tuple(_type_check(p, msg) for p in parameters)
- return super(TupleMeta, self).__getitem__(parameters)
-
- def __instancecheck__(self, obj):
- if self.__args__ is None:
- return isinstance(obj, tuple)
- raise TypeError("Parameterized Tuple cannot be used "
- "with isinstance().")
-
- def __subclasscheck__(self, cls):
- if self.__args__ is None:
- return issubclass(cls, tuple)
- raise TypeError("Parameterized Tuple cannot be used "
- "with issubclass().")
-
-
-class Tuple(tuple):
- """Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
-
- Example: Tuple[T1, T2] is a tuple of two elements corresponding
- to type variables T1 and T2. Tuple[int, float, str] is a tuple
- of an int, a float and a string.
-
- To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].
- """
-
- __metaclass__ = TupleMeta
- __extra__ = tuple
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Tuple):
- raise TypeError("Type Tuple cannot be instantiated; "
- "use tuple() instead")
- return _generic_new(tuple, cls, *args, **kwds)
-
-
-class CallableMeta(GenericMeta):
- """ Metaclass for Callable."""
-
- def __repr__(self):
- if self.__origin__ is None:
- return super(CallableMeta, self).__repr__()
- return self._tree_repr(self._subs_tree())
-
- def _tree_repr(self, tree):
- if _gorg(self) is not Callable:
- return super(CallableMeta, self)._tree_repr(tree)
- # For actual Callable (not its subclass) we override
- # super(CallableMeta, self)._tree_repr() for nice formatting.
- arg_list = []
- for arg in tree[1:]:
- if not isinstance(arg, tuple):
- arg_list.append(_type_repr(arg))
- else:
- arg_list.append(arg[0]._tree_repr(arg))
- if arg_list[0] == '...':
- return repr(tree[0]) + '[..., %s]' % arg_list[1]
- return (repr(tree[0]) +
- '[[%s], %s]' % (', '.join(arg_list[:-1]), arg_list[-1]))
-
- def __getitem__(self, parameters):
- """A thin wrapper around __getitem_inner__ to provide the latter
- with hashable arguments to improve speed.
- """
-
- if self.__origin__ is not None or not _geqv(self, Callable):
- return super(CallableMeta, self).__getitem__(parameters)
- if not isinstance(parameters, tuple) or len(parameters) != 2:
- raise TypeError("Callable must be used as "
- "Callable[[arg, ...], result].")
- args, result = parameters
- if args is Ellipsis:
- parameters = (Ellipsis, result)
- else:
- if not isinstance(args, list):
- raise TypeError("Callable[args, result]: args must be a list."
- " Got %.100r." % (args,))
- parameters = (tuple(args), result)
- return self.__getitem_inner__(parameters)
-
- @_tp_cache
- def __getitem_inner__(self, parameters):
- args, result = parameters
- msg = "Callable[args, result]: result must be a type."
- result = _type_check(result, msg)
- if args is Ellipsis:
- return super(CallableMeta, self).__getitem__((_TypingEllipsis, result))
- msg = "Callable[[arg, ...], result]: each arg must be a type."
- args = tuple(_type_check(arg, msg) for arg in args)
- parameters = args + (result,)
- return super(CallableMeta, self).__getitem__(parameters)
-
-
-class Callable(object):
- """Callable type; Callable[[int], str] is a function of (int) -> str.
-
- The subscription syntax must always be used with exactly two
- values: the argument list and the return type. The argument list
- must be a list of types or ellipsis; the return type must be a single type.
-
- There is no syntax to indicate optional or keyword arguments,
- such function types are rarely used as callback types.
- """
-
- __metaclass__ = CallableMeta
- __extra__ = collections_abc.Callable
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Callable):
- raise TypeError("Type Callable cannot be instantiated; "
- "use a non-abstract subclass instead")
- return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
-
-
-def cast(typ, val):
- """Cast a value to a type.
-
- This returns the value unchanged. To the type checker this
- signals that the return value has the designated type, but at
- runtime we intentionally don't check anything (we want this
- to be as fast as possible).
- """
- return val
-
-
-def _get_defaults(func):
- """Internal helper to extract the default arguments, by name."""
- code = func.__code__
- pos_count = code.co_argcount
- arg_names = code.co_varnames
- arg_names = arg_names[:pos_count]
- defaults = func.__defaults__ or ()
- kwdefaults = func.__kwdefaults__
- res = dict(kwdefaults) if kwdefaults else {}
- pos_offset = pos_count - len(defaults)
- for name, value in zip(arg_names[pos_offset:], defaults):
- assert name not in res
- res[name] = value
- return res
-
-
-def get_type_hints(obj, globalns=None, localns=None):
- """In Python 2 this is not supported and always returns None."""
- return None
-
-
-def no_type_check(arg):
- """Decorator to indicate that annotations are not type hints.
-
- The argument must be a class or function; if it is a class, it
- applies recursively to all methods and classes defined in that class
- (but not to methods defined in its superclasses or subclasses).
-
- This mutates the function(s) or class(es) in place.
- """
- if isinstance(arg, type):
- arg_attrs = arg.__dict__.copy()
- for attr, val in arg.__dict__.items():
- if val in arg.__bases__:
- arg_attrs.pop(attr)
- for obj in arg_attrs.values():
- if isinstance(obj, types.FunctionType):
- obj.__no_type_check__ = True
- if isinstance(obj, type):
- no_type_check(obj)
- try:
- arg.__no_type_check__ = True
- except TypeError: # built-in classes
- pass
- return arg
-
-
-def no_type_check_decorator(decorator):
- """Decorator to give another decorator the @no_type_check effect.
-
- This wraps the decorator with something that wraps the decorated
- function in @no_type_check.
- """
-
- @functools.wraps(decorator)
- def wrapped_decorator(*args, **kwds):
- func = decorator(*args, **kwds)
- func = no_type_check(func)
- return func
-
- return wrapped_decorator
-
-
-def _overload_dummy(*args, **kwds):
- """Helper for @overload to raise when called."""
- raise NotImplementedError(
- "You should not call an overloaded function. "
- "A series of @overload-decorated functions "
- "outside a stub module should always be followed "
- "by an implementation that is not @overload-ed.")
-
-
-def overload(func):
- """Decorator for overloaded functions/methods.
-
- In a stub file, place two or more stub definitions for the same
- function in a row, each decorated with @overload. For example:
-
- @overload
- def utf8(value: None) -> None: ...
- @overload
- def utf8(value: bytes) -> bytes: ...
- @overload
- def utf8(value: str) -> bytes: ...
-
- In a non-stub file (i.e. a regular .py file), do the same but
- follow it with an implementation. The implementation should *not*
- be decorated with @overload. For example:
-
- @overload
- def utf8(value: None) -> None: ...
- @overload
- def utf8(value: bytes) -> bytes: ...
- @overload
- def utf8(value: str) -> bytes: ...
- def utf8(value):
- # implementation goes here
- """
- return _overload_dummy
-
-
-class _ProtocolMeta(GenericMeta):
- """Internal metaclass for _Protocol.
-
- This exists so _Protocol classes can be generic without deriving
- from Generic.
- """
-
- def __instancecheck__(self, obj):
- if _Protocol not in self.__bases__:
- return super(_ProtocolMeta, self).__instancecheck__(obj)
- raise TypeError("Protocols cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- if not self._is_protocol:
- # No structural checks since this isn't a protocol.
- return NotImplemented
-
- if self is _Protocol:
- # Every class is a subclass of the empty protocol.
- return True
-
- # Find all attributes defined in the protocol.
- attrs = self._get_protocol_attrs()
-
- for attr in attrs:
- if not any(attr in d.__dict__ for d in cls.__mro__):
- return False
- return True
-
- def _get_protocol_attrs(self):
- # Get all Protocol base classes.
- protocol_bases = []
- for c in self.__mro__:
- if getattr(c, '_is_protocol', False) and c.__name__ != '_Protocol':
- protocol_bases.append(c)
-
- # Get attributes included in protocol.
- attrs = set()
- for base in protocol_bases:
- for attr in base.__dict__.keys():
- # Include attributes not defined in any non-protocol bases.
- for c in self.__mro__:
- if (c is not base and attr in c.__dict__ and
- not getattr(c, '_is_protocol', False)):
- break
- else:
- if (not attr.startswith('_abc_') and
- attr != '__abstractmethods__' and
- attr != '_is_protocol' and
- attr != '__dict__' and
- attr != '__args__' and
- attr != '__slots__' and
- attr != '_get_protocol_attrs' and
- attr != '__next_in_mro__' and
- attr != '__parameters__' and
- attr != '__origin__' and
- attr != '__orig_bases__' and
- attr != '__extra__' and
- attr != '__tree_hash__' and
- attr != '__module__'):
- attrs.add(attr)
-
- return attrs
-
-
-class _Protocol(object):
- """Internal base class for protocol classes.
-
- This implements a simple-minded structural issubclass check
- (similar but more general than the one-offs in collections.abc
- such as Hashable).
- """
-
- __metaclass__ = _ProtocolMeta
- __slots__ = ()
-
- _is_protocol = True
-
-
-# Various ABCs mimicking those in collections.abc.
-# A few are simply re-exported for completeness.
-
-Hashable = collections_abc.Hashable # Not generic.
-
-
-class Iterable(Generic[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Iterable
-
-
-class Iterator(Iterable[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Iterator
-
-
-class SupportsInt(_Protocol):
- __slots__ = ()
-
- @abstractmethod
- def __int__(self):
- pass
-
-
-class SupportsFloat(_Protocol):
- __slots__ = ()
-
- @abstractmethod
- def __float__(self):
- pass
-
-
-class SupportsComplex(_Protocol):
- __slots__ = ()
-
- @abstractmethod
- def __complex__(self):
- pass
-
-
-class SupportsAbs(_Protocol[T_co]):
- __slots__ = ()
-
- @abstractmethod
- def __abs__(self):
- pass
-
-
-if hasattr(collections_abc, 'Reversible'):
- class Reversible(Iterable[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Reversible
-else:
- class Reversible(_Protocol[T_co]):
- __slots__ = ()
-
- @abstractmethod
- def __reversed__(self):
- pass
-
-
-Sized = collections_abc.Sized # Not generic.
-
-
-class Container(Generic[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Container
-
-
-# Callable was defined earlier.
-
-
-class AbstractSet(Sized, Iterable[T_co], Container[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Set
-
-
-class MutableSet(AbstractSet[T]):
- __slots__ = ()
- __extra__ = collections_abc.MutableSet
-
-
-# NOTE: It is only covariant in the value type.
-class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co]):
- __slots__ = ()
- __extra__ = collections_abc.Mapping
-
-
-class MutableMapping(Mapping[KT, VT]):
- __slots__ = ()
- __extra__ = collections_abc.MutableMapping
-
-
-if hasattr(collections_abc, 'Reversible'):
- class Sequence(Sized, Reversible[T_co], Container[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Sequence
-else:
- class Sequence(Sized, Iterable[T_co], Container[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.Sequence
-
-
-class MutableSequence(Sequence[T]):
- __slots__ = ()
- __extra__ = collections_abc.MutableSequence
-
-
-class ByteString(Sequence[int]):
- pass
-
-
-ByteString.register(str)
-ByteString.register(bytearray)
-
-
-class List(list, MutableSequence[T]):
- __slots__ = ()
- __extra__ = list
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, List):
- raise TypeError("Type List cannot be instantiated; "
- "use list() instead")
- return _generic_new(list, cls, *args, **kwds)
-
-
-class Deque(collections.deque, MutableSequence[T]):
- __slots__ = ()
- __extra__ = collections.deque
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Deque):
- return collections.deque(*args, **kwds)
- return _generic_new(collections.deque, cls, *args, **kwds)
-
-
-class Set(set, MutableSet[T]):
- __slots__ = ()
- __extra__ = set
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Set):
- raise TypeError("Type Set cannot be instantiated; "
- "use set() instead")
- return _generic_new(set, cls, *args, **kwds)
-
-
-class FrozenSet(frozenset, AbstractSet[T_co]):
- __slots__ = ()
- __extra__ = frozenset
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, FrozenSet):
- raise TypeError("Type FrozenSet cannot be instantiated; "
- "use frozenset() instead")
- return _generic_new(frozenset, cls, *args, **kwds)
-
-
-class MappingView(Sized, Iterable[T_co]):
- __slots__ = ()
- __extra__ = collections_abc.MappingView
-
-
-class KeysView(MappingView[KT], AbstractSet[KT]):
- __slots__ = ()
- __extra__ = collections_abc.KeysView
-
-
-class ItemsView(MappingView[Tuple[KT, VT_co]],
- AbstractSet[Tuple[KT, VT_co]],
- Generic[KT, VT_co]):
- __slots__ = ()
- __extra__ = collections_abc.ItemsView
-
-
-class ValuesView(MappingView[VT_co]):
- __slots__ = ()
- __extra__ = collections_abc.ValuesView
-
-
-class ContextManager(Generic[T_co]):
- __slots__ = ()
-
- def __enter__(self):
- return self
-
- @abc.abstractmethod
- def __exit__(self, exc_type, exc_value, traceback):
- return None
-
- @classmethod
- def __subclasshook__(cls, C):
- if cls is ContextManager:
- # In Python 3.6+, it is possible to set a method to None to
- # explicitly indicate that the class does not implement an ABC
- # (https://bugs.python.org/issue25958), but we do not support
- # that pattern here because this fallback class is only used
- # in Python 3.5 and earlier.
- if (any("__enter__" in B.__dict__ for B in C.__mro__) and
- any("__exit__" in B.__dict__ for B in C.__mro__)):
- return True
- return NotImplemented
-
-
-class Dict(dict, MutableMapping[KT, VT]):
- __slots__ = ()
- __extra__ = dict
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Dict):
- raise TypeError("Type Dict cannot be instantiated; "
- "use dict() instead")
- return _generic_new(dict, cls, *args, **kwds)
-
-
-class DefaultDict(collections.defaultdict, MutableMapping[KT, VT]):
- __slots__ = ()
- __extra__ = collections.defaultdict
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, DefaultDict):
- return collections.defaultdict(*args, **kwds)
- return _generic_new(collections.defaultdict, cls, *args, **kwds)
-
-
-class Counter(collections.Counter, Dict[T, int]):
- __slots__ = ()
- __extra__ = collections.Counter
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Counter):
- return collections.Counter(*args, **kwds)
- return _generic_new(collections.Counter, cls, *args, **kwds)
-
-
-# Determine what base class to use for Generator.
-if hasattr(collections_abc, 'Generator'):
- # Sufficiently recent versions of 3.5 have a Generator ABC.
- _G_base = collections_abc.Generator
-else:
- # Fall back on the exact type.
- _G_base = types.GeneratorType
-
-
-class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]):
- __slots__ = ()
- __extra__ = _G_base
-
- def __new__(cls, *args, **kwds):
- if _geqv(cls, Generator):
- raise TypeError("Type Generator cannot be instantiated; "
- "create a subclass instead")
- return _generic_new(_G_base, cls, *args, **kwds)
-
-
-# Internal type variable used for Type[].
-CT_co = TypeVar('CT_co', covariant=True, bound=type)
-
-
-# This is not a real generic class. Don't use outside annotations.
-class Type(Generic[CT_co]):
- """A special construct usable to annotate class objects.
-
- For example, suppose we have the following classes::
-
- class User: ... # Abstract base for User classes
- class BasicUser(User): ...
- class ProUser(User): ...
- class TeamUser(User): ...
-
- And a function that takes a class argument that's a subclass of
- User and returns an instance of the corresponding class::
-
- U = TypeVar('U', bound=User)
- def new_user(user_class: Type[U]) -> U:
- user = user_class()
- # (Here we could write the user object to a database)
- return user
-
- joe = new_user(BasicUser)
-
- At this point the type checker knows that joe has type BasicUser.
- """
- __slots__ = ()
- __extra__ = type
-
-
-def NamedTuple(typename, fields):
- """Typed version of namedtuple.
-
- Usage::
-
- Employee = typing.NamedTuple('Employee', [('name', str), ('id', int)])
-
- This is equivalent to::
-
- Employee = collections.namedtuple('Employee', ['name', 'id'])
-
- The resulting class has one extra attribute: _field_types,
- giving a dict mapping field names to types. (The field names
- are in the _fields attribute, which is part of the namedtuple
- API.)
- """
- fields = [(n, t) for n, t in fields]
- cls = collections.namedtuple(typename, [n for n, t in fields])
- cls._field_types = dict(fields)
- # Set the module to the caller's module (otherwise it'd be 'typing').
- try:
- cls.__module__ = sys._getframe(1).f_globals.get('__name__', '__main__')
- except (AttributeError, ValueError):
- pass
- return cls
-
-
-def NewType(name, tp):
- """NewType creates simple unique types with almost zero
- runtime overhead. NewType(name, tp) is considered a subtype of tp
- by static type checkers. At runtime, NewType(name, tp) returns
- a dummy function that simply returns its argument. Usage::
-
- UserId = NewType('UserId', int)
-
- def name_by_id(user_id):
- # type: (UserId) -> str
- ...
-
- UserId('user') # Fails type check
-
- name_by_id(42) # Fails type check
- name_by_id(UserId(42)) # OK
-
- num = UserId(5) + 1 # type: int
- """
-
- def new_type(x):
- return x
-
- # Some versions of Python 2 complain because of making all strings unicode
- new_type.__name__ = str(name)
- new_type.__supertype__ = tp
- return new_type
-
-
-# Python-version-specific alias (Python 2: unicode; Python 3: str)
-Text = unicode
-
-
-# Constant that's True when type checking, but False here.
-TYPE_CHECKING = False
-
-
-class IO(Generic[AnyStr]):
- """Generic base class for TextIO and BinaryIO.
-
- This is an abstract, generic version of the return of open().
-
- NOTE: This does not distinguish between the different possible
- classes (text vs. binary, read vs. write vs. read/write,
- append-only, unbuffered). The TextIO and BinaryIO subclasses
- below capture the distinctions between text vs. binary, which is
- pervasive in the interface; however we currently do not offer a
- way to track the other distinctions in the type system.
- """
-
- __slots__ = ()
-
- @abstractproperty
- def mode(self):
- pass
-
- @abstractproperty
- def name(self):
- pass
-
- @abstractmethod
- def close(self):
- pass
-
- @abstractmethod
- def closed(self):
- pass
-
- @abstractmethod
- def fileno(self):
- pass
-
- @abstractmethod
- def flush(self):
- pass
-
- @abstractmethod
- def isatty(self):
- pass
-
- @abstractmethod
- def read(self, n=-1):
- pass
-
- @abstractmethod
- def readable(self):
- pass
-
- @abstractmethod
- def readline(self, limit=-1):
- pass
-
- @abstractmethod
- def readlines(self, hint=-1):
- pass
-
- @abstractmethod
- def seek(self, offset, whence=0):
- pass
-
- @abstractmethod
- def seekable(self):
- pass
-
- @abstractmethod
- def tell(self):
- pass
-
- @abstractmethod
- def truncate(self, size=None):
- pass
-
- @abstractmethod
- def writable(self):
- pass
-
- @abstractmethod
- def write(self, s):
- pass
-
- @abstractmethod
- def writelines(self, lines):
- pass
-
- @abstractmethod
- def __enter__(self):
- pass
-
- @abstractmethod
- def __exit__(self, type, value, traceback):
- pass
-
-
-class BinaryIO(IO[bytes]):
- """Typed version of the return of open() in binary mode."""
-
- __slots__ = ()
-
- @abstractmethod
- def write(self, s):
- pass
-
- @abstractmethod
- def __enter__(self):
- pass
-
-
-class TextIO(IO[unicode]):
- """Typed version of the return of open() in text mode."""
-
- __slots__ = ()
-
- @abstractproperty
- def buffer(self):
- pass
-
- @abstractproperty
- def encoding(self):
- pass
-
- @abstractproperty
- def errors(self):
- pass
-
- @abstractproperty
- def line_buffering(self):
- pass
-
- @abstractproperty
- def newlines(self):
- pass
-
- @abstractmethod
- def __enter__(self):
- pass
-
-
-class io(object):
- """Wrapper namespace for IO generic classes."""
-
- __all__ = ['IO', 'TextIO', 'BinaryIO']
- IO = IO
- TextIO = TextIO
- BinaryIO = BinaryIO
-
-
-io.__name__ = __name__ + b'.io'
-sys.modules[io.__name__] = io
-
-
-Pattern = _TypeAlias('Pattern', AnyStr, type(stdlib_re.compile('')),
- lambda p: p.pattern)
-Match = _TypeAlias('Match', AnyStr, type(stdlib_re.match('', '')),
- lambda m: m.re.pattern)
-
-
-class re(object):
- """Wrapper namespace for re type aliases."""
-
- __all__ = ['Pattern', 'Match']
- Pattern = Pattern
- Match = Match
-
-
-re.__name__ = __name__ + b'.re'
-sys.modules[re.__name__] = re