summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp55
-rw-r--r--Android_tests.py33
-rw-r--r--CHANGELOG19
-rw-r--r--LICENSE13
-rw-r--r--MANIFEST.in7
-rw-r--r--METADATA21
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--Makefile39
-rw-r--r--OWNERS5
-rw-r--r--README.rst83
-rw-r--r--docs/Makefile153
-rw-r--r--docs/_templates/page.html9
-rw-r--r--docs/conf.py251
-rw-r--r--docs/index.rst315
-rw-r--r--funcsigs/Android.bp31
-rw-r--r--funcsigs/__init__.py818
-rw-r--r--funcsigs/odict.py261
-rw-r--r--funcsigs/version.py1
-rw-r--r--requirements/development.txt6
-rw-r--r--requirements/production.txt0
-rw-r--r--setup.cfg2
-rw-r--r--setup.py55
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/test_formatannotation.py27
-rw-r--r--tests/test_funcsigs.py93
-rw-r--r--tests/test_inspect.py1019
26 files changed, 1 insertions, 3315 deletions
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 2f4dfa8..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["external_python_funcsigs_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
- name: "external_python_funcsigs_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-PSF-2.0",
- ],
- license_text: [
- "LICENSE",
- ],
-}
-
-python_test {
- name: "py3-funcsigs-tests",
- main: "Android_tests.py",
- srcs: [
- "tests/*.py",
- "Android_tests.py",
- ],
- host_supported: true,
- libs: ["py-funcsigs"],
- data: ["README.rst"],
-}
diff --git a/Android_tests.py b/Android_tests.py
deleted file mode 100644
index ac84729..0000000
--- a/Android_tests.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2018 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-# this runs any test*.py files located anywhere in this subtree
-if __name__ == '__main__':
- test_loader = unittest.defaultTestLoader
- # output is normal text formatting (as if running from a CLI), prints to stderr
- test_runner = unittest.TextTestRunner(stream=sys.stderr)
-
- # look at tests relative to the dir of this file.
- this_dir = os.path.dirname(os.path.abspath(__file__))
-
- # automagically find all tests recursively whose file name matches test*.py
- test_suite = test_loader.discover(this_dir, pattern='test*.py')
-
- # execute all the found tests
- test_runner.run(test_suite)
-
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 602eec5..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,19 +0,0 @@
-Changelog
----------
-
-0.4 (2013-12-20)
-````````````````
-* Fix unbound methods getting their first parameter curried
-* Publish Python wheel packages
-
-0.3 (2013-05-29)
-````````````````
-* Fix annotation formatting of builtin types on Python 2.x
-
-0.2 (2012-01-07)
-````````````````
-* PyPy compatability
-
-0.1 (2012-01-06)
-````````````````
-* Initial release
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 3e563d6..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2013 Aaron Iles
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index f0abb42..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,7 +0,0 @@
-recursive-include docs *
-recursive-include tests *.py
-include *.py
-include CHANGELOG
-include LICENSE
-include MANIFEST.in
-include README.rst
diff --git a/METADATA b/METADATA
deleted file mode 100644
index 1539e3a..0000000
--- a/METADATA
+++ /dev/null
@@ -1,21 +0,0 @@
-name: "funcsigs"
-description:
- "funcsigs is a backport of the PEP 362 function signature features from "
- "Python 3.3's inspect module. The backport is compatible with Python 2.6, "
- "2.7 as well as 3.2 and up. "
- " "
- "(The primary purpose for importing this is as a pytest dependency)"
-
-third_party {
- url {
- type: HOMEPAGE
- value: "https://pypi.org/project/funcsigs/"
- }
- url {
- type: GIT
- value: "https://github.com/aliles/funcsigs.git"
- }
- version: "0.4"
- last_upgrade_date { year: 2018 month: 8 day: 2 }
- license_type: NOTICE
-}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/Makefile b/Makefile
deleted file mode 100644
index e232923..0000000
--- a/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-SHELL := /bin/bash
-
-deps:
- pip install --upgrade \
- -r requirements/development.txt \
- -r requirements/production.txt
-
-sdist:
- python setup.py sdist
- python setup.py bdist_wheel
-
-register:
- python setup.py register
- python setup.py sdist upload
- python setup.py bdist_wheel upload
-
-site:
- cd docs; make html
-
-test:
- coverage run setup.py test
-
-unittest:
- coverage run -m unittest discover
-
-lint:
- flake8 --exit-zero funcsigs tests
-
-coverage:
- coverage report --show-missing
-
-clean:
- python setup.py clean --all
- find . -type f -name "*.pyc" -exec rm '{}' +
- find . -type d -name "__pycache__" -exec rmdir '{}' +
- rm -rf *.egg-info .coverage
- cd docs; make clean
-
-docs: site
diff --git a/OWNERS b/OWNERS
index 136a553..7529cb9 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1 @@
-# Default owners are top 3 or more active developers of the past 1 or 2 years
-# or people with more than 10 commits last year.
-# Please update this list if you find better owner candidates.
-iam@google.com
+include platform/system/core:/janitors/OWNERS
diff --git a/README.rst b/README.rst
deleted file mode 100644
index f04b7b4..0000000
--- a/README.rst
+++ /dev/null
@@ -1,83 +0,0 @@
-funcsigs
-========
-
-``funcsigs`` is a backport of the `PEP 362`_ function signature features from
-Python 3.3's `inspect`_ module. The backport is compatible with Python 2.6, 2.7
-as well as 3.2 and up.
-
-|pypi_version|
-
-Documentation
--------------
-
-The reference documentation is standard library documentation for the
-`inspect`_ module in Python3. This documentation has been included in the
-``funcsigs`` package documentation hosted on `Read The Docs`_.
-
-Example
--------
-
-To obtain a signature object, pass the target function to the
-``funcsigs.signature`` function. ::
-
- >>> from funcsigs import signature
- >>> def foo(a, b=None, *args, **kwargs):
- ... pass
-
- >>> sig = signature(foo)
-
-For the details of the signature object, refer to the either the package of
-standard library documentation.
-
-Compatability
--------------
-
-The ``funcsigs`` backport has been tested against:
-
-* CPython 2.6
-* CPython 2.7
-* CPython 3.2
-* PyPy 1.9
-
-Continuous integration testing is provided by `Travis CI`_.
-
-Under Python 2.x there is a compatability issue when a function is assigned to
-the ``__wrapped__`` property of a class after it has been constructed.
-Similiarily there under PyPy directly passing the ``__call__`` method of a
-builtin is also a compatability issues. Otherwise the functionality is
-believed to be uniform between both Python2 and Python3.
-
-Issues
-------
-
-Source code for ``funcsigs`` is hosted on `GitHub`_. Any bug reports or feature
-requests can be made using GitHub's `issues system`_. |build_status| |coverage|
-
-Copyright
----------
-
-This is a derived work of CPython under the terms of the `PSF License
-Agreement`_. The original CPython inspect module, its unit tests and
-documentation are the copyright of the Python Software Foundation. The derived
-work is distributed under the `Apache License Version 2.0`_.
-
-.. _Apache License Version 2.0: http://opensource.org/licenses/Apache-2.0
-.. _GitHub: https://github.com/aliles/funcsigs
-.. _PSF License Agreement: http://docs.python.org/3/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
-.. _Travis CI: http://travis-ci.org/
-.. _Read The Docs: http://funcsigs.readthedocs.org/
-.. _PEP 362: http://www.python.org/dev/peps/pep-0362/
-.. _inspect: http://docs.python.org/3/library/inspect.html#introspecting-callables-with-the-signature-object
-.. _issues system: https://github.com/alies/funcsigs/issues
-
-.. |build_status| image:: https://secure.travis-ci.org/aliles/funcsigs.png?branch=master
- :target: http://travis-ci.org/#!/aliles/funcsigs
- :alt: Current build status
-
-.. |coverage| image:: https://coveralls.io/repos/aliles/funcsigs/badge.png?branch=master
- :target: https://coveralls.io/r/aliles/funcsigs?branch=master
- :alt: Coverage status
-
-.. |pypi_version| image:: https://pypip.in/v/funcsigs/badge.png
- :target: https://crate.io/packages/funcsigs/
- :alt: Latest PyPI version
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index f7ab3d1..0000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,153 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/funcsigs.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/funcsigs.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/funcsigs"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/funcsigs"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/_templates/page.html b/docs/_templates/page.html
deleted file mode 100644
index 5e1e00b..0000000
--- a/docs/_templates/page.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "!page.html" %}
-{% block extrahead %}
- <a href="https://github.com/aliles/funcsigs">
- <img style="position: absolute; top: 0; right: 0; border: 0;"
- src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"
- alt="Fork me on GitHub">
- </a>
- {{ super() }}
-{% endblock %}
diff --git a/docs/conf.py b/docs/conf.py
deleted file mode 100644
index c6e4194..0000000
--- a/docs/conf.py
+++ /dev/null
@@ -1,251 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-#
-# funcsigs documentation build configuration file, created by
-# sphinx-quickstart on Fri Apr 20 20:27:52 2012.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('..'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = 'funcsigs'
-copyright = '2013, Aaron Iles'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-from funcsigs import __version__
-version = '.'.join(__version__.split('.')[:2])
-# The full version, including alpha/beta/rc tags.
-release = __version__
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'agogo'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'funcsigsdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('index', 'funcsigs.tex', 'funcsigs Documentation',
- 'Aaron Iles', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'funcsigs', 'funcsigs Documentation',
- ['Aaron Iles'], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output ------------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- ('index', 'funcsigs', 'funcsigs Documentation',
- 'Aaron Iles', 'funcsigs', 'One line description of project.',
- 'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {
- 'python3': ('http://docs.python.org/py3k', None),
- 'python': ('http://docs.python.org/', None)
-}
diff --git a/docs/index.rst b/docs/index.rst
deleted file mode 100644
index 5d0f42f..0000000
--- a/docs/index.rst
+++ /dev/null
@@ -1,315 +0,0 @@
-.. funcsigs documentation master file, created by
- sphinx-quickstart on Fri Apr 20 20:27:52 2012.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-Introducing funcsigs
-====================
-
-The Funcsigs Package
---------------------
-
-*funcsigs* is a backport of the `PEP 362`_ function signature features from
-Python 3.3's `inspect`_ module. The backport is compatible with Python 2.6, 2.7
-as well as 3.2 and up.
-
-.. _PEP 362: http://www.python.org/dev/peps/pep-0362/
-.. _inspect: http://docs.python.org/3/library/inspect.html#introspecting-callables-with-the-signature-object
-
-Compatability
-`````````````
-
-The *funcsigs* backport has been tested against:
-
-* CPython 2.6
-* CPython 2.7
-* CPython 3.2
-* PyPy 1.9
-
-Continuous integration testing is provided by `Travis CI`_.
-
-Under Python 2.x there is a compatability issue when a function is assigned to
-the ``__wrapped__`` property of a class after it has been constructed.
-Similiarily there under PyPy directly passing the ``__call__`` method of a
-builtin is also a compatability issues. Otherwise the functionality is
-believed to be uniform between both Python2 and Python3.
-
-.. _Travis CI: http://travis-ci.org/
-
-Issues
-``````
-
-Source code for *funcsigs* is hosted on `GitHub`_. Any bug reports or feature
-requests can be made using GitHub's `issues system`_.
-
-.. _GitHub: https://github.com/aliles/funcsigs
-.. _issues system: https://github.com/alies/funcsigs/issues
-
-Introspecting callables with the Signature object
--------------------------------------------------
-
-.. note::
-
- This section of documentation is a direct repoduction of the Python
- standard library documentation for the inspect module.
-
-The Signature object represents the call signature of a callable object and its
-return annotation. To retrieve a Signature object, use the :func:`signature`
-function.
-
-.. function:: signature(callable)
-
- Return a :class:`Signature` object for the given ``callable``::
-
- >>> from inspect import signature
- >>> def foo(a, *, b:int, **kwargs):
- ... pass
-
- >>> sig = signature(foo)
-
- >>> str(sig)
- '(a, *, b:int, **kwargs)'
-
- >>> str(sig.parameters['b'])
- 'b:int'
-
- >>> sig.parameters['b'].annotation
- <class 'int'>
-
- Accepts a wide range of python callables, from plain functions and classes to
- :func:`functools.partial` objects.
-
- .. note::
-
- Some callables may not be introspectable in certain implementations of
- Python. For example, in CPython, built-in functions defined in C provide
- no metadata about their arguments.
-
-
-.. class:: Signature
-
- A Signature object represents the call signature of a function and its return
- annotation. For each parameter accepted by the function it stores a
- :class:`Parameter` object in its :attr:`parameters` collection.
-
- Signature objects are *immutable*. Use :meth:`Signature.replace` to make a
- modified copy.
-
- .. attribute:: Signature.empty
-
- A special class-level marker to specify absence of a return annotation.
-
- .. attribute:: Signature.parameters
-
- An ordered mapping of parameters' names to the corresponding
- :class:`Parameter` objects.
-
- .. attribute:: Signature.return_annotation
-
- The "return" annotation for the callable. If the callable has no "return"
- annotation, this attribute is set to :attr:`Signature.empty`.
-
- .. method:: Signature.bind(*args, **kwargs)
-
- Create a mapping from positional and keyword arguments to parameters.
- Returns :class:`BoundArguments` if ``*args`` and ``**kwargs`` match the
- signature, or raises a :exc:`TypeError`.
-
- .. method:: Signature.bind_partial(*args, **kwargs)
-
- Works the same way as :meth:`Signature.bind`, but allows the omission of
- some required arguments (mimics :func:`functools.partial` behavior.)
- Returns :class:`BoundArguments`, or raises a :exc:`TypeError` if the
- passed arguments do not match the signature.
-
- .. method:: Signature.replace(*[, parameters][, return_annotation])
-
- Create a new Signature instance based on the instance replace was invoked
- on. It is possible to pass different ``parameters`` and/or
- ``return_annotation`` to override the corresponding properties of the base
- signature. To remove return_annotation from the copied Signature, pass in
- :attr:`Signature.empty`.
-
- ::
-
- >>> def test(a, b):
- ... pass
- >>> sig = signature(test)
- >>> new_sig = sig.replace(return_annotation="new return anno")
- >>> str(new_sig)
- "(a, b) -> 'new return anno'"
-
-
-.. class:: Parameter
-
- Parameter objects are *immutable*. Instead of modifying a Parameter object,
- you can use :meth:`Parameter.replace` to create a modified copy.
-
- .. attribute:: Parameter.empty
-
- A special class-level marker to specify absence of default values and
- annotations.
-
- .. attribute:: Parameter.name
-
- The name of the parameter as a string. Must be a valid python identifier
- name (with the exception of ``POSITIONAL_ONLY`` parameters, which can have
- it set to ``None``).
-
- .. attribute:: Parameter.default
-
- The default value for the parameter. If the parameter has no default
- value, this attribute is set to :attr:`Parameter.empty`.
-
- .. attribute:: Parameter.annotation
-
- The annotation for the parameter. If the parameter has no annotation,
- this attribute is set to :attr:`Parameter.empty`.
-
- .. attribute:: Parameter.kind
-
- Describes how argument values are bound to the parameter. Possible values
- (accessible via :class:`Parameter`, like ``Parameter.KEYWORD_ONLY``):
-
- +------------------------+----------------------------------------------+
- | Name | Meaning |
- +========================+==============================================+
- | *POSITIONAL_ONLY* | Value must be supplied as a positional |
- | | argument. |
- | | |
- | | Python has no explicit syntax for defining |
- | | positional-only parameters, but many built-in|
- | | and extension module functions (especially |
- | | those that accept only one or two parameters)|
- | | accept them. |
- +------------------------+----------------------------------------------+
- | *POSITIONAL_OR_KEYWORD*| Value may be supplied as either a keyword or |
- | | positional argument (this is the standard |
- | | binding behaviour for functions implemented |
- | | in Python.) |
- +------------------------+----------------------------------------------+
- | *VAR_POSITIONAL* | A tuple of positional arguments that aren't |
- | | bound to any other parameter. This |
- | | corresponds to a ``*args`` parameter in a |
- | | Python function definition. |
- +------------------------+----------------------------------------------+
- | *KEYWORD_ONLY* | Value must be supplied as a keyword argument.|
- | | Keyword only parameters are those which |
- | | appear after a ``*`` or ``*args`` entry in a |
- | | Python function definition. |
- +------------------------+----------------------------------------------+
- | *VAR_KEYWORD* | A dict of keyword arguments that aren't bound|
- | | to any other parameter. This corresponds to a|
- | | ``**kwargs`` parameter in a Python function |
- | | definition. |
- +------------------------+----------------------------------------------+
-
- Example: print all keyword-only arguments without default values::
-
- >>> def foo(a, b, *, c, d=10):
- ... pass
-
- >>> sig = signature(foo)
- >>> for param in sig.parameters.values():
- ... if (param.kind == param.KEYWORD_ONLY and
- ... param.default is param.empty):
- ... print('Parameter:', param)
- Parameter: c
-
- .. method:: Parameter.replace(*[, name][, kind][, default][, annotation])
-
- Create a new Parameter instance based on the instance replaced was invoked
- on. To override a :class:`Parameter` attribute, pass the corresponding
- argument. To remove a default value or/and an annotation from a
- Parameter, pass :attr:`Parameter.empty`.
-
- ::
-
- >>> from inspect import Parameter
- >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42)
- >>> str(param)
- 'foo=42'
-
- >>> str(param.replace()) # Will create a shallow copy of 'param'
- 'foo=42'
-
- >>> str(param.replace(default=Parameter.empty, annotation='spam'))
- "foo:'spam'"
-
-
-.. class:: BoundArguments
-
- Result of a :meth:`Signature.bind` or :meth:`Signature.bind_partial` call.
- Holds the mapping of arguments to the function's parameters.
-
- .. attribute:: BoundArguments.arguments
-
- An ordered, mutable mapping (:class:`collections.OrderedDict`) of
- parameters' names to arguments' values. Contains only explicitly bound
- arguments. Changes in :attr:`arguments` will reflect in :attr:`args` and
- :attr:`kwargs`.
-
- Should be used in conjunction with :attr:`Signature.parameters` for any
- argument processing purposes.
-
- .. note::
-
- Arguments for which :meth:`Signature.bind` or
- :meth:`Signature.bind_partial` relied on a default value are skipped.
- However, if needed, it is easy to include them.
-
- ::
-
- >>> def foo(a, b=10):
- ... pass
-
- >>> sig = signature(foo)
- >>> ba = sig.bind(5)
-
- >>> ba.args, ba.kwargs
- ((5,), {})
-
- >>> for param in sig.parameters.values():
- ... if param.name not in ba.arguments:
- ... ba.arguments[param.name] = param.default
-
- >>> ba.args, ba.kwargs
- ((5, 10), {})
-
-
- .. attribute:: BoundArguments.args
-
- A tuple of positional arguments values. Dynamically computed from the
- :attr:`arguments` attribute.
-
- .. attribute:: BoundArguments.kwargs
-
- A dict of keyword arguments values. Dynamically computed from the
- :attr:`arguments` attribute.
-
- The :attr:`args` and :attr:`kwargs` properties can be used to invoke
- functions::
-
- def test(a, *, b):
- ...
-
- sig = signature(test)
- ba = sig.bind(10, b=20)
- test(*ba.args, **ba.kwargs)
-
-
-.. seealso::
-
- :pep:`362` - Function Signature Object.
- The detailed specification, implementation details and examples.
-
-Copyright
----------
-
-*funcsigs* is a derived work of CPython under the terms of the `PSF License
-Agreement`_. The original CPython inspect module, its unit tests and
-documentation are the copyright of the Python Software Foundation. The derived
-work is distributed under the `Apache License Version 2.0`_.
-
-.. _PSF License Agreement: http://docs.python.org/3/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
-.. _Apache License Version 2.0: http://opensource.org/licenses/Apache-2.0
diff --git a/funcsigs/Android.bp b/funcsigs/Android.bp
deleted file mode 100644
index 74882e7..0000000
--- a/funcsigs/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "external_python_funcsigs_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["external_python_funcsigs_license"],
-}
-
-python_library {
- name: "py-funcsigs",
- host_supported: true,
- srcs: [
- "*.py",
- ],
- pkg_path: "funcsigs",
-}
diff --git a/funcsigs/__init__.py b/funcsigs/__init__.py
deleted file mode 100644
index fd2f47b..0000000
--- a/funcsigs/__init__.py
+++ /dev/null
@@ -1,818 +0,0 @@
-# Copyright 2001-2013 Python Software Foundation; All Rights Reserved
-"""Function signature objects for callables
-
-Back port of Python 3.3's function signature tools from the inspect module,
-modified to be compatible with Python 2.6, 2.7 and 3.2+.
-"""
-from __future__ import absolute_import, division, print_function
-import itertools
-import functools
-import re
-import types
-
-try:
- from collections import OrderedDict
-except ImportError:
- from funcsigs.odict import OrderedDict
-
-from funcsigs.version import __version__
-
-__all__ = ['BoundArguments', 'Parameter', 'Signature', 'signature']
-
-
-_WrapperDescriptor = type(type.__call__)
-_MethodWrapper = type(all.__call__)
-
-_NonUserDefinedCallables = (_WrapperDescriptor,
- _MethodWrapper,
- types.BuiltinFunctionType)
-
-
-def formatannotation(annotation, base_module=None):
- if isinstance(annotation, type):
- if annotation.__module__ in ('builtins', '__builtin__', base_module):
- return annotation.__name__
- return annotation.__module__+'.'+annotation.__name__
- return repr(annotation)
-
-
-def _get_user_defined_method(cls, method_name, *nested):
- try:
- if cls is type:
- return
- meth = getattr(cls, method_name)
- for name in nested:
- meth = getattr(meth, name, meth)
- except AttributeError:
- return
- else:
- if not isinstance(meth, _NonUserDefinedCallables):
- # Once '__signature__' will be added to 'C'-level
- # callables, this check won't be necessary
- return meth
-
-
-def signature(obj):
- '''Get a signature object for the passed callable.'''
-
- if not callable(obj):
- raise TypeError('{0!r} is not a callable object'.format(obj))
-
- if isinstance(obj, types.MethodType):
- sig = signature(obj.__func__)
- if obj.__self__ is None:
- # Unbound method: the first parameter becomes positional-only
- if sig.parameters:
- first = sig.parameters.values()[0].replace(
- kind=_POSITIONAL_ONLY)
- return sig.replace(
- parameters=(first,) + tuple(sig.parameters.values())[1:])
- else:
- return sig
- else:
- # In this case we skip the first parameter of the underlying
- # function (usually `self` or `cls`).
- return sig.replace(parameters=tuple(sig.parameters.values())[1:])
-
- try:
- sig = obj.__signature__
- except AttributeError:
- pass
- else:
- if sig is not None:
- return sig
-
- try:
- # Was this function wrapped by a decorator?
- wrapped = obj.__wrapped__
- except AttributeError:
- pass
- else:
- return signature(wrapped)
-
- if isinstance(obj, types.FunctionType):
- return Signature.from_function(obj)
-
- if isinstance(obj, functools.partial):
- sig = signature(obj.func)
-
- new_params = OrderedDict(sig.parameters.items())
-
- partial_args = obj.args or ()
- partial_keywords = obj.keywords or {}
- try:
- ba = sig.bind_partial(*partial_args, **partial_keywords)
- except TypeError as ex:
- msg = 'partial object {0!r} has incorrect arguments'.format(obj)
- raise ValueError(msg)
-
- for arg_name, arg_value in ba.arguments.items():
- param = new_params[arg_name]
- if arg_name in partial_keywords:
- # We set a new default value, because the following code
- # is correct:
- #
- # >>> def foo(a): print(a)
- # >>> print(partial(partial(foo, a=10), a=20)())
- # 20
- # >>> print(partial(partial(foo, a=10), a=20)(a=30))
- # 30
- #
- # So, with 'partial' objects, passing a keyword argument is
- # like setting a new default value for the corresponding
- # parameter
- #
- # We also mark this parameter with '_partial_kwarg'
- # flag. Later, in '_bind', the 'default' value of this
- # parameter will be added to 'kwargs', to simulate
- # the 'functools.partial' real call.
- new_params[arg_name] = param.replace(default=arg_value,
- _partial_kwarg=True)
-
- elif (param.kind not in (_VAR_KEYWORD, _VAR_POSITIONAL) and
- not param._partial_kwarg):
- new_params.pop(arg_name)
-
- return sig.replace(parameters=new_params.values())
-
- sig = None
- if isinstance(obj, type):
- # obj is a class or a metaclass
-
- # First, let's see if it has an overloaded __call__ defined
- # in its metaclass
- call = _get_user_defined_method(type(obj), '__call__')
- if call is not None:
- sig = signature(call)
- else:
- # Now we check if the 'obj' class has a '__new__' method
- new = _get_user_defined_method(obj, '__new__')
- if new is not None:
- sig = signature(new)
- else:
- # Finally, we should have at least __init__ implemented
- init = _get_user_defined_method(obj, '__init__')
- if init is not None:
- sig = signature(init)
- elif not isinstance(obj, _NonUserDefinedCallables):
- # An object with __call__
- # We also check that the 'obj' is not an instance of
- # _WrapperDescriptor or _MethodWrapper to avoid
- # infinite recursion (and even potential segfault)
- call = _get_user_defined_method(type(obj), '__call__', 'im_func')
- if call is not None:
- sig = signature(call)
-
- if sig is not None:
- # For classes and objects we skip the first parameter of their
- # __call__, __new__, or __init__ methods
- return sig.replace(parameters=tuple(sig.parameters.values())[1:])
-
- if isinstance(obj, types.BuiltinFunctionType):
- # Raise a nicer error message for builtins
- msg = 'no signature found for builtin function {0!r}'.format(obj)
- raise ValueError(msg)
-
- raise ValueError('callable {0!r} is not supported by signature'.format(obj))
-
-
-class _void(object):
- '''A private marker - used in Parameter & Signature'''
-
-
-class _empty(object):
- pass
-
-
-class _ParameterKind(int):
- def __new__(self, *args, **kwargs):
- obj = int.__new__(self, *args)
- obj._name = kwargs['name']
- return obj
-
- def __str__(self):
- return self._name
-
- def __repr__(self):
- return '<_ParameterKind: {0!r}>'.format(self._name)
-
-
-_POSITIONAL_ONLY = _ParameterKind(0, name='POSITIONAL_ONLY')
-_POSITIONAL_OR_KEYWORD = _ParameterKind(1, name='POSITIONAL_OR_KEYWORD')
-_VAR_POSITIONAL = _ParameterKind(2, name='VAR_POSITIONAL')
-_KEYWORD_ONLY = _ParameterKind(3, name='KEYWORD_ONLY')
-_VAR_KEYWORD = _ParameterKind(4, name='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 not set.
- * annotation
- The annotation for the parameter if specified. If the
- parameter has no annotation, this attribute is not set.
- * 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', '_partial_kwarg')
-
- 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,
- _partial_kwarg=False):
-
- 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 = '{0} parameters cannot have default values'.format(kind)
- raise ValueError(msg)
- self._default = default
- self._annotation = annotation
-
- if name is None:
- if kind != _POSITIONAL_ONLY:
- raise ValueError("None is not a valid name for a "
- "non-positional-only parameter")
- self._name = name
- else:
- name = str(name)
- if kind != _POSITIONAL_ONLY and not re.match(r'[a-z_]\w*$', name, re.I):
- msg = '{0!r} is not a valid parameter name'.format(name)
- raise ValueError(msg)
- self._name = name
-
- self._partial_kwarg = _partial_kwarg
-
- @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, _partial_kwarg=_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
-
- if _partial_kwarg is _void:
- _partial_kwarg = self._partial_kwarg
-
- return type(self)(name, kind, default=default, annotation=annotation,
- _partial_kwarg=_partial_kwarg)
-
- def __str__(self):
- kind = self.kind
-
- formatted = self._name
- if kind == _POSITIONAL_ONLY:
- if formatted is None:
- formatted = ''
- formatted = '<{0}>'.format(formatted)
-
- # Add annotation and default value
- if self._annotation is not _empty:
- formatted = '{0}:{1}'.format(formatted,
- formatannotation(self._annotation))
-
- if self._default is not _empty:
- formatted = '{0}={1}'.format(formatted, repr(self._default))
-
- if kind == _VAR_POSITIONAL:
- formatted = '*' + formatted
- elif kind == _VAR_KEYWORD:
- formatted = '**' + formatted
-
- return formatted
-
- def __repr__(self):
- return '<{0} at {1:#x} {2!r}>'.format(self.__class__.__name__,
- id(self), self.name)
-
- def __hash__(self):
- msg = "unhashable type: '{0}'".format(self.__class__.__name__)
- raise TypeError(msg)
-
- def __eq__(self, other):
- return (issubclass(other.__class__, Parameter) and
- self._name == other._name and
- self._kind == other._kind and
- self._default == other._default and
- self._annotation == other._annotation)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
-
-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.
- '''
-
- 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) or
- param._partial_kwarg):
- # Keyword arguments mapped by 'functools.partial'
- # (Parameter._partial_kwarg is True) are mapped
- # in 'BoundArguments.kwargs', along with 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) or
- param._partial_kwarg):
- 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 __hash__(self):
- msg = "unhashable type: '{0}'".format(self.__class__.__name__)
- raise TypeError(msg)
-
- def __eq__(self, other):
- return (issubclass(other.__class__, BoundArguments) and
- self.signature == other.signature and
- self.arguments == other.arguments)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
-
-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 not set.
- * 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
-
- for idx, param in enumerate(parameters):
- kind = param.kind
- if kind < top_kind:
- msg = 'wrong parameter order: {0} before {1}'
- msg = msg.format(top_kind, param.kind)
- raise ValueError(msg)
- else:
- top_kind = kind
-
- name = param.name
- if name is None:
- name = str(idx)
- param = param.replace(name=name)
-
- if name in params:
- msg = 'duplicate parameter name: {0!r}'.format(name)
- raise ValueError(msg)
- params[name] = param
- else:
- params = OrderedDict(((param.name, param)
- for param in parameters))
-
- self._parameters = params
- self._return_annotation = return_annotation
-
- @classmethod
- def from_function(cls, func):
- '''Constructs Signature for the given python function'''
-
- if not isinstance(func, types.FunctionType):
- raise TypeError('{0!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 = getattr(func_code, 'co_kwonlyargcount', 0)
- keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)]
- annotations = getattr(func, '__annotations__', {})
- defaults = func.__defaults__
- kwdefaults = getattr(func, '__kwdefaults__', None)
-
- 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 & 0x04:
- 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 & 0x08:
- index = pos_count + keyword_only_count
- if func_code.co_flags & 0x04:
- index += 1
-
- name = arg_names[index]
- annotation = annotations.get(name, _empty)
- parameters.append(Parameter(name, annotation=annotation,
- kind=_VAR_KEYWORD))
-
- return cls(parameters,
- return_annotation=annotations.get('return', _empty),
- __validate_parameters__=False)
-
- @property
- def parameters(self):
- try:
- return types.MappingProxyType(self._parameters)
- except AttributeError:
- return OrderedDict(self._parameters.items())
-
- @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__(self):
- msg = "unhashable type: '{0}'".format(self.__class__.__name__)
- raise TypeError(msg)
-
- def __eq__(self, other):
- if (not issubclass(type(other), Signature) or
- self.return_annotation != other.return_annotation or
- len(self.parameters) != len(other.parameters)):
- return False
-
- other_positions = dict((param, idx)
- for idx, param in enumerate(other.parameters.keys()))
-
- for idx, (param_name, param) in enumerate(self.parameters.items()):
- if param.kind == _KEYWORD_ONLY:
- try:
- other_param = other.parameters[param_name]
- except KeyError:
- return False
- else:
- if param != other_param:
- return False
- else:
- try:
- other_idx = other_positions[param_name]
- except KeyError:
- return False
- else:
- if (idx != other_idx or
- param != other.parameters[param_name]):
- return False
-
- return True
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- 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)
-
- if partial:
- # Support for binding arguments to 'functools.partial' objects.
- # See 'functools.partial' case in 'signature()' implementation
- # for details.
- for param_name, param in self.parameters.items():
- if (param._partial_kwarg and param_name not in kwargs):
- # Simulating 'functools.partial' behavior
- kwargs[param_name] = param.default
-
- 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)
- 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:
- if partial:
- parameters_ex = (param,)
- break
- else:
- msg = '{arg!r} parameter lacking default value'
- msg = msg.format(arg=param.name)
- raise TypeError(msg)
- else:
- # We have a positional argument to process
- try:
- param = next(parameters)
- except StopIteration:
- raise TypeError('too many positional arguments')
- 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')
-
- 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))
-
- 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 == _POSITIONAL_ONLY:
- # This should never happen in case of a properly built
- # Signature object (but let's have this check here
- # to ensure correct behaviour just in case)
- raise TypeError('{arg!r} parameter is positional only, '
- 'but was passed as a keyword'. \
- format(arg=param.name))
-
- if param.kind == _VAR_KEYWORD:
- # Memorize that we have a '**kwargs'-like parameter
- kwargs_param = param
- 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('{arg!r} parameter lacking default value'. \
- format(arg=param_name))
-
- else:
- 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('too many keyword arguments')
-
- return self._bound_arguments_cls(self, arguments)
-
- def bind(self, *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 self._bind(args, kwargs)
-
- def bind_partial(self, *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 self._bind(args, kwargs, partial=True)
-
- def __str__(self):
- result = []
- render_kw_only_separator = True
- for idx, param in enumerate(self.parameters.values()):
- formatted = str(param)
-
- kind = param.kind
- 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)
-
- rendered = '({0})'.format(', '.join(result))
-
- if self.return_annotation is not _empty:
- anno = formatannotation(self.return_annotation)
- rendered += ' -> {0}'.format(anno)
-
- return rendered
diff --git a/funcsigs/odict.py b/funcsigs/odict.py
deleted file mode 100644
index 6221e97..0000000
--- a/funcsigs/odict.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
-# Passes Python2.7's test suite and incorporates all the latest updates.
-# Copyright 2009 Raymond Hettinger
-# http://code.activestate.com/recipes/576693/
-"Ordered dictionary"
-
-try:
- from thread import get_ident as _get_ident
-except ImportError:
- from dummy_thread import get_ident as _get_ident
-
-try:
- from _abcoll import KeysView, ValuesView, ItemsView
-except ImportError:
- pass
-
-
-class OrderedDict(dict):
- 'Dictionary that remembers insertion order'
- # An inherited dict maps keys to values.
- # The inherited dict provides __getitem__, __len__, __contains__, and get.
- # The remaining methods are order-aware.
- # Big-O running times for all methods are the same as for regular dictionaries.
-
- # The internal self.__map dictionary maps keys to links in a doubly linked list.
- # The circular doubly linked list starts and ends with a sentinel element.
- # The sentinel element never gets deleted (this simplifies the algorithm).
- # Each link is stored as a list of length three: [PREV, NEXT, KEY].
-
- def __init__(self, *args, **kwds):
- '''Initialize an ordered dictionary. Signature is the same as for
- regular dictionaries, but keyword arguments are not recommended
- because their insertion order is arbitrary.
-
- '''
- if len(args) > 1:
- raise TypeError('expected at most 1 arguments, got %d' % len(args))
- try:
- self.__root
- except AttributeError:
- self.__root = root = [] # sentinel node
- root[:] = [root, root, None]
- self.__map = {}
- self.__update(*args, **kwds)
-
- def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
- 'od.__setitem__(i, y) <==> od[i]=y'
- # Setting a new item creates a new link which goes at the end of the linked
- # list, and the inherited dictionary is updated with the new key/value pair.
- if key not in self:
- root = self.__root
- last = root[0]
- last[1] = root[0] = self.__map[key] = [last, root, key]
- dict_setitem(self, key, value)
-
- def __delitem__(self, key, dict_delitem=dict.__delitem__):
- 'od.__delitem__(y) <==> del od[y]'
- # Deleting an existing item uses self.__map to find the link which is
- # then removed by updating the links in the predecessor and successor nodes.
- dict_delitem(self, key)
- link_prev, link_next, key = self.__map.pop(key)
- link_prev[1] = link_next
- link_next[0] = link_prev
-
- def __iter__(self):
- 'od.__iter__() <==> iter(od)'
- root = self.__root
- curr = root[1]
- while curr is not root:
- yield curr[2]
- curr = curr[1]
-
- def __reversed__(self):
- 'od.__reversed__() <==> reversed(od)'
- root = self.__root
- curr = root[0]
- while curr is not root:
- yield curr[2]
- curr = curr[0]
-
- def clear(self):
- 'od.clear() -> None. Remove all items from od.'
- try:
- for node in self.__map.itervalues():
- del node[:]
- root = self.__root
- root[:] = [root, root, None]
- self.__map.clear()
- except AttributeError:
- pass
- dict.clear(self)
-
- def popitem(self, last=True):
- '''od.popitem() -> (k, v), return and remove a (key, value) pair.
- Pairs are returned in LIFO order if last is true or FIFO order if false.
-
- '''
- if not self:
- raise KeyError('dictionary is empty')
- root = self.__root
- if last:
- link = root[0]
- link_prev = link[0]
- link_prev[1] = root
- root[0] = link_prev
- else:
- link = root[1]
- link_next = link[1]
- root[1] = link_next
- link_next[0] = root
- key = link[2]
- del self.__map[key]
- value = dict.pop(self, key)
- return key, value
-
- # -- the following methods do not depend on the internal structure --
-
- def keys(self):
- 'od.keys() -> list of keys in od'
- return list(self)
-
- def values(self):
- 'od.values() -> list of values in od'
- return [self[key] for key in self]
-
- def items(self):
- 'od.items() -> list of (key, value) pairs in od'
- return [(key, self[key]) for key in self]
-
- def iterkeys(self):
- 'od.iterkeys() -> an iterator over the keys in od'
- return iter(self)
-
- def itervalues(self):
- 'od.itervalues -> an iterator over the values in od'
- for k in self:
- yield self[k]
-
- def iteritems(self):
- 'od.iteritems -> an iterator over the (key, value) items in od'
- for k in self:
- yield (k, self[k])
-
- def update(*args, **kwds):
- '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
-
- If E is a dict instance, does: for k in E: od[k] = E[k]
- If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
- Or if E is an iterable of items, does: for k, v in E: od[k] = v
- In either case, this is followed by: for k, v in F.items(): od[k] = v
-
- '''
- if len(args) > 2:
- raise TypeError('update() takes at most 2 positional '
- 'arguments (%d given)' % (len(args),))
- elif not args:
- raise TypeError('update() takes at least 1 argument (0 given)')
- self = args[0]
- # Make progressively weaker assumptions about "other"
- other = ()
- if len(args) == 2:
- other = args[1]
- if isinstance(other, dict):
- for key in other:
- self[key] = other[key]
- elif hasattr(other, 'keys'):
- for key in other.keys():
- self[key] = other[key]
- else:
- for key, value in other:
- self[key] = value
- for key, value in kwds.items():
- self[key] = value
-
- __update = update # let subclasses override update without breaking __init__
-
- __marker = object()
-
- def pop(self, key, default=__marker):
- '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
- If key is not found, d is returned if given, otherwise KeyError is raised.
-
- '''
- if key in self:
- result = self[key]
- del self[key]
- return result
- if default is self.__marker:
- raise KeyError(key)
- return default
-
- def setdefault(self, key, default=None):
- 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
- if key in self:
- return self[key]
- self[key] = default
- return default
-
- def __repr__(self, _repr_running={}):
- 'od.__repr__() <==> repr(od)'
- call_key = id(self), _get_ident()
- if call_key in _repr_running:
- return '...'
- _repr_running[call_key] = 1
- try:
- if not self:
- return '%s()' % (self.__class__.__name__,)
- return '%s(%r)' % (self.__class__.__name__, self.items())
- finally:
- del _repr_running[call_key]
-
- def __reduce__(self):
- 'Return state information for pickling'
- items = [[k, self[k]] for k in self]
- inst_dict = vars(self).copy()
- for k in vars(OrderedDict()):
- inst_dict.pop(k, None)
- if inst_dict:
- return (self.__class__, (items,), inst_dict)
- return self.__class__, (items,)
-
- def copy(self):
- 'od.copy() -> a shallow copy of od'
- return self.__class__(self)
-
- @classmethod
- def fromkeys(cls, iterable, value=None):
- '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
- and values equal to v (which defaults to None).
-
- '''
- d = cls()
- for key in iterable:
- d[key] = value
- return d
-
- def __eq__(self, other):
- '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
- while comparison to a regular mapping is order-insensitive.
-
- '''
- if isinstance(other, OrderedDict):
- return len(self)==len(other) and self.items() == other.items()
- return dict.__eq__(self, other)
-
- def __ne__(self, other):
- return not self == other
-
- # -- the following methods are only used in Python 2.7 --
-
- def viewkeys(self):
- "od.viewkeys() -> a set-like object providing a view on od's keys"
- return KeysView(self)
-
- def viewvalues(self):
- "od.viewvalues() -> an object providing a view on od's values"
- return ValuesView(self)
-
- def viewitems(self):
- "od.viewitems() -> a set-like object providing a view on od's items"
- return ItemsView(self)
diff --git a/funcsigs/version.py b/funcsigs/version.py
deleted file mode 100644
index 896a370..0000000
--- a/funcsigs/version.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "0.4"
diff --git a/requirements/development.txt b/requirements/development.txt
deleted file mode 100644
index ecafb0a..0000000
--- a/requirements/development.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-coverage
-coveralls
-pip
-flake8
-sphinx
-wheel
diff --git a/requirements/production.txt b/requirements/production.txt
deleted file mode 100644
index e69de29..0000000
--- a/requirements/production.txt
+++ /dev/null
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 5e40900..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-[wheel]
-universal = 1
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 98b0912..0000000
--- a/setup.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python
-from setuptools import setup
-import re
-import sys
-
-def load_version(filename='funcsigs/version.py'):
- "Parse a __version__ number from a source file"
- with open(filename) as source:
- text = source.read()
- match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", text)
- if not match:
- msg = "Unable to find version number in {}".format(filename)
- raise RuntimeError(msg)
- version = match.group(1)
- return version
-
-def load_rst(filename='docs/source/guide_content.rst'):
- "Purge refs directives from restructured text"
- with open(filename) as source:
- text = source.read()
- doc = re.sub(r':\w+:`~?([a-zA-Z._()]+)`', r'*\1*', text)
- return doc
-
-setup(
- name="funcsigs",
- version=load_version(),
- packages=['funcsigs'],
- zip_safe=False,
- author="Aaron Iles",
- author_email="aaron.iles@gmail.com",
- url="http://funcsigs.readthedocs.org",
- description="Python function signatures from PEP362 for Python 2.6, 2.7 and 3.2+",
- long_description=open('README.rst').read(),
- # long_description=load_rst(),
- license="ASL",
- install_requires = [],
- classifiers = [
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.2',
- 'Programming Language :: Python :: 3.3',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- tests_require = [] if sys.version_info[0] > 2 else ['unittest2'],
- test_suite = "tests" if sys.version_info[0] > 2 else 'unittest2.collector'
-)
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/__init__.py
+++ /dev/null
diff --git a/tests/test_formatannotation.py b/tests/test_formatannotation.py
deleted file mode 100644
index fd7a887..0000000
--- a/tests/test_formatannotation.py
+++ /dev/null
@@ -1,27 +0,0 @@
-try:
- # python 2.x
- import unittest2 as unittest
-except ImportError:
- # python 3.x
- import unittest
-
-import funcsigs
-
-
-class TestFormatAnnotation(unittest.TestCase):
- def test_string (self):
- self.assertEqual(funcsigs.formatannotation("annotation"),
- "'annotation'")
-
- def test_builtin_type (self):
- self.assertEqual(funcsigs.formatannotation(int),
- "int")
-
- def test_user_type (self):
- class dummy (object): pass
- self.assertEqual(funcsigs.formatannotation(dummy),
- "tests.test_formatannotation.dummy")
-
-
-if __name__ == "__main__":
- unittest.begin()
diff --git a/tests/test_funcsigs.py b/tests/test_funcsigs.py
deleted file mode 100644
index eecc0a8..0000000
--- a/tests/test_funcsigs.py
+++ /dev/null
@@ -1,93 +0,0 @@
-try:
- # python 2.x
- import unittest2 as unittest
-except ImportError:
- # python 3.x
- import unittest
-
-import doctest
-import sys
-
-import funcsigs as inspect
-
-
-class TestFunctionSignatures(unittest.TestCase):
-
- @staticmethod
- def signature(func):
- sig = inspect.signature(func)
- return (tuple((param.name,
- (Ellipsis if param.default is param.empty else param.default),
- (Ellipsis if param.annotation is param.empty
- else param.annotation),
- str(param.kind).lower())
- for param in sig.parameters.values()),
- (Ellipsis if sig.return_annotation is sig.empty
- else sig.return_annotation))
-
- def test_zero_arguments(self):
- def test():
- pass
- self.assertEqual(self.signature(test),
- ((), Ellipsis))
-
- def test_single_positional_argument(self):
- def test(a):
- pass
- self.assertEqual(self.signature(test),
- (((('a', Ellipsis, Ellipsis, "positional_or_keyword")),), Ellipsis))
-
- def test_single_keyword_argument(self):
- def test(a=None):
- pass
- self.assertEqual(self.signature(test),
- (((('a', None, Ellipsis, "positional_or_keyword")),), Ellipsis))
-
- def test_var_args(self):
- def test(*args):
- pass
- self.assertEqual(self.signature(test),
- (((('args', Ellipsis, Ellipsis, "var_positional")),), Ellipsis))
-
- def test_keywords_args(self):
- def test(**kwargs):
- pass
- self.assertEqual(self.signature(test),
- (((('kwargs', Ellipsis, Ellipsis, "var_keyword")),), Ellipsis))
-
- def test_multiple_arguments(self):
- def test(a, b=None, *args, **kwargs):
- pass
- self.assertEqual(self.signature(test), ((
- ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', None, Ellipsis, "positional_or_keyword"),
- ('args', Ellipsis, Ellipsis, "var_positional"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword"),
- ), Ellipsis))
-
- def test_has_version(self):
- self.assertTrue(inspect.__version__)
-
- def test_readme(self):
- doctest.testfile('../README.rst')
-
- def test_unbound_method(self):
- if sys.version_info < (3,):
- self_kind = "positional_only"
- else:
- self_kind = "positional_or_keyword"
- class Test(object):
- def method(self):
- pass
- def method_with_args(self, a):
- pass
- self.assertEqual(self.signature(Test.method),
- (((('self', Ellipsis, Ellipsis, self_kind)),), Ellipsis))
- self.assertEqual(self.signature(Test.method_with_args), ((
- ('self', Ellipsis, Ellipsis, self_kind),
- ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ), Ellipsis))
-
-
-if __name__ == "__main__":
- unittest.begin()
diff --git a/tests/test_inspect.py b/tests/test_inspect.py
deleted file mode 100644
index 323c323..0000000
--- a/tests/test_inspect.py
+++ /dev/null
@@ -1,1019 +0,0 @@
-# Copyright 2001-2013 Python Software Foundation; All Rights Reserved
-from __future__ import absolute_import, division, print_function
-import collections
-import sys
-
-try:
- import unittest2 as unittest
-except ImportError:
- import unittest
-
-import funcsigs as inspect
-
-
-class TestSignatureObject(unittest.TestCase):
- @staticmethod
- def signature(func):
- sig = inspect.signature(func)
- return (tuple((param.name,
- (Ellipsis if param.default is param.empty else param.default),
- (Ellipsis if param.annotation is param.empty
- else param.annotation),
- str(param.kind).lower())
- for param in sig.parameters.values()),
- (Ellipsis if sig.return_annotation is sig.empty
- else sig.return_annotation))
-
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- if not hasattr(self, 'assertRaisesRegex'):
- self.assertRaisesRegex = self.assertRaisesRegexp
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_object(self):
- S = inspect.Signature
- P = inspect.Parameter
-
- self.assertEqual(str(S()), '()')
-
- def test(po, pk, *args, ko, **kwargs):
- pass
- sig = inspect.signature(test)
- po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
- pk = sig.parameters['pk']
- args = sig.parameters['args']
- ko = sig.parameters['ko']
- kwargs = sig.parameters['kwargs']
-
- S((po, pk, args, ko, kwargs))
-
- with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
- S((pk, po, args, ko, kwargs))
-
- with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
- S((po, args, pk, ko, kwargs))
-
- with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
- S((args, po, pk, ko, kwargs))
-
- with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
- S((po, pk, args, kwargs, ko))
-
- kwargs2 = kwargs.replace(name='args')
- with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
- S((po, pk, args, kwargs2, ko))
-""")
-
- def test_signature_immutability(self):
- def test(a):
- pass
- sig = inspect.signature(test)
-
- with self.assertRaises(AttributeError):
- sig.foo = 'bar'
-
- # Python2 does not have MappingProxyType class
- if sys.version_info[:2] < (3, 3):
- return
-
- with self.assertRaises(TypeError):
- sig.parameters['a'] = None
-
- def test_signature_on_noarg(self):
- def test():
- pass
- self.assertEqual(self.signature(test), ((), Ellipsis))
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_wargs(self):
- def test(a, b:'foo') -> 123:
- pass
- self.assertEqual(self.signature(test),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', Ellipsis, 'foo', "positional_or_keyword")),
- 123))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_wkwonly(self):
- def test(*, a:float, b:str) -> int:
- pass
- self.assertEqual(self.signature(test),
- ((('a', Ellipsis, float, "keyword_only"),
- ('b', Ellipsis, str, "keyword_only")),
- int))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_complex_args(self):
- def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
- pass
- self.assertEqual(self.signature(test),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', 10, 'foo', "positional_or_keyword"),
- ('args', Ellipsis, 'bar', "var_positional"),
- ('spam', Ellipsis, 'baz', "keyword_only"),
- ('ham', 123, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, int, "var_keyword")),
- Ellipsis))
-""")
-
- def test_signature_on_builtin_function(self):
- with self.assertRaisesRegex(ValueError, 'not supported by signature'):
- inspect.signature(type)
- with self.assertRaisesRegex(ValueError, 'not supported by signature'):
- # support for 'wrapper_descriptor'
- inspect.signature(type.__call__)
- if hasattr(sys, 'pypy_version_info'):
- raise ValueError('not supported by signature')
- with self.assertRaisesRegex(ValueError, 'not supported by signature'):
- # support for 'method-wrapper'
- inspect.signature(min.__call__)
- if hasattr(sys, 'pypy_version_info'):
- raise ValueError('not supported by signature')
- with self.assertRaisesRegex(ValueError,
- 'no signature found for builtin function'):
- # support for 'method-wrapper'
- inspect.signature(min)
-
- def test_signature_on_non_function(self):
- with self.assertRaisesRegex(TypeError, 'is not a callable object'):
- inspect.signature(42)
-
- with self.assertRaisesRegex(TypeError, 'is not a Python function'):
- inspect.Signature.from_function(42)
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_method(self):
- class Test:
- def foo(self, arg1, arg2=1) -> int:
- pass
-
- meth = Test().foo
-
- self.assertEqual(self.signature(meth),
- ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('arg2', 1, Ellipsis, "positional_or_keyword")),
- int))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_classmethod(self):
- class Test:
- @classmethod
- def foo(cls, arg1, *, arg2=1):
- pass
-
- meth = Test().foo
- self.assertEqual(self.signature(meth),
- ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('arg2', 1, Ellipsis, "keyword_only")),
- Ellipsis))
-
- meth = Test.foo
- self.assertEqual(self.signature(meth),
- ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('arg2', 1, Ellipsis, "keyword_only")),
- Ellipsis))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_staticmethod(self):
- class Test:
- @staticmethod
- def foo(cls, *, arg):
- pass
-
- meth = Test().foo
- self.assertEqual(self.signature(meth),
- ((('cls', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('arg', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-
- meth = Test.foo
- self.assertEqual(self.signature(meth),
- ((('cls', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('arg', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_partial(self):
- from functools import partial
-
- def test():
- pass
-
- self.assertEqual(self.signature(partial(test)), ((), Ellipsis))
-
- with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
- inspect.signature(partial(test, 1))
-
- with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
- inspect.signature(partial(test, a=1))
-
- def test(a, b, *, c, d):
- pass
-
- self.assertEqual(self.signature(partial(test)),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('c', Ellipsis, Ellipsis, "keyword_only"),
- ('d', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, 1)),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('c', Ellipsis, Ellipsis, "keyword_only"),
- ('d', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, 1, c=2)),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('c', 2, Ellipsis, "keyword_only"),
- ('d', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, b=1, c=2)),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', 1, Ellipsis, "positional_or_keyword"),
- ('c', 2, Ellipsis, "keyword_only"),
- ('d', Ellipsis, Ellipsis, "keyword_only")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
- ((('b', 1, Ellipsis, "positional_or_keyword"),
- ('c', 2, Ellipsis, "keyword_only"),
- ('d', Ellipsis, Ellipsis, "keyword_only"),),
- Ellipsis))
-
- def test(a, *args, b, **kwargs):
- pass
-
- self.assertEqual(self.signature(partial(test, 1)),
- ((('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', Ellipsis, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, 1, 2, 3)),
- ((('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', Ellipsis, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
-
- self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
- ((('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', Ellipsis, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
- ((('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', 0, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, b=0)),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', 0, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(partial(test, b=0, test=1)),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('args', Ellipsis, Ellipsis, "var_positional"),
- ('b', 0, Ellipsis, "keyword_only"),
- ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
- Ellipsis))
-
- def test(a, b, c:int) -> 42:
- pass
-
- sig = test.__signature__ = inspect.signature(test)
-
- self.assertEqual(self.signature(partial(partial(test, 1))),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('c', Ellipsis, int, "positional_or_keyword")),
- 42))
-
- self.assertEqual(self.signature(partial(partial(test, 1), 2)),
- ((('c', Ellipsis, int, "positional_or_keyword"),),
- 42))
-
- psig = inspect.signature(partial(partial(test, 1), 2))
-
- def foo(a):
- return a
- _foo = partial(partial(foo, a=10), a=20)
- self.assertEqual(self.signature(_foo),
- ((('a', 20, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
- # check that we don't have any side-effects in signature(),
- # and the partial object is still functioning
- self.assertEqual(_foo(), 20)
-
- def foo(a, b, c):
- return a, b, c
- _foo = partial(partial(foo, 1, b=20), b=30)
- self.assertEqual(self.signature(_foo),
- ((('b', 30, Ellipsis, "positional_or_keyword"),
- ('c', Ellipsis, Ellipsis, "positional_or_keyword")),
- Ellipsis))
- self.assertEqual(_foo(c=10), (1, 30, 10))
- _foo = partial(_foo, 2) # now 'b' has two values -
- # positional and keyword
- with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
- inspect.signature(_foo)
-
- def foo(a, b, c, *, d):
- return a, b, c, d
- _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
- self.assertEqual(self.signature(_foo),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', 10, Ellipsis, "positional_or_keyword"),
- ('c', 20, Ellipsis, "positional_or_keyword"),
- ('d', 30, Ellipsis, "keyword_only")),
- Ellipsis))
- ba = inspect.signature(_foo).bind(a=200, b=11)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
-
- def foo(a=1, b=2, c=3):
- return a, b, c
- _foo = partial(foo, a=10, c=13)
- ba = inspect.signature(_foo).bind(11)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
- ba = inspect.signature(_foo).bind(11, 12)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
- ba = inspect.signature(_foo).bind(11, b=12)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
- ba = inspect.signature(_foo).bind(b=12)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
- _foo = partial(_foo, b=10)
- ba = inspect.signature(_foo).bind(12, 14)
- self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_decorated(self):
- import functools
-
- def decorator(func):
- @functools.wraps(func)
- def wrapper(*args, **kwargs) -> int:
- return func(*args, **kwargs)
- return wrapper
-
- class Foo:
- @decorator
- def bar(self, a, b):
- pass
-
- self.assertEqual(self.signature(Foo.bar),
- ((('self', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(Foo().bar),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
- Ellipsis))
-
- # Test that we handle method wrappers correctly
- def decorator(func):
- @functools.wraps(func)
- def wrapper(*args, **kwargs) -> int:
- return func(42, *args, **kwargs)
- sig = inspect.signature(func)
- new_params = tuple(sig.parameters.values())[1:]
- wrapper.__signature__ = sig.replace(parameters=new_params)
- return wrapper
-
- class Foo:
- @decorator
- def __call__(self, a, b):
- pass
-
- self.assertEqual(self.signature(Foo.__call__),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(Foo().__call__),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_on_class(self):
- class C:
- def __init__(self, a):
- pass
-
- self.assertEqual(self.signature(C),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- class CM(type):
- def __call__(cls, a):
- pass
- class C(metaclass=CM):
- def __init__(self, b):
- pass
-
- self.assertEqual(self.signature(C),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- class CM(type):
- def __new__(mcls, name, bases, dct, *, foo=1):
- return super().__new__(mcls, name, bases, dct)
- class C(metaclass=CM):
- def __init__(self, b):
- pass
-
- self.assertEqual(self.signature(C),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- self.assertEqual(self.signature(CM),
- ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('foo', 1, Ellipsis, "keyword_only")),
- Ellipsis))
-
- class CMM(type):
- def __new__(mcls, name, bases, dct, *, foo=1):
- return super().__new__(mcls, name, bases, dct)
- def __call__(cls, nm, bs, dt):
- return type(nm, bs, dt)
- class CM(type, metaclass=CMM):
- def __new__(mcls, name, bases, dct, *, bar=2):
- return super().__new__(mcls, name, bases, dct)
- class C(metaclass=CM):
- def __init__(self, b):
- pass
-
- self.assertEqual(self.signature(CMM),
- ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('foo', 1, Ellipsis, "keyword_only")),
- Ellipsis))
-
- self.assertEqual(self.signature(CM),
- ((('nm', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('bs', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('dt', Ellipsis, Ellipsis, "positional_or_keyword")),
- Ellipsis))
-
- self.assertEqual(self.signature(C),
- ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- class CM(type):
- def __init__(cls, name, bases, dct, *, bar=2):
- return super().__init__(name, bases, dct)
- class C(metaclass=CM):
- def __init__(self, b):
- pass
-
- self.assertEqual(self.signature(CM),
- ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
- ('bar', 2, Ellipsis, "keyword_only")),
- Ellipsis))
-""")
-
- def test_signature_on_callable_objects(self):
- class Foo(object):
- def __call__(self, a):
- pass
-
- self.assertEqual(self.signature(Foo()),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- class Spam(object):
- pass
- with self.assertRaisesRegex(TypeError, "is not a callable object"):
- inspect.signature(Spam())
-
- class Bar(Spam, Foo):
- pass
-
- self.assertEqual(self.signature(Bar()),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- class ToFail(object):
- __call__ = type
- with self.assertRaisesRegex(ValueError, "not supported by signature"):
- inspect.signature(ToFail())
-
- if sys.version_info[0] < 3:
- return
-
- class Wrapped(object):
- pass
- Wrapped.__wrapped__ = lambda a: None
- self.assertEqual(self.signature(Wrapped),
- ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- def test_signature_on_lambdas(self):
- self.assertEqual(self.signature((lambda a=10: a)),
- ((('a', 10, Ellipsis, "positional_or_keyword"),),
- Ellipsis))
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_equality(self):
- def foo(a, *, b:int) -> float: pass
- self.assertNotEqual(inspect.signature(foo), 42)
-
- def bar(a, *, b:int) -> float: pass
- self.assertEqual(inspect.signature(foo), inspect.signature(bar))
-
- def bar(a, *, b:int) -> int: pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
-
- def bar(a, *, b:int): pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
-
- def bar(a, *, b:int=42) -> float: pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
-
- def bar(a, *, c) -> float: pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
-
- def bar(a, b:int) -> float: pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
- def spam(b:int, a) -> float: pass
- self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
-
- def foo(*, a, b, c): pass
- def bar(*, c, b, a): pass
- self.assertEqual(inspect.signature(foo), inspect.signature(bar))
-
- def foo(*, a=1, b, c): pass
- def bar(*, c, b, a=1): pass
- self.assertEqual(inspect.signature(foo), inspect.signature(bar))
-
- def foo(pos, *, a=1, b, c): pass
- def bar(pos, *, c, b, a=1): pass
- self.assertEqual(inspect.signature(foo), inspect.signature(bar))
-
- def foo(pos, *, a, b, c): pass
- def bar(pos, *, c, b, a=1): pass
- self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
-
- def foo(pos, *args, a=42, b, c, **kwargs:int): pass
- def bar(pos, *args, c, b, a=42, **kwargs:int): pass
- self.assertEqual(inspect.signature(foo), inspect.signature(bar))
-""")
-
- def test_signature_unhashable(self):
- def foo(a): pass
- sig = inspect.signature(foo)
- with self.assertRaisesRegex(TypeError, 'unhashable type'):
- hash(sig)
-
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_str(self):
- def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
- pass
- self.assertEqual(str(inspect.signature(foo)),
- '(a:int=1, *, b, c=None, **kwargs) -> 42')
-
- def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
- pass
- self.assertEqual(str(inspect.signature(foo)),
- '(a:int=1, *args, b, c=None, **kwargs) -> 42')
-
- def foo():
- pass
- self.assertEqual(str(inspect.signature(foo)), '()')
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_str_positional_only(self):
- P = inspect.Parameter
-
- def test(a_po, *, b, **kwargs):
- return a_po, kwargs
-
- sig = inspect.signature(test)
- new_params = list(sig.parameters.values())
- new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
- test.__signature__ = sig.replace(parameters=new_params)
-
- self.assertEqual(str(inspect.signature(test)),
- '(<a_po>, *, b, **kwargs)')
-
- sig = inspect.signature(test)
- new_params = list(sig.parameters.values())
- new_params[0] = new_params[0].replace(name=None)
- test.__signature__ = sig.replace(parameters=new_params)
- self.assertEqual(str(inspect.signature(test)),
- '(<0>, *, b, **kwargs)')
-""")
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_replace_anno(self):
- def test() -> 42:
- pass
-
- sig = inspect.signature(test)
- sig = sig.replace(return_annotation=None)
- self.assertIs(sig.return_annotation, None)
- sig = sig.replace(return_annotation=sig.empty)
- self.assertIs(sig.return_annotation, sig.empty)
- sig = sig.replace(return_annotation=42)
- self.assertEqual(sig.return_annotation, 42)
- self.assertEqual(sig, inspect.signature(test))
-""")
-
-
-class TestParameterObject(unittest.TestCase):
-
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- if not hasattr(self, 'assertRaisesRegex'):
- self.assertRaisesRegex = self.assertRaisesRegexp
-
- def test_signature_parameter_kinds(self):
- P = inspect.Parameter
- self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
- P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
-
- self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
- self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
-
- def test_signature_parameter_object(self):
- p = inspect.Parameter('foo', default=10,
- kind=inspect.Parameter.POSITIONAL_ONLY)
- self.assertEqual(p.name, 'foo')
- self.assertEqual(p.default, 10)
- self.assertIs(p.annotation, p.empty)
- self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
-
- with self.assertRaisesRegex(ValueError, 'invalid value'):
- inspect.Parameter('foo', default=10, kind='123')
-
- with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
- inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
-
- with self.assertRaisesRegex(ValueError,
- 'non-positional-only parameter'):
- inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
-
- with self.assertRaisesRegex(ValueError, 'cannot have default values'):
- inspect.Parameter('a', default=42,
- kind=inspect.Parameter.VAR_KEYWORD)
-
- with self.assertRaisesRegex(ValueError, 'cannot have default values'):
- inspect.Parameter('a', default=42,
- kind=inspect.Parameter.VAR_POSITIONAL)
-
- p = inspect.Parameter('a', default=42,
- kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
- with self.assertRaisesRegex(ValueError, 'cannot have default values'):
- p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
-
- self.assertTrue(repr(p).startswith('<Parameter'))
-
- def test_signature_parameter_equality(self):
- P = inspect.Parameter
- p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
-
- self.assertEqual(p, p)
- self.assertNotEqual(p, 42)
-
- self.assertEqual(p, P('foo', default=42,
- kind=inspect.Parameter.KEYWORD_ONLY))
-
- def test_signature_parameter_unhashable(self):
- p = inspect.Parameter('foo', default=42,
- kind=inspect.Parameter.KEYWORD_ONLY)
-
- with self.assertRaisesRegex(TypeError, 'unhashable type'):
- hash(p)
-
- def test_signature_parameter_replace(self):
- p = inspect.Parameter('foo', default=42,
- kind=inspect.Parameter.KEYWORD_ONLY)
-
- self.assertIsNot(p, p.replace())
- self.assertEqual(p, p.replace())
-
- p2 = p.replace(annotation=1)
- self.assertEqual(p2.annotation, 1)
- p2 = p2.replace(annotation=p2.empty)
- self.assertEqual(p, p2)
-
- p2 = p2.replace(name='bar')
- self.assertEqual(p2.name, 'bar')
- self.assertNotEqual(p2, p)
-
- with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
- p2 = p2.replace(name=p2.empty)
-
- p2 = p2.replace(name='foo', default=None)
- self.assertIs(p2.default, None)
- self.assertNotEqual(p2, p)
-
- p2 = p2.replace(name='foo', default=p2.empty)
- self.assertIs(p2.default, p2.empty)
-
-
- p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
- self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
- self.assertNotEqual(p2, p)
-
- with self.assertRaisesRegex(ValueError, 'invalid value for'):
- p2 = p2.replace(kind=p2.empty)
-
- p2 = p2.replace(kind=p2.KEYWORD_ONLY)
- self.assertEqual(p2, p)
-
- def test_signature_parameter_positional_only(self):
- p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
- self.assertEqual(str(p), '<>')
-
- p = p.replace(name='1')
- self.assertEqual(str(p), '<1>')
-
- def test_signature_parameter_immutability(self):
- p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
-
- with self.assertRaises(AttributeError):
- p.foo = 'bar'
-
- with self.assertRaises(AttributeError):
- p.kind = 123
-
-
-class TestSignatureBind(unittest.TestCase):
- @staticmethod
- def call(func, *args, **kwargs):
- sig = inspect.signature(func)
- ba = sig.bind(*args, **kwargs)
- return func(*ba.args, **ba.kwargs)
-
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- if not hasattr(self, 'assertRaisesRegex'):
- self.assertRaisesRegex = self.assertRaisesRegexp
-
- def test_signature_bind_empty(self):
- def test():
- return 42
-
- self.assertEqual(self.call(test), 42)
- with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
- self.call(test, 1)
- with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
- self.call(test, 1, spam=10)
- with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
- self.call(test, spam=1)
-
- def test_signature_bind_var(self):
- def test(*args, **kwargs):
- return args, kwargs
-
- self.assertEqual(self.call(test), ((), {}))
- self.assertEqual(self.call(test, 1), ((1,), {}))
- self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
- self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
- self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
- self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
- self.assertEqual(self.call(test, 1, 2, foo='bar'),
- ((1, 2), {'foo': 'bar'}))
-
- def test_signature_bind_just_args(self):
- def test(a, b, c):
- return a, b, c
-
- self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
-
- with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
- self.call(test, 1, 2, 3, 4)
-
- with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
- self.call(test, 1)
-
- with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
- self.call(test)
-
- def test(a, b, c=10):
- return a, b, c
- self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
- self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
-
- def test(a=1, b=2, c=3):
- return a, b, c
- self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
- self.assertEqual(self.call(test, a=10), (10, 2, 3))
- self.assertEqual(self.call(test, b=10), (1, 10, 3))
-
- def test_signature_bind_varargs_order(self):
- def test(*args):
- return args
-
- self.assertEqual(self.call(test), ())
- self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
-
- def test_signature_bind_args_and_varargs(self):
- def test(a, b, c=3, *args):
- return a, b, c, args
-
- self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
- self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
- self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
- self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
-
- with self.assertRaisesRegex(TypeError,
- "multiple values for argument 'c'"):
- self.call(test, 1, 2, 3, c=4)
-
- def test_signature_bind_just_kwargs(self):
- def test(**kwargs):
- return kwargs
-
- self.assertEqual(self.call(test), {})
- self.assertEqual(self.call(test, foo='bar', spam='ham'),
- {'foo': 'bar', 'spam': 'ham'})
-
- def test_signature_bind_args_and_kwargs(self):
- def test(a, b, c=3, **kwargs):
- return a, b, c, kwargs
-
- self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
- self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
- (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
- self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
- (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
- self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
- (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
- self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
- (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
- self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
- (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
- self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
- (1, 2, 4, {'foo': 'bar'}))
- self.assertEqual(self.call(test, c=5, a=4, b=3),
- (4, 3, 5, {}))
-
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_bind_kwonly(self):
- def test(*, foo):
- return foo
- with self.assertRaisesRegex(TypeError,
- 'too many positional arguments'):
- self.call(test, 1)
- self.assertEqual(self.call(test, foo=1), 1)
-
- def test(a, *, foo=1, bar):
- return foo
- with self.assertRaisesRegex(TypeError,
- "'bar' parameter lacking default value"):
- self.call(test, 1)
-
- def test(foo, *, bar):
- return foo, bar
- self.assertEqual(self.call(test, 1, bar=2), (1, 2))
- self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
-
- with self.assertRaisesRegex(TypeError,
- 'too many keyword arguments'):
- self.call(test, bar=2, foo=1, spam=10)
-
- with self.assertRaisesRegex(TypeError,
- 'too many positional arguments'):
- self.call(test, 1, 2)
-
- with self.assertRaisesRegex(TypeError,
- 'too many positional arguments'):
- self.call(test, 1, 2, bar=2)
-
- with self.assertRaisesRegex(TypeError,
- 'too many keyword arguments'):
- self.call(test, 1, bar=2, spam='ham')
-
- with self.assertRaisesRegex(TypeError,
- "'bar' parameter lacking default value"):
- self.call(test, 1)
-
- def test(foo, *, bar, **bin):
- return foo, bar, bin
- self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
- self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
- self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
- (1, 2, {'spam': 'ham'}))
- self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
- (1, 2, {'spam': 'ham'}))
- with self.assertRaisesRegex(TypeError,
- "'foo' parameter lacking default value"):
- self.call(test, spam='ham', bar=2)
- self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
- (1, 2, {'bin': 1, 'spam': 10}))
-""")
-#
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_bind_arguments(self):
- def test(a, *args, b, z=100, **kwargs):
- pass
- sig = inspect.signature(test)
- ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
- # we won't have 'z' argument in the bound arguments object, as we didn't
- # pass it to the 'bind'
- self.assertEqual(tuple(ba.arguments.items()),
- (('a', 10), ('args', (20,)), ('b', 30),
- ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
- self.assertEqual(ba.kwargs,
- {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
- self.assertEqual(ba.args, (10, 20))
-""")
-#
- if sys.version_info[0] > 2:
- exec("""
-def test_signature_bind_positional_only(self):
- P = inspect.Parameter
-
- def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
- return a_po, b_po, c_po, foo, bar, kwargs
-
- sig = inspect.signature(test)
- new_params = collections.OrderedDict(tuple(sig.parameters.items()))
- for name in ('a_po', 'b_po', 'c_po'):
- new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
- new_sig = sig.replace(parameters=new_params.values())
- test.__signature__ = new_sig
-
- self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
- (1, 2, 4, 5, 6, {}))
-
- with self.assertRaisesRegex(TypeError, "parameter is positional only"):
- self.call(test, 1, 2, c_po=4)
-
- with self.assertRaisesRegex(TypeError, "parameter is positional only"):
- self.call(test, a_po=1, b_po=2)
-""")
-
-
-class TestBoundArguments(unittest.TestCase):
-
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- if not hasattr(self, 'assertRaisesRegex'):
- self.assertRaisesRegex = self.assertRaisesRegexp
-
- def test_signature_bound_arguments_unhashable(self):
- def foo(a): pass
- ba = inspect.signature(foo).bind(1)
-
- with self.assertRaisesRegex(TypeError, 'unhashable type'):
- hash(ba)
-
- def test_signature_bound_arguments_equality(self):
- def foo(a): pass
- ba = inspect.signature(foo).bind(1)
- self.assertEqual(ba, ba)
-
- ba2 = inspect.signature(foo).bind(1)
- self.assertEqual(ba, ba2)
-
- ba3 = inspect.signature(foo).bind(2)
- self.assertNotEqual(ba, ba3)
- ba3.arguments['a'] = 1
- self.assertEqual(ba, ba3)
-
- def bar(b): pass
- ba4 = inspect.signature(bar).bind(1)
- self.assertNotEqual(ba, ba4)
-
-
-if __name__ == "__main__":
- unittest.begin()