~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/decorators.py

(spiv) Preserve identity of default values in the pretty decorators.
 (#718569) (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
def _get_parameters(func):
31
31
    """Recreate the parameters for a function using introspection.
32
32
 
33
 
    :return: (function_params, calling_params)
 
33
    :return: (function_params, calling_params, default_values)
34
34
        function_params: is a string representing the parameters of the
35
35
            function. (such as "a, b, c=None, d=1")
36
36
            This is used in the function declaration.
37
37
        calling_params: is another string representing how you would call the
38
38
            function with the correct parameters. (such as "a, b, c=c, d=d")
39
 
            Assuming you sued function_params in the function declaration, this
 
39
            Assuming you used function_params in the function declaration, this
40
40
            is the parameters to put in the function call.
 
41
        default_values_block: a dict with the default values to be passed as
 
42
            the scope for the 'exec' statement.
41
43
 
42
44
        For example:
43
45
 
49
51
    # it globally.
50
52
    import inspect
51
53
    args, varargs, varkw, defaults = inspect.getargspec(func)
 
54
    defaults_dict = {}
 
55
    def formatvalue(value):
 
56
        default_name = '__default_%d' % len(defaults_dict)
 
57
        defaults_dict[default_name] = value
 
58
        return '=' + default_name
52
59
    formatted = inspect.formatargspec(args, varargs=varargs,
53
60
                                      varkw=varkw,
54
 
                                      defaults=defaults)
 
61
                                      defaults=defaults,
 
62
                                      formatvalue=formatvalue)
55
63
    if defaults is None:
56
64
        args_passed = args
57
65
    else:
65
73
        args_passed.append('**' + varkw)
66
74
    args_passed = ', '.join(args_passed)
67
75
 
68
 
    return formatted[1:-1], args_passed
 
76
    return formatted[1:-1], args_passed, defaults_dict
69
77
 
70
78
 
71
79
def _pretty_needs_read_lock(unbound):
107
115
        return result
108
116
read_locked = %(name)s_read_locked
109
117
"""
110
 
    params, passed_params = _get_parameters(unbound)
 
118
    params, passed_params, defaults_dict = _get_parameters(unbound)
111
119
    variables = {'name':unbound.__name__,
112
120
                 'params':params,
113
121
                 'passed_params':passed_params,
114
122
                }
115
123
    func_def = template % variables
116
124
 
117
 
    exec func_def in locals()
 
125
    scope = dict(defaults_dict)
 
126
    scope['unbound'] = unbound
 
127
    exec func_def in scope
 
128
    read_locked = scope['read_locked']
118
129
 
119
130
    read_locked.__doc__ = unbound.__doc__
120
131
    read_locked.__name__ = unbound.__name__
172
183
        return result
173
184
write_locked = %(name)s_write_locked
174
185
"""
175
 
    params, passed_params = _get_parameters(unbound)
 
186
    params, passed_params, defaults_dict = _get_parameters(unbound)
176
187
    variables = {'name':unbound.__name__,
177
188
                 'params':params,
178
189
                 'passed_params':passed_params,
179
190
                }
180
191
    func_def = template % variables
181
192
 
182
 
    exec func_def in locals()
 
193
    scope = dict(defaults_dict)
 
194
    scope['unbound'] = unbound
 
195
    exec func_def in scope
 
196
    write_locked = scope['write_locked']
183
197
 
184
198
    write_locked.__doc__ = unbound.__doc__
185
199
    write_locked.__name__ = unbound.__name__