[Python-modules-commits] [python-deprecation] 01/03: import python-deprecation_1.0.1.orig.tar.gz

Ondrej Koblizek kobla-guest at moszumanska.debian.org
Fri Aug 4 16:39:08 UTC 2017


This is an automated email from the git hooks/post-receive script.

kobla-guest pushed a commit to branch master
in repository python-deprecation.

commit 83c47129f909290e996f04ae216b1bc3e164f529
Author: Ondřej Kobližek <ondrej.koblizek at firma.seznam.cz>
Date:   Fri Aug 4 11:34:53 2017 -0400

    import python-deprecation_1.0.1.orig.tar.gz
---
 LICENSE                   | 201 +++++++++++++++++++++++++++++++++++++++++++
 MANIFEST.in               |   1 +
 README.rst                |  83 ++++++++++++++++++
 deprecation.py            | 212 ++++++++++++++++++++++++++++++++++++++++++++++
 docs/Makefile             |  20 +++++
 docs/conf.py              | 154 +++++++++++++++++++++++++++++++++
 docs/index.rst            | 104 +++++++++++++++++++++++
 docs/sample.rst           |  10 +++
 example.py                |  10 +++
 sample.py                 |  41 +++++++++
 setup.py                  |  33 ++++++++
 test-requirements.txt     |   4 +
 tests/__init__.py         |   0
 tests/test_deprecation.py | 128 ++++++++++++++++++++++++++++
 tox.ini                   |  24 ++++++
 15 files changed, 1025 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..1aba38f
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include LICENSE
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..75d8d93
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,83 @@
+deprecation
+===========
+
+.. image:: https://readthedocs.org/projects/deprecation/badge/?version=latest
+   :target: http://deprecation.readthedocs.io/en/latest/
+   :alt: Documentation Status
+
+.. image:: https://travis-ci.org/briancurtin/deprecation.svg?branch=master
+    :target: https://travis-ci.org/briancurtin/deprecation
+
+.. image:: https://codecov.io/gh/briancurtin/deprecation/branch/master/graph/badge.svg
+  :target: https://codecov.io/gh/briancurtin/deprecation
+
+The ``deprecation`` library provides a ``deprecated`` decorator and a
+``fail_if_not_removed`` decorator for your tests. Together, the two
+enable the automation of several things:
+
+1. The docstring of a deprecated method gets the deprecation details
+   appended to the end of it. If you generate your API docs direct
+   from your source, you don't need to worry about writing your own
+   notification. You also don't need to worry about forgetting to
+   write it. It's done for you.
+2. Rather than having code live on forever because you only deprecated
+   it but never actually moved on from it, you can have your tests
+   tell you when it's time to remove the code. The ``@deprecated``
+   decorator can be told when it's time to entirely remove the code,
+   which causes ``@fail_if_not_removed`` to raise an ``AssertionError``,
+   causing either your unittest or py.test tests to fail.
+
+See http://deprecation.readthedocs.io/ for the full documentation.
+
+Installation
+============
+
+ ::
+
+    pip install deprecation
+
+Usage
+=====
+
+ ::
+
+    import deprecation
+
+    @deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
+                            current_version=__version__,
+                            details="Use the bar function instead")
+    def foo():
+        """Do some stuff"""
+        return 1
+
+...but doesn't Python ignore ``DeprecationWarning``?
+====================================================
+
+Yes, by default since 2.7—and for good reason [#]_ —and this works fine
+with that.
+
+1. It often makes sense for you to run your tests with a ``-W`` flag or
+   the ``PYTHONWARNINGS`` environment variable so you catch warnings
+   in development and handle them appropriately. The warnings raised by
+   this library show up there, as they're subclasses of the built-in
+   ``DeprecationWarning``. See the `Command Line
+   <https://docs.python.org/2/using/cmdline.html#cmdoption-W>`_
+   and `Environment Variable
+   <https://docs.python.org/2/using/cmdline.html#envvar-PYTHONWARNINGS>`_
+   documentation for more details.
+2. Even if you don't enable those things, the behavior of this library
+   remains the same. The docstrings will still be updated and the tests
+   will still fail when they need to. You'll get the benefits regardless
+   of what Python cares about ``DeprecationWarning``.
+
+----
+
+.. [#] Exposing application users to ``DeprecationWarning``\s that are
+       emitted by lower-level code needlessly involves end-users in
+       "how things are done." It often leads to users raising issues
+       about warnings they're presented, which on one hand is done
+       rightfully so, as it's been presented to them as some sort of
+       issue to resolve. However, at the same time, the warning could
+       be well known and planned for. From either side, loud
+       ``DeprecationWarning``\s can be seen as noise that isn't
+       necessary outside of development.
diff --git a/deprecation.py b/deprecation.py
new file mode 100644
index 0000000..4a07e0f
--- /dev/null
+++ b/deprecation.py
@@ -0,0 +1,212 @@
+# 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.
+
+from distutils import version
+import functools
+import warnings
+
+__version__ = "1.0"
+
+# This is mostly here so automodule docs are ordered more ideally.
+__all__ = ["deprecated", "fail_if_not_removed",
+           "DeprecatedWarning", "UnsupportedWarning"]
+
+
+class DeprecatedWarning(DeprecationWarning):
+    """A warning class for deprecated methods
+
+    This is a specialization of the built-in :class:`DeprecationWarning`,
+    adding parameters that allow us to get information into the __str__
+    that ends up being sent through the :mod:`warnings` system.
+    The attributes aren't able to be retrieved after the warning gets
+    raised and passed through the system as only the class--not the
+    instance--and message are what gets preserved.
+
+    :param function: The function being deprecated.
+    :param deprecated_in: The version that ``function`` is deprecated in
+    :param removed_in: The version that ``function`` gets removed in
+    :param details: Optional details about the deprecation. Most often
+                    this will include directions on what to use instead
+                    of the now deprecated code.
+    """
+
+    def __init__(self, function, deprecated_in, removed_in, details=""):
+        # NOTE: The docstring only works for this class if it appears up
+        # near the class name, not here inside __init__. I think it has
+        # to do with being an exception class.
+        self.function = function
+        self.deprecated_in = deprecated_in
+        self.removed_in = removed_in
+        self.details = details
+        super(DeprecatedWarning, self).__init__()
+
+    def __str__(self):
+        return ("%s is deprecated as of %s and will "
+                "be removed in %s. %s" % (self.function, self.deprecated_in,
+                                          self.removed_in, self.details))
+
+
+class UnsupportedWarning(DeprecatedWarning):
+    """A warning class for methods to be removed
+
+    This is a subclass of :class:`~deprecation.DeprecatedWarning` and is used
+    to output a proper message about a function being unsupported.
+    Additionally, the :func:`~deprecation.fail_if_not_removed` decorator
+    will handle this warning and cause any tests to fail if the system
+    under test uses code that raises this warning.
+    """
+
+    def __str__(self):
+        return ("%s is unsupported as of %s. %s" % (self.function,
+                                                    self.removed_in,
+                                                    self.details))
+
+
+def deprecated(deprecated_in=None, removed_in=None, current_version=None,
+               details=""):
+    """Decorate a function to signify its deprecation
+
+    This function wraps a method that will soon be removed and does two things:
+        * The docstring of the method will be modified to include a notice
+          about deprecation, e.g., "Deprecated since 0.9.11. Use foo instead."
+        * Raises a :class:`~deprecation.DeprecatedWarning`
+          via the :mod:`warnings` module, which is a subclass of the built-in
+          :class:`DeprecationWarning`. Note that built-in
+          :class:`DeprecationWarning`\s are ignored by default, so for users
+          to be informed of said warnings they will need to enable them--see
+          the :mod:`warnings` module documentation for more details.
+
+    :param deprecated_in: The version at which the decorated method is
+                          considered deprecated. This will usually be the
+                          next version to be released when the decorator is
+                          added. The default is **None**, which effectively
+                          means immediate deprecation. If this is not
+                          specified, then the `removed_in` and
+                          `current_version` arguments are ignored.
+    :param removed_in: The version when the decorated method will be removed.
+                       The default is **None**, specifying that the function
+                       is not currently planned to be removed.
+                       Note: This cannot be set to a value if
+                       `deprecated_in=None`.
+    :param current_version: The source of version information for the
+                            currently running code. This will usually be
+                            a `__version__` attribute on your library.
+                            The default is `None`.
+                            When `current_version=None` the automation to
+                            determine if the wrapped function is actually
+                            in a period of deprecation or time for removal
+                            does not work, causing a
+                            :class:`~deprecation.DeprecatedWarning`
+                            to be raised in all cases.
+    :param details: Extra details to be added to the method docstring and
+                    warning. For example, the details may point users to
+                    a replacement method, such as "Use the foo_bar
+                    method instead". By default there are no details.
+    """
+    # You can't just jump to removal. It's weird, unfair, and also makes
+    # building up the docstring weird.
+    if deprecated_in is None and removed_in is not None:
+        raise TypeError("Cannot set removed_in to a value "
+                        "without also setting deprecated_in")
+
+    # Only warn when it's appropriate. There may be cases when it makes sense
+    # to add this decorator before a formal deprecation period begins.
+    # In CPython, PendingDeprecatedWarning gets used in that period,
+    # so perhaps mimick that at some point.
+    is_deprecated = False
+    is_unsupported = False
+
+    # StrictVersion won't take a None or a "", so make whatever goes to it
+    # is at least *something*.
+    if current_version:
+        current_version = version.StrictVersion(current_version)
+
+        if (removed_in
+           and current_version >= version.StrictVersion(removed_in)):
+            is_unsupported = True
+        elif (deprecated_in
+              and current_version >= version.StrictVersion(deprecated_in)):
+            is_deprecated = True
+    else:
+        # If we can't actually calculate that we're in a period of
+        # deprecation...well, they used the decorator, so it's deprecated.
+        # This will cover the case of someone just using
+        # @deprecated("1.0") without the other advantages.
+        is_deprecated = True
+
+    should_warn = any([is_deprecated, is_unsupported])
+
+    def _function_wrapper(function):
+        if should_warn:
+            # Everything *should* have a docstring, but just in case...
+            existing_docstring = function.__doc__ or ""
+
+            # The various parts of this decorator being optional makes for
+            # a number of ways the deprecation notice could go. The following
+            # makes for a nicely constructed sentence with or without any
+            # of the parts.
+            parts = {
+                "deprecated_in":
+                    " in %s" % deprecated_in if deprecated_in else "",
+                "removed_in":
+                    ", to be removed in %s" % removed_in if removed_in else "",
+                "period":
+                    "." if deprecated_in or removed_in or details else "",
+                "details":
+                    " %s" % details if details else ""}
+
+            deprecation_note = ("*Deprecated{deprecated_in}{removed_in}"
+                                "{period}{details}*".format(**parts))
+
+            function.__doc__ = "\n\n".join([existing_docstring,
+                                            deprecation_note])
+
+        @functools.wraps(function)
+        def _inner(*args, **kwargs):
+            if should_warn:
+                if is_unsupported:
+                    cls = UnsupportedWarning
+                else:
+                    cls = DeprecatedWarning
+
+                the_warning = cls(function.__name__, deprecated_in,
+                                  removed_in, details)
+                warnings.warn(the_warning)
+
+            return function(*args, **kwargs)
+        return _inner
+    return _function_wrapper
+
+
+def fail_if_not_removed(method):
+    """Decorate a test method to track removal of deprecated code
+
+    This decorator catches :class:`~deprecation.UnsupportedWarning`
+    warnings that occur during testing and causes unittests to fail,
+    making it easier to keep track of when code should be removed.
+
+    :raises: :class:`AssertionError` if an
+             :class:`~deprecation.UnsupportedWarning`
+             is raised while running the test method.
+    """
+    def _inner(*args, **kwargs):
+        with warnings.catch_warnings(record=True) as caught_warnings:
+            warnings.simplefilter("always")
+            rv = method(*args, **kwargs)
+
+        for warning in caught_warnings:
+            if warning.category == UnsupportedWarning:
+                raise AssertionError(
+                    ("%s uses a function that should be removed: %s" %
+                     (method, str(warning.message))))
+        return rv
+    return _inner
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..7aebaba
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SPHINXPROJ    = deprecation
+SOURCEDIR     = .
+BUILDDIR      = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..ee9da7e
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# deprecation documentation build configuration file, created by
+# sphinx-quickstart on Fri Jan 13 16:03:40 2017.
+#
+# 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.
+
+# 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.
+#
+import os
+import sys
+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']
+intersphinx_mapping = {'python': ('https://docs.python.org/dev', None)}
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'deprecation'
+copyright = '2017, Brian Curtin'
+author = 'Brian Curtin'
+
+# 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.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- 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 = 'nature'
+
+# 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 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 = ['_static']
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'deprecationdoc'
+
+
+# -- 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': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'deprecation.tex', 'deprecation Documentation',
+     'Brian Curtin', 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'deprecation', 'deprecation Documentation',
+     [author], 1)
+]
+
+
+# -- 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 = [
+    (master_doc, 'deprecation', 'deprecation Documentation',
+     author, 'deprecation', 'A library to handle automated deprecations.',
+     'Miscellaneous'),
+]
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..321a0c9
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,104 @@
+.. deprecation documentation master file, created by
+   sphinx-quickstart on Fri Jan 13 16:03:40 2017.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+``deprecation``
+===============
+
+``deprecation`` is a library that enables automated deprecations. It offers
+the :func:`~deprecation.deprecated` decorator to wrap functions, providing
+proper warnings both in documentation and via Python's :mod:`warnings` system,
+as well as the :func:`deprecation.fail_if_not_removed` decorator for test
+methods to ensure that deprecated code is eventually removed.
+
+See `API Documentation`_ to jump straight into the options.
+
+Installation
+============
+
+ ::
+
+    pip install deprecation
+
+Using ``@deprecated``
+=====================
+
+To mark a function or method as deprecated, wrap it in the
+:func:`~deprecation.deprecated` decorator. This does several things for you:
+
+1. The docstring of the wrapped function will have details appended
+   to it from the arguments you set on :func:`~deprecation.deprecated`.
+   This takes care of telling your users not only that the function
+   is deprecated, but can also tell them when it's going away and
+   what they can do in the meantime.
+2. In conjunction with the :func:`~deprecation.fail_if_not_removed`
+   decorator it removes the need for any sort of manual tracking of
+   when a sufficiently deprecated piece of code should be removed
+   from the codebase. It causes tests to fail when they contain
+   code which should be removed.
+
+ ::
+
+    import deprecation
+
+    @deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
+                            current_version=__version__,
+                            details="Use the bar function instead")
+    def foo():
+        """Do some stuff"""
+        return 1
+
+Now look at the docs. If you you generate API documentation from your source
+like the :doc:`sample` module does, you'll see that the a sentence has been
+appended to a deprecated function's docstring to include information about
+when the function is deprecated, when it'll be removed, and what you can do
+instead. For example, run ``help(foo)`` and this is what you'll get:
+
+ ::
+
+    Help on function foo in module example:
+
+    foo()
+        Do some stuff
+
+        *Deprecated in 1.0, to be removed in 2.0. Use the bar function instead*
+
+You can pass varying amounts of detail to this decorator, but note that
+in most cases it removes the ability to use
+:func:`~deprecation.fail_if_not_removed`. See the `API Documentation`_
+for full details.
+
+Using ``@fail_if_not_removed``
+==============================
+
+Once you've marked code for deprecation via :func:`~deprecation.deprecated`,
+you can sit back and relax as most of the work has been done for you.
+Assuming you've provided sufficient detail to the decorator, you now just
+wait for your tests to tell you it's time to delete the code in question.
+
+If you wrap test methods which use your now deprecated code in
+:func:`~deprecation.fail_if_not_removed`, the test will fail with a message
+notifying you that you should remove this code.
+
+ ::
+
+    @deprecation.fail_if_not_removed
+    def test_won(self):
+        self.assertEqual(1, won())
+
+Looking at the :doc:`sample` docs, we can see that this function would
+fail the tests at version 2.0, when it should be removed. The following
+shows what test output will look like for a failure.
+
+ ::
+
+    AssertionError: <function Tests.test_won at 0x10af33268> uses a function
+    that should be removed: who is unsupported as of 2.0. Use the ``one``
+    function instead
+
+API Documentation
+=================
+
+.. automodule:: deprecation
+   :members:
diff --git a/docs/sample.rst b/docs/sample.rst
new file mode 100644
index 0000000..d27d673
--- /dev/null
+++ b/docs/sample.rst
@@ -0,0 +1,10 @@
+:orphan:
+
+``sample`` module
+=================
+
+The following documents the ``sample`` module to show what documentation
+looks like when :func:`~deprecation.deprecated` has modified it.
+
+.. automodule:: sample
+   :members:
diff --git a/example.py b/example.py
new file mode 100644
index 0000000..44dff18
--- /dev/null
+++ b/example.py
@@ -0,0 +1,10 @@
+import deprecation
+__version__ = "1.5"
+
+
+ at deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
+                        current_version=__version__,
+                        details="Use the bar function instead")
+def foo():
+    """Do some stuff"""
+    return 1
diff --git a/sample.py b/sample.py
new file mode 100644
index 0000000..be00938
--- /dev/null
+++ b/sample.py
@@ -0,0 +1,41 @@
+import unittest2
+
+import deprecation
+
+__version__ = "1.5"
+
+
+ at deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
+                        current_version=__version__,
+                        details="Use the ``one`` function instead")
+def won():
+    """This function returns 1"""
+    # Oops, it's one, not won. Let's deprecate this and get it right.
+    return 1
+
+
+def one():
+    """This function returns 1"""
+    return 1
+
+
+ at deprecation.deprecated(deprecated_in="1.0", removed_in="1.5",
+                        current_version=__version__,
+                        details="Why would you ever do this anyway?")
+def why():
+    """This isn't necessary"""
+    return None
+
+
+class Tests(unittest2.TestCase):
+
+    @deprecation.fail_if_not_removed
+    def test_won(self):
+        self.assertEqual(1, won())
+
+    @deprecation.fail_if_not_removed
+    def test_why(self):
+        self.assertIsNone(why())
+
+    def test_one(self):
+        self.assertEqual(1, one())
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..ea8feed
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,33 @@
+import io
+from setuptools import setup
+
+AUTHOR = "Brian Curtin"
+EMAIL = "brian at python.org"
+
+
+setup(name="deprecation",
+      version="1.0.1",
+      description="A library to handle automated deprecations",
+      license="Apache 2",
+      url="http://deprecation.readthedocs.io/",
+      author=AUTHOR,
+      author_email=EMAIL,
+      maintainer=AUTHOR,
+      maintainer_email=EMAIL,
+      keywords=["deprecation"],
+      long_description=io.open("README.rst", encoding="utf-8").read(),
+      py_modules=["deprecation"],
+      classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "License :: OSI Approved :: Apache Software License",
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: Implementation :: CPython",
+        "Programming Language :: Python :: Implementation :: PyPy",
+        "Topic :: Software Development :: Libraries :: Python Modules"]
+      )
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..b292a77
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,4 @@
+codecov>=2.0
+coverage>=4.3
+flake8>=3.2
+unittest2>=1.1
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py
new file mode 100644
index 0000000..3364f9c
--- /dev/null
+++ b/tests/test_deprecation.py
@@ -0,0 +1,128 @@
+# 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.
+
+# As we unfortunately support Python 2.7, it lacks TestCase.subTest which
+# is in 3.4+ or in unittest2
+import unittest2
+import warnings
+
+import deprecation
+
+
+class Test_deprecated(unittest2.TestCase):
+
... 136 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-deprecation.git



More information about the Python-modules-commits mailing list