diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..3e4d7015c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,33 @@ +# vim ft=yaml +# travis-ci.org definition for python-patterns build +language: python + +sudo: false + +python: + - "2.7" + - "3.3" + - "3.4" + - "3.5" +# Disabled for now since cause more pain than gain +# - "pypy" +# - "pypy3" + +cache: + - pip + +install: + - travis_retry pip install -q coveralls codecov + - pip install flake8 # eventually worth + +script: + # Run tests + - PYTHONPATH=. nosetests -s -v --with-doctest --with-cov --cover-package . --logging-level=INFO -v . + # Actually run all the scripts, contributing to coverage + - ./run_all.sh + # for now failure in flaking is ignored + - flake8 *py || echo "PEP8 the code" + +after_success: + - coveralls + - codecov diff --git a/3-tier.py b/3-tier.py index 8b52216aa..625870a33 100644 --- a/3-tier.py +++ b/3-tier.py @@ -19,8 +19,7 @@ def __get__(self, obj, klas): class BusinessLogic(object): """ Business logic holding data store instances """ - def __init__(self, data): - self.data = data + data = Data() def product_list(self): return self.data['products'].keys() @@ -32,8 +31,8 @@ def product_information(self, product): class Ui(object): """ UI interaction class """ - def __init__(self, logic): - self.business_logic = logic + def __init__(self): + self.business_logic = BusinessLogic() def get_product_list(self): print('PRODUCT LIST:') @@ -54,9 +53,7 @@ def get_product_information(self, product): def main(): - data = Data() - logic = BusinessLogic(data) - ui = Ui(logic) + ui = Ui() ui.get_product_list() ui.get_product_information('cheese') ui.get_product_information('eggs') @@ -72,7 +69,7 @@ def main(): # cheese # eggs # milk -# +# # (Fetching from Data Store) # PRODUCT INFORMATION: # Name: Cheese, Price: 2.00, Quantity: 10 diff --git a/adapter.py b/adapter.py index 25cbec973..b0bc1f238 100644 --- a/adapter.py +++ b/adapter.py @@ -46,8 +46,10 @@ class Adapter(object): >>> objects = [] >>> dog = Dog() >>> print(dog.__dict__) + {'name': 'Dog'} >>> objects.append(Adapter(dog, make_noise=dog.bark)) >>> print(objects[0].original_dict()) + {'name': 'Dog'} >>> cat = Cat() >>> objects.append(Adapter(cat, make_noise=cat.meow)) >>> human = Human() diff --git a/chain.py b/chain.py index 4e087ec66..c037a4552 100644 --- a/chain.py +++ b/chain.py @@ -57,7 +57,7 @@ def delegate(self, requests): def coroutine(func): def start(*args, **kwargs): cr = func(*args, **kwargs) - cr.next() + next(cr) return cr return start diff --git a/chaining_method.py b/chaining_method.py index e03747618..de9c115d1 100644 --- a/chaining_method.py +++ b/chaining_method.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import print_function + class Person(object): def __init__(self, name, action): diff --git a/command.py b/command.py index 310432cdb..27c255558 100644 --- a/command.py +++ b/command.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- import os - +from os.path import lexists class MoveFileCommand(object): @@ -28,13 +28,23 @@ def main(): command_stack.append(MoveFileCommand('foo.txt', 'bar.txt')) command_stack.append(MoveFileCommand('bar.txt', 'baz.txt')) - # they can be executed later on - for cmd in command_stack: - cmd.execute() - - # and can also be undone at will - for cmd in reversed(command_stack): - cmd.undo() + # verify that none of the target files exist + assert(not lexists("foo.txt")) + assert(not lexists("bar.txt")) + assert(not lexists("baz.txt")) + try: + with open("foo.txt", "w"): # Creating the file + pass + + # they can be executed later on + for cmd in command_stack: + cmd.execute() + + # and can also be undone at will + for cmd in reversed(command_stack): + cmd.undo() + finally: + os.unlink("foo.txt") if __name__ == "__main__": main() diff --git a/decorator.py b/decorator.py index c90749875..e0a6fa46c 100644 --- a/decorator.py +++ b/decorator.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python """https://docs.python.org/2/library/functools.html#functools.wraps""" """https://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python/739665#739665""" diff --git a/delegation_pattern.py b/delegation_pattern.py old mode 100755 new mode 100644 diff --git a/facade.py b/facade.py index a92e4d25b..b314b1b3c 100644 --- a/facade.py +++ b/facade.py @@ -3,7 +3,7 @@ import time -SLEEP = 0.5 +SLEEP = 0.1 # Complex Parts diff --git a/flyweight.py b/flyweight.py index 557f12720..0e7d71e81 100644 --- a/flyweight.py +++ b/flyweight.py @@ -74,6 +74,11 @@ def __init__(self, *args, **kwargs): if __name__ == '__main__': + import sys + if sys.version_info[0] > 2: + sys.stderr.write("!!! This example is compatible only with Python 2 ATM !!!\n") + raise SystemExit(0) + # comment __new__ and uncomment __init__ to see the difference c1 = Card('9', 'h') c2 = Card('9', 'h') diff --git a/proxy.py b/proxy.py index 4934b0bc9..9aea8a8b4 100644 --- a/proxy.py +++ b/proxy.py @@ -18,17 +18,17 @@ def talk(self): print("Proxy checking for Sales Manager availability") if self.busy == 'No': self.sales = SalesManager() - time.sleep(2) + time.sleep(0.1) self.sales.talk() else: - time.sleep(2) + time.sleep(0.1) print("Sales Manager is busy") class NoTalkProxy(Proxy): def talk(self): print("Proxy checking for Sales Manager availability") - time.sleep(2) + time.sleep(0.1) print("This Sales Manager will not talk to you whether he/she is busy or not") diff --git a/run_all.sh b/run_all.sh new file mode 100755 index 000000000..1a90150dc --- /dev/null +++ b/run_all.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Little helper to run all the scripts, under python coverage if coverage is available +# + +set -eu +failed="" + +if which coverage > /dev/null; then + COVERAGE="`which coverage` run -a" +else + COVERAGE='' +fi +for f in [^_]*py; do + python $COVERAGE $f || failed+=" $f" + echo "I: done $f. Exit code $?" +done; + +if [ ! -z "$failed" ]; then + echo "Failed: $failed"; + exit 1 +fi \ No newline at end of file diff --git a/state.py b/state.py index 45cc30a3b..ef7bfb560 100644 --- a/state.py +++ b/state.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python """Implementation of the state pattern""" # http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ diff --git a/strategy.py b/strategy.py index 8c7a9b5a4..b7808ceac 100644 --- a/strategy.py +++ b/strategy.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # http://stackoverflow.com/questions/963965/how-is-this-strategy-pattern # -written-in-python-the-sample-in-wikipedia """ diff --git a/test_abstract_factory.py b/test_abstract_factory.py index ff228a410..c43b655a0 100644 --- a/test_abstract_factory.py +++ b/test_abstract_factory.py @@ -9,7 +9,10 @@ else: import unittest -from unittest.mock import patch +try: + from unittest.mock import patch +except ImportError: + from mock import patch class TestPetShop(unittest.TestCase): diff --git a/test_adapter.py b/test_adapter.py index 2af0926cf..1961127d0 100644 --- a/test_adapter.py +++ b/test_adapter.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python from adapter import Dog, Cat, Human, Car, Adapter import sys diff --git a/test_borg.py b/test_borg.py index c08fd19d5..97470eaf9 100644 --- a/test_borg.py +++ b/test_borg.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python from borg import Borg, YourBorg import sys diff --git a/test_bridge.py b/test_bridge.py index 4c4b5220d..c4db5e8c8 100644 --- a/test_bridge.py +++ b/test_bridge.py @@ -4,12 +4,16 @@ from bridge import DrawingAPI1, DrawingAPI2, CircleShape from sys import version_info -if version_info < (2, 7): +if version_info < (2, 7): # pragma: no cover import unittest2 as unittest else: import unittest -from unittest.mock import patch +try: + from unittest.mock import patch +except ImportError: + from mock import patch + class BridgeTest(unittest.TestCase): diff --git a/test_command.py b/test_command.py index d3b42f6c1..584b273b5 100644 --- a/test_command.py +++ b/test_command.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python from command import MoveFileCommand import os, shutil, subprocess, sys diff --git a/test_flyweight.py b/test_flyweight.py index 5cb62f143..11017ad58 100644 --- a/test_flyweight.py +++ b/test_flyweight.py @@ -4,7 +4,7 @@ from flyweight import Card from sys import version_info -if version_info < (2, 7): +if version_info < (2, 7): # pragma: no cover import unittest2 as unittest else: import unittest diff --git a/test_hsm.py b/test_hsm.py index be468d8ef..79e38440e 100644 --- a/test_hsm.py +++ b/test_hsm.py @@ -1,13 +1,17 @@ +#!/usr/bin/env python from hsm import HierachicalStateMachine, UnsupportedMessageType,\ UnsupportedState, UnsupportedTransition, Active, Standby, Suspect, Failed from sys import version_info -if version_info < (2, 7): +if version_info < (2, 7): # pragma: no cover import unittest2 as unittest else: import unittest -from unittest.mock import patch +try: + from unittest.mock import patch +except ImportError: + from mock import patch class HsmMethodTest(unittest.TestCase): @@ -74,18 +78,18 @@ def test_given_standby_on_message_fault_trigger_shall_set_suspect(cls): def test_given_standby_on_message_diagnostics_failed_shall_raise_exception_and_keep_in_state(cls): with cls.assertRaises(UnsupportedTransition) as context: cls.hsm.on_message('diagnostics failed') - cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) + cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) def test_given_standby_on_message_diagnostics_passed_shall_raise_exception_and_keep_in_state(cls): with cls.assertRaises(UnsupportedTransition) as context: cls.hsm.on_message('diagnostics passed') - cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) + cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) def test_given_standby_on_message_operator_inservice_shall_raise_exception_and_keep_in_state(cls): with cls.assertRaises(UnsupportedTransition) as context: cls.hsm.on_message('operator inservice') - cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) + cls.assertEqual(isinstance(cls.hsm._current_state, Standby), True) if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file diff --git a/test_observer.py b/test_observer.py index 473603bd5..733ee6333 100644 --- a/test_observer.py +++ b/test_observer.py @@ -7,11 +7,14 @@ if sys.version_info < (2, 7): import unittest2 as unittest - else: import unittest -from unittest.mock import patch +try: + from unittest.mock import patch +except ImportError: + from mock import patch + class TestSubject(unittest.TestCase): diff --git a/test_proxy.py b/test_proxy.py new file mode 100755 index 000000000..839b4130b --- /dev/null +++ b/test_proxy.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from proxy import Proxy, NoTalkProxy +import sys +from time import time + +if sys.version_info[0] == 2: + from StringIO import StringIO +else: + from io import StringIO + +if sys.version_info < (2, 7): + import unittest2 as unittest +else: + import unittest + + +class ProxyTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + """ Class scope setup. """ + cls.p = Proxy() + + def setUp(cls): + """ Function/test case scope setup. """ + cls.output = StringIO() + cls.saved_stdout = sys.stdout + sys.stdout = cls.output + + def tearDown(cls): + """ Function/test case scope teardown. """ + cls.output.close() + sys.stdout = cls.saved_stdout + + def test_sales_manager_shall_talk_through_proxy_with_delay(cls): + cls.p.busy = 'No' + start_time = time() + cls.p.talk() + end_time = time() + execution_time = end_time - start_time + print_output = cls.output.getvalue() + expected_print_output = 'Proxy checking for Sales Manager availability\n\ +Sales Manager ready to talk\n' + cls.assertEqual(print_output, expected_print_output) + expected_execution_time = 1 + cls.assertEqual(int(execution_time*10), expected_execution_time) + + def test_sales_manager_shall_respond_through_proxy_with_delay(cls): + cls.p.busy = 'Yes' + start_time = time() + cls.p.talk() + end_time = time() + execution_time = end_time - start_time + print_output = cls.output.getvalue() + expected_print_output = 'Proxy checking for Sales Manager availability\n\ +Sales Manager is busy\n' + cls.assertEqual(print_output, expected_print_output) + expected_execution_time = 1 + cls.assertEqual(int(execution_time*10), expected_execution_time) + + +class NoTalkProxyTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + """ Class scope setup. """ + cls.ntp = NoTalkProxy() + + def setUp(cls): + """ Function/test case scope setup. """ + cls.output = StringIO() + cls.saved_stdout = sys.stdout + sys.stdout = cls.output + + def tearDown(cls): + """ Function/test case scope teardown. """ + cls.output.close() + sys.stdout = cls.saved_stdout + + def test_sales_manager_shall_not_talk_through_proxy_with_delay(cls): + cls.ntp.busy = 'No' + start_time = time() + cls.ntp.talk() + end_time = time() + execution_time = end_time - start_time + print_output = cls.output.getvalue() + expected_print_output = 'Proxy checking for Sales Manager availability\n\ +This Sales Manager will not talk to you whether he/she is busy or not\n' + cls.assertEqual(print_output, expected_print_output) + expected_execution_time = 1 + cls.assertEqual(int(execution_time*10), expected_execution_time) + + def test_sales_manager_shall_not_respond_through_proxy_with_delay(cls): + cls.ntp.busy = 'Yes' + start_time = time() + cls.ntp.talk() + end_time = time() + execution_time = end_time - start_time + print_output = cls.output.getvalue() + expected_print_output = 'Proxy checking for Sales Manager availability\n\ +This Sales Manager will not talk to you whether he/she is busy or not\n' + cls.assertEqual(print_output, expected_print_output) + expected_execution_time = 1 + cls.assertEqual(int(execution_time*10), expected_execution_time) + +if __name__ == "__main__": + unittest.main() diff --git a/test_publish_subscribe.py b/test_publish_subscribe.py index 4d154a157..962a12990 100644 --- a/test_publish_subscribe.py +++ b/test_publish_subscribe.py @@ -4,13 +4,16 @@ from sys import version_info from publish_subscribe import Provider, Publisher, Subscriber -if version_info < (2, 7): +if version_info < (2, 7): # pragma: no cover import unittest2 as unittest - else: import unittest -from unittest.mock import patch, call +try: + from unittest.mock import patch, call +except ImportError: + from mock import patch, call + class TestProvider(unittest.TestCase): """ diff --git a/test_state.py b/test_state.py index 079602b0e..e96f8fbed 100644 --- a/test_state.py +++ b/test_state.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python from state import Radio import sys diff --git a/test_strategy.py b/test_strategy.py index a5f3ee3ee..22bfe43d7 100644 --- a/test_strategy.py +++ b/test_strategy.py @@ -1,14 +1,18 @@ +#!/usr/bin/env python """ Tests for strategy.py """ -import subprocess, sys +import os +import subprocess +import sys if sys.version_info < (2, 7): import unittest2 as unittest else: import unittest + class StrategyTest(unittest.TestCase): def test_print_output(self): @@ -18,12 +22,15 @@ def test_print_output(self): line when running 'python strategy.py'. """ output = subprocess.check_output(["python", "strategy.py"]) - expected_output = 'Strategy Example 0\r\n\ -Strategy Example 1 from execute 1\r\n\ -Strategy Example 2 from execute 2\r\n' + expected_output = os.linesep.join([ + 'Strategy Example 0', + 'Strategy Example 1 from execute 1', + 'Strategy Example 2 from execute 2', + '' + ]) # byte representation required due to EOF returned subprocess expected_output_as_bytes = expected_output.encode(encoding='UTF-8') self.assertEqual(output, expected_output_as_bytes) if __name__ == "__main__": - unitest.main() + unittest.main()