From 36ecc7a1d57277391b3ed8151719d38d7a4a229f Mon Sep 17 00:00:00 2001 From: tylerlaberge Date: Sun, 14 Aug 2016 14:04:38 -0400 Subject: [PATCH] implemented adapter design pattern. --- pypatterns/structural/__init__.py | 0 pypatterns/structural/adapter.py | 31 ++++++++++ setup.py | 3 +- tests/structural_tests/__init__.py | 0 tests/structural_tests/test_adapter.py | 82 ++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 pypatterns/structural/__init__.py create mode 100644 pypatterns/structural/adapter.py create mode 100644 tests/structural_tests/__init__.py create mode 100644 tests/structural_tests/test_adapter.py diff --git a/pypatterns/structural/__init__.py b/pypatterns/structural/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pypatterns/structural/adapter.py b/pypatterns/structural/adapter.py new file mode 100644 index 0000000..4d9fe0c --- /dev/null +++ b/pypatterns/structural/adapter.py @@ -0,0 +1,31 @@ +class Adapter(object): + """ + Adapter class as part of the Adapter design pattern. + """ + def __init__(self, adaptee, **adapted_methods): + """ + Initialize a new adapter instance. + + @param adaptee: The object to adapt to a new interface. + @type adaptee: Object + @param adapted_methods: A dictionary of methods to adapt. + @type adapted_methods: dict + """ + self.__adaptee = adaptee + self.__dict__.update({k: v for k, v in adapted_methods.items() if callable(v) and + getattr(self.__adaptee, v.__name__, None)}) + + def __getattr__(self, attr): + """ + All non-adapted calls are passed to the adaptee. + + @param attr: The attribute to get from the adaptee. + """ + return getattr(self.__adaptee, attr) + + def original_dict(self): + """ + Get the adaptee's __dict__ + """ + return self.__adaptee.__dict__ + diff --git a/setup.py b/setup.py index 2736ff4..fa63040 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,8 @@ setup( packages=[ 'pypatterns', 'pypatterns.creational', - 'pypatterns.behavioral' + 'pypatterns.behavioral', + 'pypatterns.structural' ], ) diff --git a/tests/structural_tests/__init__.py b/tests/structural_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/structural_tests/test_adapter.py b/tests/structural_tests/test_adapter.py new file mode 100644 index 0000000..fa688f0 --- /dev/null +++ b/tests/structural_tests/test_adapter.py @@ -0,0 +1,82 @@ +from unittest import TestCase +from pypatterns.structural.adapter import Adapter + + +class AdapterTestCase(TestCase): + """ + Unit testing class for the Adapter class. + """ + def setUp(self): + """ + Initialize testing data. + """ + class Dog(object): + def __init__(self): + self.name = "Dog" + + def bark(self): + return "woof!" + + class Cat(object): + def __init__(self): + self.name = "Cat" + + def meow(self): + return "meow!" + + self.cat = Cat() + self.dog = Dog() + + def test_init(self): + """ + Test the init method. + + @raise AssertionError: If the test fails. + """ + cat_adapter = Adapter(self.cat, make_noise=self.cat.meow, foo=self.cat.name) + dog_adapter = Adapter(self.dog, make_noise=self.dog.bark, foo=self.dog.name) + + self.assertIn('make_noise', cat_adapter.__dict__) + self.assertIn('make_noise', dog_adapter.__dict__) + + self.assertNotIn('foo', cat_adapter.__dict__) + self.assertNotIn('foo', dog_adapter.__dict__) + + self.assertEquals(cat_adapter.make_noise, self.cat.meow) + self.assertEquals(dog_adapter.make_noise, self.dog.bark) + + def test_getattr(self): + """ + Test the __getattr__ method. + + @raise AssertionError: If the test fails. + """ + cat_adapter = Adapter(self.cat, make_noise=self.cat.meow) + dog_adapter = Adapter(self.dog, make_noise=self.dog.bark) + + self.assertEquals('Cat', cat_adapter.name) + self.assertEquals('Dog', dog_adapter.name) + + def test_original_dict(self): + """ + Test the original_dict method. + + @raise AssertionError: If the test fails. + """ + cat_adapter = Adapter(self.cat, make_noise=self.cat.meow) + dog_adapter = Adapter(self.dog, make_noise=self.dog.bark) + + self.assertEquals(self.cat.__dict__, cat_adapter.original_dict()) + self.assertEquals(self.dog.__dict__, dog_adapter.original_dict()) + + def test_adapted_method(self): + """ + Test and adapted method. + + @raise AssertionError: If the test fails. + """ + cat_adapter = Adapter(self.cat, make_noise=self.cat.meow) + dog_adapter = Adapter(self.dog, make_noise=self.dog.bark) + + self.assertEquals('meow!', cat_adapter.make_noise()) + self.assertEquals('woof!', dog_adapter.make_noise())