Skip to content

Commit d9de283

Browse files
author
fkromer
committed
Merge remote-tracking branch 'upstream/master' into hsm
2 parents 2ffad3a + ad59bd5 commit d9de283

14 files changed

+441
-84
lines changed

builder.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ def __init__(self):
3131
def new_building(self):
3232
self.building = Building()
3333

34+
def build_floor(self):
35+
raise NotImplementedError
36+
37+
def build_size(self):
38+
raise NotImplementedError
3439

3540
# Concrete Builder
3641
class BuilderHouse(Builder):

catalog.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def _instance_method_2(self):
7575

7676
def main_method(self):
7777
"""
78-
will execute either _instance_method_1 or _instance_method_1
78+
will execute either _instance_method_1 or _instance_method_2
7979
depending on self.param value
8080
"""
8181
self._instance_method_choices[self.param].__get__(self)()
@@ -111,7 +111,7 @@ def _class_method_2(cls):
111111

112112
def main_method(self):
113113
"""
114-
will execute either _instance_method_1 or _instance_method_1
114+
will execute either _class_method_1 or _class_method_2
115115
depending on self.param value
116116
"""
117117
self._class_method_choices[self.param].__get__(None, self.__class__)()
@@ -143,7 +143,7 @@ def _static_method_2():
143143

144144
def main_method(self):
145145
"""
146-
will execute either _instance_method_1 or _instance_method_1
146+
will execute either _static_method_1 or _static_method_2
147147
depending on self.param value
148148
"""
149149
self._static_method_choices[self.param].__get__(None, self.__class__)()

chain.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
"""http://www.testingperspective.com/wiki/doku.php/collaboration/chetan/designpatternsinpython/chain-of-responsibilitypattern"""
54
"""http://www.dabeaz.com/coroutines/"""
65

76
import time

delegation_pattern.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
Reference: https://en.wikipedia.org/wiki/Delegation_pattern
6+
Author: https://github.com/IuryAlves
7+
"""
8+
9+
10+
class Delegator(object):
11+
"""
12+
>>> delegator = Delegator(Delegate())
13+
>>> delegator.do_something("nothing")
14+
'Doing nothing'
15+
>>> delegator.do_anything()
16+
17+
"""
18+
def __init__(self, delegate):
19+
self.delegate = delegate
20+
21+
def __getattr__(self, name):
22+
def wrapper(*args, **kwargs):
23+
if hasattr(self.delegate, name):
24+
attr = getattr(self.delegate, name)
25+
if callable(attr):
26+
return attr(*args, **kwargs)
27+
return wrapper
28+
29+
30+
class Delegate(object):
31+
32+
def do_something(self, something):
33+
return "Doing %s" % something
34+
35+
36+
if __name__ == '__main__':
37+
import doctest
38+
doctest.testmod()

facade.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def __init__(self):
5656
self.tc1 = TC1()
5757
self.tc2 = TC2()
5858
self.tc3 = TC3()
59-
self.tests = [i for i in (self.tc1, self.tc2, self.tc3)]
59+
self.tests = [self.tc1, self.tc2, self.tc3]
6060

6161
def runAll(self):
6262
[i.run() for i in self.tests]

mvc.py

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,121 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
54
class Model(object):
5+
def __iter__(self):
6+
raise NotImplementedError
7+
8+
def get(self, item):
9+
"""Returns an object with a .items() call method
10+
that iterates over key,value pairs of its information."""
11+
raise NotImplementedError
12+
13+
@property
14+
def item_type(self):
15+
raise NotImplementedError
16+
17+
18+
19+
class ProductModel(Model):
20+
21+
class Price(float):
22+
"""A polymorphic way to pass a float with a particular __str__ functionality."""
23+
def __str__(self):
24+
first_digits_str = str(round(self,2))
25+
try:
26+
dot_location = first_digits_str.index('.')
27+
except ValueError:
28+
return (first_digits_str + '.00')
29+
else:
30+
return (first_digits_str +
31+
'0'*(3 + dot_location - len(first_digits_str)))
632

733
products = {
8-
'milk': {'price': 1.50, 'quantity': 10},
9-
'eggs': {'price': 0.20, 'quantity': 100},
10-
'cheese': {'price': 2.00, 'quantity': 10}
34+
'milk': {'price': Price(1.50), 'quantity': 10},
35+
'eggs': {'price': Price(0.20), 'quantity': 100},
36+
'cheese': {'price': Price(2.00), 'quantity': 10}
1137
}
1238

39+
item_type = 'product'
40+
41+
def __iter__(self):
42+
for item in self.products:
43+
yield item
44+
45+
def get(self, product):
46+
try:
47+
return self.products[product]
48+
except KeyError as e:
49+
raise KeyError((str(e) + " not in the model's item list."))
1350

1451
class View(object):
52+
def show_item_list(self, item_type, item_list):
53+
raise NotImplementedError
1554

16-
def product_list(self, product_list):
17-
print('PRODUCT LIST:')
18-
for product in product_list:
19-
print(product)
20-
print('')
55+
def show_item_information(self, item_type, item_name, item_info):
56+
"""Will look for item information by iterating over key,value pairs
57+
yielded by item_info.items()"""
58+
raise NotImplementedError
2159

22-
def product_information(self, product, product_info):
23-
print('PRODUCT INFORMATION:')
24-
print('Name: %s, Price: %.2f, Quantity: %d\n' %
25-
(product.title(), product_info.get('price', 0),
26-
product_info.get('quantity', 0)))
60+
def item_not_found(self, item_type, item_name):
61+
raise NotImplementedError
2762

28-
def product_not_found(self, product):
29-
print('That product "%s" does not exist in the records' % product)
63+
class ConsoleView(View):
3064

65+
def show_item_list(self, item_type, item_list):
66+
print(item_type.upper() + ' LIST:')
67+
for item in item_list:
68+
print(item)
69+
print('')
3170

32-
class Controller(object):
71+
@staticmethod
72+
def capitalizer(string):
73+
return string[0].upper() + string[1:].lower()
3374

34-
def __init__(self):
35-
self.model = Model()
36-
self.view = View()
75+
def show_item_information(self, item_type, item_name, item_info):
76+
print(item_type.upper() + ' INFORMATION:')
77+
printout = 'Name: %s' % item_name
78+
for key, value in item_info.items():
79+
printout += (', ' + self.capitalizer(str(key)) + ': ' + str(value))
80+
printout += '\n'
81+
print(printout)
3782

38-
def get_product_list(self):
39-
product_list = self.model.products.keys()
40-
self.view.product_list(product_list)
83+
def item_not_found(self, item_type, item_name):
84+
print('That %s "%s" does not exist in the records' % (item_type, item_name))
85+
86+
87+
class Controller(object):
4188

42-
def get_product_information(self, product):
43-
product_info = self.model.products.get(product, None)
44-
if product_info is not None:
45-
self.view.product_information(product, product_info)
89+
def __init__(self, model, view):
90+
self.model = model
91+
self.view = view
92+
93+
def show_items(self):
94+
items = list(self.model)
95+
item_type = self.model.item_type
96+
self.view.show_item_list(item_type, items)
97+
98+
def show_item_information(self, item_name):
99+
try:
100+
item_info = self.model.get(item_name)
101+
except:
102+
item_type = self.model.item_type
103+
self.view.item_not_found(item_type, item_name)
46104
else:
47-
self.view.product_not_found(product)
105+
item_type = self.model.item_type
106+
self.view.show_item_information(item_type, item_name, item_info)
48107

49108

50109
if __name__ == '__main__':
51110

52-
controller = Controller()
53-
controller.get_product_list()
54-
controller.get_product_information('cheese')
55-
controller.get_product_information('eggs')
56-
controller.get_product_information('milk')
57-
controller.get_product_information('arepas')
111+
model = ProductModel()
112+
view = ConsoleView()
113+
controller = Controller(model, view)
114+
controller.show_items()
115+
controller.show_item_information('cheese')
116+
controller.show_item_information('eggs')
117+
controller.show_item_information('milk')
118+
controller.show_item_information('arepas')
58119

59120
### OUTPUT ###
60121
# PRODUCT LIST:

prototype.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,24 @@
66

77
class Prototype:
88

9+
value = 'default'
10+
11+
def clone(self, **attrs):
12+
"""Clone a prototype and update inner attributes dictionary"""
13+
obj = copy.deepcopy(self)
14+
obj.__dict__.update(attrs)
15+
return obj
16+
17+
18+
class PrototypeDispatcher:
19+
920
def __init__(self):
1021
self._objects = {}
1122

23+
def get_objects(self):
24+
"""Get all objects"""
25+
return self._objects
26+
1227
def register_object(self, name, obj):
1328
"""Register an object"""
1429
self._objects[name] = obj
@@ -17,34 +32,21 @@ def unregister_object(self, name):
1732
"""Unregister an object"""
1833
del self._objects[name]
1934

20-
def clone(self, name, **attr):
21-
"""Clone a registered object and update inner attributes dictionary"""
22-
obj = copy.deepcopy(self._objects.get(name))
23-
obj.__dict__.update(attr)
24-
return obj
25-
26-
27-
class A:
28-
def __init__(self):
29-
self.x = 3
30-
self.y = 8
31-
self.z = 15
32-
self.garbage = [38, 11, 19]
33-
34-
def __str__(self):
35-
return '{} {} {} {}'.format(self.x, self.y, self.z, self.garbage)
36-
3735

3836
def main():
39-
a = A()
37+
dispatcher = PrototypeDispatcher()
4038
prototype = Prototype()
41-
prototype.register_object('objecta', a)
42-
b = prototype.clone('objecta')
43-
c = prototype.clone('objecta', x=1, y=2, garbage=[88, 1])
44-
print([str(i) for i in (a, b, c)])
39+
40+
d = prototype.clone()
41+
a = prototype.clone(value='a-value', category='a')
42+
b = prototype.clone(value='b-value', is_checked=True)
43+
dispatcher.register_object('objecta', a)
44+
dispatcher.register_object('objectb', b)
45+
dispatcher.register_object('default', d)
46+
print([{n: p.value} for n, p in dispatcher.get_objects().items()])
4547

4648
if __name__ == '__main__':
4749
main()
4850

4951
### OUTPUT ###
50-
# ['3 8 15 [38, 11, 19]', '3 8 15 [38, 11, 19]', '1 2 15 [88, 1]']
52+
# [{'objectb': 'b-value'}, {'default': 'default'}, {'objecta': 'a-value'}]

proxy.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66

77
class SalesManager:
8-
def work(self):
9-
print("Sales Manager working...")
10-
118
def talk(self):
129
print("Sales Manager ready to talk")
1310

@@ -17,7 +14,7 @@ def __init__(self):
1714
self.busy = 'No'
1815
self.sales = None
1916

20-
def work(self):
17+
def talk(self):
2118
print("Proxy checking for Sales Manager availability")
2219
if self.busy == 'No':
2320
self.sales = SalesManager()
@@ -29,24 +26,21 @@ def work(self):
2926

3027

3128
class NoTalkProxy(Proxy):
32-
def __init__(self):
33-
Proxy.__init__(self)
34-
35-
def work(self):
29+
def talk(self):
3630
print("Proxy checking for Sales Manager availability")
3731
time.sleep(2)
3832
print("This Sales Manager will not talk to you whether he/she is busy or not")
3933

4034

4135
if __name__ == '__main__':
4236
p = Proxy()
43-
p.work()
37+
p.talk()
4438
p.busy = 'Yes'
45-
p.work()
39+
p.talk()
4640
p = NoTalkProxy()
47-
p.work()
41+
p.talk()
4842
p.busy = 'Yes'
49-
p.work()
43+
p.talk()
5044

5145
### OUTPUT ###
5246
# Proxy checking for Sales Manager availability

publish_subscribe.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def __init__(self, name, msg_center):
4848
def subscribe(self, msg):
4949
self.provider.subscribe(msg, self)
5050

51+
def unsubscribe(self, msg):
52+
self.provider.unsubscribe(msg, self)
53+
5154
def run(self, msg):
5255
print("{} got {}".format(self.name, msg))
5356

@@ -63,6 +66,9 @@ def main():
6366
jack.subscribe("music")
6467
gee = Subscriber("gee", message_center)
6568
gee.subscribe("movie")
69+
vani = Subscriber("vani", message_center)
70+
vani.subscribe("movie")
71+
vani.unsubscribe("movie")
6672

6773
fftv.publish("cartoon")
6874
fftv.publish("music")

0 commit comments

Comments
 (0)