/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/symbol_versioning.py

  • Committer: John Arbash Meinel
  • Date: 2006-07-18 18:57:54 UTC
  • mto: This revision was merged to the branch mainline in revision 1868.
  • Revision ID: john@arbash-meinel.com-20060718185754-4007745748e28db9
Commit timestamp restricted to 1ms precision.

The old code would restrict to 1s resolution if the timestamp was
supplied, while it preserved full resolution if the timestamp was
auto generated. Now both paths preserve only 1ms resolution.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 by Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
"""Symbol versioning
 
19
 
 
20
The methods here allow for api symbol versioning.
 
21
"""
 
22
 
 
23
__all__ = ['deprecated_function',
 
24
           'deprecated_method',
 
25
           'DEPRECATED_PARAMETER',
 
26
           'deprecated_passed',
 
27
           'warn', 'set_warning_method', 'zero_seven',
 
28
           'zero_eight',
 
29
           'zero_nine',
 
30
           ]
 
31
 
 
32
from warnings import warn
 
33
 
 
34
 
 
35
DEPRECATED_PARAMETER = "A deprecated parameter marker."
 
36
zero_seven = "%s was deprecated in version 0.7."
 
37
zero_eight = "%s was deprecated in version 0.8."
 
38
zero_nine = "%s was deprecated in version 0.9."
 
39
 
 
40
 
 
41
def set_warning_method(method):
 
42
    """Set the warning method to be used by this module.
 
43
 
 
44
    It should take a message and a warning category as warnings.warn does.
 
45
    """
 
46
    global warn
 
47
    warn = method
 
48
 
 
49
 
 
50
# TODO - maybe this would be easier to use as one 'smart' method that
 
51
# guess if it is a method or a class or an attribute ? If so, we can
 
52
# add that on top of the primitives, once we have all three written
 
53
# - RBC 20050105
 
54
 
 
55
def deprecated_function(deprecation_version):
 
56
    """Decorate a function so that use of it will trigger a warning."""
 
57
 
 
58
    def function_decorator(callable):
 
59
        """This is the function python calls to perform the decoration."""
 
60
        
 
61
        def decorated_function(*args, **kwargs):
 
62
            """This is the decorated function."""
 
63
            symbol = "%s.%s" % (callable.__module__, 
 
64
                                callable.__name__
 
65
                                )
 
66
            warn(deprecation_version % symbol, DeprecationWarning, stacklevel=2)
 
67
            return callable(*args, **kwargs)
 
68
        _populate_decorated(callable, deprecation_version, "function",
 
69
                            decorated_function)
 
70
        return decorated_function
 
71
    return function_decorator
 
72
 
 
73
 
 
74
def deprecated_method(deprecation_version):
 
75
    """Decorate a method so that use of it will trigger a warning.
 
76
    
 
77
    To deprecate an entire class, decorate __init__.
 
78
    """
 
79
 
 
80
    def method_decorator(callable):
 
81
        """This is the function python calls to perform the decoration."""
 
82
        
 
83
        def decorated_method(self, *args, **kwargs):
 
84
            """This is the decorated method."""
 
85
            symbol = "%s.%s.%s" % (self.__class__.__module__, 
 
86
                                   self.__class__.__name__,
 
87
                                   callable.__name__
 
88
                                   )
 
89
            warn(deprecation_version % symbol, DeprecationWarning, stacklevel=2)
 
90
            return callable(self, *args, **kwargs)
 
91
        _populate_decorated(callable, deprecation_version, "method",
 
92
                            decorated_method)
 
93
        return decorated_method
 
94
    return method_decorator
 
95
 
 
96
 
 
97
def deprecated_passed(parameter_value):
 
98
    """Return True if parameter_value was used."""
 
99
    # FIXME: it might be nice to have a parameter deprecation decorator. 
 
100
    # it would need to handle positional and *args and **kwargs parameters,
 
101
    # which means some mechanism to describe how the parameter was being
 
102
    # passed before deprecation, and some way to deprecate parameters that
 
103
    # were not at the end of the arg list. Thats needed for __init__ where
 
104
    # we cannot just forward to a new method name.I.e. in the following
 
105
    # examples we would want to have callers that pass any value to 'bad' be
 
106
    # given a warning - because we have applied:
 
107
    # @deprecated_parameter('bad', zero_seven)
 
108
    #
 
109
    # def __init__(self, bad=None)
 
110
    # def __init__(self, bad, other)
 
111
    # def __init__(self, **kwargs)
 
112
    # RBC 20060116
 
113
    return not parameter_value is DEPRECATED_PARAMETER
 
114
 
 
115
 
 
116
def _decorate_docstring(callable, deprecation_version, label,
 
117
                        decorated_callable):
 
118
    if callable.__doc__:
 
119
        docstring_lines = callable.__doc__.split('\n')
 
120
    else:
 
121
        docstring_lines = []
 
122
    if len(docstring_lines) == 0:
 
123
        decorated_callable.__doc__ = deprecation_version % ("This " + label)
 
124
    elif len(docstring_lines) == 1:
 
125
        decorated_callable.__doc__ = (callable.__doc__ 
 
126
                                    + "\n"
 
127
                                    + "\n"
 
128
                                    + deprecation_version % ("This " + label)
 
129
                                    + "\n")
 
130
    else:
 
131
        spaces = len(docstring_lines[-1])
 
132
        new_doc = callable.__doc__
 
133
        new_doc += "\n" + " " * spaces
 
134
        new_doc += deprecation_version % ("This " + label)
 
135
        new_doc += "\n" + " " * spaces
 
136
        decorated_callable.__doc__ = new_doc
 
137
 
 
138
 
 
139
def _populate_decorated(callable, deprecation_version, label,
 
140
                        decorated_callable):
 
141
    """Populate attributes like __name__ and __doc__ on the decorated callable.
 
142
    """
 
143
    _decorate_docstring(callable, deprecation_version, label,
 
144
                        decorated_callable)
 
145
    decorated_callable.__module__ = callable.__module__
 
146
    decorated_callable.__name__ = callable.__name__
 
147
    decorated_callable.is_deprecated = True