forwardable
Advanced tools
| Metadata-Version: 1.1 | ||
| Name: forwardable | ||
| Version: 0.1.1 | ||
| Version: 0.2.0 | ||
| Summary: Forwardable as in Ruby's stdlib | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/5long/forwardable |
@@ -1,3 +0,20 @@ | ||
| __version__ = '0.1.1' | ||
| """ | ||
| Easy delegation definition. A quick example: | ||
| from forwardable import forwardable | ||
| @forwardable() # Note the () here, which is required. | ||
| class Foo(object): | ||
| def_delegators('bar', ('add', '__len__')) | ||
| def __init__(self) | ||
| self.bar = set() | ||
| foo = Foo() | ||
| foo.add(1) # Delegates to foo.bar.add() | ||
| assert len(foo) == 1 | ||
| """ | ||
| __version__ = '0.2.0' | ||
| __all__ = ["forwardable", "def_delegator", "def_delegators"] | ||
@@ -12,2 +29,9 @@ | ||
| def def_delegator(wrapped, attr_name, _call_stack_depth=1): | ||
| """ | ||
| Define a property ``attr_name`` in the current class scope which | ||
| forwards accessing of ``self.<attr_name>`` to property | ||
| ``self.<wrapped>.<attr_name>``. | ||
| Must be called in a class scope. | ||
| """ | ||
| frame = sys._getframe(_call_stack_depth) | ||
@@ -18,10 +42,25 @@ | ||
| def get_wrapped_obj(self): | ||
| return getattr(self, wrapped) | ||
| def getter(self): | ||
| return getattr(getattr(self, wrapped), attr_name) | ||
| return getattr(get_wrapped_obj(self), attr_name) | ||
| def setter(self, value): | ||
| return setattr(get_wrapped_obj(self), attr_name, value) | ||
| def deleter(self): | ||
| return delattr(get_wrapped_obj(self), attr_name) | ||
| scope = frame.f_locals | ||
| scope[attr_name] = property(getter) | ||
| scope[attr_name] = property(getter, setter, deleter) | ||
| def def_delegators(wrapped, attrs): | ||
| """ | ||
| Define multiple delegations for a single delegatee. Roughly equivalent | ||
| to def_delegator() in a for-loop. | ||
| Must be called in a class scope. | ||
| """ | ||
| for a in attrs: | ||
@@ -52,2 +91,10 @@ def_delegator(wrapped, a, _call_stack_depth=2) | ||
| def forwardable(): | ||
| """ | ||
| A class decorator which makes def_delegator() and def_delegators() | ||
| available in the class scope. | ||
| This decorator must be used in the form of `@forwardable()`, instead of | ||
| `@forwardable`. And it must be called in a module scope (which should be | ||
| the case for most common class definitions). | ||
| """ | ||
| frame = sys._getframe(1) | ||
@@ -54,0 +101,0 @@ inject(frame) |
@@ -6,2 +6,6 @@ from unittest import TestCase | ||
| class Object(object): | ||
| pass | ||
| class TestForwardable(TestCase): | ||
@@ -41,1 +45,37 @@ def test_def_delegator(self): | ||
| self.assertEqual(len(Foo()), 0) | ||
| def test_property_deleting(self): | ||
| class Foo(object): | ||
| def_delegator("bar", "baz") | ||
| foo = Foo() | ||
| foo.bar = Object() | ||
| foo.bar.baz = 42 | ||
| del foo.baz | ||
| self.assertFalse(hasattr(foo, 'baz')) | ||
| def test_hasattr(self): | ||
| class Foo(object): | ||
| def_delegator("bar", "baz") | ||
| foo = Foo() | ||
| foo.bar = Object() | ||
| self.assertFalse(hasattr(foo, 'baz')) | ||
| foo.bar.baz = 42 | ||
| self.assertTrue(hasattr(foo, 'baz')) | ||
| def test_setattr(self): | ||
| class Foo(object): | ||
| def_delegator("bar", "baz") | ||
| foo = Foo() | ||
| foo.bar = Object() | ||
| foo.baz = 42 | ||
| self.assertTrue(foo.bar.baz, 42) |
+1
-1
| Metadata-Version: 1.1 | ||
| Name: forwardable | ||
| Version: 0.1.1 | ||
| Version: 0.2.0 | ||
| Summary: Forwardable as in Ruby's stdlib | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/5long/forwardable |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
14048
17.49%182
50.41%