Fix to preserve argspec
The positional wrapper is fixed so that the argspec of the wrapped function is preserved.
This commit is contained in:
parent
3c3f08b4b6
commit
b913f827bb
@ -10,11 +10,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import functools
|
|
||||||
import inspect
|
import inspect
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import pbr.version
|
import pbr.version
|
||||||
|
import wrapt
|
||||||
|
|
||||||
__version__ = pbr.version.VersionInfo('positional').version_string()
|
__version__ = pbr.version.VersionInfo('positional').version_string()
|
||||||
|
|
||||||
@ -76,14 +76,21 @@ class positional(object):
|
|||||||
|
|
||||||
plural = '' if self._max_positional_args == 1 else 's'
|
plural = '' if self._max_positional_args == 1 else 's'
|
||||||
|
|
||||||
@functools.wraps(func)
|
@wrapt.decorator
|
||||||
def inner(*args, **kwargs):
|
def inner(wrapped, instance, args, kwargs):
|
||||||
if len(args) > self._max_positional_args:
|
|
||||||
|
# If called on an instance, adjust args len for the 'self'
|
||||||
|
# parameter.
|
||||||
|
args_len = len(args)
|
||||||
|
if instance:
|
||||||
|
args_len += 1
|
||||||
|
|
||||||
|
if args_len > self._max_positional_args:
|
||||||
message = ('%(name)s takes at most %(max)d positional '
|
message = ('%(name)s takes at most %(max)d positional '
|
||||||
'argument%(plural)s (%(given)d given)' %
|
'argument%(plural)s (%(given)d given)' %
|
||||||
{'name': func.__name__,
|
{'name': wrapped.__name__,
|
||||||
'max': self._max_positional_args,
|
'max': self._max_positional_args,
|
||||||
'given': len(args),
|
'given': args_len,
|
||||||
'plural': plural})
|
'plural': plural})
|
||||||
|
|
||||||
if self._enforcement == self.EXCEPT:
|
if self._enforcement == self.EXCEPT:
|
||||||
@ -91,6 +98,6 @@ class positional(object):
|
|||||||
elif self._enforcement == self.WARN:
|
elif self._enforcement == self.WARN:
|
||||||
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return wrapped(*args, **kwargs)
|
||||||
|
|
||||||
return inner
|
return inner(func)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import inspect
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
@ -81,3 +82,15 @@ class TestPositional(testtools.TestCase):
|
|||||||
def test_normal_method(self):
|
def test_normal_method(self):
|
||||||
self.assertEqual((self, 1, 2), self.normal_method(1, b=2))
|
self.assertEqual((self, 1, 2), self.normal_method(1, b=2))
|
||||||
self.assertRaises(TypeError, self.normal_method, 1, 2)
|
self.assertRaises(TypeError, self.normal_method, 1, 2)
|
||||||
|
|
||||||
|
def test_argspec_preserved(self):
|
||||||
|
|
||||||
|
@positional()
|
||||||
|
def f_wrapped(my_arg=False):
|
||||||
|
return my_arg
|
||||||
|
|
||||||
|
def f_not_wrapped(my_arg=False):
|
||||||
|
return my_arg
|
||||||
|
|
||||||
|
self.assertEqual(inspect.getargspec(f_not_wrapped),
|
||||||
|
inspect.getargspec(f_wrapped))
|
||||||
|
@ -2,3 +2,4 @@
|
|||||||
# of appearance.
|
# of appearance.
|
||||||
|
|
||||||
pbr>=1.6
|
pbr>=1.6
|
||||||
|
wrapt
|
||||||
|
Loading…
Reference in New Issue
Block a user