├── 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 |
--------------------------------------------------------------------------------