diff options
author | Alex Stapleton <alexs@prol.etari.at> | 2015-01-03 10:17:57 +0000 |
---|---|---|
committer | Alex Stapleton <alexs@prol.etari.at> | 2015-01-03 10:17:57 +0000 |
commit | b23a554dc5a6b71c3b543714d61a70fdf59c5ad1 (patch) | |
tree | fd3736d0403205effd0d0b6516f2da1992b07d01 | |
parent | 5ffea405885710c6836d1318c00b67162cb4faf9 (diff) | |
parent | 75341e185b48100b9acda696d173990e6eb4624c (diff) | |
download | cryptography-b23a554dc5a6b71c3b543714d61a70fdf59c5ad1.tar.gz cryptography-b23a554dc5a6b71c3b543714d61a70fdf59c5ad1.tar.bz2 cryptography-b23a554dc5a6b71c3b543714d61a70fdf59c5ad1.zip |
Merge pull request #1600 from alex/deprecated
Added a utility for deprecating a module attribute
-rw-r--r-- | src/cryptography/utils.py | 41 | ||||
-rw-r--r-- | tests/test_warnings.py | 47 |
2 files changed, 84 insertions, 4 deletions
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index ac2f787d..72f9a347 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -7,12 +7,17 @@ from __future__ import absolute_import, division, print_function import abc import inspect import sys +import warnings # DeprecatedIn07 objects exist. This comment exists to remind developers to # look for them when it's time for the ninth release cycle deprecation dance. +def read_only_property(name): + return property(lambda self: getattr(self, name)) + + def register_interface(iface): def register_decorator(klass): verify_interface(iface, klass) @@ -21,10 +26,6 @@ def register_interface(iface): return register_decorator -def read_only_property(name): - return property(lambda self: getattr(self, name)) - - class InterfaceNotImplemented(Exception): pass @@ -55,3 +56,35 @@ if sys.version_info >= (2, 7): else: def bit_length(x): return len(bin(x)) - (2 + (x <= 0)) + + +class _DeprecatedValue(object): + def __init__(self, value, message, warning_class): + self.value = value + self.message = message + self.warning_class = warning_class + + +class _ModuleWithDeprecations(object): + def __init__(self, module): + self.__dict__["_module"] = module + + def __getattr__(self, attr): + obj = getattr(self._module, attr) + if isinstance(obj, _DeprecatedValue): + warnings.warn(obj.message, obj.warning_class, stacklevel=2) + obj = obj.value + return obj + + def __setattr__(self, attr, value): + setattr(self._module, attr, value) + + def __dir__(self): + return ["_module"] + dir(self._module) + + +def deprecated(value, module_name, message, warning_class): + module = sys.modules[module_name] + if not isinstance(module, _ModuleWithDeprecations): + sys.modules[module_name] = module = _ModuleWithDeprecations(module) + return _DeprecatedValue(value, message, warning_class) diff --git a/tests/test_warnings.py b/tests/test_warnings.py new file mode 100644 index 00000000..9946baa7 --- /dev/null +++ b/tests/test_warnings.py @@ -0,0 +1,47 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import sys +import types +import warnings + +from cryptography.utils import deprecated + + +class TestDeprecated(object): + def test_deprecated(self, monkeypatch): + mod = types.ModuleType("TestDeprecated/test_deprecated") + monkeypatch.setitem(sys.modules, mod.__name__, mod) + mod.X = deprecated( + value=1, + module_name=mod.__name__, + message="deprecated message text", + warning_class=DeprecationWarning + ) + mod.Y = deprecated( + value=2, + module_name=mod.__name__, + message="more deprecated text", + warning_class=PendingDeprecationWarning, + ) + mod = sys.modules[mod.__name__] + mod.Z = 3 + + with warnings.catch_warnings(record=True) as log: + warnings.simplefilter("always", PendingDeprecationWarning) + warnings.simplefilter("always", DeprecationWarning) + assert mod.X == 1 + assert mod.Y == 2 + assert mod.Z == 3 + + [msg1, msg2] = log + assert msg1.category is DeprecationWarning + assert msg1.message.args == ("deprecated message text",) + + assert msg2.category is PendingDeprecationWarning + assert msg2.message.args == ("more deprecated text",) + + assert "Y" in dir(mod) |