├── 9324OS_13_code ├── old │ ├── note │ ├── test.py │ └── observer.py └── observer.py ├── README.md ├── 9324OS_05_code ├── fibonacci_naive.py ├── old │ ├── fibonacci_naive.py │ ├── fibonacci.py │ └── mymath.py ├── fibonacci.py └── mymath.py ├── 9324OS_03_code └── clone.py ├── 9324OS_04_code ├── external.py ├── old │ ├── external.py │ └── adapter.py └── adapter.py ├── 9324OS_15_code ├── langs.py ├── old │ ├── langs.py │ └── strategy.py └── strategy.py ├── 9324OS_11_code ├── first-class.py ├── old │ ├── first-class.py │ └── command.py └── command.py ├── 9324OS_16_code └── old │ ├── template.py │ ├── graph-template.py │ └── graph.py ├── 9324OS_02_code ├── fluent_builder.py ├── apple-factory.py ├── computer-builder.py └── builder.py ├── .gitignore ├── 9324OS_09_code ├── lazy.py └── proxy.py ├── LICENSE ├── 9324OS_08_code ├── old │ └── mvc.py └── mvc.py ├── 9324OS_07_code ├── old │ └── flyweight.py └── flyweight.py ├── 9324OS_10_code ├── chain.py └── old │ └── chain.py ├── 9324OS_01_code ├── data │ ├── person.xml │ └── donut.json ├── old │ ├── data │ │ ├── person.xml │ │ └── donut.json │ ├── factory_method.py │ └── abstract_factory.py ├── factory_method.py └── abstract_factory.py ├── 9324OS_06_code ├── old │ └── facade.py └── facade.py ├── 9324OS_14_code ├── old │ └── state.py └── state.py └── 9324OS_12_code ├── interpreter.py └── old └── interpreter.py /9324OS_13_code/old/note: -------------------------------------------------------------------------------- 1 | solution with decorators instead of subject class 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mastering-Python-Design-Patterns-Example 2 | Mastering-Python-Design-Patterns code example 3 | -------------------------------------------------------------------------------- /9324OS_05_code/fibonacci_naive.py: -------------------------------------------------------------------------------- 1 | def fibonacci(n): 2 | assert(n >= 0), 'n must be >= 0' 3 | return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) 4 | 5 | if __name__ == '__main__': 6 | from timeit import Timer 7 | t = Timer('fibonacci(8)', 'from __main__ import fibonacci') 8 | print(t.timeit()) 9 | -------------------------------------------------------------------------------- /9324OS_05_code/old/fibonacci_naive.py: -------------------------------------------------------------------------------- 1 | def fibonacci(n): 2 | assert(n >= 0), 'n must be >= 0' 3 | return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) 4 | 5 | if __name__ == '__main__': 6 | from timeit import Timer 7 | t = Timer('fibonacci(8)', 'from __main__ import fibonacci') 8 | print(t.timeit()) 9 | -------------------------------------------------------------------------------- /9324OS_05_code/fibonacci.py: -------------------------------------------------------------------------------- 1 | known = {0:0, 1:1} 2 | 3 | def fibonacci(n): 4 | assert(n >= 0), 'n must be >= 0' 5 | if n in known: 6 | return known[n] 7 | res = fibonacci(n-1) + fibonacci(n-2) 8 | known[n] = res 9 | return res 10 | 11 | if __name__ == '__main__': 12 | from timeit import Timer 13 | t = Timer('fibonacci(100)', 'from __main__ import fibonacci') 14 | print(t.timeit()) 15 | -------------------------------------------------------------------------------- /9324OS_05_code/old/fibonacci.py: -------------------------------------------------------------------------------- 1 | known = {0:0, 1:1} 2 | 3 | def fibonacci(n): 4 | assert(n >= 0), 'n must be >= 0' 5 | if n in known: 6 | return known[n] 7 | res = fibonacci(n-1) + fibonacci(n-2) 8 | known[n] = res 9 | return res 10 | 11 | if __name__ == '__main__': 12 | from timeit import Timer 13 | t = Timer('fibonacci(100)', 'from __main__ import fibonacci') 14 | print(t.timeit()) 15 | -------------------------------------------------------------------------------- /9324OS_03_code/clone.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | class A: 4 | def __init__(self): 5 | self.x = 18 6 | self.msg = 'Hello' 7 | 8 | class B(A): 9 | def __init__(self): 10 | A.__init__(self) 11 | self.y = 34 12 | 13 | def __str__(self): 14 | return '{}, {}, {}'.format(self.x, self.msg, self.y) 15 | 16 | if __name__ == '__main__': 17 | b = B() 18 | c = copy.deepcopy(b) 19 | print([str(i) for i in (b, c)]) 20 | print([i for i in (b, c)]) 21 | -------------------------------------------------------------------------------- /9324OS_04_code/external.py: -------------------------------------------------------------------------------- 1 | class Synthesizer: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return 'the {} synthesizer'.format(self.name) 7 | 8 | def play(self): 9 | return 'is playing an electronic song' 10 | 11 | class Human: 12 | def __init__(self, name): 13 | self.name = name 14 | 15 | def __str__(self): 16 | return '{} the human'.format(self.name) 17 | 18 | def speak(self): 19 | return 'says hello' 20 | -------------------------------------------------------------------------------- /9324OS_04_code/old/external.py: -------------------------------------------------------------------------------- 1 | class Synthesizer: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return 'the {} synthesizer'.format(self.name) 7 | 8 | def play(self): 9 | return 'is playing an electronic song' 10 | 11 | class Human: 12 | def __init__(self, name): 13 | self.name = name 14 | 15 | def __str__(self): 16 | return '{} the human'.format(self.name) 17 | 18 | def speak(self): 19 | return 'says hello' 20 | -------------------------------------------------------------------------------- /9324OS_13_code/old/test.py: -------------------------------------------------------------------------------- 1 | def notify(f): 2 | def g(self, n): 3 | print n 4 | return f(self, n) 5 | return g 6 | 7 | class Point(object): 8 | def __init__(self, x, y): 9 | self.x = x 10 | self.y = y 11 | 12 | def __str__(self): 13 | return '{},{}'.format(self.x, self.y) 14 | 15 | @notify 16 | def scale(self, n): 17 | self.x = n * self.x 18 | self.y = n * self.y 19 | 20 | p = Point(2.0, 3.0) 21 | p.scale(2.5) 22 | print(p) 23 | 24 | 25 | -------------------------------------------------------------------------------- /9324OS_15_code/langs.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | from collections import namedtuple 3 | from operator import attrgetter 4 | 5 | if __name__ == '__main__': 6 | ProgrammingLang = namedtuple('ProgrammingLang', 'name ranking') 7 | 8 | stats = ( ('Ruby', 14), ('Javascript', 8), ('Python', 7), 9 | ('Scala', 31), ('Swift', 18), ('Lisp', 23) ) 10 | 11 | lang_stats = [ProgrammingLang(n, r) for n, r in stats] 12 | pp = pprint.PrettyPrinter(indent=5) 13 | pp.pprint(sorted(lang_stats, key=attrgetter('name'))) 14 | print() 15 | pp.pprint(sorted(lang_stats, key=attrgetter('ranking'))) 16 | 17 | 18 | -------------------------------------------------------------------------------- /9324OS_15_code/old/langs.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | from collections import namedtuple 3 | from operator import attrgetter 4 | 5 | if __name__ == '__main__': 6 | ProgrammingLang = namedtuple('ProgrammingLang', 'name ranking') 7 | 8 | stats = ( ('Ruby', 14), ('Javascript', 8), ('Python', 7), 9 | ('Scala', 31), ('Swift', 18), ('Lisp', 23) ) 10 | 11 | lang_stats = [ProgrammingLang(n, r) for n, r in stats] 12 | pp = pprint.PrettyPrinter(indent=5) 13 | pp.pprint(sorted(lang_stats, key=attrgetter('name'))) 14 | print() 15 | pp.pprint(sorted(lang_stats, key=attrgetter('ranking'))) 16 | 17 | 18 | -------------------------------------------------------------------------------- /9324OS_11_code/first-class.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | verbose = True 4 | 5 | def delete_file(path): 6 | if verbose: 7 | print("deleting file '{}".format(path)) 8 | os.remove(path) 9 | 10 | def main(): 11 | orig_name = 'file1' 12 | df=delete_file 13 | 14 | commands = [] 15 | commands.append(df) 16 | 17 | for c in commands: 18 | try: 19 | c.execute() 20 | except AttributeError as e: 21 | df(orig_name) 22 | 23 | for c in reversed(commands): 24 | try: 25 | c.undo() 26 | except AttributeError as e: 27 | pass 28 | 29 | if __name__ == "__main__": 30 | main() 31 | -------------------------------------------------------------------------------- /9324OS_11_code/old/first-class.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | verbose = True 4 | 5 | def delete_file(path): 6 | if verbose: 7 | print("deleting file '{}".format(path)) 8 | os.remove(path) 9 | 10 | def main(): 11 | orig_name = 'file1' 12 | df=delete_file 13 | 14 | commands = [] 15 | commands.append(df) 16 | 17 | for c in commands: 18 | try: 19 | c.execute() 20 | except AttributeError as e: 21 | df(orig_name) 22 | 23 | for c in reversed(commands): 24 | try: 25 | c.undo() 26 | except AttributeError as e: 27 | pass 28 | 29 | if __name__ == "__main__": 30 | main() 31 | -------------------------------------------------------------------------------- /9324OS_16_code/old/template.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | def dots_style(msg): 5 | msg = msg.capitalize() 6 | msg = '.' * 10 + msg + '.' * 10 7 | return msg 8 | 9 | def admire_style(msg): 10 | msg = msg.upper() 11 | return '!'.join(msg) 12 | 13 | def cow_style(msg): 14 | cmd = 'cowpy -r ' + msg 15 | msg = subprocess.getoutput(cmd) 16 | return msg 17 | 18 | def generate_banner(msg, style=dots_style): 19 | print('-- start of banner --') 20 | print(style(msg)) 21 | print('-- end of banner --\n\n') 22 | 23 | def main(): 24 | msg = 'happy coding' 25 | [generate_banner(msg, style) for style in (dots_style, admire_style, cow_style)] 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /9324OS_02_code/fluent_builder.py: -------------------------------------------------------------------------------- 1 | class Pizza: 2 | def __init__(self, builder): 3 | self.garlic = builder.garlic 4 | self.extra_cheese = builder.extra_cheese 5 | 6 | def __str__(self): 7 | garlic = 'yes' if self.garlic else 'no' 8 | cheese = 'yes' if self.extra_cheese else 'no' 9 | info = ('Garlic: {}'.format(garlic), 10 | 'Extra cheese: {}'.format(cheese)) 11 | return '\n'.join(info) 12 | 13 | class PizzaBuilder: 14 | def __init__(self): 15 | self.extra_cheese = False 16 | self.garlic = False 17 | 18 | def add_garlic(self): 19 | self.garlic = True 20 | return self 21 | 22 | def add_extra_cheese(self): 23 | self.extra_cheese = True 24 | return self 25 | 26 | def build(self): 27 | return Pizza(self) 28 | 29 | 30 | if __name__ == '__main__': 31 | pizza = Pizza.PizzaBuilder().add_garlic().add_extra_cheese().build() 32 | print(pizza) 33 | -------------------------------------------------------------------------------- /9324OS_04_code/adapter.py: -------------------------------------------------------------------------------- 1 | from external import Synthesizer, Human 2 | 3 | class Computer: 4 | def __init__(self, name): 5 | self.name = name 6 | 7 | def __str__(self): 8 | return 'the {} computer'.format(self.name) 9 | 10 | def execute(self): 11 | return 'executes a program' 12 | 13 | class Adapter: 14 | def __init__(self, obj, adapted_methods): 15 | self.obj = obj 16 | self.__dict__.update(adapted_methods) 17 | 18 | def __str__(self): 19 | return str(self.obj) 20 | 21 | def main(): 22 | objects = [Computer('Asus')] 23 | synth = Synthesizer('moog') 24 | objects.append(Adapter(synth, dict(execute=synth.play))) 25 | human = Human('Bob') 26 | objects.append(Adapter(human, dict(execute=human.speak))) 27 | 28 | for i in objects: 29 | print('{} {}'.format(str(i), i.execute())) 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /9324OS_04_code/old/adapter.py: -------------------------------------------------------------------------------- 1 | from external import Synthesizer, Human 2 | 3 | class Computer: 4 | def __init__(self, name): 5 | self.name = name 6 | 7 | def __str__(self): 8 | return 'the {} computer'.format(self.name) 9 | 10 | def execute(self): 11 | return 'executes a program' 12 | 13 | class Adapter: 14 | def __init__(self, obj, adapted_methods): 15 | self.obj = obj 16 | self.__dict__.update(adapted_methods) 17 | 18 | def __str__(self): 19 | return str(self.obj) 20 | 21 | def main(): 22 | objects = [Computer('Asus')] 23 | synth = Synthesizer('moog') 24 | objects.append(Adapter(synth, dict(execute=synth.play))) 25 | human = Human('Bob') 26 | objects.append(Adapter(human, dict(execute=human.speak))) 27 | 28 | for i in objects: 29 | print('{} {}'.format(str(i), i.execute())) 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /9324OS_02_code/apple-factory.py: -------------------------------------------------------------------------------- 1 | MINI14 = '1.4GHz Mac mini' 2 | 3 | class AppleFactory: 4 | class MacMini14: 5 | def __init__(self): 6 | self.memory = 4 # in gigabytes 7 | self.hdd = 500 # in gigabytes 8 | self.gpu = 'Intel HD Graphics 5000' 9 | 10 | def __str__(self): 11 | info = ('Model: {}'.format(MINI14), 12 | 'Memory: {}GB'.format(self.memory), 13 | 'Hard Disk: {}GB'.format(self.hdd), 14 | 'Graphics Card: {}'.format(self.gpu)) 15 | return '\n'.join(info) 16 | 17 | def build_computer(self, model): 18 | if (model == MINI14): 19 | return self.MacMini14() 20 | else: 21 | print("I don't know how to build {}".format(model)) 22 | 23 | if __name__ == '__main__': 24 | afac = AppleFactory() 25 | mac_mini = afac.build_computer(MINI14) 26 | print(mac_mini) 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /9324OS_09_code/lazy.py: -------------------------------------------------------------------------------- 1 | class LazyProperty: 2 | def __init__(self, method): 3 | self.method = method 4 | self.method_name = method.__name__ 5 | # print('method overriden: {}'.format(self.method)) 6 | # print("method's name: {}".format(self.method_name)) 7 | 8 | def __get__(self, obj, cls): 9 | if not obj: 10 | return None 11 | value = self.method(obj) 12 | # print('value {}'.format(value)) 13 | setattr(obj, self.method_name, value) 14 | return value 15 | 16 | class Test: 17 | def __init__(self): 18 | self.x = 'foo' 19 | self.y = 'bar' 20 | self._resource = None 21 | 22 | @LazyProperty 23 | def resource(self): 24 | print('initializing self._resource which is: {}'.format(self._resource)) 25 | self._resource = tuple(range(5)) # expensive initialization goes here 26 | return self._resource 27 | 28 | def main(): 29 | t = Test() 30 | print(t.x) 31 | print(t.y) 32 | # do more work... 33 | print(t.resource) 34 | print(t.resource) 35 | 36 | if __name__ == '__main__': 37 | main() 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 TienYang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /9324OS_05_code/mymath.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | def memoize(fn): 4 | known = dict() 5 | 6 | @functools.wraps(fn) 7 | def memoizer(*args): 8 | if args not in known: 9 | known[args] = fn(*args) 10 | return known[args] 11 | 12 | return memoizer 13 | 14 | @memoize 15 | def nsum(n): 16 | '''Returns the sum of the first n numbers''' 17 | assert(n >= 0), 'n must be >= 0' 18 | return 0 if n == 0 else n + nsum(n-1) 19 | 20 | @memoize 21 | def fibonacci(n): 22 | '''Returns the nth number of the Fibonacci sequence''' 23 | assert(n >= 0), 'n must be >= 0' 24 | return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) 25 | 26 | if __name__ == '__main__': 27 | from timeit import Timer 28 | measure = [ {'exec':'fibonacci(100)', 'import':'fibonacci', 'func':fibonacci}, 29 | {'exec':'nsum(200)', 'import':'nsum', 'func':nsum} ] 30 | for m in measure: 31 | t = Timer('{}'.format(m['exec']), 'from __main__ import {}'.format(m['import'])) 32 | print('name: {}, doc: {}, executing: {}, time: {}'.format(m['func'].__name__, m['func'].__doc__, m['exec'], t.timeit())) 33 | 34 | -------------------------------------------------------------------------------- /9324OS_05_code/old/mymath.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | def memoize(fn): 4 | known = dict() 5 | 6 | @functools.wraps(fn) 7 | def memoizer(*args): 8 | if args not in known: 9 | known[args] = fn(*args) 10 | return known[args] 11 | 12 | return memoizer 13 | 14 | @memoize 15 | def nsum(n): 16 | '''Returns the sum of the first n numbers''' 17 | assert(n >= 0), 'n must be >= 0' 18 | return 0 if n == 0 else n + nsum(n-1) 19 | 20 | @memoize 21 | def fibonacci(n): 22 | '''Returns the nth number of the Fibonacci sequence''' 23 | assert(n >= 0), 'n must be >= 0' 24 | return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) 25 | 26 | if __name__ == '__main__': 27 | from timeit import Timer 28 | measure = [ {'exec':'fibonacci(100)', 'import':'fibonacci', 'func':fibonacci}, 29 | {'exec':'nsum(200)', 'import':'nsum', 'func':nsum} ] 30 | for m in measure: 31 | t = Timer('{}'.format(m['exec']), 'from __main__ import {}'.format(m['import'])) 32 | print('name: {}, doc: {}, executing: {}, time: {}'.format(m['func'].__name__, m['func'].__doc__, m['exec'], t.timeit())) 33 | 34 | -------------------------------------------------------------------------------- /9324OS_09_code/proxy.py: -------------------------------------------------------------------------------- 1 | class SensitiveInfo: 2 | def __init__(self): 3 | self.users = ['nick', 'tom', 'ben', 'mike'] 4 | 5 | def read(self): 6 | print('There are {} users: {}'.format(len(self.users), ' '.join(self.users))) 7 | 8 | def add(self, user): 9 | self.users.append(user) 10 | print('Added user {}'.format(user)) 11 | 12 | class Info: 13 | '''protection proxy to SensitiveInfo''' 14 | 15 | def __init__(self): 16 | self.protected = SensitiveInfo() 17 | self.secret = '0xdeadbeef' 18 | 19 | def read(self): 20 | self.protected.read() 21 | 22 | def add(self, user): 23 | sec = input('what is the secret? ') 24 | self.protected.add(user) if sec == self.secret else print("That's wrong!") 25 | 26 | def main(): 27 | info = Info() 28 | 29 | while True: 30 | print('1. read list |==| 2. add user |==| 3. quit') 31 | key = input('choose option: ') 32 | if key == '1': 33 | info.read() 34 | elif key == '2': 35 | name = input('choose username: ') 36 | info.add(name) 37 | elif key == '3': 38 | exit() 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /9324OS_08_code/old/mvc.py: -------------------------------------------------------------------------------- 1 | quotes = ('A man is not complete until he is married. Then he is finished.', 2 | 'As I said before, I never repeat myself.', 3 | 'Behind a successful man is an exhausted woman.', 4 | 'Black holes really suck...', 5 | 'Facts are stubborn things.') 6 | 7 | class QuoteModel: 8 | def get_quote(self, n): 9 | try: 10 | value = quotes[n] 11 | except IndexError as err: 12 | value = 'Not found!' 13 | return value 14 | 15 | class QuoteTerminalView: 16 | def show(self, quote): 17 | print('And the quote is: "{}"'.format(quote)) 18 | 19 | def error(self, msg): 20 | print('Error: {}'.format(msg)) 21 | 22 | def select_quote(self): 23 | return input('Which quote number would you like to see? ') 24 | 25 | class QuoteTerminalController: 26 | def __init__(self): 27 | self.model = QuoteModel() 28 | self.view = QuoteTerminalView() 29 | 30 | def run(self): 31 | valid_input = False 32 | while not valid_input: 33 | try: 34 | n = self.view.select_quote() 35 | n = int(n) 36 | valid_input = True 37 | except ValueError as err: 38 | self.view.error("Incorrect index '{}'".format(n)) 39 | quote = self.model.get_quote(n) 40 | self.view.show(quote) 41 | 42 | def main(): 43 | controller = QuoteTerminalController() 44 | while True: 45 | controller.run() 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /9324OS_08_code/mvc.py: -------------------------------------------------------------------------------- 1 | quotes = ('A man is not complete until he is married. Then he is finished.', 2 | 'As I said before, I never repeat myself.', 3 | 'Behind a successful man is an exhausted woman.', 4 | 'Black holes really suck...', 5 | 'Facts are stubborn things.') 6 | 7 | class QuoteModel: 8 | def get_quote(self, n): 9 | try: 10 | value = quotes[n] 11 | except IndexError as err: 12 | value = 'Not found!' 13 | return value 14 | 15 | class QuoteTerminalView: 16 | def show(self, quote): 17 | print('And the quote is: "{}"'.format(quote)) 18 | 19 | def error(self, msg): 20 | print('Error: {}'.format(msg)) 21 | 22 | def select_quote(self): 23 | return input('Which quote number would you like to see? ') 24 | 25 | class QuoteTerminalController: 26 | def __init__(self): 27 | self.model = QuoteModel() 28 | self.view = QuoteTerminalView() 29 | 30 | def run(self): 31 | valid_input = False 32 | while not valid_input: 33 | n = self.view.select_quote() 34 | try: 35 | n = int(n) 36 | except ValueError as err: 37 | self.view.error("Incorrect index '{}'".format(n)) 38 | else: 39 | valid_input = True 40 | quote = self.model.get_quote(n) 41 | self.view.show(quote) 42 | 43 | def main(): 44 | controller = QuoteTerminalController() 45 | while True: 46 | controller.run() 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /9324OS_02_code/computer-builder.py: -------------------------------------------------------------------------------- 1 | class Computer: 2 | def __init__(self, serial_number): 3 | self.serial = serial_number 4 | self.memory = None # in gigabytes 5 | self.hdd = None # in gigabytes 6 | self.gpu = None 7 | 8 | def __str__(self): 9 | info = ('Memory: {}GB'.format(self.memory), 10 | 'Hard Disk: {}GB'.format(self.hdd), 11 | 'Graphics Card: {}'.format(self.gpu)) 12 | return '\n'.join(info) 13 | 14 | class ComputerBuilder: 15 | def __init__(self): 16 | self.computer = Computer('AG23385193') 17 | 18 | def configure_memory(self, amount): 19 | self.computer.memory = amount 20 | 21 | def configure_hdd(self, amount): 22 | self.computer.hdd = amount 23 | 24 | def configure_gpu(self, gpu_model): 25 | self.computer.gpu = gpu_model 26 | 27 | class HardwareEngineer: 28 | def __init__(self): 29 | self.builder = None 30 | 31 | def construct_computer(self, memory, hdd, gpu): 32 | self.builder = ComputerBuilder() 33 | [step for step in (self.builder.configure_memory(memory), 34 | self.builder.configure_hdd(hdd), 35 | self.builder.configure_gpu(gpu))] 36 | 37 | @property 38 | def computer(self): 39 | return self.builder.computer 40 | 41 | def main(): 42 | engineer = HardwareEngineer() 43 | engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti') 44 | computer = engineer.computer 45 | print(computer) 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /9324OS_07_code/old/flyweight.py: -------------------------------------------------------------------------------- 1 | import random 2 | from enum import Enum 3 | 4 | TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree') 5 | 6 | class Tree: 7 | pool = dict() 8 | 9 | def __new__(cls, tree_type): 10 | obj = cls.pool.get(tree_type, None) 11 | if not obj: 12 | obj = object.__new__(cls) 13 | cls.pool[tree_type] = obj 14 | obj.tree_type = tree_type 15 | return obj 16 | 17 | def render(self, age): 18 | print('render a tree of type {} and age {}'.format(self.tree_type, age)) 19 | 20 | def main(): 21 | rnd = random.Random() 22 | age_min, age_max = 1, 30 # in years 23 | tree_counter = 0 24 | 25 | for _ in range(10): 26 | t1 = Tree(TreeType.apple_tree) 27 | t1.render(rnd.randint(age_min, age_max)) 28 | tree_counter += 1 29 | 30 | for _ in range(3): 31 | t2 = Tree(TreeType.cherry_tree) 32 | t2.render(rnd.randint(age_min, age_max)) 33 | tree_counter += 1 34 | 35 | for _ in range(5): 36 | t3 = Tree(TreeType.peach_tree) 37 | t3.render(rnd.randint(age_min, age_max)) 38 | tree_counter += 1 39 | 40 | print('trees rendered: {}'.format(tree_counter)) 41 | print('trees actually created: {}'.format(len(Tree.pool))) 42 | 43 | t4 = Tree(TreeType.cherry_tree) 44 | t5 = Tree(TreeType.cherry_tree) 45 | t6 = Tree(TreeType.apple_tree) 46 | print('{} == {}? {}'.format(id(t4), id(t5), id(t4) == id(t5))) 47 | print('{} == {}? {}'.format(id(t5), id(t6), id(t5) == id(t6))) 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /9324OS_10_code/chain.py: -------------------------------------------------------------------------------- 1 | class Event: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return self.name 7 | 8 | class Widget: 9 | def __init__(self, parent=None): 10 | self.parent = parent 11 | 12 | def handle(self, event): 13 | handler = 'handle_{}'.format(event) 14 | if hasattr(self, handler): 15 | method = getattr(self, handler) 16 | method(event) 17 | elif self.parent: 18 | self.parent.handle(event) 19 | elif hasattr(self, 'handle_default'): 20 | self.handle_default(event) 21 | 22 | class MainWindow(Widget): 23 | def handle_close(self, event): 24 | print('MainWindow: {}'.format(event)) 25 | 26 | def handle_default(self, event): 27 | print('MainWindow Default: {}'.format(event)) 28 | 29 | class SendDialog(Widget): 30 | def handle_paint(self, event): 31 | print('SendDialog: {}'.format(event)) 32 | 33 | class MsgText(Widget): 34 | def handle_down(self, event): 35 | print('MsgText: {}'.format(event)) 36 | 37 | def main(): 38 | mw = MainWindow() 39 | sd = SendDialog(mw) 40 | msg = MsgText(sd) 41 | 42 | for e in ('down', 'paint', 'unhandled', 'close'): 43 | evt = Event(e) 44 | print('\nSending event -{}- to MainWindow'.format(evt)) 45 | mw.handle(evt) 46 | print('Sending event -{}- to SendDialog'.format(evt)) 47 | sd.handle(evt) 48 | print('Sending event -{}- to MsgText'.format(evt)) 49 | msg.handle(evt) 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /9324OS_10_code/old/chain.py: -------------------------------------------------------------------------------- 1 | class Event: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return self.name 7 | 8 | class Widget: 9 | def __init__(self, parent=None): 10 | self.parent = parent 11 | 12 | def handle(self, event): 13 | handler = 'handle_{}'.format(event) 14 | if hasattr(self, handler): 15 | method = getattr(self, handler) 16 | method(event) 17 | elif self.parent: 18 | self.parent.handle(event) 19 | elif hasattr(self, 'handle_default'): 20 | self.handle_default(event) 21 | 22 | class MainWindow(Widget): 23 | def handle_close(self, event): 24 | print('MainWindow: {}'.format(event)) 25 | 26 | def handle_default(self, event): 27 | print('MainWindow Default: {}'.format(event)) 28 | 29 | class SendDialog(Widget): 30 | def handle_paint(self, event): 31 | print('SendDialog: {}'.format(event)) 32 | 33 | class MsgText(Widget): 34 | def handle_down(self, event): 35 | print('MsgText: {}'.format(event)) 36 | 37 | def main(): 38 | mw = MainWindow() 39 | sd = SendDialog(mw) 40 | msg = MsgText(sd) 41 | 42 | for e in ('down', 'paint', 'unhandled', 'close'): 43 | evt = Event(e) 44 | print('\nSending event -{}- to MainWindow'.format(evt)) 45 | mw.handle(evt) 46 | print('Sending event -{}- to SendDialog'.format(evt)) 47 | sd.handle(evt) 48 | print('Sending event -{}- to MsgText'.format(evt)) 49 | msg.handle(evt) 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /9324OS_01_code/data/person.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | John 4 | Smith 5 | 25 6 |
7 | 21 2nd Street 8 | New York 9 | NY 10 | 10021 11 |
12 | 13 | 212 555-1234 14 | 646 555-4567 15 | 16 | 17 | male 18 | 19 |
20 | 21 | Jimy 22 | Liar 23 | 19 24 |
25 | 18 2nd Street 26 | New York 27 | NY 28 | 10021 29 |
30 | 31 | 212 555-1234 32 | 33 | 34 | male 35 | 36 |
37 | 38 | Patty 39 | Liar 40 | 20 41 |
42 | 18 2nd Street 43 | New York 44 | NY 45 | 10021 46 |
47 | 48 | 212 555-1234 49 | 001 452-8819 50 | 51 | 52 | female 53 | 54 |
55 |
-------------------------------------------------------------------------------- /9324OS_01_code/old/data/person.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | John 4 | Smith 5 | 25 6 |
7 | 21 2nd Street 8 | New York 9 | NY 10 | 10021 11 |
12 | 13 | 212 555-1234 14 | 646 555-4567 15 | 16 | 17 | male 18 | 19 |
20 | 21 | Jimy 22 | Liar 23 | 19 24 |
25 | 18 2nd Street 26 | New York 27 | NY 28 | 10021 29 |
30 | 31 | 212 555-1234 32 | 33 | 34 | male 35 | 36 |
37 | 38 | Patty 39 | Liar 40 | 20 41 |
42 | 18 2nd Street 43 | New York 44 | NY 45 | 10021 46 |
47 | 48 | 212 555-1234 49 | 001 452-8819 50 | 51 | 52 | female 53 | 54 |
55 |
-------------------------------------------------------------------------------- /9324OS_01_code/data/donut.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "0001", 4 | "type": "donut", 5 | "name": "Cake", 6 | "ppu": 0.55, 7 | "batters": 8 | { 9 | "batter": 10 | [ 11 | { "id": "1001", "type": "Regular" }, 12 | { "id": "1002", "type": "Chocolate" }, 13 | { "id": "1003", "type": "Blueberry" }, 14 | { "id": "1004", "type": "Devil's Food" } 15 | ] 16 | }, 17 | "topping": 18 | [ 19 | { "id": "5001", "type": "None" }, 20 | { "id": "5002", "type": "Glazed" }, 21 | { "id": "5005", "type": "Sugar" }, 22 | { "id": "5007", "type": "Powdered Sugar" }, 23 | { "id": "5006", "type": "Chocolate with Sprinkles" }, 24 | { "id": "5003", "type": "Chocolate" }, 25 | { "id": "5004", "type": "Maple" } 26 | ] 27 | }, 28 | { 29 | "id": "0002", 30 | "type": "donut", 31 | "name": "Raised", 32 | "ppu": 0.55, 33 | "batters": 34 | { 35 | "batter": 36 | [ 37 | { "id": "1001", "type": "Regular" } 38 | ] 39 | }, 40 | "topping": 41 | [ 42 | { "id": "5001", "type": "None" }, 43 | { "id": "5002", "type": "Glazed" }, 44 | { "id": "5005", "type": "Sugar" }, 45 | { "id": "5003", "type": "Chocolate" }, 46 | { "id": "5004", "type": "Maple" } 47 | ] 48 | }, 49 | { 50 | "id": "0003", 51 | "type": "donut", 52 | "name": "Old Fashioned", 53 | "ppu": 0.55, 54 | "batters": 55 | {"batter": 56 | [ 57 | { "id": "1001", "type": "Regular" }, 58 | { "id": "1002", "type": "Chocolate" } 59 | ] 60 | }, 61 | "topping": 62 | [ 63 | { "id": "5001", "type": "None" }, 64 | { "id": "5002", "type": "Glazed" }, 65 | { "id": "5003", "type": "Chocolate" }, 66 | { "id": "5004", "type": "Maple" } 67 | ] 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /9324OS_01_code/old/data/donut.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "0001", 4 | "type": "donut", 5 | "name": "Cake", 6 | "ppu": 0.55, 7 | "batters": 8 | { 9 | "batter": 10 | [ 11 | { "id": "1001", "type": "Regular" }, 12 | { "id": "1002", "type": "Chocolate" }, 13 | { "id": "1003", "type": "Blueberry" }, 14 | { "id": "1004", "type": "Devil's Food" } 15 | ] 16 | }, 17 | "topping": 18 | [ 19 | { "id": "5001", "type": "None" }, 20 | { "id": "5002", "type": "Glazed" }, 21 | { "id": "5005", "type": "Sugar" }, 22 | { "id": "5007", "type": "Powdered Sugar" }, 23 | { "id": "5006", "type": "Chocolate with Sprinkles" }, 24 | { "id": "5003", "type": "Chocolate" }, 25 | { "id": "5004", "type": "Maple" } 26 | ] 27 | }, 28 | { 29 | "id": "0002", 30 | "type": "donut", 31 | "name": "Raised", 32 | "ppu": 0.55, 33 | "batters": 34 | { 35 | "batter": 36 | [ 37 | { "id": "1001", "type": "Regular" } 38 | ] 39 | }, 40 | "topping": 41 | [ 42 | { "id": "5001", "type": "None" }, 43 | { "id": "5002", "type": "Glazed" }, 44 | { "id": "5005", "type": "Sugar" }, 45 | { "id": "5003", "type": "Chocolate" }, 46 | { "id": "5004", "type": "Maple" } 47 | ] 48 | }, 49 | { 50 | "id": "0003", 51 | "type": "donut", 52 | "name": "Old Fashioned", 53 | "ppu": 0.55, 54 | "batters": 55 | {"batter": 56 | [ 57 | { "id": "1001", "type": "Regular" }, 58 | { "id": "1002", "type": "Chocolate" } 59 | ] 60 | }, 61 | "topping": 62 | [ 63 | { "id": "5001", "type": "None" }, 64 | { "id": "5002", "type": "Glazed" }, 65 | { "id": "5003", "type": "Chocolate" }, 66 | { "id": "5004", "type": "Maple" } 67 | ] 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /9324OS_15_code/strategy.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | SLOW = 3 # in seconds 4 | LIMIT = 5 # in characters 5 | WARNING = 'too bad, you picked the slow algorithm :(' 6 | 7 | def pairs(seq): 8 | n = len(seq) 9 | for i in range(n): 10 | yield seq[i], seq[(i + 1) % n] 11 | 12 | def allUniqueSort(s): 13 | if len(s) > LIMIT: 14 | print(WARNING) 15 | time.sleep(SLOW) 16 | srtStr = sorted(s) 17 | for (c1, c2) in pairs(srtStr): 18 | if c1 == c2: 19 | return False 20 | return True 21 | 22 | def allUniqueSet(s): 23 | if len(s) < LIMIT: 24 | print(WARNING) 25 | time.sleep(SLOW) 26 | return True if len(set(s)) == len(s) else False 27 | 28 | def allUnique(s, strategy): 29 | return strategy(s) 30 | 31 | def main(): 32 | while True: 33 | word = None 34 | while not word: 35 | word = input('Insert word (type quit to exit)> ') 36 | 37 | if word == 'quit': 38 | print('bye') 39 | return 40 | 41 | strategy_picked = None 42 | strategies = { '1': allUniqueSet, '2': allUniqueSort } 43 | while strategy_picked not in strategies.keys(): 44 | strategy_picked = input('Choose strategy: [1] Use a set, [2] Sort and pair> ') 45 | 46 | try: 47 | strategy = strategies[strategy_picked] 48 | print('allUnique({}): {}'.format(word, allUnique(word, strategy))) 49 | except KeyError as err: 50 | print('Incorrect option: {}'.format(strategy_picked)) 51 | print() 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /9324OS_15_code/old/strategy.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | SLOW = 3 # in seconds 4 | LIMIT = 5 # in characters 5 | WARNING = 'too bad, you picked the slow algorithm :(' 6 | 7 | def pairs(seq): 8 | n = len(seq) 9 | for i in range(n): 10 | yield seq[i], seq[(i + 1) % n] 11 | 12 | def allUniqueSort(s): 13 | if len(s) > LIMIT: 14 | print(WARNING) 15 | time.sleep(SLOW) 16 | srtStr = sorted(s) 17 | for (c1, c2) in pairs(srtStr): 18 | if c1 == c2: 19 | return False 20 | return True 21 | 22 | def allUniqueSet(s): 23 | if len(s) < LIMIT: 24 | print(WARNING) 25 | time.sleep(SLOW) 26 | charsTable = set() 27 | for c in s: 28 | if c in charsTable: 29 | return False 30 | charsTable.add(c) 31 | return True 32 | 33 | def allUnique(s, strategy): 34 | return strategy(s) 35 | 36 | def main(): 37 | while True: 38 | word = None 39 | while not word: 40 | word = input('Insert word (type quit to exit)> ') 41 | 42 | if word == 'quit': 43 | print('bye') 44 | return 45 | 46 | strategy_picked = None 47 | strategies = { '1': allUniqueSet, '2': allUniqueSort } 48 | while strategy_picked not in strategies.keys(): 49 | strategy_picked = input('Choose strategy: [1] Use a set, [2] Sort and pair> ') 50 | 51 | try: 52 | strategy = strategies[strategy_picked] 53 | print('allUnique({}): {}'.format(word, allUnique(word, strategy))) 54 | except KeyError as err: 55 | print('Incorrect option: {}'.format(strategy_picked)) 56 | print() 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /9324OS_16_code/old/graph-template.py: -------------------------------------------------------------------------------- 1 | def traverse(graph, start, end, action): 2 | path = [] 3 | visited = [start] 4 | while visited: 5 | current = visited.pop(0) 6 | if current not in path: 7 | path.append(current) 8 | if current == end: 9 | return (True, path) 10 | # skip vertices with no connections 11 | if current not in graph: 12 | continue 13 | visited = action(visited, graph[current]) 14 | return (False, path) 15 | 16 | def extend_bfs_path(visited, current): 17 | return visited + current 18 | 19 | def extend_dfs_path(visited, current): 20 | return current + visited 21 | 22 | def main(): 23 | graph = { 24 | 'Frankfurt': ['Mannheim', 'Wurzburg', 'Kassel'], 25 | 'Mannheim': ['Karlsruhe'], 26 | 'Karlsruhe': ['Augsburg'], 27 | 'Augsburg': ['Munchen'], 28 | 'Wurzburg': ['Erfurt', 'Nurnberg'], 29 | 'Nurnberg': ['Stuttgart', 'Munchen'], 30 | 'Kassel': ['Munchen'], 31 | 'Erfurt': [], 32 | 'Stuttgart': [], 33 | 'Munchen': [] 34 | } 35 | 36 | bfs_path = traverse(graph, 'Frankfurt', 'Nurnberg', extend_bfs_path) 37 | dfs_path = traverse(graph, 'Frankfurt', 'Nurnberg', extend_dfs_path) 38 | print('bfs Frankfurt-Nurnberg: {}'.format(bfs_path[1] if bfs_path[0] else 'Not found')) 39 | print('dfs Frankfurt-Nurnberg: {}'.format(dfs_path[1] if dfs_path[0] else 'Not found')) 40 | 41 | bfs_nopath = traverse(graph, 'Wurzburg', 'Kassel', extend_bfs_path) 42 | dfs_nopath = traverse(graph, 'Wurzburg', 'Kassel', extend_dfs_path) 43 | print('bfs Wurzburg-Kassel: {}'.format(bfs_nopath[1] if bfs_nopath[0] else 'Not found')) 44 | print('dfs Wurzburg-Kassel: {}'.format(dfs_nopath[1] if dfs_nopath[0] else 'Not found')) 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /9324OS_07_code/flyweight.py: -------------------------------------------------------------------------------- 1 | import random 2 | from enum import Enum 3 | 4 | TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree') 5 | 6 | class Tree: 7 | pool = dict() 8 | 9 | def __new__(cls, tree_type): 10 | obj = cls.pool.get(tree_type, None) 11 | if not obj: 12 | obj = object.__new__(cls) 13 | cls.pool[tree_type] = obj 14 | obj.tree_type = tree_type 15 | return obj 16 | 17 | def render(self, age, x, y): 18 | print('render a tree of type {} and age {} at ({}, {})'.format(self.tree_type, age, x, y)) 19 | 20 | def main(): 21 | rnd = random.Random() 22 | age_min, age_max = 1, 30 # in years 23 | min_point, max_point = 0, 100 24 | tree_counter = 0 25 | 26 | for _ in range(10): 27 | t1 = Tree(TreeType.apple_tree) 28 | t1.render(rnd.randint(age_min, age_max), 29 | rnd.randint(min_point, max_point), 30 | rnd.randint(min_point, max_point)) 31 | tree_counter += 1 32 | 33 | for _ in range(3): 34 | t2 = Tree(TreeType.cherry_tree) 35 | t2.render(rnd.randint(age_min, age_max), 36 | rnd.randint(min_point, max_point), 37 | rnd.randint(min_point, max_point)) 38 | tree_counter += 1 39 | 40 | for _ in range(5): 41 | t3 = Tree(TreeType.peach_tree) 42 | t3.render(rnd.randint(age_min, age_max), 43 | rnd.randint(min_point, max_point), 44 | rnd.randint(min_point, max_point)) 45 | tree_counter += 1 46 | 47 | print('trees rendered: {}'.format(tree_counter)) 48 | print('trees actually created: {}'.format(len(Tree.pool))) 49 | 50 | t4 = Tree(TreeType.cherry_tree) 51 | t5 = Tree(TreeType.cherry_tree) 52 | t6 = Tree(TreeType.apple_tree) 53 | print('{} == {}? {}'.format(id(t4), id(t5), id(t4) == id(t5))) 54 | print('{} == {}? {}'.format(id(t5), id(t6), id(t5) == id(t6))) 55 | 56 | if __name__ == '__main__': 57 | main() 58 | -------------------------------------------------------------------------------- /9324OS_11_code/command.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | verbose = True 4 | 5 | class RenameFile: 6 | def __init__(self, path_src, path_dest): 7 | self.src, self.dest = path_src, path_dest 8 | 9 | def execute(self): 10 | if verbose: 11 | print("[renaming '{}' to '{}']".format(self.src, self.dest)) 12 | os.rename(self.src, self.dest) 13 | 14 | def undo(self): 15 | if verbose: 16 | print("[renaming '{}' back to '{}']".format(self.dest, self.src)) 17 | os.rename(self.dest, self.src) 18 | 19 | class CreateFile: 20 | def __init__(self, path, txt='hello world\n'): 21 | self.path, self.txt = path, txt 22 | 23 | def execute(self): 24 | if verbose: 25 | print("[creating file '{}']".format(self.path)) 26 | with open(self.path, mode='w', encoding='utf-8') as out_file: 27 | out_file.write(self.txt) 28 | 29 | def undo(self): 30 | delete_file(self.path) 31 | 32 | class ReadFile: 33 | def __init__(self, path): 34 | self.path = path 35 | 36 | def execute(self): 37 | if verbose: 38 | print("[reading file '{}']".format(self.path)) 39 | with open(self.path, mode='r', encoding='utf-8') as in_file: 40 | print(in_file.read(), end='') 41 | 42 | def delete_file(path): 43 | if verbose: 44 | print("deleting file '{}".format(path)) 45 | os.remove(path) 46 | 47 | def main(): 48 | orig_name, new_name = 'file1', 'file2' 49 | 50 | commands = [] 51 | for cmd in CreateFile(orig_name), ReadFile(orig_name), RenameFile(orig_name, new_name): 52 | commands.append(cmd) 53 | 54 | [c.execute() for c in commands] 55 | 56 | answer = input('reverse the executed commands? [y/n] ') 57 | 58 | if answer not in 'yY': 59 | print("the result is {}".format(new_name)) 60 | exit() 61 | 62 | for c in reversed(commands): 63 | try: 64 | c.undo() 65 | except AttributeError as e: 66 | pass 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /9324OS_11_code/old/command.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | verbose = True 4 | 5 | class RenameFile: 6 | def __init__(self, path_src, path_dest): 7 | self.src, self.dest = path_src, path_dest 8 | 9 | def execute(self): 10 | if verbose: 11 | print("[renaming '{}' to '{}']".format(self.src, self.dest)) 12 | os.rename(self.src, self.dest) 13 | 14 | def undo(self): 15 | if verbose: 16 | print("[renaming '{}' back to '{}']".format(self.dest, self.src)) 17 | os.rename(self.dest, self.src) 18 | 19 | class CreateFile: 20 | def __init__(self, path, txt='hello world\n'): 21 | self.path, self.txt = path, txt 22 | 23 | def execute(self): 24 | if verbose: 25 | print("[creating file '{}']".format(self.path)) 26 | with open(self.path, mode='w', encoding='utf-8') as out_file: 27 | out_file.write(self.txt) 28 | 29 | def undo(self): 30 | delete_file(self.path) 31 | 32 | class ReadFile: 33 | def __init__(self, path): 34 | self.path = path 35 | 36 | def execute(self): 37 | if verbose: 38 | print("[reading file '{}']".format(self.path)) 39 | with open(self.path, mode='r', encoding='utf-8') as in_file: 40 | print(in_file.read(), end='') 41 | 42 | def delete_file(path): 43 | if verbose: 44 | print("deleting file '{}".format(path)) 45 | os.remove(path) 46 | 47 | def main(): 48 | orig_name, new_name = 'file1', 'file2' 49 | 50 | commands = [] 51 | for cmd in CreateFile(orig_name), ReadFile(orig_name), RenameFile(orig_name, new_name): 52 | commands.append(cmd) 53 | 54 | [c.execute() for c in commands] 55 | 56 | answer = input('reverse the executed commands? [y/n] ') 57 | 58 | if answer != 'y' and answer != 'Y': 59 | print("the result is {}".format(new_name)) 60 | exit() 61 | 62 | for c in reversed(commands): 63 | try: 64 | c.undo() 65 | except AttributeError as e: 66 | pass 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /9324OS_01_code/factory_method.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as etree 2 | import json 3 | 4 | class JSONConnector: 5 | def __init__(self, filepath): 6 | self.data = dict() 7 | with open(filepath, mode='r', encoding='utf-8') as f: 8 | self.data = json.load(f) 9 | 10 | @property 11 | def parsed_data(self): 12 | return self.data 13 | 14 | class XMLConnector: 15 | def __init__(self, filepath): 16 | self.tree = etree.parse(filepath) 17 | 18 | @property 19 | def parsed_data(self): 20 | return self.tree 21 | 22 | def connection_factory(filepath): 23 | if filepath.endswith('json'): 24 | connector = JSONConnector 25 | elif filepath.endswith('xml'): 26 | connector = XMLConnector 27 | else: 28 | raise ValueError('Cannot connect to {}'.format(filepath)) 29 | return connector(filepath) 30 | 31 | def connect_to(filepath): 32 | factory = None 33 | try: 34 | factory = connection_factory(filepath) 35 | except ValueError as ve: 36 | print(ve) 37 | return factory 38 | 39 | def main(): 40 | sqlite_factory = connect_to('data/person.sq3') 41 | print() 42 | 43 | xml_factory = connect_to('data/person.xml') 44 | xml_data = xml_factory.parsed_data 45 | liars = xml_data.findall(".//person[lastName='{}']".format('Liar')) 46 | print('found: {} persons'.format(len(liars))) 47 | for liar in liars: 48 | print('first name: {}'.format(liar.find('firstName').text)) 49 | print('last name: {}'.format(liar.find('lastName').text)) 50 | [print('phone number ({}):'.format(p.attrib['type']), p.text) for p in liar.find('phoneNumbers')] 51 | print() 52 | 53 | json_factory = connect_to('data/donut.json') 54 | json_data = json_factory.parsed_data 55 | print('found: {} donuts'.format(len(json_data))) 56 | for donut in json_data: 57 | print('name: {}'.format(donut['name'])) 58 | print('price: ${}'.format(donut['ppu'])) 59 | [print('topping: {} {}'.format(t['id'], t['type'])) for t in donut['topping']] 60 | 61 | if __name__ == '__main__': 62 | main() 63 | -------------------------------------------------------------------------------- /9324OS_01_code/old/factory_method.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as etree 2 | import json 3 | 4 | class JSONConnector: 5 | def __init__(self, filepath): 6 | self.data = dict() 7 | with open(filepath, mode='r', encoding='utf-8') as f: 8 | self.data = json.load(f) 9 | 10 | @property 11 | def parsed_data(self): 12 | return self.data 13 | 14 | class XMLConnector: 15 | def __init__(self, filepath): 16 | self.tree = etree.parse(filepath) 17 | 18 | @property 19 | def parsed_data(self): 20 | return self.tree 21 | 22 | def connection_factory(filepath): 23 | if filepath.endswith('json'): 24 | connector = JSONConnector 25 | elif filepath.endswith('xml'): 26 | connector = XMLConnector 27 | else: 28 | raise ValueError('Cannot connect to {}'.format(filepath)) 29 | return connector(filepath) 30 | 31 | def connect_to(filepath): 32 | factory = None 33 | try: 34 | factory = connection_factory(filepath) 35 | except ValueError as ve: 36 | print(ve) 37 | return factory 38 | 39 | def main(): 40 | sqlite_factory = connect_to('data/person.sq3') 41 | print() 42 | 43 | xml_factory = connect_to('data/person.xml') 44 | xml_data = xml_factory.parsed_data 45 | liars = xml_data.findall(".//{}[{}='{}']".format('person', 'lastName', 'Liar')) 46 | print('found: {} persons'.format(len(liars))) 47 | for liar in liars: 48 | print('first name: {}'.format(liar.find('firstName').text)) 49 | print('last name: {}'.format(liar.find('lastName').text)) 50 | [print('phone number ({}):'.format(p.attrib['type']), p.text) for p in liar.find('phoneNumbers')] 51 | print() 52 | 53 | json_factory = connect_to('data/donut.json') 54 | json_data = json_factory.parsed_data 55 | print('found: {} donuts'.format(len(json_data))) 56 | for donut in json_data: 57 | print('name: {}'.format(donut['name'])) 58 | print('price: ${}'.format(donut['ppu'])) 59 | [print('topping: {} {}'.format(t['id'], t['type'])) for t in donut['topping']] 60 | 61 | if __name__ == '__main__': 62 | main() 63 | -------------------------------------------------------------------------------- /9324OS_13_code/old/observer.py: -------------------------------------------------------------------------------- 1 | class Publisher: 2 | def __init__(self): 3 | self.observers = [] 4 | 5 | def add(self, observer): 6 | if observer not in self.observers: 7 | self.observers.append(observer) 8 | else: 9 | print('Failed to add: {}'.format(observer)) 10 | 11 | def remove(self, observer): 12 | try: 13 | self.observers.remove(observer) 14 | except ValueError: 15 | print('Failed to remove: {}'.format(observer)) 16 | 17 | def notify(self): 18 | [o.notify(self) for o in self.observers] 19 | 20 | class DefaultFormatter(Publisher): 21 | def __init__(self, name): 22 | Publisher.__init__(self) 23 | self.name = name 24 | self._data = 0 25 | 26 | def __str__(self): 27 | return "{}: '{}' has data = {}".format(type(self).__name__, self.name, self._data) 28 | 29 | @property 30 | def data(self): 31 | return self._data 32 | 33 | @data.setter 34 | def data(self, new_value): 35 | try: 36 | self._data = int(new_value) 37 | except ValueError as e: 38 | print('Error: {}'.format(e)) 39 | self.notify() 40 | 41 | class HexFormatter: 42 | def notify(self, publisher): 43 | print("{}: '{}' has now hex data = {}".format(type(self).__name__, publisher.name, hex(publisher.data))) 44 | 45 | class BinaryFormatter: 46 | def notify(self, publisher): 47 | print("{}: '{}' has now bin data = {}".format(type(self).__name__, publisher.name, bin(publisher.data))) 48 | 49 | def main(): 50 | df = DefaultFormatter('test1') 51 | print(df) 52 | 53 | print() 54 | hf = HexFormatter() 55 | df.add(hf) 56 | df.data = 3 57 | print(df) 58 | 59 | print() 60 | bf = BinaryFormatter() 61 | df.add(bf) 62 | df.data = 21 63 | print(df) 64 | 65 | print() 66 | df.remove(hf) 67 | df.data = 40 68 | print(df) 69 | 70 | print() 71 | df.remove(hf) 72 | df.add(bf) 73 | 74 | df.data = 'hello' 75 | print(df) 76 | 77 | print() 78 | df.data = 15.8 79 | print(df) 80 | 81 | if __name__ == '__main__': 82 | main() 83 | -------------------------------------------------------------------------------- /9324OS_13_code/observer.py: -------------------------------------------------------------------------------- 1 | class Publisher: 2 | def __init__(self): 3 | self.observers = [] 4 | 5 | def add(self, observer): 6 | if observer not in self.observers: 7 | self.observers.append(observer) 8 | else: 9 | print('Failed to add: {}'.format(observer)) 10 | 11 | def remove(self, observer): 12 | try: 13 | self.observers.remove(observer) 14 | except ValueError: 15 | print('Failed to remove: {}'.format(observer)) 16 | 17 | def notify(self): 18 | [o.notify(self) for o in self.observers] 19 | 20 | class DefaultFormatter(Publisher): 21 | def __init__(self, name): 22 | Publisher.__init__(self) 23 | self.name = name 24 | self._data = 0 25 | 26 | def __str__(self): 27 | return "{}: '{}' has data = {}".format(type(self).__name__, self.name, self._data) 28 | 29 | @property 30 | def data(self): 31 | return self._data 32 | 33 | @data.setter 34 | def data(self, new_value): 35 | try: 36 | self._data = int(new_value) 37 | except ValueError as e: 38 | print('Error: {}'.format(e)) 39 | else: 40 | self.notify() 41 | 42 | class HexFormatter: 43 | def notify(self, publisher): 44 | print("{}: '{}' has now hex data = {}".format(type(self).__name__, publisher.name, hex(publisher.data))) 45 | 46 | class BinaryFormatter: 47 | def notify(self, publisher): 48 | print("{}: '{}' has now bin data = {}".format(type(self).__name__, publisher.name, bin(publisher.data))) 49 | 50 | def main(): 51 | df = DefaultFormatter('test1') 52 | print(df) 53 | 54 | print() 55 | hf = HexFormatter() 56 | df.add(hf) 57 | df.data = 3 58 | print(df) 59 | 60 | print() 61 | bf = BinaryFormatter() 62 | df.add(bf) 63 | df.data = 21 64 | print(df) 65 | 66 | print() 67 | df.remove(hf) 68 | df.data = 40 69 | print(df) 70 | 71 | print() 72 | df.remove(hf) 73 | df.add(bf) 74 | 75 | df.data = 'hello' 76 | print(df) 77 | 78 | print() 79 | df.data = 15.8 80 | print(df) 81 | 82 | if __name__ == '__main__': 83 | main() 84 | -------------------------------------------------------------------------------- /9324OS_16_code/old/graph.py: -------------------------------------------------------------------------------- 1 | def bfs(graph, start, end): 2 | path = [] 3 | visited = [start] 4 | while visited: 5 | current = visited.pop(0) 6 | if current not in path: 7 | path.append(current) 8 | if current == end: 9 | return (True, path) 10 | # skip vertices with no connections 11 | if current not in graph: 12 | continue 13 | visited = visited + graph[current] 14 | return (False, path) 15 | 16 | def dfs(graph, start, end): 17 | path = [] 18 | visited = [start] 19 | while visited: 20 | current = visited.pop(0) 21 | if current not in path: 22 | path.append(current) 23 | if current == end: 24 | return (True, path) 25 | # skip vertices with no connections 26 | if current not in graph: 27 | continue 28 | visited = graph[current] + visited 29 | return (False, path) 30 | 31 | def main(): 32 | graph = { 33 | 'Frankfurt': ['Mannheim', 'Wurzburg', 'Kassel'], 34 | 'Mannheim': ['Karlsruhe'], 35 | 'Karlsruhe': ['Augsburg'], 36 | 'Augsburg': ['Munchen'], 37 | 'Wurzburg': ['Erfurt', 'Nurnberg'], 38 | 'Nurnberg': ['Stuttgart', 'Munchen'], 39 | 'Kassel': ['Munchen'], 40 | 'Erfurt': [], 41 | 'Stuttgart': [], 42 | 'Munchen': [] 43 | } 44 | 45 | bfs_path = bfs(graph, 'Frankfurt', 'Nurnberg') 46 | dfs_path = dfs(graph, 'Frankfurt', 'Nurnberg') 47 | print('bfs Frankfurt-Nurnberg: {}'.format(bfs_path[1] if bfs_path[0] else 'Not found')) 48 | print('dfs Frankfurt-Nurnberg: {}'.format(dfs_path[1] if dfs_path[0] else 'Not found')) 49 | 50 | bfs_nopath = bfs(graph, 'Wurzburg', 'Kassel') 51 | print('bfs Wurzburg-Kassel: {}'.format(bfs_nopath[1] if bfs_nopath[0] else 'Not found')) 52 | dfs_nopath = dfs(graph, 'Wurzburg', 'Kassel') 53 | print('dfs Wurzburg-Kassel: {}'.format(dfs_nopath[1] if dfs_nopath[0] else 'Not found')) 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /9324OS_01_code/abstract_factory.py: -------------------------------------------------------------------------------- 1 | class Frog: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return self.name 7 | 8 | def interact_with(self, obstacle): 9 | print('{} the Frog encounters {} and {}!'.format(self, obstacle, obstacle.action())) 10 | 11 | class Bug: 12 | def __str__(self): 13 | return 'a bug' 14 | 15 | def action(self): 16 | return 'eats it' 17 | 18 | class FrogWorld: 19 | def __init__(self, name): 20 | print(self) 21 | self.player_name = name 22 | 23 | def __str__(self): 24 | return '\n\n\t------ Frog World -------' 25 | 26 | def make_character(self): 27 | return Frog(self.player_name) 28 | 29 | def make_obstacle(self): 30 | return Bug() 31 | 32 | class Wizard: 33 | def __init__(self, name): 34 | self.name = name 35 | 36 | def __str__(self): 37 | return self.name 38 | 39 | def interact_with(self, obstacle): 40 | print('{} the Wizard battles against {} and {}!'.format(self, obstacle, obstacle.action())) 41 | 42 | class Ork: 43 | def __str__(self): 44 | return 'an evil ork' 45 | 46 | def action(self): 47 | return 'kills it' 48 | 49 | class WizardWorld: 50 | def __init__(self, name): 51 | print(self) 52 | self.player_name = name 53 | 54 | def __str__(self): 55 | return '\n\n\t------ Wizard World -------' 56 | 57 | def make_character(self): 58 | return Wizard(self.player_name) 59 | 60 | def make_obstacle(self): 61 | return Ork() 62 | 63 | class GameEnvironment: 64 | def __init__(self, factory): 65 | self.hero = factory.make_character() 66 | self.obstacle = factory.make_obstacle() 67 | 68 | def play(self): 69 | self.hero.interact_with(self.obstacle) 70 | 71 | def main(): 72 | name = input("Hello. What's your name? ") 73 | valid_input = False 74 | while not valid_input: 75 | try: 76 | age = input('Welcome {}. How old are you? '.format(name)) 77 | age = int(age) 78 | valid_input = True 79 | game = FrogWorld if age < 18 else WizardWorld 80 | environment = GameEnvironment(game(name)) 81 | environment.play() 82 | except ValueError as err: 83 | print("Age {} is invalid, please try again...".format(age)) 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /9324OS_01_code/old/abstract_factory.py: -------------------------------------------------------------------------------- 1 | class Frog: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def __str__(self): 6 | return self.name 7 | 8 | def interact_with(self, obstacle): 9 | print('{} the Frog encounters {} and {}!'.format(self, obstacle, obstacle.action())) 10 | 11 | class Bug: 12 | def __str__(self): 13 | return 'a bug' 14 | 15 | def action(self): 16 | return 'eats it' 17 | 18 | class FrogWorld: 19 | def __init__(self, name): 20 | print(self) 21 | self.player_name = name 22 | 23 | def __str__(self): 24 | return '\n\n\t------ Frog World -------' 25 | 26 | def make_character(self): 27 | return Frog(self.player_name) 28 | 29 | def make_obstacle(self): 30 | return Bug() 31 | 32 | class Wizard: 33 | def __init__(self, name): 34 | self.name = name 35 | 36 | def __str__(self): 37 | return self.name 38 | 39 | def interact_with(self, obstacle): 40 | print('{} the Wizard battles against {} and {}!'.format(self, obstacle, obstacle.action())) 41 | 42 | class Ork: 43 | def __str__(self): 44 | return 'an evil ork' 45 | 46 | def action(self): 47 | return 'kills it' 48 | 49 | class WizardWorld: 50 | def __init__(self, name): 51 | print(self) 52 | self.player_name = name 53 | 54 | def __str__(self): 55 | return '\n\n\t------ Wizard World -------' 56 | 57 | def make_character(self): 58 | return Wizard(self.player_name) 59 | 60 | def make_obstacle(self): 61 | return Ork() 62 | 63 | class GameEnvironment: 64 | def __init__(self, factory): 65 | self.hero = factory.make_character() 66 | self.obstacle = factory.make_obstacle() 67 | 68 | def play(self): 69 | self.hero.interact_with(self.obstacle) 70 | 71 | def main(): 72 | name = input("Hello. What's your name? ") 73 | valid_input = False 74 | while not valid_input: 75 | try: 76 | age = input('Welcome {}. How old are you? '.format(name)) 77 | age = int(age) 78 | valid_input = True 79 | game = FrogWorld if age < 18 else WizardWorld 80 | environment = GameEnvironment(game(name)) 81 | environment.play() 82 | except ValueError as err: 83 | print("Age {} is invalid, please try again...".format(age)) 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /9324OS_06_code/old/facade.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from abc import ABCMeta, abstractmethod 3 | 4 | State = Enum('State', 'new running sleeping restart zombie') 5 | 6 | class User: 7 | pass 8 | 9 | class Process: 10 | pass 11 | 12 | class File: 13 | pass 14 | 15 | class Server(metaclass=ABCMeta): 16 | @abstractmethod 17 | def __init__(self): 18 | pass 19 | 20 | def __str__(self): 21 | return self.name 22 | 23 | @abstractmethod 24 | def boot(self): 25 | pass 26 | 27 | @abstractmethod 28 | def kill(self, restart=True): 29 | pass 30 | 31 | class FileServer(Server): 32 | def __init__(self): 33 | '''actions required for initializing the file server''' 34 | self.name = 'FileServer' 35 | self.state = State.new 36 | 37 | def boot(self): 38 | print('booting the {}'.format(self)) 39 | '''actions required for booting the file server''' 40 | self.state = State.running 41 | 42 | def kill(self, restart=True): 43 | print('Killing {}'.format(self)) 44 | '''actions required for killing the file server''' 45 | self.state = State.restart if restart else State.zombie 46 | 47 | def create_file(self, user, name, permissions): 48 | '''check validity of permissions, user rights, etc.''' 49 | pass 50 | 51 | class ProcessServer(Server): 52 | def __init__(self): 53 | '''actions required for initializing the process server''' 54 | self.name = 'ProcessServer' 55 | self.state = State.new 56 | 57 | def boot(self): 58 | print('booting the {}'.format(self)) 59 | '''actions required for booting the process server''' 60 | self.state = State.running 61 | 62 | def kill(self, restart=True): 63 | print('Killing {}'.format(self)) 64 | '''actions required for killing the process server''' 65 | self.state = State.restart if restart else State.zombie 66 | 67 | def create_process(self, user, name): 68 | '''check user rights, generate PID, etc.''' 69 | pass 70 | 71 | class WindowServer: 72 | pass 73 | 74 | class NetworkServer: 75 | pass 76 | 77 | class OperatingSystem: 78 | '''The Facade''' 79 | def __init__(self): 80 | self.fs = FileServer() 81 | self.ps = ProcessServer() 82 | 83 | def start(self): 84 | [i.boot() for i in (self.fs, self.ps)] 85 | 86 | def create_file(self, user, name, permissions): 87 | return self.fs.create_file(user, name, permissions) 88 | 89 | def create_process(self, user, name): 90 | return self.ps.create_process(user, name) 91 | 92 | def main(): 93 | os = OperatingSystem() 94 | os.start() 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /9324OS_14_code/old/state.py: -------------------------------------------------------------------------------- 1 | from state_machine import State, Event, acts_as_state_machine, after, before 2 | 3 | @acts_as_state_machine 4 | class Process: 5 | created = State(initial=True) 6 | waiting = State() 7 | running = State() 8 | terminated = State() 9 | blocked = State() 10 | swapped_out_waiting = State() 11 | swapped_out_blocked = State() 12 | 13 | wait = Event(from_states=(created, running, blocked, swapped_out_waiting), to_state=waiting) 14 | run = Event(from_states=waiting, to_state=running) 15 | terminate = Event(from_states=running, to_state=terminated) 16 | block = Event(from_states=(running, swapped_out_blocked), to_state=blocked) 17 | swap_wait = Event(from_states=waiting, to_state=swapped_out_waiting) 18 | swap_block = Event(from_states=blocked, to_state=swapped_out_blocked) 19 | 20 | def __init__(self, name): 21 | self.name = name 22 | 23 | @after('wait') 24 | def wait_info(self): 25 | print('{} entered waiting mode'.format(self.name)) 26 | 27 | @after('run') 28 | def run_info(self): 29 | print('{} is running'.format(self.name)) 30 | 31 | @before('terminate') 32 | def terminate_info(self): 33 | print('{} terminated'.format(self.name)) 34 | 35 | @after('block') 36 | def block_info(self): 37 | print('{} is blocked'.format(self.name)) 38 | 39 | @after('swap_wait') 40 | def swap_wait_info(self): 41 | print('{} is swapped out and waiting'.format(self.name)) 42 | 43 | @after('swap_block') 44 | def swap_block_info(self): 45 | print('{} is swapped out and blocked'.format(self.name)) 46 | 47 | def transition(process, event, event_name): 48 | try: 49 | event() 50 | except Exception as err: 51 | print('Error: transition of {} from {} to {} failed'.format(process.name, process.current_state, event_name)) 52 | 53 | def state_info(process): 54 | print('state of {}: {}'.format(process.name, process.current_state)) 55 | 56 | def main(): 57 | RUNNING = 'running' 58 | WAITING = 'waiting' 59 | BLOCKED = 'blocked' 60 | TERMINATED = 'terminated' 61 | 62 | p1, p2 = Process('process1'), Process('process2') 63 | [state_info(p) for p in (p1, p2)] 64 | 65 | print() 66 | transition(p1, p1.wait, WAITING) 67 | transition(p2, p2.terminate, TERMINATED) 68 | [state_info(p) for p in (p1, p2)] 69 | 70 | print() 71 | transition(p1, p1.run, RUNNING) 72 | transition(p2, p2.wait, WAITING) 73 | [state_info(p) for p in (p1, p2)] 74 | 75 | print() 76 | transition(p2, p2.run, RUNNING) 77 | [state_info(p) for p in (p1, p2)] 78 | 79 | print() 80 | [transition(p, p.block, BLOCKED) for p in (p1, p2)] 81 | [state_info(p) for p in (p1, p2)] 82 | 83 | print() 84 | [transition(p, p.terminate, TERMINATED) for p in (p1, p2)] 85 | [state_info(p) for p in (p1, p2)] 86 | 87 | if __name__ == '__main__': 88 | main() 89 | -------------------------------------------------------------------------------- /9324OS_14_code/state.py: -------------------------------------------------------------------------------- 1 | from state_machine import State, Event, acts_as_state_machine, after, before, InvalidStateTransition 2 | 3 | @acts_as_state_machine 4 | class Process: 5 | created = State(initial=True) 6 | waiting = State() 7 | running = State() 8 | terminated = State() 9 | blocked = State() 10 | swapped_out_waiting = State() 11 | swapped_out_blocked = State() 12 | 13 | wait = Event(from_states=(created, running, blocked, swapped_out_waiting), to_state=waiting) 14 | run = Event(from_states=waiting, to_state=running) 15 | terminate = Event(from_states=running, to_state=terminated) 16 | block = Event(from_states=(running, swapped_out_blocked), to_state=blocked) 17 | swap_wait = Event(from_states=waiting, to_state=swapped_out_waiting) 18 | swap_block = Event(from_states=blocked, to_state=swapped_out_blocked) 19 | 20 | def __init__(self, name): 21 | self.name = name 22 | 23 | @after('wait') 24 | def wait_info(self): 25 | print('{} entered waiting mode'.format(self.name)) 26 | 27 | @after('run') 28 | def run_info(self): 29 | print('{} is running'.format(self.name)) 30 | 31 | @before('terminate') 32 | def terminate_info(self): 33 | print('{} terminated'.format(self.name)) 34 | 35 | @after('block') 36 | def block_info(self): 37 | print('{} is blocked'.format(self.name)) 38 | 39 | @after('swap_wait') 40 | def swap_wait_info(self): 41 | print('{} is swapped out and waiting'.format(self.name)) 42 | 43 | @after('swap_block') 44 | def swap_block_info(self): 45 | print('{} is swapped out and blocked'.format(self.name)) 46 | 47 | def transition(process, event, event_name): 48 | try: 49 | event() 50 | except InvalidStateTransition as err: 51 | print('Error: transition of {} from {} to {} failed'.format(process.name, process.current_state, event_name)) 52 | 53 | def state_info(process): 54 | print('state of {}: {}'.format(process.name, process.current_state)) 55 | 56 | def main(): 57 | RUNNING = 'running' 58 | WAITING = 'waiting' 59 | BLOCKED = 'blocked' 60 | TERMINATED = 'terminated' 61 | 62 | p1, p2 = Process('process1'), Process('process2') 63 | [state_info(p) for p in (p1, p2)] 64 | 65 | print() 66 | transition(p1, p1.wait, WAITING) 67 | transition(p2, p2.terminate, TERMINATED) 68 | [state_info(p) for p in (p1, p2)] 69 | 70 | print() 71 | transition(p1, p1.run, RUNNING) 72 | transition(p2, p2.wait, WAITING) 73 | [state_info(p) for p in (p1, p2)] 74 | 75 | print() 76 | transition(p2, p2.run, RUNNING) 77 | [state_info(p) for p in (p1, p2)] 78 | 79 | print() 80 | [transition(p, p.block, BLOCKED) for p in (p1, p2)] 81 | [state_info(p) for p in (p1, p2)] 82 | 83 | print() 84 | [transition(p, p.terminate, TERMINATED) for p in (p1, p2)] 85 | [state_info(p) for p in (p1, p2)] 86 | 87 | if __name__ == '__main__': 88 | main() 89 | -------------------------------------------------------------------------------- /9324OS_06_code/facade.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from abc import ABCMeta, abstractmethod 3 | 4 | State = Enum('State', 'new running sleeping restart zombie') 5 | 6 | class User: 7 | pass 8 | 9 | class Process: 10 | pass 11 | 12 | class File: 13 | pass 14 | 15 | class Server(metaclass=ABCMeta): 16 | @abstractmethod 17 | def __init__(self): 18 | pass 19 | 20 | def __str__(self): 21 | return self.name 22 | 23 | @abstractmethod 24 | def boot(self): 25 | pass 26 | 27 | @abstractmethod 28 | def kill(self, restart=True): 29 | pass 30 | 31 | class FileServer(Server): 32 | def __init__(self): 33 | '''actions required for initializing the file server''' 34 | self.name = 'FileServer' 35 | self.state = State.new 36 | 37 | def boot(self): 38 | print('booting the {}'.format(self)) 39 | '''actions required for booting the file server''' 40 | self.state = State.running 41 | 42 | def kill(self, restart=True): 43 | print('Killing {}'.format(self)) 44 | '''actions required for killing the file server''' 45 | self.state = State.restart if restart else State.zombie 46 | 47 | def create_file(self, user, name, permissions): 48 | '''check validity of permissions, user rights, etc.''' 49 | print("trying to create the file '{}' for user '{}' with permissions {}".format(name, user, permissions)) 50 | 51 | class ProcessServer(Server): 52 | def __init__(self): 53 | '''actions required for initializing the process server''' 54 | self.name = 'ProcessServer' 55 | self.state = State.new 56 | 57 | def boot(self): 58 | print('booting the {}'.format(self)) 59 | '''actions required for booting the process server''' 60 | self.state = State.running 61 | 62 | def kill(self, restart=True): 63 | print('Killing {}'.format(self)) 64 | '''actions required for killing the process server''' 65 | self.state = State.restart if restart else State.zombie 66 | 67 | def create_process(self, user, name): 68 | '''check user rights, generate PID, etc.''' 69 | print("trying to create the process '{}' for user '{}'".format(name, user)) 70 | 71 | class WindowServer: 72 | pass 73 | 74 | class NetworkServer: 75 | pass 76 | 77 | class OperatingSystem: 78 | '''The Facade''' 79 | def __init__(self): 80 | self.fs = FileServer() 81 | self.ps = ProcessServer() 82 | 83 | def start(self): 84 | [i.boot() for i in (self.fs, self.ps)] 85 | 86 | def create_file(self, user, name, permissions): 87 | return self.fs.create_file(user, name, permissions) 88 | 89 | def create_process(self, user, name): 90 | return self.ps.create_process(user, name) 91 | 92 | def main(): 93 | os = OperatingSystem() 94 | os.start() 95 | os.create_file('foo', 'hello', '-rw-r-r') 96 | os.create_process('bar', 'ls /tmp') 97 | 98 | if __name__ == '__main__': 99 | main() 100 | -------------------------------------------------------------------------------- /9324OS_02_code/builder.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | import time 3 | 4 | PizzaProgress = Enum('PizzaProgress', 'queued preparation baking ready') 5 | PizzaDough = Enum('PizzaDough', 'thin thick') 6 | PizzaSauce = Enum('PizzaSauce', 'tomato creme_fraiche') 7 | PizzaTopping = Enum('PizzaTopping', 'mozzarella double_mozzarella bacon ham mushrooms red_onion oregano') 8 | STEP_DELAY = 3 # in seconds for the sake of the example 9 | 10 | class Pizza: 11 | def __init__(self, name): 12 | self.name = name 13 | self.dough = None 14 | self.sauce = None 15 | self.topping = [] 16 | 17 | def __str__(self): 18 | return self.name 19 | 20 | def prepare_dough(self, dough): 21 | self.dough = dough 22 | print('preparing the {} dough of your {}...'.format(self.dough.name, self)) 23 | time.sleep(STEP_DELAY) 24 | print('done with the {} dough'.format(self.dough.name)) 25 | 26 | class MargaritaBuilder: 27 | def __init__(self): 28 | self.pizza = Pizza('margarita') 29 | self.progress = PizzaProgress.queued 30 | self.baking_time = 5 # in seconds for the sake of the example 31 | 32 | def prepare_dough(self): 33 | self.progress = PizzaProgress.preparation 34 | self.pizza.prepare_dough(PizzaDough.thin) 35 | 36 | def add_sauce(self): 37 | print('adding the tomato sauce to your margarita...') 38 | self.pizza.sauce = PizzaSauce.tomato 39 | time.sleep(STEP_DELAY) 40 | print('done with the tomato sauce') 41 | 42 | def add_topping(self): 43 | print('adding the topping (double mozzarella, oregano) to your margarita') 44 | self.pizza.topping.append([i for i in (PizzaTopping.double_mozzarella, PizzaTopping.oregano)]) 45 | time.sleep(STEP_DELAY) 46 | print('done with the topping (double mozzarrella, oregano)') 47 | 48 | def bake(self): 49 | self.progress = PizzaProgress.baking 50 | print('baking your margarita for {} seconds'.format(self.baking_time)) 51 | time.sleep(self.baking_time) 52 | self.progress = PizzaProgress.ready 53 | print('your margarita is ready') 54 | 55 | class CreamyBaconBuilder: 56 | def __init__(self): 57 | self.pizza = Pizza('creamy bacon') 58 | self.progress = PizzaProgress.queued 59 | self.baking_time = 7 # in seconds for the sake of the example 60 | 61 | def prepare_dough(self): 62 | self.progress = PizzaProgress.preparation 63 | self.pizza.prepare_dough(PizzaDough.thick) 64 | 65 | def add_sauce(self): 66 | print('adding the crème fraîche sauce to your creamy bacon') 67 | self.pizza.sauce = PizzaSauce.creme_fraiche 68 | time.sleep(STEP_DELAY) 69 | print('done with the crème fraîche sauce') 70 | 71 | def add_topping(self): 72 | print('adding the topping (mozzarella, bacon, ham, mushrooms, red onion, oregano) to your creamy bacon') 73 | self.pizza.topping.append([t for t in (PizzaTopping.mozzarella, PizzaTopping.bacon, 74 | PizzaTopping.ham, PizzaTopping.mushrooms, 75 | PizzaTopping.red_onion, PizzaTopping.oregano)]) 76 | time.sleep(STEP_DELAY) 77 | print('done with the topping (mozzarella, bacon, ham, mushrooms, red onion, oregano)') 78 | 79 | def bake(self): 80 | self.progress = PizzaProgress.baking 81 | print('baking your creamy bacon for {} seconds'.format(self.baking_time)) 82 | time.sleep(self.baking_time) 83 | self.progress = PizzaProgress.ready 84 | print('your creamy bacon is ready') 85 | 86 | class Waiter: 87 | def __init__(self): 88 | self.builder = None 89 | 90 | def construct_pizza(self, builder): 91 | self.builder = builder 92 | [step() for step in (builder.prepare_dough, builder.add_sauce, builder.add_topping, builder.bake)] 93 | 94 | @property 95 | def pizza(self): 96 | return self.builder.pizza 97 | 98 | def validate_style(builders): 99 | try: 100 | pizza_style = input('What pizza would you like, [m]argarita or [c]reamy bacon? ') 101 | builder = builders[pizza_style]() 102 | valid_input = True 103 | except KeyError as err: 104 | print('Sorry, only margarita (key m) and creamy bacon (key c) are available') 105 | return (False, None) 106 | return (True, builder) 107 | 108 | def main(): 109 | builders = dict(m=MargaritaBuilder, c=CreamyBaconBuilder) 110 | valid_input = False 111 | while not valid_input: 112 | valid_input, builder = validate_style(builders) 113 | print() 114 | waiter = Waiter() 115 | waiter.construct_pizza(builder) 116 | pizza = waiter.pizza 117 | print() 118 | print('Enjoy your {}!'.format(pizza)) 119 | 120 | if __name__ == '__main__': 121 | main() 122 | -------------------------------------------------------------------------------- /9324OS_12_code/interpreter.py: -------------------------------------------------------------------------------- 1 | from pyparsing import Word, OneOrMore, Optional, Group, Suppress, alphanums 2 | 3 | class Gate: 4 | def __init__(self): 5 | self.is_open = False 6 | 7 | def __str__(self): 8 | return 'open' if self.is_open else 'closed' 9 | 10 | def open(self): 11 | print('opening the gate') 12 | self.is_open = True 13 | 14 | def close(self): 15 | print('closing the gate') 16 | self.is_open = False 17 | 18 | class Garage: 19 | def __init__(self): 20 | self.is_open = False 21 | 22 | def __str__(self): 23 | return 'open' if self.is_open else 'closed' 24 | 25 | def open(self): 26 | print('opening the garage') 27 | self.is_open = True 28 | 29 | def close(self): 30 | print('closing the garage') 31 | self.is_open = False 32 | 33 | class Aircondition: 34 | def __init__(self): 35 | self.is_on = False 36 | 37 | def __str__(self): 38 | return 'on' if self.is_on else 'off' 39 | 40 | def turn_on(self): 41 | print('turning on the aircondition') 42 | self.is_on = True 43 | 44 | def turn_off(self): 45 | print('turning off the aircondition') 46 | self.is_on = False 47 | 48 | class Heating: 49 | def __init__(self): 50 | self.is_on = False 51 | 52 | def __str__(self): 53 | return 'on' if self.is_on else 'off' 54 | 55 | def turn_on(self): 56 | print('turning on the heating') 57 | self.is_on = True 58 | 59 | def turn_off(self): 60 | print('turning off the heating') 61 | self.is_on = False 62 | 63 | class Boiler: 64 | def __init__(self): 65 | self.temperature = 83 # in celsius 66 | 67 | def __str__(self): 68 | return 'boiler temperature: {}'.format(self.temperature) 69 | 70 | def increase_temperature(self, amount): 71 | print("increasing the boiler's temperature by {} degrees".format(amount)) 72 | self.temperature += amount 73 | 74 | def decrease_temperature(self, amount): 75 | print("decreasing the boiler's temperature by {} degrees".format(amount)) 76 | self.temperature -= amount 77 | 78 | class Fridge: 79 | def __init__(self): 80 | self.temperature = 2 # in celsius 81 | 82 | def __str__(self): 83 | return 'fridge temperature: {}'.format(self.temperature) 84 | 85 | def increase_temperature(self, amount): 86 | print("increasing the fridge's temperature by {} degrees".format(amount)) 87 | self.temperature += amount 88 | 89 | def decrease_temperature(self, amount): 90 | print("decreasing the fridge's temperature by {} degrees".format(amount)) 91 | self.temperature -= amount 92 | 93 | 94 | def main(): 95 | word = Word(alphanums) 96 | command = Group(OneOrMore(word)) 97 | token = Suppress("->") 98 | device = Group(OneOrMore(word)) 99 | argument = Group(OneOrMore(word)) 100 | event = command + token + device + Optional(token + argument) 101 | 102 | gate = Gate() 103 | garage = Garage() 104 | airco = Aircondition() 105 | heating = Heating() 106 | boiler = Boiler() 107 | fridge = Fridge() 108 | 109 | tests = ('open -> gate', 110 | 'close -> garage', 111 | 'turn on -> aircondition', 112 | 'turn off -> heating', 113 | 'increase -> boiler temperature -> 5 degrees', 114 | 'decrease -> fridge temperature -> 2 degrees') 115 | 116 | open_actions = {'gate':gate.open, 'garage':garage.open, 'aircondition':airco.turn_on, 117 | 'heating':heating.turn_on, 'boiler temperature':boiler.increase_temperature, 118 | 'fridge temperature':fridge.increase_temperature} 119 | close_actions = {'gate':gate.close, 'garage':garage.close, 'aircondition':airco.turn_off, 120 | 'heating':heating.turn_off, 'boiler temperature':boiler.decrease_temperature, 121 | 'fridge temperature':fridge.decrease_temperature} 122 | 123 | for t in tests: 124 | if len(event.parseString(t)) == 2: # no argument 125 | cmd, dev = event.parseString(t) 126 | cmd_str, dev_str = ' '.join(cmd), ' '.join(dev) 127 | if 'open' in cmd_str or 'turn on' in cmd_str: 128 | open_actions[dev_str]() 129 | elif 'close' in cmd_str or 'turn off' in cmd_str: 130 | close_actions[dev_str]() 131 | elif len(event.parseString(t)) == 3: # argument 132 | cmd, dev, arg = event.parseString(t) 133 | cmd_str, dev_str, arg_str = ' '.join(cmd), ' '.join(dev), ' '.join(arg) 134 | num_arg = 0 135 | try: 136 | num_arg = int(arg_str.split()[0]) # extract the numeric part 137 | except ValueError as err: 138 | print("expected number but got: '{}'".format(arg_str[0])) 139 | if 'increase' in cmd_str and num_arg > 0: 140 | open_actions[dev_str](num_arg) 141 | elif 'decrease' in cmd_str and num_arg > 0: 142 | close_actions[dev_str](num_arg) 143 | 144 | if __name__ == '__main__': 145 | main() 146 | -------------------------------------------------------------------------------- /9324OS_12_code/old/interpreter.py: -------------------------------------------------------------------------------- 1 | from pyparsing import Word, OneOrMore, Optional, Group, Suppress, alphanums 2 | 3 | class Gate: 4 | def __init__(self): 5 | self.is_open = False 6 | 7 | def __str__(self): 8 | return 'open' if self.is_open else 'closed' 9 | 10 | def open(self): 11 | print('opening the gate') 12 | self.is_open = True 13 | 14 | def close(self): 15 | print('closing the gate') 16 | self.is_open = False 17 | 18 | class Garage: 19 | def __init__(self): 20 | self.is_open = False 21 | 22 | def __str__(self): 23 | return 'open' if self.is_open else 'closed' 24 | 25 | def open(self): 26 | print('opening the garage') 27 | self.is_open = True 28 | 29 | def close(self): 30 | print('closing the garage') 31 | self.is_open = False 32 | 33 | class Aircondition: 34 | def __init__(self): 35 | self.is_on = False 36 | 37 | def __str__(self): 38 | return 'on' if self.is_on else 'off' 39 | 40 | def turn_on(self): 41 | print('turning on the aircondition') 42 | self.is_on = True 43 | 44 | def turn_off(self): 45 | print('turning off the aircondition') 46 | self.is_on = False 47 | 48 | class Heating: 49 | def __init__(self): 50 | self.is_on = False 51 | 52 | def __str__(self): 53 | return 'on' if self.is_on else 'off' 54 | 55 | def turn_on(self): 56 | print('turning on the heating') 57 | self.is_on = True 58 | 59 | def turn_off(self): 60 | print('turning off the heating') 61 | self.is_on = False 62 | 63 | class Boiler: 64 | def __init__(self): 65 | self.temperature = 180 # in fahrenheit 66 | 67 | def __str__(self): 68 | return 'boiler temperature: {}'.format(self.temperature) 69 | 70 | def increase_temperature(self, amount): 71 | print("increasing the boiler's temperature by {} degrees".format(amount)) 72 | self.temperature += amount 73 | 74 | def decrease_temperature(self, amount): 75 | print("decreasing the boiler's temperature by {} degrees".format(amount)) 76 | self.temperature -= amount 77 | 78 | class Fridge: 79 | def __init__(self): 80 | self.temperature = 35 # in fahrenheit 81 | 82 | def __str__(self): 83 | return 'fridge temperature: {}'.format(self.temperature) 84 | 85 | def increase_temperature(self, amount): 86 | print("increasing the fridge's temperature by {} degrees".format(amount)) 87 | self.temperature += amount 88 | 89 | def decrease_temperature(self, amount): 90 | print("decreasing the fridge's temperature by {} degrees".format(amount)) 91 | self.temperature -= amount 92 | 93 | 94 | def main(): 95 | word = Word(alphanums) 96 | command = Group(OneOrMore(word)) 97 | token = Suppress("->") 98 | device = Group(OneOrMore(word)) 99 | argument = Group(OneOrMore(word)) 100 | event = command + token + device + Optional(token + argument) 101 | 102 | gate = Gate() 103 | garage = Garage() 104 | airco = Aircondition() 105 | heating = Heating() 106 | boiler = Boiler() 107 | fridge = Fridge() 108 | 109 | tests = ('open -> gate', 110 | 'close -> garage', 111 | 'turn on -> aircondition', 112 | 'turn off -> heating', 113 | 'increase -> boiler temperature -> 20 degrees', 114 | 'decrease -> fridge temperature -> 6 degree') 115 | 116 | open_actions = {'gate':gate.open, 'garage':garage.open, 'aircondition':airco.turn_on, 117 | 'heating':heating.turn_on, 'boiler temperature':boiler.increase_temperature, 118 | 'fridge temperature':fridge.increase_temperature} 119 | close_actions = {'gate':gate.close, 'garage':garage.close, 'aircondition':airco.turn_off, 120 | 'heating':heating.turn_off, 'boiler temperature':boiler.decrease_temperature, 121 | 'fridge temperature':fridge.decrease_temperature} 122 | 123 | for t in tests: 124 | if len(event.parseString(t)) == 2: # no argument 125 | cmd, dev = event.parseString(t) 126 | cmd_str, dev_str = ' '.join(cmd), ' '.join(dev) 127 | if 'open' in cmd_str or 'turn on' in cmd_str: 128 | open_actions[dev_str]() 129 | elif 'close' in cmd_str or 'turn off' in cmd_str: 130 | close_actions[dev_str]() 131 | elif len(event.parseString(t)) == 3: # argument 132 | cmd, dev, arg = event.parseString(t) 133 | cmd_str, dev_str, arg_str = ' '.join(cmd), ' '.join(dev), ' '.join(arg) 134 | num_arg = 0 135 | try: 136 | num_arg = int(arg_str.split()[0]) # extract the numeric part 137 | except ValueError as err: 138 | print("expected number but got: '{}'".format(arg_str[0])) 139 | if 'increase' in cmd_str and num_arg > 0: 140 | open_actions[dev_str](num_arg) 141 | elif 'decrease' in cmd_str and num_arg > 0: 142 | close_actions[dev_str](num_arg) 143 | 144 | if __name__ == '__main__': 145 | main() 146 | --------------------------------------------------------------------------------