├── .gitignore
├── .idea
├── furtherpython3.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── chapter11
├── HelloWorldGame.py
└── MousePlayApp.py
├── chapter12
├── StarshipMeteors.py
├── meteor.png
└── starship.png
├── chapter14
├── calculator.py
├── exercises
│ ├── accounts-app.py
│ ├── fintech
│ │ ├── __init__.py
│ │ └── accounts.py
│ └── test_CurrentAccount.py
├── external_module
│ └── __init__.py
├── test.py
├── test_calculator.py
└── testing-functions.py
├── chapter15
├── exercises
│ └── deck_of_cards.py
├── external_module
│ └── __init__.py
├── mock_test1.py
├── mock_test2.py
├── mock_test3.py
├── mock_test4.py
├── mock_test5.py
├── mock_test6.py
├── mock_test7.py
├── people.py
└── pytest-mock1.py
├── chapter17
├── directories1.py
├── exercise
│ ├── create_file_with_date.py
│ └── load_date_from_file.py
├── files1.py
├── files2.py
├── files3.py
├── files4.py
├── files5.py
├── my-new-file.txt
├── myfile.txt
├── paths-app.py
├── rand-file-acces.py
├── read-file-using-with.py
├── tempfiles1.py
├── text.txt
├── textfile1.txt
├── textfile2.txt
└── textfileexample.py
├── chapter18
├── binary_streams.py
├── myfile.dat
├── myfile.txt
├── raw_io_example.py
├── sockets.py
├── starship.png
├── stdinout_examples.py
├── streams_options.py
└── text_streams.py
├── chapter19
├── __init__.py
├── csvdictexample.py
├── csvexample.py
├── exercises
│ ├── __init__.py
│ ├── fintech
│ │ ├── __init__.py
│ │ └── accounts.py
│ └── write_accounts_file.py
├── names.csv
└── sample.csv
├── chapter2
└── rgb_colours.py
├── chapter20
├── exercises
│ ├── __init__.py
│ ├── accounts.xlsx
│ ├── fintech
│ │ ├── __init__.py
│ │ └── accounts.py
│ └── write_accounts_file.py
├── readExcelExample.py
├── sample.xlsx
├── sample2.xlsx
└── writeExcelExample.py
├── chapter21
├── exercises
│ └── regex_solutions.py
└── regex_examples.py
├── chapter24
├── connect_example.py
├── create5.py
├── delete4.py
├── exercise
│ ├── create_tables.py
│ ├── fintech
│ │ ├── __init__.py
│ │ └── accounts.py
│ └── write_account_info.py
├── insert2.py
├── mongo_examples.py
├── query1.py
├── query2.py
└── update3.py
├── chapter26
├── exercises
│ ├── accounts-app.py
│ ├── accounts.logging.config.yaml
│ └── fintech
│ │ ├── __init__.py
│ │ └── accounts.py
├── logging.config.yaml
├── logging_example.py
├── logging_example1.py
├── logging_example10.py
├── logging_example11.py
├── logging_example2.py
├── logging_example3.py
├── logging_example4.py
├── logging_example5.py
├── logging_example6.py
├── logging_example7.py
├── logging_example8.py
├── logging_example9.py
└── printer_lib.py
├── chapter28
├── exercises
│ └── printer_threading_app.py
├── threads.py
├── threads1.py
├── threads2.py
├── threads3.py
├── threads4.py
├── threads5.py
├── threads6.py
├── threads7.py
└── timer_example.py
├── chapter29
├── exercises
│ └── multiprocessing_factorial.py
├── multiprocessing1.py
├── multiprocessing2.py
├── multiprocessing3.py
├── multiprocessing4.py
├── multiprocessing5.py
├── multiprocessing6.py
└── multiprocessing7.py
├── chapter3
├── coloured_shapes.py
├── exercises
│ └── draw-hexagons.py
├── sample-window1.py
├── sample-window2.py
├── sample-window3.py
└── sphere_example.py
├── chapter30
├── barriers-app.py
├── barriers-app2.py
├── cond-app.py
├── events-app.py
├── events-app2.py
├── exercises
│ ├── stack
│ │ ├── Stack.py
│ │ └── __init__.py
│ └── stack_multithreaded_app.py
├── locks-app.py
├── queue-example.py
└── semaphore-app.py
├── chapter31
├── exercises
│ └── factorial_future.py
├── future1.py
├── future2.py
├── future3.py
├── future4.py
├── future5.py
├── future6.py
└── future7.py
├── chapter32
├── asyncioapp1.py
├── asyncioapp2.py
├── asyncioapp3.py
├── asyncioapp4.py
└── exercises
│ └── async_factorial.py
├── chapter34
├── reactive1.py
├── reactive2.py
├── reactive3a.py
├── reactive3b.py
└── reactive4.py
├── chapter35
├── exercises
│ └── stocks.py
├── reactive_ops1.py
├── reactive_ops2.py
├── reactive_ops3.py
├── reactive_ops4.py
└── reactive_ops5.py
├── chapter37
├── BasicTCPIPSocketServer.py
├── BroadcastClient.py
├── BroadcastServer.py
├── MyHttpServer.py
├── MyTCPHandler.py
├── TCPIPSocketClient.py
└── exercises
│ ├── SimpleClient.py
│ └── SimpleServer.py
├── chapter38
├── hello_flask_world.py
└── hello_flask_world2.py
├── chapter39
├── bookshop_service1.py
├── bookshop_service2.py
├── bookshop_service3.py
└── image_service4.py
├── chapter4
├── circles-picture.py
├── exercises
│ └── fractal_trees.py
├── mandelbrot.py
├── snowflake.py
└── snowflake_koch.py
├── chapter5
├── bar_chart8a.py
├── bar_chart8b.py
├── bar_chart8c.py
├── bar_chart8d.py
├── bar_chart8e.py
├── configuringaplot4.py
├── figure_example7.py
├── line_graph3.py
├── matplotlib2.py
├── pie_chart5.py
├── pie_chart_5a.py
├── scatter_plot6.py
├── scatter_plot_trendline6.py
├── simple_plot1.py
├── sub_plots9.py
└── three-d-plot10.py
├── chapter7
├── FrameAndPanelApp.py
├── SampleDCApp.py
└── SimpleHelloWorldApp.py
├── chapter8
├── HelloNamedApp.py
├── SimpleEventHandlerApp.py
└── exercises
│ ├── BirthdayGUIApp.py
│ └── TicTacToeGuiApp.py
├── chapter9
├── PyDraw.py
├── load.gif
├── new.gif
└── save.gif
├── django-server
└── mysite
│ ├── db.sqlite3
│ ├── manage.py
│ ├── mysite
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│ └── polls
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── graphql
├── main.py
├── model.py
└── schema.graphql
├── messaging
├── publisher.py
└── receiver.py
└── profiling
├── get_pay.log
├── memory_usage1.py
├── memory_usage2.py
├── memory_usage3.py
├── memory_usage4.py
├── profile_example1.py
├── profile_example2.py
├── timings1.py
└── timings2.py
/.gitignore:
--------------------------------------------------------------------------------
1 | /venv/bin/
2 | /venv/lib/python3.8/site-packages/
3 | /venv/pyvenv.cfg
4 | /.idea/shelf/
5 |
--------------------------------------------------------------------------------
/.idea/furtherpython3.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Advanced Guide to Python3 Programming
2 | Code Repository for Advanced Guide to Python 3 Programming
3 |
--------------------------------------------------------------------------------
/chapter11/HelloWorldGame.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 |
4 | def main():
5 | print('Starting Game')
6 |
7 | print('Initialising PyGame')
8 | pygame.init() # Required by every PyGame application
9 |
10 | print('Initialising HelloWorldGame')
11 | pygame.display.set_mode((200, 100)) # Note that this takes a tuple specifying the width and highet of the display
12 | pygame.display.set_caption('Hello World')
13 | print('Update display')
14 | pygame.display.update()
15 |
16 | print('Starting main Game Playing Loop')
17 | running = True
18 | while running:
19 | for event in pygame.event.get():
20 | # There are lots of events generated by we are only interested on the Quit event
21 | if event.type == pygame.QUIT:
22 | print('Received Quit Event:', event)
23 | running = False
24 |
25 | print('Game Over')
26 | # Now tidy up and quit Python
27 | pygame.quit()
28 |
29 |
30 | if __name__ == '__main__':
31 | main()
32 |
--------------------------------------------------------------------------------
/chapter11/MousePlayApp.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | FRAME_REFRESH_RATE = 30
4 | BLUE = (0, 0, 255)
5 | BACKGROUND = (255, 255, 255)
6 | WIDTH = 10
7 | HEIGHT = 10
8 |
9 |
10 | def main():
11 | print('Initialising PyGame')
12 | pygame.init() # Required by every PyGame application
13 |
14 | print('Initialising Box Game')
15 | display_surface = pygame.display.set_mode((400, 300))
16 | pygame.display.set_caption('Box Game')
17 | print('Update display')
18 | pygame.display.update()
19 | print('Setup the Clock')
20 | clock = pygame.time.Clock()
21 | # Clear the screen of current contents
22 | display_surface.fill(BACKGROUND)
23 |
24 | print('Starting main Game Playing Loop')
25 | running = True
26 | while running:
27 | for event in pygame.event.get():
28 | # There are lots of events generated by we are only interested on the Quit event
29 | if event.type == pygame.QUIT:
30 | print('Received Quit Event:', event)
31 | running = False
32 | elif event.type == pygame.MOUSEBUTTONDOWN:
33 | print('Received Mouse Event', event)
34 | x, y = event.pos
35 | pygame.draw.rect(display_surface, BLUE, [x, y, WIDTH, HEIGHT])
36 |
37 | # Update the display
38 | pygame.display.update()
39 |
40 | # Defines the frame rate. The number is number of frames per second
41 | # Should be called once per frame (but only once)
42 | clock.tick(FRAME_REFRESH_RATE)
43 |
44 | print('Game Over')
45 | # Now tidy up and quit Python
46 | pygame.quit()
47 |
48 |
49 | if __name__ == '__main__':
50 | main()
51 |
--------------------------------------------------------------------------------
/chapter12/meteor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter12/meteor.png
--------------------------------------------------------------------------------
/chapter12/starship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter12/starship.png
--------------------------------------------------------------------------------
/chapter14/calculator.py:
--------------------------------------------------------------------------------
1 | class Calculator:
2 | def __init__(self):
3 | self.current = 0
4 | self.total = 0
5 |
6 | def set(self, value):
7 | self.current = value
8 |
9 | def add(self):
10 | self.total += self.current
11 |
12 | def sub(self):
13 | self.total -= self.current
14 |
15 | def total(self):
16 | return self.total
--------------------------------------------------------------------------------
/chapter14/exercises/accounts-app.py:
--------------------------------------------------------------------------------
1 | import fintech.accounts as accounts
2 |
3 | acc1 = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
4 | acc2 = accounts.DepositAccount('345', 'John', 23.55, 0.5)
5 | acc3 = accounts.InvestmentAccount('567', 'Phoebe', 12.45, 'high risk')
6 |
7 | print(acc1)
8 | print(acc2)
9 | print(acc3)
10 |
11 | acc1.deposit(23.45)
12 | acc1.withdraw(12.33)
13 | print('balance:', acc1.balance)
14 |
15 | print('Number of Account instances created:', accounts.Account.instance_count)
16 |
17 | try:
18 | print('balance:', acc1.balance)
19 | acc1.withdraw(300.00)
20 | print('balance:', acc1.balance)
21 | except accounts.BalanceError as e:
22 | print('Handling Exception')
23 | print(e)
24 |
25 | with accounts.CurrentAccount ('891', 'Adam', 5.0, 50.0) as acc:
26 | acc.deposit(23.0)
27 | acc.withdraw(12.50)
28 | print(acc.balance)
29 |
30 | print('acc1.branch:', acc1.branch)
31 |
32 | for transaction in acc1:
33 | print(transaction)
34 |
35 | acc1.deposit(-1.0)
--------------------------------------------------------------------------------
/chapter14/exercises/fintech/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter14/exercises/fintech/__init__.py
--------------------------------------------------------------------------------
/chapter14/exercises/fintech/accounts.py:
--------------------------------------------------------------------------------
1 | from abc import ABCMeta
2 | from timeit import default_timer
3 |
4 |
5 | # Accounts module
6 |
7 |
8 | def timer(func):
9 | def inner(self, value):
10 | print('calling ', func.__name__, 'on', self, 'with', value)
11 | start = default_timer()
12 | func(self, value)
13 | end = default_timer()
14 | print('returned from ', func.__name__, 'it took', end - start, 'seconds')
15 |
16 | return inner
17 |
18 |
19 | class BalanceError(Exception):
20 | """ The Balance will be invalid """
21 |
22 | def __init__(self, account):
23 | self.account = account
24 |
25 |
26 | class AmountError(Exception):
27 |
28 | def __init__(self, account, msg):
29 | self.account = account
30 | self.message = msg
31 |
32 | def __str__(self):
33 | return 'AmountError (' + self.message + ') on ' + str(self.account)
34 |
35 |
36 | class Transaction:
37 | """ A Class used to represent an individual Transaction """
38 | def __init__(self, action, amount):
39 | self.action = action
40 | self.amount = amount
41 |
42 | def __str__(self):
43 | return 'Transaction[' + self.action + ': ' + str(self.amount) + ']'
44 |
45 |
46 | class Account(metaclass=ABCMeta):
47 | """" A class used to represent a type of account """
48 |
49 | instance_count = 0
50 |
51 | @classmethod
52 | def increment_instance_count(cls):
53 | print('Creating new Account')
54 | cls.instance_count += 1
55 |
56 | def __init__(self, account_number, account_holder, opening_balance, account_type):
57 | Account.increment_instance_count()
58 | self.account_number = account_number
59 | self.account_holder = account_holder
60 | self._balance = opening_balance
61 | self.type = account_type
62 | # Note need to initialise the history list before you try to add a Transaction
63 | self.history = []
64 | self._add_deposit_transaction(opening_balance)
65 |
66 | def __enter__(self):
67 | print('__enter__')
68 | return self
69 |
70 | def __exit__(self, *args):
71 | print('__exit__:', args)
72 | return True
73 |
74 | # Method called if attribute is unknown
75 | def __getattr__(self, attribute):
76 | print('__getattr__: unknown attribute accessed - ', attribute)
77 | return -1
78 |
79 | # Return the transaction hsitory as the iterable object for an Account
80 | # and any subclass of Account
81 | def __iter__(self):
82 | return iter(self.history)
83 |
84 | # Provide internal support for adding transactions
85 | # Note by convention methods starting with an '_' shoudl not be called
86 | # by clients of this class
87 | def _add_transaction(self, transaction):
88 | self.history.append(transaction)
89 |
90 | # These are convenience methods to make it easier to
91 | # record a deposit or withdrawal.
92 | def _add_deposit_transaction(self, amount):
93 | self._add_transaction(Transaction('deposit', amount))
94 |
95 | def _add_withdraw_transaction(self, amount):
96 | self._add_transaction(Transaction('withdraw', amount))
97 |
98 | @timer
99 | def deposit(self, amount):
100 | if amount < 0:
101 | print('You cannot deposit negative amounts')
102 | raise AmountError(account=self, msg='Cannot deposit negative amounts')
103 | else:
104 | self._balance += amount
105 | self._add_deposit_transaction(amount)
106 |
107 | @timer
108 | def withdraw(self, amount):
109 | if amount < 0:
110 | print('You cannot withdraw negative amounts')
111 | raise AmountError(self, 'Cannot withdraw negative amounts')
112 | else:
113 | self._balance -= amount
114 | self._add_withdraw_transaction(amount)
115 |
116 | @property
117 | def balance(self):
118 | """ Provides the current balance """
119 | return self._balance
120 |
121 | def __str__(self):
122 | return 'Account[' + self.account_number + '] - ' + \
123 | self.account_holder + ', ' + self.type + ' account = ' + str(self.balance)
124 |
125 |
126 | class CurrentAccount(Account):
127 |
128 | def __init__(self, account_number, account_holder, opening_balance, overdraft_limit):
129 | super().__init__(account_number, account_holder, opening_balance, 'current')
130 | self.overdraft_limit = -overdraft_limit
131 |
132 | @timer
133 | def withdraw(self, amount):
134 | if amount < 0:
135 | print('You cannot withdraw negative amounts')
136 | raise AmountError(self, 'Cannot withdraw negative amounts')
137 | elif self.balance - amount < self.overdraft_limit:
138 | print('Withdrawal would exceed your overdraft limit')
139 | raise BalanceError(self)
140 | else:
141 | self._balance -= amount
142 | self._add_withdraw_transaction(amount)
143 |
144 | def __str__(self):
145 | return super().__str__() + 'overdraft limit: ' + str(self.overdraft_limit)
146 |
147 |
148 | class DepositAccount(Account):
149 |
150 | def __init__(self, account_number, account_holder, opening_balance, interest_rate):
151 | super().__init__(account_number, account_holder, opening_balance, 'deposit')
152 | self.interest_rate = interest_rate
153 |
154 | def __str__(self):
155 | return super().__str__() + 'interest rate: ' + str(self.interest_rate)
156 |
157 |
158 | class InvestmentAccount(Account):
159 | def __init__(self, account_number, account_holder, opening_balance, investment_type):
160 | super().__init__(account_number, account_holder, opening_balance, 'investment')
161 | self.investment_type = investment_type
162 |
163 | def __str__(self):
164 | return super().__str__() + ', type: ' + self.type
165 |
--------------------------------------------------------------------------------
/chapter14/exercises/test_CurrentAccount.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import fintech.accounts as accounts
3 |
4 |
5 | @pytest.fixture
6 | def current_account():
7 | """Returns a CurrentAccount instance"""
8 | print('CurrentAccount fixture')
9 | return accounts.CurrentAccount('123', 'John', 0.0, 100.0)
10 |
11 |
12 | def test_opening_balance(current_account):
13 | assert current_account.balance == 0.0
14 |
15 |
16 | def test_alternative_opening_balance():
17 | current_account = accounts.CurrentAccount('123', 'John', 10.0, 100.0)
18 | assert current_account.balance == 10.00
19 |
20 |
21 | def test_negative_opening_balance():
22 | current_account = accounts.CurrentAccount('123', 'John', -10.0, 100.0)
23 | assert current_account.balance == -10.00
24 |
25 |
26 | def test_current_account_attributes(current_account):
27 | assert current_account.account_holder == 'John'
28 | assert current_account.account_number == '123'
29 | assert current_account.overdraft_limit == -100.0
30 | assert current_account.type == 'current'
31 |
32 |
33 | def test_deposit(current_account):
34 | current_account.deposit(5.0)
35 | assert current_account.balance == 5.0
36 |
37 |
38 | def test_deposit_twice(current_account):
39 | current_account.deposit(5.0)
40 | current_account.deposit(5.0)
41 | assert current_account.balance == 10.0
42 |
43 |
44 | def test_deposit_negative_amount(current_account):
45 | with pytest.raises(accounts.AmountError):
46 | current_account.deposit(-10.00)
47 |
48 |
49 | def test_deposit_zero(current_account):
50 | current_account.deposit(0.00)
51 | assert current_account.balance == 0.0
52 |
53 |
54 | def test_withdraw(current_account):
55 | current_account.withdraw(5.0)
56 | assert current_account.balance == -5.0
57 |
58 |
59 | def test_withdraw_negative_amount(current_account):
60 | with pytest.raises(accounts.AmountError):
61 | current_account.withdraw(-5.0)
62 |
63 |
64 | def test_withdraw_zero(current_account):
65 | current_account.withdraw(0.0)
66 | assert current_account.balance == 0.0
67 |
68 |
69 | def test_withdraw_twice(current_account):
70 | current_account.withdraw(5.0)
71 | current_account.withdraw(5.0)
72 | assert current_account.balance == -10.0
73 |
74 |
75 | def test_deposit_and_withdraw(current_account):
76 | current_account.deposit(10.0)
77 | current_account.withdraw(5.0)
78 | assert current_account.balance == 5.0
79 |
80 |
81 | def test_withdraw_and_deposit(current_account):
82 | current_account.withdraw(5.0)
83 | current_account.deposit(10.0)
84 | assert current_account.balance == 5.0
85 |
86 |
87 | def test_withdraw_above_overdraftlimit(current_account):
88 | with pytest.raises(accounts.BalanceError):
89 | current_account.withdraw(200.0)
90 |
91 |
92 | def test_initial_transaction_history_length(current_account):
93 | assert len(current_account.history) == 1
94 |
95 |
96 | def test_initial_transaction_details(current_account):
97 | transaction = current_account.history[0]
98 | assert transaction.action == 'deposit'
99 | assert transaction.amount == 0.0
100 |
101 |
102 | def test_deposit_transaction_history(current_account):
103 | current_account.deposit(10.0)
104 | current_account.deposit(5.0)
105 | assert len(current_account.history) == 3
106 | transaction1 = current_account.history[1]
107 | transaction2 = current_account.history[2]
108 | assert transaction1.action == 'deposit'
109 | assert transaction1.amount == 10.0
110 | assert transaction2.action == 'deposit'
111 | assert transaction2.amount == 5.0
112 |
113 |
114 | def test_withdrawal_transaction_history(current_account):
115 | current_account.withdraw(10.0)
116 | current_account.withdraw(5.0)
117 | assert len(current_account.history) == 3
118 | transaction1 = current_account.history[1]
119 | transaction2 = current_account.history[2]
120 | assert transaction1.action == 'withdraw'
121 | assert transaction1.amount == 10.0
122 | assert transaction2.action == 'withdraw'
123 | assert transaction2.amount == 5.0
124 |
125 |
126 | def test_withdrawal_and_deposit_transaction_history(current_account):
127 | current_account.deposit(10.0)
128 | current_account.withdraw(5.0)
129 | assert len(current_account.history) == 3
130 | transaction1 = current_account.history[1]
131 | transaction2 = current_account.history[2]
132 | assert transaction1.action == 'deposit'
133 | assert transaction1.amount == 10.0
134 | assert transaction2.action == 'withdraw'
135 | assert transaction2.amount == 5.0
136 |
--------------------------------------------------------------------------------
/chapter14/external_module/__init__.py:
--------------------------------------------------------------------------------
1 | def api_call():
2 | return ''
--------------------------------------------------------------------------------
/chapter14/test.py:
--------------------------------------------------------------------------------
1 | from utils.functions import *
2 | f1()
3 |
4 | from utils.classes import *
5 | p = Processor()
6 |
--------------------------------------------------------------------------------
/chapter14/test_calculator.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from calculator import Calculator
3 |
4 |
5 | @pytest.fixture(scope='session', autouse=True)
6 | def session_scope_fixture():
7 | print('session_scope_fixture')
8 |
9 |
10 | @pytest.fixture(scope='module', autouse=True)
11 | def module_scope_fixture():
12 | print('module_scope_fixture')
13 |
14 |
15 | @pytest.fixture(scope='class', autouse=True)
16 | def class_scope_fixture():
17 | print('class_scope_fixture')
18 |
19 |
20 | @pytest.fixture
21 | def calculator():
22 | """ Returns a Calculator instance """
23 | print('calculator fixture')
24 | return Calculator()
25 |
26 |
27 | def test_initial_value(calculator):
28 | assert calculator.total == 0
29 |
30 |
31 | def test_add_one(calculator):
32 | calculator.set(1)
33 | calculator.add()
34 | assert calculator.total == 1
35 |
36 |
37 | def test_subtract_one(calculator):
38 | calculator.set(1)
39 | calculator.sub()
40 | assert calculator.total == -1
41 |
42 |
43 | def test_add_one_and_one(calculator):
44 | calculator.set(1)
45 | calculator.add()
46 | calculator.set(1)
47 | calculator.add()
48 | assert calculator.total == 2
49 |
50 |
51 | @pytest.mark.parametrize('input1,input2,expected', [
52 | (3, 1, 4),
53 | (3, 2, 5),
54 | ])
55 | def test_calculator_add_operation(calculator, input1, input2, expected):
56 | calculator.set(input1)
57 | calculator.add()
58 | calculator.set(input2)
59 | calculator.add()
60 | assert calculator.total == expected
61 |
62 |
63 | @pytest.mark.skip(reason='not implemented yet')
64 | def test_calculator_multiply(calculator):
65 | calculator.multiply(2, 3)
66 | assert calculator.total == 6
67 |
--------------------------------------------------------------------------------
/chapter14/testing-functions.py:
--------------------------------------------------------------------------------
1 | def increment(x):
2 | return x + 1
3 |
4 |
5 | def test_increment_integer_3():
6 | assert increment(3) == 4
7 |
--------------------------------------------------------------------------------
/chapter15/exercises/deck_of_cards.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | def create_suite(suite):
4 | return [ (i, suite) for i in range(1, 14)]
5 |
6 | def pick_a_card(deck):
7 | print('You picked')
8 | position = random.randint(0, 52)
9 | print(deck[position][0], "of", deck[position][1])
10 | return (deck[position])
11 |
12 | # Set up the data
13 | hearts = create_suite('hearts')
14 | spades = create_suite('spades')
15 | diamonds = create_suite('diamonds')
16 | clubs = create_suite('clubs')
17 |
18 | # Make the deck of cards
19 | deck = hearts + spades + diamonds + clubs
20 |
21 | # Randomly pick from the deck of cards
22 | card = pick_a_card(deck)
23 |
--------------------------------------------------------------------------------
/chapter15/external_module/__init__.py:
--------------------------------------------------------------------------------
1 | def api_call():
2 | return ''
3 |
4 | def api_call_with_param(param):
5 | return param + 'done'
--------------------------------------------------------------------------------
/chapter15/mock_test1.py:
--------------------------------------------------------------------------------
1 | from unittest.mock import *
2 |
3 | from unittest import TestCase
4 | from unittest import main
5 |
6 | class SomeClass():
7 |
8 | def _hidden_method(self):
9 | return 0
10 |
11 | def public_method(self, x):
12 | return self._hidden_method() + x
13 |
14 | class test_SomeClass_public_interface(TestCase):
15 |
16 | def test_public_method(self):
17 | test_object = SomeClass()
18 | # Set up canned response on mock method
19 | test_object._hidden_method = MagicMock(name = 'hidden_method')
20 | test_object._hidden_method.return_value = 10
21 | # Test the object
22 | result = test_object.public_method(5)
23 | self.assertEqual(15, result, 'return value from public_method incorrect')
24 |
25 | if __name__ == '__main__':
26 | main()
--------------------------------------------------------------------------------
/chapter15/mock_test2.py:
--------------------------------------------------------------------------------
1 | from unittest.mock import *
2 |
3 | from unittest import TestCase
4 | from unittest import main
5 |
6 | class SomeClass():
7 |
8 | def _hidden_method(self):
9 | return 0
10 |
11 | def public_method(self, x):
12 | return self._hidden_method() + x
13 |
14 | class test_SomeClass_public_interface(TestCase):
15 |
16 | @patch.object(SomeClass, '_hidden_method')
17 | def test_public_method(self, mock_method):
18 | # Set up canned response
19 | mock_method.return_value = 10
20 | # Create object to be tested
21 | test_object = SomeClass()
22 | result = test_object.public_method(5)
23 | self.assertEqual(15, result, 'return value from public_method incorrect')
24 |
25 | if __name__ == '__main__':
26 | main()
27 |
--------------------------------------------------------------------------------
/chapter15/mock_test3.py:
--------------------------------------------------------------------------------
1 | import external_module
2 |
3 | from unittest.mock import *
4 |
5 | from unittest import TestCase
6 | from unittest import main
7 | import json
8 |
9 |
10 | def some_func():
11 | # Calls out to external API - which we want to mock
12 | response = external_module.api_call()
13 | return response
14 |
15 |
16 | def some_func_with_param(param):
17 | # call out to api module
18 | response = external_module.api_call_with_param(param)
19 | return response
20 |
21 |
22 | class test_some_func_calling_api(TestCase):
23 |
24 | @patch('external_module.api_call')
25 | def test_some_func(self, mock_api_call):
26 | # Sets up mock version of api_call
27 | mock_api_call.return_value = MagicMock(status_code=200, response=json.dumps({'key': 'value'}))
28 | # Calls some_func() that calls the (mock) api_call() function
29 | result = some_func()
30 | # Check that the result returned from some_func() is what was expected
31 | self.assertEqual(result.status_code, 200, "returned status code is not 200")
32 | self.assertEqual(result.response, '{"key": "value"}', "response JSON incorrect")
33 |
34 | @patch('external_module.api_call_with_param')
35 | def test_some_func_with_param(self, mock_api_call):
36 | # Sets up mock version of api_call
37 | mock_api_call.return_value = MagicMock(status_code=200, response=json.dumps({'age': '23'}))
38 | result = some_func_with_param('Phoebe')
39 | # Check that the result returned from some_func() is what was expected
40 | self.assertEqual(result.response, '{age": "23"}', 'JSON result incorrect')
41 | # Verify that the mock_api_call was called with the correct params
42 | mock_api_call.api_call_with_param.assert_called_with('Phoebe')
43 |
44 |
45 | if __name__ == '__main__':
46 | main()
47 |
--------------------------------------------------------------------------------
/chapter15/mock_test4.py:
--------------------------------------------------------------------------------
1 | import people
2 |
3 | from unittest.mock import *
4 | from unittest import TestCase
5 | from unittest import main
6 |
7 |
8 | class MyTest(TestCase):
9 |
10 | @patch('people.Person')
11 | def test_one(self, MockPerson):
12 | self.assertIs(people.Person, MockPerson)
13 | instance = MockPerson.return_value
14 | instance.calculate_pay.return_value = 250.0
15 | payroll = people.Payroll()
16 | result = payroll.generate_payslip(instance)
17 | self.assertEqual('You earned 250.0', result, 'payslip incorrect')
18 |
--------------------------------------------------------------------------------
/chapter15/mock_test5.py:
--------------------------------------------------------------------------------
1 | import people
2 |
3 | from unittest.mock import *
4 | from unittest import TestCase
5 |
6 |
7 | class MyTest(TestCase):
8 |
9 | @patch('people.Person')
10 | def test_one(self, MockPerson):
11 | self.assertIs(people.Person, MockPerson)
12 | instance = MockPerson.return_value
13 | instance.age = 24
14 | instance.name = 'Adam'
15 | self.assertEqual(24, instance.age, 'age incorrect')
16 | self.assertEqual('Adam', instance.name, 'name incorrect')
17 | instance.address = MagicMock(name='Address')
18 |
--------------------------------------------------------------------------------
/chapter15/mock_test6.py:
--------------------------------------------------------------------------------
1 | import people
2 |
3 | from unittest.mock import *
4 | from unittest import TestCase
5 | from unittest import main
6 |
7 |
8 | @patch('people.Person')
9 | class MyTest(TestCase):
10 |
11 | def test_one(self, MockPerson):
12 | self.assertIs(people.Person, MockPerson)
13 |
14 | def test_two(self, MockSomeClass):
15 | self.assertIs(people.Person, MockSomeClass)
16 |
17 | def do_something(self):
18 | return 'something'
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/chapter15/mock_test7.py:
--------------------------------------------------------------------------------
1 | import people
2 |
3 | from unittest.mock import *
4 | from unittest import TestCase
5 | from unittest import main
6 |
7 |
8 | class MyTest(TestCase):
9 |
10 | def test_one(self):
11 | with patch('people.Person') as MockPerson:
12 | self.assertIs(people.Person, MockPerson)
13 | instance = MockPerson.return_value
14 | instance.calculate_pay.return_value = 250.0
15 | payroll = people.Payroll()
16 | result = payroll.generate_payslip(instance)
17 | self.assertEqual('You earned 250.0', result, 'payslip incorrect')
--------------------------------------------------------------------------------
/chapter15/people.py:
--------------------------------------------------------------------------------
1 | class Person:
2 |
3 | def calculate_pay(self):
4 | return 0.0
5 |
6 |
7 | class Payroll:
8 |
9 | def generate_payslip(self, person):
10 | return 'You earned ' + str(person.calculate_pay())
11 |
--------------------------------------------------------------------------------
/chapter15/pytest-mock1.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest_mock import mocker
3 |
4 | import people
5 |
6 |
7 | @pytest.fixture
8 | def payroll():
9 | """ Returns a Payroll instance """
10 | print('Payroll fixture')
11 | return people.Payroll()
12 |
13 |
14 | def test_payroll(mocker, payroll):
15 | # Create a mock version of Person with default return result
16 | mocker.patch.object(people.Person, 'calculate_pay')
17 | people.Person.calculate_pay.return_value = 250.0
18 | result = payroll.generate_payslip(people.Person())
19 | # Verify that mock method was called
20 | people.Person.calculate_pay.assert_called()
21 | # Verify that the result from payroll was correct
22 | assert 'You earned 250.0' == result
23 |
--------------------------------------------------------------------------------
/chapter17/directories1.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | print('os.getcwd(:', os.getcwd())
4 | print('List contents of directory')
5 | print(os.listdir())
6 |
7 | print('Create mydir')
8 | os.mkdir('mydir')
9 | print('List the updated contents of directory')
10 | print(os.listdir())
11 |
12 | print('Change into mydir directory')
13 | os.chdir('mydir')
14 | print('os.getcwd(:', os.getcwd())
15 |
16 | print('Change back to parent directory')
17 | os.chdir('..')
18 | print('os.getcwd(:', os.getcwd())
19 |
20 | print('Remove mydir directory')
21 | os.rmdir('mydir')
22 | print('List the resulting contents of directory')
23 | print(os.listdir())
24 |
25 |
--------------------------------------------------------------------------------
/chapter17/exercise/create_file_with_date.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | print('Creating file')
4 | file = open('date_file.txt', 'w')
5 | print('Writing date information to file')
6 | todays_date = str(datetime.today())
7 | file.write(todays_date)
8 | print('closing file')
9 | file.close()
10 | print('Done')
11 |
12 |
13 |
--------------------------------------------------------------------------------
/chapter17/exercise/load_date_from_file.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | print('Opening file')
4 | file = open('date_file.txt', 'r')
5 | print('Reading contents)')
6 | lines = file.readlines()
7 | print('Accessing first line')
8 | date_str = lines[0]
9 | print('Date as a string:', date_str)
10 | datetime_object = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S.%f')
11 | print('Date as an object:', datetime_object)
12 |
13 | print('Done')
14 |
--------------------------------------------------------------------------------
/chapter17/files1.py:
--------------------------------------------------------------------------------
1 | file = open('myfile.txt', 'r+')
2 | print('file.name:', file.name)
3 | print('file.closed:', file.closed)
4 | print('file.mode:', file.mode)
5 | file.close()
6 | print('file.closed now:', file.closed)
--------------------------------------------------------------------------------
/chapter17/files2.py:
--------------------------------------------------------------------------------
1 | file = open('myfile.txt', 'r+')
2 |
3 | lines = file.readlines()
4 | for line in lines:
5 | print(line, end='')
6 |
7 | file.close()
8 |
--------------------------------------------------------------------------------
/chapter17/files3.py:
--------------------------------------------------------------------------------
1 | print('Writing file')
2 | f = open('my-new-file.txt', 'w')
3 | f.write('Hello from Python!!\n')
4 | f.write('Working with files is easy...\n')
5 | f.write('It is cool ...\n')
6 | f.close()
7 |
--------------------------------------------------------------------------------
/chapter17/files4.py:
--------------------------------------------------------------------------------
1 | import fileinput
2 |
3 | # Read multiple files
4 | with fileinput.input(files=('textfile1.txt', 'textfile2.txt')) as f:
5 | for line in f:
6 | print(line, end='')
7 | print()
8 |
9 | # Indicate some facilities
10 | with fileinput.input(files=('textfile1.txt', 'textfile2.txt')) as f:
11 | line = f.readline()
12 | print('f.filename():', f.filename())
13 | print('f.isfirstline():', f.isfirstline())
14 | print('f.lineno():', f.lineno())
15 | print('f.filelineno():', f.filelineno())
16 | for line in f:
17 | print(line, end='')
18 |
--------------------------------------------------------------------------------
/chapter17/files5.py:
--------------------------------------------------------------------------------
1 | # Alternative to reading lines from a file
2 | # A file object is iterable
3 |
4 | file = open('myfile.txt', 'r')
5 |
6 | for line in file:
7 | print(line, end='')
8 |
9 | file.close()
10 |
--------------------------------------------------------------------------------
/chapter17/my-new-file.txt:
--------------------------------------------------------------------------------
1 | Hello from Python!!
2 | Working with files is easy...
3 | It is cool ...
4 |
--------------------------------------------------------------------------------
/chapter17/myfile.txt:
--------------------------------------------------------------------------------
1 | This is a line from a file
2 | To be or not to be
3 |
--------------------------------------------------------------------------------
/chapter17/paths-app.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | print('Create Path object for current directory')
4 | p = Path('.')
5 | print('p:', p)
6 | print('p.exists():', p.exists())
7 | print('p.is_dir():', p.is_dir())
8 | print('p.is_file():', p.is_file())
9 | print('p.absolute():', p.absolute())
10 |
11 | print('-' * 10)
12 | for file in p.glob('*.txt'):
13 | print('file:', file)
14 | print('-' * 10)
15 |
16 | p = Path.cwd()
17 | print('Set up new directory')
18 | newdir = p / 'test'
19 | print('Check to see if newdir exists')
20 | print('newdir.exists():', newdir.exists())
21 | print('Create new dir')
22 | newdir.mkdir()
23 | print('newdir.exists():', newdir.exists())
24 |
25 | dir = Path('./test')
26 | print('Create new file')
27 | newfile = dir / 'text.txt'
28 | print('Write some text to file')
29 | newfile.write_text('Hello Python World!')
30 | print('Read the text back again')
31 | print(newfile.read_text())
32 |
33 | print('Remove the file')
34 | newfile.unlink()
35 | print('Remove the directory')
36 | newdir.rmdir()
--------------------------------------------------------------------------------
/chapter17/rand-file-acces.py:
--------------------------------------------------------------------------------
1 | f = open('text.txt', 'w')
2 | f.write('abcdefghijklmnopqrstuvwxyz\n')
3 |
4 | f.seek(10,0)
5 | f.write('HELLO')
6 | f.seek(6, 0)
7 | f.write ('BOO')
8 | f.close()
9 |
10 | with open('text.txt', 'r') as f:
11 | for line in f:
12 | print(line, end='')
13 |
--------------------------------------------------------------------------------
/chapter17/read-file-using-with.py:
--------------------------------------------------------------------------------
1 | # File type implements the Context Manager Protocol
2 | # can therefore use a file in a with as statement
3 |
4 | with open('myfile.txt', 'r') as f:
5 | lines = f.readlines()
6 | for line in lines:
7 | print(line, end='')
8 |
9 | print('Done')
10 |
--------------------------------------------------------------------------------
/chapter17/tempfiles1.py:
--------------------------------------------------------------------------------
1 | import tempfile
2 |
3 | print('tempfile.gettempdir():', tempfile.gettempdir())
4 |
5 | temp = tempfile.TemporaryFile('w+')
6 | print('temp.name:', temp.name)
7 | print('temp.mode:', temp.mode)
8 |
9 | temp.write('Hello world!')
10 | temp.seek(0)
11 | line = temp.readline()
12 | print('line:', line)
13 |
14 |
--------------------------------------------------------------------------------
/chapter17/text.txt:
--------------------------------------------------------------------------------
1 | abcdefBOOjHELLOpqrstuvwxyz
2 |
--------------------------------------------------------------------------------
/chapter17/textfile1.txt:
--------------------------------------------------------------------------------
1 | a
2 | b
3 | c
4 |
--------------------------------------------------------------------------------
/chapter17/textfile2.txt:
--------------------------------------------------------------------------------
1 | X
2 | Y
3 | Z
--------------------------------------------------------------------------------
/chapter17/textfileexample.py:
--------------------------------------------------------------------------------
1 | print('Writing file')
2 | f = open('python1', 'w')
3 | f.write('Hello from Python!!\n')
4 | f.write('Working with files is easy...\n')
5 | f.write('It is cool ...\n')
6 | f.close()
7 |
8 | print('Reading file')
9 | f = open('python1', 'r')
10 | line1 = f.readline()
11 | line2 = f.readline()
12 | line3 = f.readline()
13 | print('---')
14 | print(line1, end='')
15 | print(line2, end='')
16 | print(line3, end='')
17 |
18 | f = open('python1', 'r')
19 | i = 0
20 | for line in f:
21 | print(i, ':', line, end='')
22 | i = i + 1
23 | f.close()
24 |
25 | f = open('python1', 'r')
26 | l = [line.upper() for line in f]
27 | f.close()
28 | print(l)
29 |
30 | f = open('python1', 'r')
31 | try:
32 | for line in f:
33 | print(line, end='')
34 | finally:
35 | f.close()
36 |
37 | with open('python1', 'r') as f:
38 | for line in f:
39 | print(line, end='')
40 |
41 | print('RAM')
42 | f = open('python2', 'w')
43 | f.write('abcdefghijklmnopqrstuvwxyz\n');
44 | f.seek(10,0)
45 | f.write('HELLO')
46 | f.seek(6, 0)
47 | f.write ('BOO')
48 | f.close()
49 | with open('python2', 'r') as f:
50 | for line in f:
51 | print(line, end='')
52 |
--------------------------------------------------------------------------------
/chapter18/binary_streams.py:
--------------------------------------------------------------------------------
1 | import io, os
2 |
3 | print('In memory Binary Streams')
4 | binary_stream = io.BytesIO()
5 | print('binary_stream', binary_stream)
6 |
7 | # Binary data and strings are different types, so a str
8 | # must be encoded to binary using ascii, utf-8, or other.
9 | binary_stream.write("Hello, world!\n".encode('ascii'))
10 |
11 | # Move cursor back to the beginning of the buffer
12 | binary_stream.seek(0)
13 |
14 | # Read all data from the stream
15 | stream_data = binary_stream.read()
16 |
17 | # The stream_data is type 'bytes', immutable
18 | print(type(stream_data))
19 | print(stream_data)
20 |
21 | # To modify the actual contents of the existing buffer
22 | # use getbuffer() to get an object you can modify.
23 | # Modifying this object updates the underlying BytesIO buffer
24 | mutable_buffer = binary_stream.getbuffer()
25 | print(type(mutable_buffer)) # class 'memoryview'
26 | mutable_buffer[0] = 0xEF
27 |
28 | # Re-read the original stream. Contents will be modified
29 | # because we modified the mutable buffer
30 | binary_stream.seek(0)
31 | print(binary_stream.read())
32 |
33 | print('-' * 25)
34 |
35 | print('File based binary stream')
36 |
37 | # Binary IO aka Buffered IO
38 | binary_stream_from_file = io.BufferedReader(io.BytesIO(b'starship.png'))
39 | print('f3', binary_stream_from_file)
40 | print('f3.read()', binary_stream_from_file.read()) # Read the whole of the file
41 | file_length_in_bytes = os.path.getsize('starship.png')
42 | print('file_length_in_bytes', file_length_in_bytes)
43 | binary_stream_from_file.seek(0, 0) # Go to the start fo the file
44 | bytes = binary_stream_from_file.read(4)
45 | print(bytes)
46 |
47 |
48 |
--------------------------------------------------------------------------------
/chapter18/myfile.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter18/myfile.dat
--------------------------------------------------------------------------------
/chapter18/myfile.txt:
--------------------------------------------------------------------------------
1 | Hello Python World
--------------------------------------------------------------------------------
/chapter18/raw_io_example.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | f4 = io.FileIO('starship.png', mode='rb')
4 |
5 | print('f4', f4)
--------------------------------------------------------------------------------
/chapter18/sockets.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | raw = SocketIO(xxx, 'r')
4 | buffer = io.BufferedReader(raw, io.DEFAULT_BUFFER_SIZE)
5 |
--------------------------------------------------------------------------------
/chapter18/starship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter18/starship.png
--------------------------------------------------------------------------------
/chapter18/stdinout_examples.py:
--------------------------------------------------------------------------------
1 | # Standard IO streams
2 | import io, sys
3 |
4 | print(sys.stdin)
5 | print(sys.stdout)
6 | print(sys.stderr)
7 |
8 | print('-' *25)
9 |
10 | wrapper = io.TextIOWrapper(sys.stdout, line_buffering=True)
11 | wrapper.write('Hello World')
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/chapter18/streams_options.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | # Text stream
4 | f1 = open('myfile.txt', mode='r', encoding='utf-8')
5 | print(f1)
6 |
7 | # Binary IO aka Buffered IO
8 | f2 = open('myfile.dat', mode='rb')
9 | print(f2)
10 |
11 | f3 = open('myfile.dat', mode='wb')
12 | print(f3)
13 |
14 | # Raw IO aka Unbufferedf IO
15 | f4 = open('starship.png', mode='rb', buffering=0)
16 | print(f4)
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/chapter18/text_streams.py:
--------------------------------------------------------------------------------
1 | import io, os
2 |
3 | # In memory stream
4 | in_memory_text_stream = io.StringIO('to be or not to be that is the question')
5 | print('in_memory_text_stream', in_memory_text_stream)
6 | print(in_memory_text_stream.getvalue())
7 | in_memory_text_stream.close()
8 |
9 | print('-' * 25)
10 |
11 | print('File based text stream')
12 |
13 | f = io.FileIO('myfile.txt')
14 | br = io.BufferedReader(f)
15 | text_stream = io.TextIOWrapper(br, encoding='utf-8')
16 |
17 | print('text_stream', text_stream)
18 | print('text_stream.readable():', text_stream.readable())
19 | print('text_stream.seekable()', text_stream.seekable())
20 | print('text_stream.writeable()', text_stream.writable())
21 |
22 | print(text_stream.read())
23 |
24 | text_stream.close()
25 |
26 |
27 |
--------------------------------------------------------------------------------
/chapter19/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter19/__init__.py
--------------------------------------------------------------------------------
/chapter19/csvdictexample.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 |
4 | def main():
5 | print('Starting write of dict CSV example')
6 | with open('names.csv', 'w', newline='') as csvfile:
7 | fieldnames = ['first_name', 'last_name', 'result']
8 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
9 | writer.writeheader()
10 | writer.writerow({'first_name': 'John',
11 | 'last_name': 'Smith',
12 | 'result' : 54})
13 | writer.writerow({'first_name': 'Jane', 'last_name': 'Lewis', 'result' : 63})
14 | writer.writerow({'first_name': 'Chris', 'last_name': 'Davies', 'result' : 72})
15 |
16 | print('Starting to read dict CSV example')
17 | with open('names.csv', newline='') as csvfile:
18 | reader = csv.DictReader(csvfile)
19 | for heading in reader.fieldnames:
20 | print(heading, end=' ')
21 | print('\n------------------------------')
22 | for row in reader:
23 | print(row['first_name'], row['last_name'], row['result'])
24 | print('Done')
25 |
26 |
27 | if __name__ == '__main__':
28 | main()
--------------------------------------------------------------------------------
/chapter19/csvexample.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 |
4 | def main():
5 | print('Starting CSV Exmaple')
6 | print(csv.list_dialects())
7 |
8 | print('Creating CSV file')
9 | with open('sample.csv', 'w', newline='') as csvfile:
10 | writer = csv.writer(csvfile)
11 | writer.writerow(['She Loves You', 'Sept', 1963])
12 | writer.writerow(['I Want to Hold Your Hand', 'Dec', 1963])
13 | writer.writerow(['Cant Buy Me Love', 'Apr', 1964])
14 | writer.writerow(['A Hard Days Night', 'July', ' 1964'])
15 |
16 | print('-' * 100)
17 |
18 | print('Starting to read csv file')
19 | with open('sample.csv', newline='') as csvfile:
20 | reader = csv.reader(csvfile)
21 | # Process each row in the csv file
22 | for row in reader:
23 | row_length = len(row)
24 | print('row_length', row_length)
25 | if row_length != 3:
26 | print('Error in data (length is not 3):', row)
27 | print('In line:', reader.line_num)
28 | else:
29 | for i in range(row_length):
30 | # Each element in the row can be accessed via an index
31 | print(row[i], end=': ')
32 | print()
33 | try:
34 | year = int(row[2].strip())
35 | if year == 1964:
36 | print('What a great year', row[0])
37 | except ValueError as exp:
38 | print(exp)
39 | print("issue in row ", reader.line_num)
40 | print(row)
41 |
42 | print('Done Reading')
43 |
44 | if __name__ == '__main__':
45 | main()
--------------------------------------------------------------------------------
/chapter19/exercises/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter19/exercises/__init__.py
--------------------------------------------------------------------------------
/chapter19/exercises/fintech/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter19/exercises/fintech/__init__.py
--------------------------------------------------------------------------------
/chapter19/exercises/fintech/accounts.py:
--------------------------------------------------------------------------------
1 | from abc import ABCMeta
2 | from timeit import default_timer
3 |
4 |
5 | # Accounts module
6 |
7 |
8 | def timer(func):
9 | def inner(self, value):
10 | print('calling ', func.__name__, 'on', self, 'with', value)
11 | start = default_timer()
12 | func(self, value)
13 | end = default_timer()
14 | print('returned from ', func.__name__, 'it took', end - start, 'seconds')
15 |
16 | return inner
17 |
18 |
19 | class BalanceError(Exception):
20 | """ The Balance will be invalid """
21 |
22 | def __init__(self, account):
23 | self.account = account
24 |
25 |
26 | class AmountError(Exception):
27 |
28 | def __init__(self, account, msg):
29 | self.account = account
30 | self.message = msg
31 |
32 | def __str__(self):
33 | return 'AmountError (' + self.message + ') on ' + str(self.account)
34 |
35 |
36 | class Transaction:
37 | """ A Class used to represent an individual Transaction """
38 | def __init__(self, action, amount):
39 | self.action = action
40 | self.amount = amount
41 |
42 | def __str__(self):
43 | return 'Transaction[' + self.action + ': ' + str(self.amount) + ']'
44 |
45 |
46 | class Account(metaclass=ABCMeta):
47 | """" A class used to represent a type of account """
48 |
49 | instance_count = 0
50 |
51 | @classmethod
52 | def increment_instance_count(cls):
53 | print('Creating new Account')
54 | cls.instance_count += 1
55 |
56 | def __init__(self, account_number, account_holder, opening_balance, account_type):
57 | Account.increment_instance_count()
58 | self.account_number = account_number
59 | self.account_holder = account_holder
60 | self._balance = opening_balance
61 | self.type = account_type
62 | # Note need to initialise the history list before you try to add a Transaction
63 | self.history = []
64 | self._add_deposit_transaction(opening_balance)
65 |
66 | def __enter__(self):
67 | print('__enter__')
68 | return self
69 |
70 | def __exit__(self, *args):
71 | print('__exit__:', args)
72 | return True
73 |
74 | # Method called if attribute is unknown
75 | def __getattr__(self, attribute):
76 | print('__getattr__: unknown attribute accessed - ', attribute)
77 | return -1
78 |
79 | # Return the transaction hsitory as the iterable object for an Account
80 | # and any subclass of Account
81 | def __iter__(self):
82 | return iter(self.history)
83 |
84 | # Provide internal support for adding transactions
85 | # Note by convention methods starting with an '_' shoudl not be called
86 | # by clients of this class
87 | def _add_transaction(self, transaction):
88 | self.history.append(transaction)
89 |
90 | # These are convenience methods to make it easier to
91 | # record a deposit or withdrawal.
92 | def _add_deposit_transaction(self, amount):
93 | self._add_transaction(Transaction('deposit', amount))
94 |
95 | def _add_withdraw_transaction(self, amount):
96 | self._add_transaction(Transaction('withdraw', amount))
97 |
98 | @timer
99 | def deposit(self, amount):
100 | if amount < 0:
101 | print('You cannot deposit negative amounts')
102 | raise AmountError(account=self, msg='Cannot deposit negative amounts')
103 | else:
104 | self._balance += amount
105 | self._add_deposit_transaction(amount)
106 |
107 | @timer
108 | def withdraw(self, amount):
109 | if amount < 0:
110 | print('You cannot withdraw negative amounts')
111 | raise AmountError(self, 'Cannot withdraw negative amounts')
112 | else:
113 | self._balance -= amount
114 | self._add_withdraw_transaction(amount)
115 |
116 | @property
117 | def balance(self):
118 | """ Provides the current balance """
119 | return self._balance
120 |
121 | def __str__(self):
122 | return 'Account[' + self.account_number + '] - ' + \
123 | self.account_holder + ', ' + self.type + ' account = ' + str(self.balance)
124 |
125 |
126 | class CurrentAccount(Account):
127 |
128 | def __init__(self, account_number, account_holder, opening_balance, overdraft_limit):
129 | super().__init__(account_number, account_holder, opening_balance, 'current')
130 | self.overdraft_limit = -overdraft_limit
131 |
132 | @timer
133 | def withdraw(self, amount):
134 | if amount < 0:
135 | print('You cannot withdraw negative amounts')
136 | raise AmountError(self, 'Cannot withdraw negative amounts')
137 | elif self.balance - amount < self.overdraft_limit:
138 | print('Withdrawal would exceed your overdraft limit')
139 | raise BalanceError(self)
140 | else:
141 | self._balance -= amount
142 | self._add_withdraw_transaction(amount)
143 |
144 | def __str__(self):
145 | return super().__str__() + 'overdraft limit: ' + str(self.overdraft_limit)
146 |
147 |
148 | class DepositAccount(Account):
149 |
150 | def __init__(self, account_number, account_holder, opening_balance, interest_rate):
151 | super().__init__(account_number, account_holder, opening_balance, 'deposit')
152 | self.interest_rate = interest_rate
153 |
154 | def __str__(self):
155 | return super().__str__() + 'interest rate: ' + str(self.interest_rate)
156 |
157 |
158 | class InvestmentAccount(Account):
159 | def __init__(self, account_number, account_holder, opening_balance, investment_type):
160 | super().__init__(account_number, account_holder, opening_balance, 'investment')
161 | self.investment_type = investment_type
162 |
163 | def __str__(self):
164 | return super().__str__() + ', type: ' + self.type
165 |
--------------------------------------------------------------------------------
/chapter19/exercises/write_accounts_file.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import fintech.accounts as accounts
3 |
4 |
5 | def write_account_transaction_to_csv(filename, account):
6 | print('Starting write of dict CSV example')
7 | with open(filename, 'w', newline='') as csvfile:
8 | fieldnames = ['transaction_type', 'amount']
9 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
10 | writer.writeheader()
11 | # Write out the transactions
12 | for transaction in account.history:
13 | writer.writerow({'transaction_type': transaction.action,
14 | 'amount': transaction.amount})
15 |
16 |
17 | print('Starting')
18 | acc = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
19 | acc.deposit(23.45)
20 | acc.withdraw(12.33)
21 |
22 | print('Writing Account Transactions')
23 | write_account_transaction_to_csv('accounts.csv', acc)
24 |
25 | print('Done')
26 |
--------------------------------------------------------------------------------
/chapter19/names.csv:
--------------------------------------------------------------------------------
1 | first_name,last_name,result
2 | John,Smith,54
3 | Jane,Lewis,63
4 | Chris,Davies,72
5 |
--------------------------------------------------------------------------------
/chapter19/sample.csv:
--------------------------------------------------------------------------------
1 | She Loves You,Sept,1963
2 | I Want to Hold Your Hand,Dec,1963
3 | Cant Buy Me Love,Apr,1964
4 | A Hard Days Night,July, 1964
5 | Blahh,Apr,jjj
6 |
--------------------------------------------------------------------------------
/chapter2/rgb_colours.py:
--------------------------------------------------------------------------------
1 | """ Example illustrating create different colours using RGB codes """
2 |
3 | import wx
4 | import wx.grid
5 |
6 | MAX_ROWS = 25
7 |
8 | # Create the Application Object
9 | app = wx.App()
10 |
11 | # Now create a Frame (representing the window)
12 | frame = wx.Frame(parent=None, title='Colour Chart')
13 |
14 | # Set up grid to be used to display colours
15 | grid = wx.grid.Grid(frame, -1)
16 | grid.CreateGrid(MAX_ROWS, 5)
17 | grid.SetColSize(0, 140)
18 |
19 | # Set up the column headings
20 | grid.SetColLabelValue(0, 'RGB')
21 | grid.SetColLabelValue(1, 'Solid')
22 | grid.SetColLabelValue(2, '75%')
23 | grid.SetColLabelValue(3, '50%')
24 | grid.SetColLabelValue(4, '25%')
25 |
26 | red = 0
27 | green = 0
28 | blue = 0
29 | add_green = False
30 | add_blue = False
31 |
32 | # Generate RGB colours
33 | for i in range(0, MAX_ROWS):
34 | # Set the colour and text
35 | grid.SetCellValue(i, 0, 'RGB(' + str(red) + ', ' + str(green) + ', ' + str(blue) + ')')
36 | # Solid version of colour
37 | grid.SetCellBackgroundColour(i, 1, wx.Colour(red, green, blue))
38 | # Add a bit of transparency 75%, 50% and 25%
39 | grid.SetCellBackgroundColour(i, 2, wx.Colour(red, green, blue, alpha=191))
40 | grid.SetCellBackgroundColour(i, 3, wx.Colour(red, green, blue, alpha=127))
41 | grid.SetCellBackgroundColour(i, 4, wx.Colour(red, green, blue, alpha=64))
42 | # Reset RGB values
43 | red = red + 30
44 | if red > 255:
45 | red = 0
46 | add_green = True
47 | if add_green:
48 | green = green + 30
49 | if green > 255:
50 | green = 0
51 | red = 0
52 | add_blue = True
53 | if add_blue:
54 | blue = blue + 30
55 |
56 | # Run the GUI application
57 | frame.Show()
58 |
59 | # Start the event loop
60 | app.MainLoop()
61 |
--------------------------------------------------------------------------------
/chapter20/exercises/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter20/exercises/__init__.py
--------------------------------------------------------------------------------
/chapter20/exercises/accounts.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter20/exercises/accounts.xlsx
--------------------------------------------------------------------------------
/chapter20/exercises/fintech/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter20/exercises/fintech/__init__.py
--------------------------------------------------------------------------------
/chapter20/exercises/write_accounts_file.py:
--------------------------------------------------------------------------------
1 | from openpyxl import Workbook
2 | import fintech.accounts as accounts
3 |
4 |
5 | def write_account_transaction_to_excel(filename, account):
6 | print('Starting write of Excel example')
7 | workbook = Workbook()
8 | # Get the current active worksheet
9 | ws = workbook.active
10 | ws.title = 'transactions'
11 |
12 | ws['A1'] = 'transaction type'
13 | ws['B1'] = 'amount'
14 |
15 | row = 2
16 |
17 | # Write out the transactions
18 | for transaction in account.history:
19 | ws['A' + str(row)] = transaction.action
20 | ws['B' + str(row)] = transaction.amount
21 | row += 1
22 |
23 | workbook.save(filename)
24 |
25 | print('Done Write Excel Example')
26 |
27 |
28 | print('Starting')
29 | acc = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
30 | acc.deposit(23.45)
31 | acc.withdraw(12.33)
32 |
33 | print('Writing Account Transactions')
34 | write_account_transaction_to_excel('accounts.xlsx', acc)
35 |
36 | print('Done')
37 |
--------------------------------------------------------------------------------
/chapter20/readExcelExample.py:
--------------------------------------------------------------------------------
1 | """ Example illustrating reading EXCEL files using the
2 | openpyxl library. """
3 |
4 | from openpyxl import load_workbook
5 |
6 |
7 | def main():
8 | print('Starting reading Excel file using openPyXL')
9 |
10 | # data_only = True loads cached reuslt of equations
11 | # data_only = False load equations (default)
12 | workbook = load_workbook(filename='sample.xlsx', data_only=True)
13 | print(workbook.active)
14 | print(workbook.sheetnames)
15 | print(workbook.worksheets)
16 |
17 | # print('-' * 10)
18 | ws = workbook['my worksheet']
19 | # print(ws['A1'].value)
20 | # print(ws['B1'].value)
21 |
22 | # print('-' * 10)
23 | # for sheet in workbook:
24 | # print(sheet.title)
25 |
26 | print('-' * 10)
27 | # print(ws.max_column)
28 | # print(ws.max_row)
29 |
30 | cell_range = ws[ws.calculate_dimension()]
31 | for cell in cell_range:
32 | try:
33 | print(cell[0].value, end=", ")
34 | age = int(cell[1].value)
35 | if age > 18:
36 | print('You can drink')
37 | else:
38 | print('Underage')
39 | except ValueError:
40 | print('Error in age data')
41 | print(cell)
42 | print(cell[2].value, cell[3].value, cell[4].value)
43 |
44 | print('-' * 10)
45 |
46 | print('Finished reading Excel file using openPyXL')
47 |
48 |
49 | if __name__ == '__main__':
50 | main()
51 |
--------------------------------------------------------------------------------
/chapter20/sample.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter20/sample.xlsx
--------------------------------------------------------------------------------
/chapter20/sample2.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter20/sample2.xlsx
--------------------------------------------------------------------------------
/chapter20/writeExcelExample.py:
--------------------------------------------------------------------------------
1 | from openpyxl import Workbook
2 |
3 |
4 | print('Starting Write Excel Example with openPyXL')
5 |
6 | # Create an empty workbook
7 | workbook = Workbook()
8 | # Get the current active worksheet
9 | sheet = workbook.active
10 | sheet.title = 'dataset1'
11 | sheet.sheet_properties.tabColor = '0F45F7'
12 |
13 | sheet['A1'] = 'John'
14 | sheet['B1'] = 42
15 | sheet['C1'] = 56
16 | sheet['D1'] = '=SUM(B1,C1)/2'
17 | sheet['A2'] = 'Adam'
18 | sheet['B2'] = 75
19 | sheet['C2'] = 86
20 | sheet['D2'] = '=SUM(B2, C2)/2'
21 |
22 | sheet2 = workbook.create_sheet(title='dataset2')
23 | sheet2.append(['John', 1, 2, 3, '=SUM(B1,D1)/3'])
24 | sheet2.append(['Adam', 5, 7, 8])
25 |
26 | sheet2.cell(column=1, row=3, value='John')
27 | sheet2.cell(column=2, row=3, value=15)
28 |
29 |
30 | workbook.save('sample2.xlsx')
31 |
32 | print('Done Write Excel Example')
33 |
--------------------------------------------------------------------------------
/chapter21/exercises/regex_solutions.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 |
4 | # function to check string only contains letters and numbers
5 | def contains_only_characters_and_numbers(string):
6 | # Returns a match for any characters except those specified
7 | re_pattern = re.compile(r'[^a-zA-Z0-9]')
8 | # invert result as we are only interested in chars and numbers
9 | return not bool(re_pattern.search(string))
10 |
11 |
12 | print(contains_only_characters_and_numbers('John')) # True
13 | print(contains_only_characters_and_numbers('!John_Hunt')) # False
14 | print(contains_only_characters_and_numbers('42')) # True
15 | print(contains_only_characters_and_numbers('John42')) # True
16 | print(contains_only_characters_and_numbers('John 42')) # False
17 |
18 |
19 | # function to verify a UK postcode
20 | def verify_postcode(postcode):
21 | re_pattern = re.compile(r'[a-zA-z]{2}[0-9]{1,2} [0-9]{1,2}[a-zA-z]{2}')
22 | return bool(re_pattern.search(postcode))
23 |
24 |
25 | print("verify_postcode('SY23 3AA'):", verify_postcode('SY23 33AA')) # True
26 | print("verify_postcode('SY23 4ZZ'):", verify_postcode('SY23 4ZZ')) # True
27 | print("verify_postcode('BB1 3PO'):", verify_postcode('BB1 3PO')) # True
28 | print("verify_postcode('AA111 NN56'):", verify_postcode('AA111 NN56')) # False
29 | print("verify_postcode('AA1 56NN'):", verify_postcode('AA1 56NN')) # True
30 | print("verify_postcode('AA156NN'):", verify_postcode('AA156NN')) # False
31 | print("verify_postcode('AA NN'):", verify_postcode('AA NN')) # False
32 |
33 |
34 | # Function that will extract value held been start and end characters
35 | def extract_values(start_char, end_char, string):
36 | return re.findall(start_char + r'(.*?)' + end_char, string)
37 |
38 |
39 | print(extract_values('<', '>', ''))
40 | print(extract_values('<', '>', '<42>'))
41 | print(extract_values('<', '>', ''))
42 | print(extract_values('<', '>', 'The was in the '))
43 |
--------------------------------------------------------------------------------
/chapter21/regex_examples.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | s = 'Hello \n world'
4 | print(s)
5 |
6 | s = r'Hello \n world'
7 | print(s)
8 |
9 | text1 = 'john williams'
10 | pattern = '[Jj]ohn'
11 | print('looking in', text1, 'for the pattern', pattern)
12 | if re.search(pattern, text1, re.MULTILINE):
13 | print('Match has been found')
14 |
15 | line1 = 'The price is 23.55'
16 | containsIntegers = r'\d+'
17 | if re.search(containsIntegers, line1):
18 | print('Line 1 contains an integer')
19 | else:
20 | print('Line 1 does not contain an integer')
21 |
22 | rePattern = re.compile(containsIntegers)
23 | matchLine1 = rePattern.search(line1)
24 | if matchLine1:
25 | print('Line 1 contains a number')
26 | else:
27 | print('Line 1 does not contain a number')
28 |
29 | print('-' * 10)
30 |
31 | matchLine1 = re.search(containsIntegers, line1)
32 | if matchLine1:
33 | print('Line 1 contains a number')
34 | else:
35 | print('Line 1 does not contain a number')
36 |
37 | # Alternative words
38 | music = r'Beatles|Adele|Gorillaz'
39 | request = 'Play some Adele'
40 | if re.search(music, request):
41 | print('Set Fire to the Rain')
42 | else:
43 | print('No Adele Available')
44 |
45 | music2 = r'A (song|ballad|ditty) from (Paloma|Adele)'
46 | request = 'A ditty from Paloma'
47 | if re.search(music2, request):
48 | print('Only Love Can Hurt like this')
49 |
50 | line = 'root:*:0:0:System Administrator:/var/root:/bin/sh'
51 | rootUser = r'root:'
52 | if re.search(rootUser, line):
53 | print('Root')
54 | else:
55 | print('Not root')
56 |
57 | usesSh = r'/bin/sh$'
58 | if re.search(usesSh, line):
59 | print('sh')
60 | else:
61 | print('Some other shell')
62 |
63 | name = 'John Smith'
64 | nameRe = r'john'
65 | if re.search(nameRe, name, re.IGNORECASE):
66 | print('Match')
67 |
68 | sound = r'boink+'
69 | if re.search(sound, 'boink'):
70 | print('boink matches')
71 | if re.search(sound, 'boinkkkk'):
72 | print('boinkkkk matches')
73 |
74 | sound = r'(boink)+'
75 | if re.search(sound, 'boink'):
76 | print('boink matches')
77 | if re.search(sound, 'boinkboink'):
78 | print('boinkboink matches')
79 |
80 | inputStr = '123-44-7890'
81 | if re.search(r'\d{3}-\d{2,4}-\d{4,8}', inputStr):
82 | print('Input Matches')
83 | else:
84 | print('Input Does Not Match')
85 |
86 | components = r'(\D+)(\d+)(\D+)(\d+)'
87 | inputText = 'abcd123defg 456 '
88 | match_results = re.search(components, inputText)
89 | captureGroups = match_results.groups()
90 | for group in captureGroups:
91 | print(group, '; ', end='')
92 | print()
93 |
94 | p = re.compile(r'\W+')
95 | s = '20 High Street'
96 | print(p.split(s))
97 |
98 | pattern = '(England|Wales|Scotland)'
99 | input = 'England for football, Wales for Rugby and Scotland for the Highland games'
100 |
101 | print(re.sub(pattern, 'England', input))
102 | print(re.subn(pattern, 'Scotland', input))
103 | x = re.sub(pattern, 'Wales', input, 2)
104 | print(x)
105 |
106 | str = 'The rain in Spain stays mainly on the plain'
107 | results = re.findall('[a-zA-Z]{2}ai.', str)
108 | print(results)
109 | for s in results:
110 | print(s)
111 |
112 | str = 'It was a hot summer night'
113 | x = re.split('\s', str)
114 | print(x)
115 |
--------------------------------------------------------------------------------
/chapter24/connect_example.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | print('Open database connection')
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 | print('connection:', connection)
6 |
7 | print('prepare a cursor object using cursor() method')
8 | cursor = connection.cursor()
9 | print('cursor:', cursor)
10 |
11 | # ... perform database operations
12 |
13 | print('disconnect from database server')
14 | connection.close()
15 | print('Done')
--------------------------------------------------------------------------------
/chapter24/create5.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 | connection.autocommit(False)
6 |
7 | # prepare a cursor object using cursor() method
8 | cursor = connection.cursor()
9 |
10 | try:
11 | # Execute CREATE command
12 | cursor.execute("CREATE TABLE log (message VARCHAR(100) NOT NULL)")
13 |
14 | # Commit the changes to the database
15 | connection.commit()
16 | except:
17 | # rollback the changes if an exception / error
18 | connection.rollback()
19 |
20 | # Close the database connection
21 | connection.close()
22 |
--------------------------------------------------------------------------------
/chapter24/delete4.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 | connection.autocommit(False)
6 |
7 | # prepare a cursor object using cursor() method
8 | cursor = connection.cursor()
9 |
10 | try:
11 | # Execute DELETE command
12 | cursor.execute("DELETE FROM students WHERE id = 7")
13 |
14 | # Commit the changes to the database
15 | connection.commit()
16 | except:
17 | # rollback the changes if an exception / error
18 | connection.rollback()
19 |
20 | # Close the database connection
21 | connection.close()
22 |
--------------------------------------------------------------------------------
/chapter24/exercise/create_tables.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'accounts')
5 |
6 | # prepare a cursor object using cursor() method
7 | cursor = connection.cursor()
8 |
9 | try:
10 | # Execute CREATE command
11 | cursor.execute("CREATE TABLE acc_info (idacc_info INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY (idacc_info))")
12 | cursor.execute("CREATE TABLE transactions (idtransactions INT NOT NULL, type VARCHAR(45) NOT NULL, amount VARCHAR(45) NOT NULL, account INT NOT NULL, PRIMARY KEY (idtransactions))")
13 |
14 | # Commit the changes to the database
15 | connection.commit()
16 | except:
17 | # rollback the changes if an exception / error
18 | connection.rollback()
19 |
20 | # Close the database connection
21 | connection.close()
22 |
--------------------------------------------------------------------------------
/chapter24/exercise/fintech/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter24/exercise/fintech/__init__.py
--------------------------------------------------------------------------------
/chapter24/exercise/fintech/accounts.py:
--------------------------------------------------------------------------------
1 | from abc import ABCMeta
2 | # Accounts module
3 |
4 |
5 | class BalanceError(Exception):
6 | """ The Balance will be invalid """
7 |
8 | def __init__(self, account):
9 | self.account = account
10 |
11 |
12 | class AmountError(Exception):
13 |
14 | def __init__(self, account, msg):
15 | self.account = account
16 | self.message = msg
17 |
18 | def __str__(self):
19 | return 'AmountError (' + self.message + ') on ' + str(self.account)
20 |
21 |
22 | class Transaction:
23 | """ A Class used to represent an individual Transaction """
24 | def __init__(self, id, action, amount):
25 | self.id = id
26 | self.action = action
27 | self.amount = amount
28 |
29 | def __str__(self):
30 | return 'Transaction[' + self.id + " - " + self.action + ': ' + str(self.amount) + ']'
31 |
32 |
33 | class CurrentAccount(metaclass=ABCMeta):
34 | """" A class used to represent a type of account """
35 |
36 | @classmethod
37 | def increment_instance_count(cls):
38 | print('Creating new Account')
39 | cls.instance_count += 1
40 |
41 | def __init__(self, account_number, account_holder, opening_balance, overdraft_limit):
42 | self.account_number = account_number
43 | self.account_holder = account_holder
44 | self._balance = opening_balance
45 | self.overdraft_limit = -overdraft_limit
46 | # Note need to initialise the history list before you try to add a Transaction
47 | self.history = []
48 | self._add_deposit_transaction(opening_balance)
49 | self.transaction_count = 0
50 |
51 | def get_next_transaction_id(self):
52 | self.transaction += 1
53 | return self.transaction
54 |
55 | def __enter__(self):
56 | print('__enter__')
57 | return self
58 |
59 | def __exit__(self, *args):
60 | print('__exit__:', args)
61 | return True
62 |
63 | # Method called if attribute is unknown
64 | def __getattr__(self, attribute):
65 | print('__getattr__: unknown attribute accessed - ', attribute)
66 | return -1
67 |
68 | # Return the transaction hsitory as the iterable object for an Account
69 | # and any subclass of Account
70 | def __iter__(self):
71 | return iter(self.history)
72 |
73 | # Provide internal support for adding transactions
74 | # Note by convention methods starting with an '_' shoudl not be called
75 | # by clients of this class
76 | def _add_transaction(self, transaction):
77 | self.history.append(transaction)
78 |
79 | # These are convenience methods to make it easier to
80 | # record a deposit or withdrawal.
81 | def _add_deposit_transaction(self, amount):
82 | self._add_transaction(Transaction(self.get_next_transaction_id(), 'deposit', amount))
83 |
84 | def _add_withdraw_transaction(self, amount):
85 | self._add_transaction(Transaction(self.get_next_transaction_id(), 'withdraw', amount))
86 |
87 | def deposit(self, amount):
88 | if amount < 0:
89 | print('You cannot deposit negative amounts')
90 | raise AmountError(account=self, msg='Cannot deposit negative amounts')
91 | else:
92 | self._balance += amount
93 | self._add_deposit_transaction(amount)
94 |
95 | def withdraw(self, amount):
96 | if amount < 0:
97 | print('You cannot withdraw negative amounts')
98 | raise AmountError(self, 'Cannot withdraw negative amounts')
99 | elif self.balance - amount < self.overdraft_limit:
100 | print('Withdrawal would exceed your overdraft limit')
101 | raise BalanceError(self)
102 | else:
103 | self._balance -= amount
104 | self._add_withdraw_transaction(amount)
105 |
106 | @property
107 | def balance(self):
108 | """ Provides the current balance """
109 | return self._balance
110 |
111 | def __str__(self):
112 | return 'Account[' + self.account_number + '] - ' + \
113 | self.account_holder + ', account = ' + str(self.balance) + \
114 | 'overdraft limit: ' + str(self.overdraft_limit)
115 |
116 |
117 |
--------------------------------------------------------------------------------
/chapter24/exercise/write_account_info.py:
--------------------------------------------------------------------------------
1 | import fintech.accounts as accounts
2 | import pymysql
3 |
4 | def write_account_transaction_to_db(filename, account):
5 | print('Starting write of DB example')
6 |
7 | # Open database connection
8 | connection = pymysql.connect('localhost', 'user', 'password', 'accounts')
9 |
10 | # prepare a cursor object using cursor() method
11 | cursor = connection.cursor()
12 |
13 | try:
14 | # Execute INSERT command
15 | account_number = account.account_number
16 | name = account.account_holder
17 | cursor.execute(
18 | "INSERT INTO acc_info (idacc_info, name) " +
19 | "VALUES (" + account_number + ", '" + name + "')")
20 | # Commit the changes to the database
21 |
22 | # Write out the transactions
23 | for transaction in account.history:
24 | id = transaction.id
25 | action = transaction.action
26 | amount = transaction.amount
27 | statement = "INSERT into transactions (idtransactions, type, amount, account) VALUES (" + str(id) + ", '" + action + "', " + str(amount) + ", " + str(account_number) + ")"
28 | print(statement)
29 | cursor.execute(statement)
30 | connection.commit()
31 | except Exception as exp:
32 | # Something went wrong
33 | # rollback the changes
34 | print(exp)
35 | connection.rollback()
36 |
37 | # Close the database connection
38 | connection.close()
39 |
40 | print('Done Write DB Example')
41 |
42 |
43 |
44 | print('Starting')
45 | acc = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
46 | acc.deposit(23.45)
47 | acc.withdraw(12.33)
48 |
49 | print('Writing Account Transactions')
50 | write_account_transaction_to_db('accounts.xlsx', acc)
51 |
52 | print('Done')
53 |
54 |
55 |
--------------------------------------------------------------------------------
/chapter24/insert2.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 | connection.autocommit(False)
6 |
7 | # prepare a cursor object using cursor() method
8 | cursor = connection.cursor()
9 |
10 | try:
11 | # Execute INSERT command
12 | cursor.execute(
13 | "INSERT INTO students (id, name, surname, subject, email) VALUES (7, 'Denise', 'Byrne', 'History', 'db@my.com')")
14 | # Commit the changes to the database
15 | connection.commit()
16 | except:
17 | # Something went wrong
18 | # rollback the changes
19 | connection.rollback()
20 |
21 | # Close the database connection
22 | connection.close()
23 |
--------------------------------------------------------------------------------
/chapter24/mongo_examples.py:
--------------------------------------------------------------------------------
1 | import pymongo
2 |
3 | print('Establishing a connection')
4 | client = pymongo.MongoClient()
5 |
6 | print('Obtain bookshop database')
7 | db = client.bookshop
8 | print(db)
9 |
10 | print('Access the books collection')
11 | books = db.books
12 |
13 | print('Create a book "document"')
14 | book = {
15 | 'author': 'Adam Cooke',
16 | 'title': 'Python Is Great',
17 | 'price': 12.99
18 | }
19 |
20 | print('Insert book')
21 | result = books.insert_one(book)
22 | print('Inserted book with id:', result.inserted_id)
23 |
24 | print('Select a book')
25 | result = books.find_one({'author': 'Adam Cooke'})
26 | print(result)
27 |
28 | results = books.find({'author': 'Adam Cooke'})
29 | for book in results:
30 | print('book:', book)
31 |
32 | print('Deleting a document')
33 | result = books.delete_one({'author': 'Adam Cooke'})
34 | print('Deleted', result.deleted_count, 'books')
35 |
36 | print('Closing connection')
37 | client.close()
38 |
--------------------------------------------------------------------------------
/chapter24/query1.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 |
6 | # prepare a cursor object using cursor() method
7 | cursor = connection.cursor()
8 |
9 | # execute SQL query using execute() method.
10 | cursor.execute('SELECT * FROM students')
11 |
12 | print('cursor.rowcount', cursor.rowcount)
13 | print('cursor.description', cursor.description)
14 |
15 | # Fetch all the rows and then iterate over the data
16 | data = cursor.fetchall()
17 | for row in data:
18 | print('row:', row)
19 |
20 | # disconnect from server
21 | connection.close()
22 |
--------------------------------------------------------------------------------
/chapter24/query2.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 |
4 | class Student:
5 | def __init__(self, id, name, surname, subject, email):
6 | self.id = id
7 | self.name = name
8 | self.surname = surname
9 | self.subject = subject
10 | self.email = email
11 |
12 | def __str__(self):
13 | return 'Student[' + str(id) + '] ' + name + ' ' + surname + ' - ' + subject + ' ' + email
14 |
15 |
16 | # Open database connection
17 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
18 |
19 | # prepare a cursor object using cursor() method
20 | cursor = connection.cursor()
21 |
22 | # execute SQL query using execute() method.
23 | cursor.execute('SELECT * FROM students')
24 |
25 | # Fetch all the rows
26 | data = cursor.fetchall()
27 |
28 | # Convert data into Student objects
29 | for row in data:
30 | student_id, name, surname, subject, email = row
31 | student = Student(student_id, name, surname, subject, email)
32 | print(student)
33 |
34 | # disconnect from server
35 | connection.close()
36 |
--------------------------------------------------------------------------------
/chapter24/update3.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 |
3 | # Open database connection
4 | connection = pymysql.connect('localhost', 'user', 'password', 'uni-database')
5 | connection.autocommit(False)
6 |
7 | # prepare a cursor object using cursor() method
8 | cursor = connection.cursor()
9 |
10 | try:
11 | # Execute UPDATE command
12 | cursor.execute("UPDATE students SET email = 'denise@my.com' WHERE id = 7")
13 |
14 | # Commit the changes to the database
15 | connection.commit()
16 | except:
17 | # rollback the changes if an exception / error
18 | connection.rollback()
19 |
20 | # Close the database connection
21 | connection.close()
22 |
--------------------------------------------------------------------------------
/chapter26/exercises/accounts-app.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 | import yaml
4 | import fintech.accounts as accounts
5 |
6 | with open('accounts.logging.config.yaml', 'r') as f:
7 | config = yaml.safe_load(f.read())
8 | logging.config.dictConfig(config)
9 |
10 | logger = logging.getLogger()
11 |
12 | acc1 = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
13 | acc2 = accounts.DepositAccount('345', 'John', 23.55, 0.5)
14 | acc3 = accounts.InvestmentAccount('567', 'Phoebe', 12.45, 'high risk')
15 |
16 | logger.info(acc1)
17 | logger.info(acc2)
18 | logger.info(acc3)
19 |
20 | acc1.deposit(23.45)
21 | acc1.withdraw(12.33)
22 | logger.info('balance:', acc1.balance)
23 |
24 | logger.info('Number of Account instances created:', accounts.Account.instance_count)
25 |
26 | try:
27 | logger.info('balance:', acc1.balance)
28 | acc1.withdraw(300.00)
29 | logger.info('balance:', acc1.balance)
30 | except accounts.BalanceError as e:
31 | logger.error('Handling a Balance Exception')
32 | logger.exception(e)
33 |
34 | with accounts.CurrentAccount ('891', 'Adam', 5.0, 50.0) as acc:
35 | acc.deposit(23.0)
36 | acc.withdraw(12.50)
37 | logger.info(acc.balance)
38 |
39 | logger.info('acc1.branch:', acc1.branch)
40 |
41 | for transaction in acc1:
42 | logger.info(transaction)
43 |
44 | try:
45 | acc1.deposit(-1.0)
46 | except accounts.AmountError as e:
47 | logger.error('Exception following a deposit')
48 | logger.exception(e)
49 |
--------------------------------------------------------------------------------
/chapter26/exercises/accounts.logging.config.yaml:
--------------------------------------------------------------------------------
1 | version: 1
2 | formatters:
3 | myformatter:
4 | format: '%(asctime)s [%(levelname)s] %(name)s.%(funcName)s: %(message)s'
5 | handlers:
6 | console:
7 | class: logging.StreamHandler
8 | level: DEBUG
9 | formatter: myformatter
10 | stream: ext://sys.stdout
11 | loggers:
12 | fintech.accounts:
13 | level: DEBUG
14 | handlers: [console]
15 | propagate: no
16 | root:
17 | level: ERROR
18 | handlers: [console]
--------------------------------------------------------------------------------
/chapter26/exercises/fintech/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter26/exercises/fintech/__init__.py
--------------------------------------------------------------------------------
/chapter26/logging.config.yaml:
--------------------------------------------------------------------------------
1 | version: 1
2 | formatters:
3 | myformatter:
4 | format: '%(asctime)s [%(levelname)s] %(name)s.%(funcName)s: %(message)s'
5 | handlers:
6 | console:
7 | class: logging.StreamHandler
8 | level: DEBUG
9 | formatter: myformatter
10 | stream: ext://sys.stdout
11 | loggers:
12 | myLogger:
13 | level: DEBUG
14 | handlers: [console]
15 | propagate: no
16 | root:
17 | level: ERROR
18 | handlers: [console]
--------------------------------------------------------------------------------
/chapter26/logging_example.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import printer_lib
3 |
4 | logging.basicConfig(filename='example.log', format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
5 |
6 | logger = logging.getLogger(__name__)
7 | logger.setLevel(logging.DEBUG)
8 |
9 | def main():
10 | logger.warning('This is a warning!')
11 | logger.info('This is just for information')
12 | logger.debug('This is to help with debugging')
13 | logger.error('This should be used with something unexpected')
14 | logger.critical('Something serious')
15 |
16 | logger.warning('%s is set to %d', 'count', 42)
17 |
18 | try:
19 | x = 1 / 0
20 | print(x)
21 | except:
22 | logger.exception('an exception message')
23 |
24 | printer_lib.do_something()
25 |
26 | pr = printer_lib.Printer()
27 | pr.print_something()
28 |
29 |
30 | if __name__ == '__main__':
31 | main()
32 |
--------------------------------------------------------------------------------
/chapter26/logging_example1.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logging.basicConfig()
4 | logger = logging.getLogger()
5 |
6 | logger.info('This should be used with something unexpected')
7 |
--------------------------------------------------------------------------------
/chapter26/logging_example10.py:
--------------------------------------------------------------------------------
1 | # Filter example
2 |
3 | import logging
4 |
5 |
6 | # Define a filter subclass
7 | class MyFilter(logging.Filter):
8 |
9 | def filter(self, record):
10 | if 'John' in record.msg:
11 | return False
12 | else:
13 | return True
14 |
15 |
16 | logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
17 |
18 | # Set up the filter on the logger
19 | logger = logging.getLogger(__name__)
20 | logger.addFilter(MyFilter())
21 |
22 | # Application code with logging
23 | logger.debug('This is to help with debugging')
24 | logger.info('This is information on John')
25 |
--------------------------------------------------------------------------------
/chapter26/logging_example11.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 | import yaml
4 |
5 | with open('logging.config.yaml', 'r') as f:
6 | config = yaml.safe_load(f.read())
7 | logging.config.dictConfig(config)
8 |
9 | logger = logging.getLogger('myLogger')
10 |
11 |
12 | # 'application' code
13 | def do_something():
14 | logger.debug('debug message')
15 | logger.info('info message')
16 | logger.warning('warn message')
17 | logger.error('error message')
18 | logger.critical('critical message')
19 |
20 |
21 | logger.info('Starting')
22 | do_something()
23 | logger.info('Done')
24 |
--------------------------------------------------------------------------------
/chapter26/logging_example2.py:
--------------------------------------------------------------------------------
1 | # Setting the default format for log message output
2 |
3 | import logging
4 |
5 | logging.basicConfig(format='%(asctime)s - %(message)s')
6 |
7 | logger = logging.getLogger()
8 |
9 | logger.debug('This is to help with debugging')
10 | logger.error('This should be used with something unexpected')
11 | logger.critical('Something serious')
12 |
13 |
--------------------------------------------------------------------------------
/chapter26/logging_example3.py:
--------------------------------------------------------------------------------
1 | # Using the logger.exception() method
2 |
3 | import logging
4 |
5 | logger = logging.getLogger()
6 |
7 | try:
8 | print('starting')
9 | x = 1 / 0
10 | print(x)
11 | except:
12 | logger.exception('an exception message')
13 |
14 | print('Done')
15 |
--------------------------------------------------------------------------------
/chapter26/logging_example4.py:
--------------------------------------------------------------------------------
1 | # Root looger exmaple
2 |
3 | import logging
4 |
5 | # Set the root logger level
6 | logging.basicConfig(level=logging.DEBUG)
7 |
8 | # Use root (default) logger
9 | logging.debug('This is to help with debugging')
10 | logging.info('This is just for information')
11 | logging.warning('This is a warning!')
12 | logging.error('This should be used with something unexpected')
13 | logging.critical('Something serious')
14 |
15 |
--------------------------------------------------------------------------------
/chapter26/logging_example5.py:
--------------------------------------------------------------------------------
1 | # Accessing named loggers
2 |
3 | import logging
4 |
5 | logger = logging.getLogger()
6 | print('Root logger:', logger)
7 |
8 | logger1 = logging.getLogger('my logger')
9 | print('Named logger:', logger1)
10 |
11 | logger2 = logging.getLogger(__name__)
12 | print('Module logger:', logger2)
13 |
14 |
--------------------------------------------------------------------------------
/chapter26/logging_example6.py:
--------------------------------------------------------------------------------
1 | # Formatting examples
2 |
3 | import logging
4 |
5 | # Several different formatting options - try uncommenting different ones
6 | # logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
7 | # logging.basicConfig(format='%(asctime)s[%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
8 | logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.DEBUG)
9 |
10 | logger = logging.getLogger(__name__)
11 |
12 |
13 | def do_something():
14 | logger.debug('This is to help with debugging')
15 | logger.info('This is just for information')
16 | logger.warning('This is a warning!')
17 | logger.error('This should be used with something unexpected')
18 | logger.critical('Something serious')
19 |
20 |
21 | do_something()
22 |
--------------------------------------------------------------------------------
/chapter26/logging_example7.py:
--------------------------------------------------------------------------------
1 | # Example of logging to a file
2 |
3 | import logging
4 |
5 | # Sets a file handler ont he root logger to
6 | # save log messages to the example.log file
7 | logging.basicConfig(filename='example.log',level=logging.DEBUG)
8 |
9 | # If no handler is explicitly set on the name logger
10 | # it will delegate the messages to the parent logger to handle
11 | logger = logging.getLogger(__name__)
12 |
13 | logger.debug('This is to help with debugging')
14 | logger.info('This is just for information')
15 | logger.warning('This is a warning!')
16 | logger.error('This should be used with something unexpected')
17 | logger.critical('Something serious')
--------------------------------------------------------------------------------
/chapter26/logging_example8.py:
--------------------------------------------------------------------------------
1 | # Programmatically setting the handler
2 |
3 | import logging
4 |
5 | # Empty basic config turns off default console handler
6 | logging.basicConfig()
7 | logger = logging.getLogger(__name__)
8 | logger.setLevel(logging.DEBUG)
9 |
10 | # create file handler which logs to the specified file
11 | file_handler = logging.FileHandler('detailed.log')
12 |
13 | # Create formatter for the file_handler
14 | formatter = logging.Formatter('%(asctime)s - %(funcName)s - %(message)s')
15 | file_handler.setFormatter(formatter)
16 |
17 | logger.addHandler(file_handler)
18 |
19 |
20 | # 'application' code
21 | def do_something():
22 | logger.debug('debug message')
23 | logger.info('info message')
24 | logger.warning('warn message')
25 | logger.error('error message')
26 | logger.critical('critical message')
27 |
28 |
29 | logger.info('Starting')
30 | do_something()
31 | logger.info('Done')
32 |
33 |
--------------------------------------------------------------------------------
/chapter26/logging_example9.py:
--------------------------------------------------------------------------------
1 | # Multiple Handlers and formatters
2 | import logging
3 |
4 | # Set up the default root logger to do nothing
5 | logging.basicConfig(handlers=[logging.NullHandler()])
6 |
7 | # Obtain the module level logger and set level to DEBUG
8 | logger = logging.getLogger(__name__)
9 | logger.setLevel(logging.DEBUG)
10 |
11 | # Create file handler
12 | file_handler = logging.FileHandler('detailed.log')
13 |
14 | # Create console handler with a higher log level
15 | console_handler = logging.StreamHandler()
16 | console_handler.setLevel(logging.WARNING)
17 |
18 | # Create formatter for the file handler
19 | fh_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s.%(funcName)s: %(message)s',
20 | datefmt='%m-%d-%Y %I:%M:%S %p')
21 | file_handler.setFormatter(fh_formatter)
22 |
23 | # Create formatter for the console handler
24 | console_formatter = logging.Formatter('%(asctime)s - %(funcName)s - %(message)s')
25 | console_handler.setFormatter(console_formatter)
26 |
27 | # Add the handlers to logger
28 | logger.addHandler(console_handler)
29 | logger.addHandler(file_handler)
30 |
31 |
32 | # 'application' code
33 | def do_something():
34 | logger.debug('debug message')
35 | logger.info('info message')
36 | logger.warning('warn message')
37 | logger.error('error message')
38 | logger.critical('critical message')
39 |
40 |
41 | logger.info('Starting')
42 | do_something()
43 | logger.info('Done')
44 |
--------------------------------------------------------------------------------
/chapter26/printer_lib.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logger = logging.getLogger(__name__)
4 | logger.setLevel(logging.DEBUG)
5 |
6 | logger.warning('Well how about that then!')
7 |
8 |
9 | def do_something():
10 | logger.info('do something!')
11 |
12 |
13 | class Printer:
14 |
15 | def print_something(self):
16 | logger.info('print it')
17 | print('something')
18 |
--------------------------------------------------------------------------------
/chapter28/exercises/printer_threading_app.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 | from time import sleep
3 | from random import randint
4 |
5 |
6 | def printer(msg, max_sleep):
7 | for _ in range(0, 10):
8 | time_to_sleep = randint(1, max_sleep)
9 | sleep(time_to_sleep)
10 | print(msg, end='')
11 |
12 |
13 | t1 = Thread(target=printer, args=('A', 10))
14 | t2 = Thread(target=printer, args=('B', 5))
15 | t3 = Thread(target=printer, args=('C', 15))
16 | t4 = Thread(target=printer, args=('D', 7))
17 | t5 = Thread(target=printer, args=('E', 2))
18 |
19 | t1.start()
20 | t2.start()
21 | t3.start()
22 | t4.start()
23 | t5.start()
24 |
--------------------------------------------------------------------------------
/chapter28/threads.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 |
3 |
4 | def simple_worker():
5 | print('hello')
6 |
7 |
8 | # Create a new thread and start it
9 | # The thread will run the function simple_worker
10 | t1 = Thread(target=simple_worker)
11 | t1.start()
12 |
--------------------------------------------------------------------------------
/chapter28/threads1.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 |
3 |
4 | def simple_worker():
5 | print('hello')
6 |
7 |
8 | t1 = Thread(target=simple_worker)
9 | t1.start()
10 |
11 | # Get information about a Thread
12 | print(t1.getName())
13 | print(t1.ident)
14 | print(t1.is_alive())
15 |
--------------------------------------------------------------------------------
/chapter28/threads2.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 | from time import sleep
3 |
4 |
5 | def worker():
6 | for i in range(0, 10):
7 | print('.', end='', flush=True)
8 | sleep(1)
9 |
10 |
11 | print('Starting')
12 |
13 | # Create read object with reference to worker function
14 | t = Thread(target=worker)
15 | # Start the thread object
16 | t.start()
17 | # Wait for the thread to complete
18 | t.join()
19 |
20 | print('\nDone')
21 |
--------------------------------------------------------------------------------
/chapter28/threads3.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 | from time import sleep
3 |
4 |
5 | def worker(msg):
6 | for i in range(0, 10):
7 | print(msg, end='', flush=True)
8 | sleep(1)
9 |
10 |
11 | print('Starting')
12 | t1 = Thread(target=worker, args='A')
13 | t2 = Thread(target=worker, args='B')
14 | t3 = Thread(target=worker, args='C')
15 | t1.start()
16 | t2.start()
17 | t3.start()
18 | print('Done')
19 |
20 |
--------------------------------------------------------------------------------
/chapter28/threads4.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 | from time import sleep
3 |
4 | # Example extending the Thread class
5 |
6 | class WorkerThread(Thread):
7 | def __init__(self, daemon=None, target=None, name=None):
8 | super().__init__(daemon=daemon, target=target, name=name)
9 |
10 | def run(self):
11 | for i in range(0, 10):
12 | print('.', end='', flush=True)
13 | sleep(1)
14 |
15 |
16 | print('Starting')
17 | t = WorkerThread()
18 | t.start()
19 | print('\nDone')
20 |
--------------------------------------------------------------------------------
/chapter28/threads5.py:
--------------------------------------------------------------------------------
1 | from threading import Thread
2 | from time import sleep
3 |
4 |
5 | def worker(msg):
6 | for i in range(0, 10):
7 | print(msg, end='', flush=True)
8 | sleep(1)
9 |
10 | print('Starting')
11 |
12 | # Create a daemon thread
13 | d = Thread(daemon=True, target=worker, args='C')
14 | d.start()
15 |
16 | sleep(5)
17 | print('Done')
--------------------------------------------------------------------------------
/chapter28/threads6.py:
--------------------------------------------------------------------------------
1 | import threading
2 | from threading import Thread
3 | from time import sleep
4 |
5 |
6 | def worker(msg):
7 | for i in range(0, 10):
8 | print(msg, end='', flush=True)
9 | sleep(1)
10 |
11 | # Start two normal threads and a daemon thread
12 |
13 |
14 | t1 = Thread(name='worker', target=worker, args='A')
15 | t2 = Thread(target=worker, args='B') # use default name e.g. Thread-1
16 | d = Thread(daemon = True, name='daemon', target=worker, args='C')
17 |
18 | t1.start()
19 | t2.start()
20 | d.start()
21 |
22 | print()
23 | for t in threading.enumerate():
24 | print(t.getName())
25 |
--------------------------------------------------------------------------------
/chapter28/threads7.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, local, currentThread
2 | from random import randint
3 |
4 |
5 | def show_value(data):
6 | try:
7 | val = data.value
8 | except AttributeError:
9 | print(currentThread().name, ' - No value yet')
10 | else:
11 | print(currentThread().name, ' - value =', val)
12 |
13 |
14 | def worker(data):
15 | show_value(data)
16 | data.value = randint(1, 100)
17 | show_value(data)
18 |
19 |
20 | print(currentThread().name, ' - Starting')
21 |
22 | # Create thread local data object
23 | local_data = local()
24 | show_value(local_data)
25 |
26 | for i in range(2):
27 | t = Thread(name='W' + str(i),
28 | target=worker, args=[local_data])
29 | t.start()
30 |
31 | show_value(local_data)
32 | print(currentThread().name, ' - Done')
33 |
--------------------------------------------------------------------------------
/chapter28/timer_example.py:
--------------------------------------------------------------------------------
1 | from threading import Timer
2 |
3 |
4 | def hello():
5 | print("hello")
6 |
7 |
8 | print('Starting')
9 |
10 | # Set up timer to wait 5 seconds
11 | # and then run hello function
12 | t = Timer(5, hello)
13 | t.start()
14 |
15 | print('Done')
16 |
--------------------------------------------------------------------------------
/chapter29/exercises/multiprocessing_factorial.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Pool
2 |
3 |
4 | def factorial(num):
5 | if num == 0:
6 | return 1
7 | else:
8 | factorial_value = 1
9 | for i in range(1, num + 1):
10 | factorial_value = factorial_value * i
11 | return factorial_value
12 |
13 |
14 | data = (5, 8, 10, 15, 3, 6, 4)
15 |
16 | # Collect results into a list and print using pool.map
17 | with Pool(processes=4) as pool:
18 | results = pool.map(factorial, data)
19 | print(results)
20 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing1.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Process
2 | from time import sleep
3 |
4 |
5 | def worker(msg):
6 | for i in range(0, 10):
7 | print(msg, end='', flush=True)
8 | sleep(1)
9 |
10 |
11 | print('Starting')
12 |
13 | t2 = Process(target=worker, args='A')
14 | t3 = Process(target=worker, args='B')
15 | t4 = Process(target=worker, args='C')
16 |
17 | t2.start()
18 | t3.start()
19 | t4.start()
20 |
21 | print('Done')
22 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing2.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Process
2 | from multiprocessing import set_start_method
3 | from time import sleep
4 | import os
5 |
6 |
7 | def worker(msg):
8 | print('module name:', __name__)
9 | print('parent process:', os.getppid())
10 | print('process id:', os.getpid())
11 | for i in range(0, 10):
12 | print(msg, end='', flush=True)
13 | sleep(1)
14 |
15 |
16 | def main():
17 | print('Starting')
18 | print('Root application process id:', os.getpid())
19 | set_start_method('spawn')
20 | t = Process(target=worker, args='A')
21 | t.start()
22 |
23 | print('Done')
24 |
25 |
26 | if __name__ == '__main__':
27 | main()
28 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing3.py:
--------------------------------------------------------------------------------
1 | # Using a Pool
2 | from multiprocessing import Pool
3 |
4 |
5 | def worker(x):
6 | print('In worker with: ', x)
7 | return x * x
8 |
9 |
10 | def main():
11 | with Pool(processes=4) as pool:
12 | print(pool.map(worker, [0, 1, 2, 3, 4, 5]))
13 |
14 |
15 | if __name__ == '__main__':
16 | main()
17 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing4.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Pool
2 |
3 |
4 | def worker(x):
5 | print('In worker with: ', x)
6 | return x * x
7 |
8 |
9 | def main():
10 | with Pool(processes=4) as pool:
11 | for result in pool.imap_unordered(worker,
12 | [0, 1, 2, 3, 4, 5]):
13 | print(result)
14 |
15 |
16 | if __name__ == '__main__':
17 | main()
18 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing5.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Pool
2 |
3 |
4 | def collect_results(result):
5 | print('In collect_results: ', result)
6 |
7 |
8 | def worker(x):
9 | print('In worker with: ', x)
10 | return x * x
11 |
12 |
13 | def main():
14 | with Pool(processes=2) as pool:
15 | # get based example
16 | res = pool.apply_async(worker, [6])
17 | print('Result from async: ', res.get(timeout=1))
18 |
19 | with Pool(processes=2) as pool:
20 | # callback based example
21 | pool.apply_async(worker, args=[4],
22 | callback=collect_results)
23 |
24 |
25 | if __name__ == '__main__':
26 | main()
27 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing6.py:
--------------------------------------------------------------------------------
1 | # Using a pipe to communicate between two processes
2 |
3 | from multiprocessing import Process, Pipe
4 | from time import sleep
5 |
6 |
7 | def worker(conn):
8 | print('Worker - started now sleeping for 1 second')
9 | sleep(1)
10 | print('Worker - sending data via Pipe')
11 | conn.send('hello')
12 | print('Worker - closing worker end of connection')
13 | conn.close()
14 |
15 |
16 | def main():
17 | print('Main - Starting, creating the Pipe')
18 | main_connection, worker_connection = Pipe()
19 | print('Main - Setting up the process')
20 | p = Process(target=worker, args=[worker_connection])
21 | print('Main - Starting the process')
22 | p.start()
23 | print('Main - Wait for a response from the child process')
24 | print(main_connection.recv())
25 | print('Main - closing parent process end of connection')
26 | main_connection.close()
27 | print('Main - Done')
28 |
29 |
30 | if __name__ == '__main__':
31 | main()
32 |
--------------------------------------------------------------------------------
/chapter29/multiprocessing7.py:
--------------------------------------------------------------------------------
1 | # Using shared data between processes
2 |
3 | from multiprocessing import Process, Value, Array
4 |
5 |
6 | def worker(n, a):
7 | n.value = 3.1415927
8 | for i in range(len(a)):
9 | a[i] = -a[i]
10 |
11 |
12 | def main():
13 | print('Starting')
14 |
15 | num = Value('d', 0.0)
16 | arr = Array('i', range(10))
17 |
18 | p = Process(target=worker, args=(num, arr))
19 | p.start()
20 | p.join()
21 |
22 | print(num.value)
23 | print(*arr)
24 |
25 | print('Done')
26 |
27 |
28 | if __name__ == '__main__':
29 | main()
30 |
--------------------------------------------------------------------------------
/chapter3/coloured_shapes.py:
--------------------------------------------------------------------------------
1 | # Lets play with some colours
2 | import turtle
3 | from random import randint
4 |
5 |
6 | def get_input_angle():
7 | """ Obtain input from user and convert to an int"""
8 | message = 'Please provide an angle:'
9 | value_as_string = input(message)
10 | while not value_as_string.isnumeric():
11 | print('The input must be an integer!')
12 | value_as_string = input(message)
13 | return int(value_as_string)
14 |
15 |
16 | def generate_random_colour():
17 | """Generates an R,G,B values randomly in range
18 | 0 to 255 """
19 | r = randint(0, 255)
20 | g = randint(0, 255)
21 | b = randint(0, 255)
22 | return r, g, b
23 |
24 |
25 | print('Set up Screen')
26 | turtle.title('Colourful pattern')
27 | turtle.setup(640, 600)
28 | turtle.hideturtle()
29 | turtle.bgcolor('black') # Set the background colour of the screen
30 | turtle.colormode(255) # Indicates RGB numbers will be in the range 0 to 255
31 | turtle.speed(10)
32 |
33 | angle = get_input_angle()
34 |
35 | print('Start the drawing')
36 | for i in range(0, 200):
37 | turtle.color(generate_random_colour())
38 | turtle.forward(i)
39 | turtle.right(angle)
40 |
41 | print('Done')
42 | turtle.done()
43 |
--------------------------------------------------------------------------------
/chapter3/exercises/draw-hexagons.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 |
4 | # Function to draw a hexagon
5 | def hexagon():
6 | for _ in range(6):
7 | turtle.forward(50)
8 | turtle.left(60)
9 |
10 | print('Set up')
11 | # Setup window
12 | turtle.title('Hexagons')
13 | turtle.setup(400, 400, 0, 0)
14 | turtle.speed(10)
15 | turtle.hideturtle()
16 | turtle.pencolor('blue')
17 | turtle.tracer(300)
18 | turtle.penup()
19 | turtle.setposition(-30,50)
20 | turtle.pendown()
21 |
22 | print('Start to draw hexagons')
23 | # Draw six hexagons
24 | for _ in range(6):
25 | hexagon()
26 | turtle.forward(50)
27 | turtle.right(60)
28 |
29 | # Ensure that all the drawing is rendered
30 | turtle.update()
31 |
32 | print('Done')
33 | turtle.done()
34 |
--------------------------------------------------------------------------------
/chapter3/sample-window1.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | # set a title for your canvas window
4 | turtle.title('My Turtle Animation')
5 |
6 | # set up the screen size (in pixels)
7 | # set the starting point of the turtle (0, 0)
8 | turtle.setup(width=200, height=200, startx=0, starty=0)
9 |
10 | # sets the pen color to red
11 | turtle.pencolor('red')
12 |
13 | # Draw a square
14 | turtle.forward(50)
15 | turtle.right(90)
16 | turtle.forward(50)
17 | turtle.right(90)
18 | turtle.forward(50)
19 | turtle.right(90)
20 | turtle.forward(50)
21 | turtle.right(90)
22 |
23 | # Add this so that the window will close when clicked on
24 | turtle.exitonclick()
25 |
--------------------------------------------------------------------------------
/chapter3/sample-window2.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 |
4 | def setup():
5 | """ Provide the config for the screen """
6 | turtle.title('Multiple Squares Animation')
7 | turtle.setup(100, 100, 0, 0)
8 | turtle.hideturtle()
9 |
10 |
11 | def draw_square(size):
12 | """ Draw a square in the current direction """
13 | turtle.forward(size)
14 | turtle.right(90)
15 | turtle.forward(size)
16 | turtle.right(90)
17 | turtle.forward(size)
18 | turtle.right(90)
19 | turtle.forward(size)
20 |
21 |
22 | setup()
23 |
24 | for _ in range(0, 12):
25 | draw_square(50)
26 | # Rotate the starting direction
27 | turtle.right(120)
28 |
29 | # Add this so that the window will close when clicked on
30 | turtle.exitonclick()
31 |
--------------------------------------------------------------------------------
/chapter3/sample-window3.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | def draw_square(size):
4 | """ Function to draw a square """
5 | turtle.forward(size)
6 | turtle.right(90)
7 | turtle.forward(size)
8 | turtle.right(90)
9 | turtle.forward(size)
10 | turtle.right(90)
11 | turtle.forward(size)
12 |
13 |
14 | turtle.title('Filled Square Example')
15 | turtle.setup(100, 100, 0, 0)
16 | turtle.hideturtle()
17 |
18 | turtle.pencolor('red')
19 | turtle.fillcolor('yellow')
20 | turtle.begin_fill()
21 |
22 | draw_square(60)
23 |
24 | turtle.end_fill()
25 | turtle.done()
26 |
--------------------------------------------------------------------------------
/chapter3/sphere_example.py:
--------------------------------------------------------------------------------
1 | from OpenGL.GLUT import *
2 | from OpenGL.GL import *
3 |
4 |
5 | def display():
6 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
7 | glPushMatrix()
8 | glRotatef(20.0, 1.0, 0.0, 0.0)
9 | glPushMatrix()
10 | glTranslatef(-0.75, 0.5, 0.0)
11 | glRotatef(90.0, 1.0, 0.0, 0.0)
12 | glutSolidTorus(0.275, 0.85, 15, 15)
13 | glPopMatrix()
14 |
15 | glPushMatrix()
16 | glTranslatef(-0.75, -0.5, 0.0)
17 | glRotatef(270.0, 1.0, 0.0, 0.0)
18 | glutSolidCone(1.0, 2.0, 15, 15)
19 | glPopMatrix()
20 |
21 | glPopMatrix()
22 | glFlush()
23 |
24 |
25 | def reshape(w, h):
26 | glViewport(0, 0, w, h)
27 | glMatrixMode(GL_PROJECTION)
28 | glLoadIdentity()
29 | if w <= h:
30 | glOrtho(-2.5, 2.5, -2.5 * h / w,
31 | 2.5 * h / w, -10.0, 10.0)
32 | else:
33 | glOrtho(-2.5 * w / h,
34 | 2.5 * w / h, -2.5, 2.5, -10.0, 10.0)
35 | glMatrixMode(GL_MODELVIEW)
36 | glLoadIdentity()
37 |
38 |
39 | glutInit()
40 | glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH)
41 | glutInitWindowSize(500, 500)
42 | glutCreateWindow('Scene')
43 | glEnable(GL_LIGHTING)
44 | glEnable(GL_LIGHT0)
45 | glEnable(GL_DEPTH_TEST)
46 |
47 | glutReshapeFunc(reshape)
48 | glutDisplayFunc(display)
49 | glutMainLoop()
50 |
--------------------------------------------------------------------------------
/chapter30/barriers-app.py:
--------------------------------------------------------------------------------
1 | from threading import Barrier, Thread
2 | from time import sleep
3 | from random import randint
4 |
5 |
6 | def print_it(msg, barrier):
7 | print('print_it for:', msg)
8 | for i in range(0, 10):
9 | print(msg, end='', flush=True)
10 | sleep(1)
11 | sleep(randint(1, 6))
12 | print('Wait for barrier with:', msg)
13 | barrier.wait()
14 | print('Returning from print_it:', msg)
15 |
16 |
17 | def callback():
18 | print('\nCallback Executing')
19 |
20 |
21 | print('Main - Starting')
22 |
23 | barrier = Barrier(3, callback)
24 | t1 = Thread(target=print_it, args=('A', barrier))
25 | t2 = Thread(target=print_it, args=('B', barrier))
26 | t3 = Thread(target=print_it, args=('C', barrier))
27 | t1.start()
28 | t2.start()
29 | t3.start()
30 |
31 | print('Main - Done')
32 |
--------------------------------------------------------------------------------
/chapter30/barriers-app2.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Barrier, Process
2 | from time import sleep
3 | from random import randint
4 |
5 |
6 | def print_it(msg, barrier):
7 | print('print_it for:', msg)
8 | for i in range(0, 10):
9 | print(msg, end='', flush=True)
10 | sleep(1)
11 | sleep(randint(1, 6))
12 | print('Wait for barrier with:', msg)
13 | barrier.wait()
14 | print('Returning from print_it:', msg)
15 |
16 |
17 | def callback():
18 | print('\nCallback Executing')
19 |
20 |
21 | print('Main - Starting')
22 | barrier = Barrier(3, callback)
23 | t1 = Process(target=print_it, args=('A', barrier))
24 | t2 = Process(target=print_it, args=('B', barrier))
25 | t3 = Process(target=print_it, args=('C', barrier))
26 | t1.start()
27 | t2.start()
28 | t3.start()
29 | print('Main - Done')
30 |
--------------------------------------------------------------------------------
/chapter30/cond-app.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, Condition, currentThread
2 | from time import sleep
3 | from random import randint
4 |
5 | class DataResource:
6 |
7 | def __init__(self):
8 | print('DataResource - Initializing the empty data')
9 | self.data = None
10 | print('DataResource - Setting up the Condition object')
11 | self.condition = Condition()
12 |
13 | def consumer(self):
14 | """wait for the condition and use the resource"""
15 | print('DataResource - Starting consumer method in', currentThread().name)
16 | with self.condition:
17 | self.condition.wait()
18 | print('DataResource - Resource is available to', currentThread().name)
19 | print('DataResource - Data read in', currentThread().name, ':', self.data)
20 |
21 | def producer(self):
22 | """set up the resource to be used by the consumer"""
23 | print('DataResource - Starting producer method')
24 | with self.condition:
25 | print('DataResource - Producer setting data')
26 | self.data = randint(1, 100)
27 | print('DataResource - Producer notifying all waiting threads')
28 | self.condition.notifyAll()
29 |
30 |
31 | print('Main - Starting')
32 | print('Main - Creating the DataResource object')
33 | resource = DataResource()
34 |
35 | print('Main - Create the Consumer Threads')
36 | c1 = Thread(target=resource.consumer)
37 | c1.name = 'Consumer1'
38 | c2 = Thread(target=resource.consumer)
39 | c2.name = 'Consumer2'
40 | print('Main - Create the Producer Thread')
41 | p = Thread(target=resource.producer)
42 |
43 | print('Main - Starting consumer threads')
44 | c1.start()
45 | c2.start()
46 | sleep(1)
47 |
48 | print('Main - Starting producer thread')
49 | p.start()
50 |
51 | print('Main - Done')
52 |
--------------------------------------------------------------------------------
/chapter30/events-app.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Process, Event
2 | from time import sleep
3 |
4 |
5 | def wait_for_event(event):
6 | print('wait_for_event - Entered and waiting')
7 | event_is_set = event.wait()
8 | print('wait_for_event - Event is set: ', event_is_set)
9 |
10 |
11 | def set_event(event):
12 | print('set_event - Entered but about to sleep')
13 | sleep(5)
14 | print('set_event - Waking up and setting event')
15 | event.set()
16 | print('set_event - Event set')
17 |
18 |
19 | print('Starting')
20 |
21 | # Create the event object
22 | event = Event()
23 |
24 | # Start a Process to wait for the event notification
25 | p1 = Process(target=wait_for_event, args=[event])
26 | p1.start()
27 |
28 | # Set up a process to set the event
29 | p2 = Process(target=set_event, args=[event])
30 | p2.start()
31 |
32 | # Wait for the first process to complete
33 | p1.join()
34 |
35 | print('Done')
36 |
--------------------------------------------------------------------------------
/chapter30/events-app2.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, Event
2 | from time import sleep
3 |
4 |
5 | def wait_for_event(e):
6 | print('wait_for_event - entered and waiting')
7 | event_is_set = e.wait()
8 | print('wait_for_event - Event is set: ', event_is_set)
9 |
10 |
11 | def set_event(e):
12 | print('set_event - entered but about to sleep')
13 | sleep(5)
14 | print('set_event - Waking up and setting event')
15 | e.set()
16 | print('set_event - Event set')
17 |
18 |
19 | print('Starting')
20 | e = Event()
21 | t1 = Thread(target=wait_for_event, args=[e])
22 | t1.start()
23 | t2 = Thread(target=set_event, args=[e])
24 | t2.start()
25 | t1.join()
26 | print('Done')
--------------------------------------------------------------------------------
/chapter30/exercises/stack/Stack.py:
--------------------------------------------------------------------------------
1 | from threading import Condition
2 |
3 | class Stack:
4 |
5 | def __init__(self):
6 | self._list = [] # initial internal data
7 | # Set up condition to use to synchronise interactions
8 | self.condition = Condition()
9 |
10 | def push(self, element):
11 | with self.condition:
12 | self._list.append(element)
13 | self.condition.notify()
14 |
15 | def pop(self):
16 | with self.condition:
17 | self.condition.wait()
18 | return self._list.pop()
19 |
20 | def top(self):
21 | return self._list[self.length() - 1]
22 |
23 | def length(self):
24 | return len(self._list)
25 |
26 | def is_empty(self):
27 | return self.length() == 0
28 |
29 | def __str__(self):
30 | return 'Stack: ' + str(self._list)
31 |
32 |
--------------------------------------------------------------------------------
/chapter30/exercises/stack/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnehunt/advancedpython3/ed210f539c42fd14f01786274cbab39e74d1c1b9/chapter30/exercises/stack/__init__.py
--------------------------------------------------------------------------------
/chapter30/exercises/stack_multithreaded_app.py:
--------------------------------------------------------------------------------
1 | from stack.Stack import Stack
2 | from time import sleep
3 | from threading import Thread
4 |
5 |
6 | def producer(stack):
7 | for i in range(0, 6):
8 | data = 'Task' + str(i)
9 | print('Producer pushing:', data)
10 | stack.push(data)
11 | sleep(2)
12 |
13 |
14 | def consumer(label, stack):
15 | while True:
16 | print(label, 'stack.pop():', stack.pop())
17 |
18 |
19 | print('Create shared stack')
20 | stack = Stack()
21 | print('Stack:', stack)
22 |
23 | print('Creating and starting consumer threads')
24 | consumer1 = Thread(target=consumer, args=('Consumer1', stack))
25 | consumer2 = Thread(target=consumer, args=('Consumer2', stack))
26 | consumer3 = Thread(target=consumer, args=('Consumer3', stack))
27 | consumer1.start()
28 | consumer2.start()
29 | consumer3.start()
30 |
31 | print('Creating and starting producer thread')
32 | producer = Thread(target=producer, args=[stack])
33 | producer.start()
34 |
--------------------------------------------------------------------------------
/chapter30/locks-app.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, Lock
2 |
3 |
4 | class SharedData(object):
5 |
6 | def __init__(self):
7 | self.value = 0
8 | self.lock = Lock()
9 |
10 | def read_value(self):
11 | try:
12 | print('read_value Acquiring Lock')
13 | self.lock.acquire()
14 | return self.value
15 | finally:
16 | print('read_value releasing Lock')
17 | self.lock.release()
18 |
19 | def change_value(self):
20 | print('change_value acquiring lock')
21 | with self.lock:
22 | self.value = self.value + 1
23 | print('change_value lock released')
24 |
25 |
26 | shared_data = SharedData()
27 |
28 |
29 | def reader():
30 | while True:
31 | print(shared_data.read_value())
32 |
33 |
34 | def updater():
35 | while True:
36 | shared_data.change_value()
37 |
38 |
39 | print('Starting')
40 |
41 | t1 = Thread(target=reader)
42 | t2 = Thread(target=updater)
43 |
44 | t1.start()
45 | t2.start()
46 |
47 | print('Done')
48 |
--------------------------------------------------------------------------------
/chapter30/queue-example.py:
--------------------------------------------------------------------------------
1 | from multiprocessing import Process, Queue
2 | from time import sleep
3 |
4 |
5 | def worker(queue):
6 | print('Worker - going to sleep')
7 | sleep(2)
8 | print('Worker - woken up and putting data on queue')
9 | queue.put('Hello World')
10 |
11 |
12 | def main():
13 | print('Main - Starting')
14 | queue = Queue()
15 | p = Process(target=worker, args=[queue])
16 | print('Main - Starting the process')
17 | p.start()
18 | print('Main - waiting for data')
19 | print(queue.get())
20 | print('Main - Done')
21 |
22 |
23 | if __name__ == '__main__':
24 | main()
25 |
--------------------------------------------------------------------------------
/chapter30/semaphore-app.py:
--------------------------------------------------------------------------------
1 | from threading import Thread, Semaphore, currentThread
2 | from time import sleep
3 |
4 |
5 | def worker(semaphore):
6 | with semaphore:
7 | print(currentThread().getName() + " - entered")
8 | sleep(0.5)
9 | print(currentThread().getName() + " - exiting")
10 |
11 |
12 | print('MainThread - Starting')
13 |
14 | semaphore = Semaphore(2)
15 | for i in range(0, 5):
16 | thread = Thread(name='T' + str(i), target=worker, args=[semaphore])
17 | thread.start()
18 |
19 | print('MainThread - Done')
20 |
--------------------------------------------------------------------------------
/chapter31/exercises/factorial_future.py:
--------------------------------------------------------------------------------
1 | from concurrent.futures import ThreadPoolExecutor
2 | from time import sleep
3 |
4 |
5 | # Function to calculate factorials
6 | def factorial(num):
7 | if num == 0:
8 | return 1
9 | else:
10 | factorial_value = 1
11 | for i in range(1, num + 1):
12 | sleep(0.1)
13 | factorial_value = factorial_value * i
14 | return factorial_value
15 |
16 |
17 | # Function to print the result
18 | def print_future_result(future):
19 | print('In callback Future result: ', future.result())
20 |
21 |
22 | print('Started')
23 | data = [5, 7, 3, 6]
24 |
25 | pool = ThreadPoolExecutor(5)
26 | for v in data:
27 | future = pool.submit(factorial, v)
28 | future.add_done_callback(print_future_result)
29 |
30 | print('Done')
31 |
--------------------------------------------------------------------------------
/chapter31/future1.py:
--------------------------------------------------------------------------------
1 | from time import sleep
2 | from concurrent.futures import ThreadPoolExecutor
3 |
4 |
5 | # define function to be used with future
6 | def worker(msg):
7 | for i in range(0, 10):
8 | print(msg, end='', flush=True)
9 | sleep(1)
10 | return i
11 |
12 |
13 | print('Setting up the ThreadPoolExecutor')
14 | pool = ThreadPoolExecutor(1)
15 |
16 | # Submit the function ot the pool to run
17 | # concurrently - obtain a future from pool
18 | print('Submitting the worker to the pool')
19 | future = pool.submit(worker, 'A')
20 |
21 | print('Obtained a reference to the future object', future)
22 |
23 | # Obtain the result form the future - wait if necessary
24 | print('future.result():', future.result())
25 |
26 | print('Done')
27 |
--------------------------------------------------------------------------------
/chapter31/future2.py:
--------------------------------------------------------------------------------
1 | from time import sleep
2 | from concurrent.futures import ProcessPoolExecutor
3 |
4 |
5 | def worker(msg):
6 | for i in range(0, 10):
7 | print(msg, end='', flush=True)
8 | sleep(1)
9 | return i
10 |
11 |
12 | print('Setting up the ThreadPoolExecutor')
13 | pool = ProcessPoolExecutor(1)
14 |
15 | print('Submitting the worker to the pool')
16 | future = pool.submit(worker, 'A')
17 |
18 | print('Obtained a reference to the future object', future)
19 | print('future.result():', future.result())
20 | print('Done')
21 |
--------------------------------------------------------------------------------
/chapter31/future3.py:
--------------------------------------------------------------------------------
1 | # Multiple futures example
2 |
3 | from concurrent.futures import ThreadPoolExecutor
4 | from time import sleep
5 |
6 |
7 | def worker(msg):
8 | for i in range(0, 10):
9 | print(msg, end='', flush=True)
10 | sleep(1)
11 | return i
12 |
13 |
14 | print('Starting...')
15 | pool = ThreadPoolExecutor(3)
16 | future1 = pool.submit(worker, 'A')
17 | future2 = pool.submit(worker, 'B')
18 | future3 = pool.submit(worker, 'C')
19 | future4 = pool.submit(worker, 'D')
20 | print('\nfuture4.result():', future4.result())
21 | print('All Done')
22 |
--------------------------------------------------------------------------------
/chapter31/future4.py:
--------------------------------------------------------------------------------
1 | from concurrent.futures import ProcessPoolExecutor
2 | from time import sleep
3 |
4 |
5 | def worker(msg):
6 | for i in range(0,10):
7 | print(msg,end='', flush=True)
8 | sleep(1)
9 | return i
10 |
11 |
12 | print('Starting...')
13 | pool = ProcessPoolExecutor(3)
14 | future1 = pool.submit(worker, 'A')
15 | future2 = pool.submit(worker, 'B')
16 | future3 = pool.submit(worker, 'C')
17 | future4 = pool.submit(worker, 'D')
18 | print('\nfuture4.result():', future4.result())
19 | print('All Done')
--------------------------------------------------------------------------------
/chapter31/future5.py:
--------------------------------------------------------------------------------
1 | from concurrent.futures import ProcessPoolExecutor
2 | from concurrent.futures import wait
3 | from time import sleep
4 |
5 |
6 | def worker(msg):
7 | for i in range(0,10):
8 | print(msg,end='', flush=True)
9 | sleep(1)
10 | return i
11 |
12 |
13 | print('Starting...setting up pool')
14 | pool = ProcessPoolExecutor(3)
15 | futures = []
16 |
17 | print('Submitting futures')
18 | future1 = pool.submit(worker, 'A')
19 | futures.append(future1)
20 | future2 = pool.submit(worker, 'B')
21 | futures.append(future2)
22 | future3 = pool.submit(worker, 'C')
23 | futures.append(future3)
24 | future4 = pool.submit(worker, 'D')
25 | futures.append(future4)
26 |
27 | print('Waiting for futures to complete')
28 | wait(futures)
29 |
30 | print('\nAll Done')
31 |
--------------------------------------------------------------------------------
/chapter31/future6.py:
--------------------------------------------------------------------------------
1 | from concurrent.futures import ThreadPoolExecutor, as_completed
2 | from time import sleep
3 | from random import randint
4 |
5 |
6 | def is_even(n):
7 | print('Checking if', n , 'is even')
8 | sleep(randint(1, 5))
9 | return str(n) + ' ' + str(n % 2 == 0)
10 |
11 |
12 | print('Started')
13 | data = [1, 2, 3, 4, 5, 6]
14 |
15 | pool = ThreadPoolExecutor(5)
16 | futures = []
17 |
18 | for v in data:
19 | futures.append(pool.submit(is_even, v))
20 |
21 | for f in as_completed(futures):
22 | print(f.result())
23 |
24 | print('Done')
25 |
--------------------------------------------------------------------------------
/chapter31/future7.py:
--------------------------------------------------------------------------------
1 | from concurrent.futures import ThreadPoolExecutor
2 | from time import sleep
3 | from random import randint
4 |
5 |
6 | def is_even(n):
7 | print('Checking if', n, 'is even')
8 | sleep(randint(1, 5))
9 | return str(n) + ' ' + str(n % 2 == 0)
10 |
11 |
12 | def print_future_result(future):
13 | print('In callback Future result: ', future.result())
14 |
15 |
16 | print('Started')
17 | data = [1, 2, 3, 4, 5, 6]
18 |
19 | pool = ThreadPoolExecutor(5)
20 |
21 | for v in data:
22 | future = pool.submit(is_even, v)
23 | future.add_done_callback(print_future_result)
24 |
25 | print('Done')
26 |
--------------------------------------------------------------------------------
/chapter32/asyncioapp1.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import time
3 |
4 |
5 | async def do_something():
6 | print('do_something - will wait for worker')
7 | result = await worker()
8 | print('do_something - result:', result)
9 |
10 |
11 | async def worker():
12 | print('worker - will take some time')
13 | time.sleep(3)
14 | print('worker - done it')
15 | return 42
16 |
17 |
18 | def main():
19 | print('Main - Starting')
20 | asyncio.run(do_something())
21 | print('Main - Done')
22 |
23 |
24 | if __name__ == '__main__':
25 | main()
26 |
--------------------------------------------------------------------------------
/chapter32/asyncioapp2.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 |
4 | async def worker():
5 | print('worker - will take some time')
6 | await asyncio.sleep(1)
7 | print('worker - Done it')
8 | return 42
9 |
10 |
11 | def print_it(task):
12 | print('print_it result:', task.result())
13 |
14 |
15 | async def do_something():
16 | print('do_something - create task for worker')
17 | task = asyncio.create_task(worker())
18 |
19 | print('do_something - add a callback')
20 | task.add_done_callback(print_it)
21 |
22 | await task
23 |
24 | # Information on task
25 | print('do_something - task.cancelled():', task.cancelled())
26 | print('do_something - task.done():', task.done())
27 | print('do_something - task.result():', task.result())
28 | print('do_something - task.exception():', task.exception())
29 |
30 | print('do_something - finished')
31 |
32 |
33 | def main():
34 | print('Main - Starting')
35 | asyncio.run(do_something())
36 | print('Main - Done')
37 |
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/chapter32/asyncioapp3.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import random
3 |
4 |
5 | async def worker():
6 | print('Worker - will take some time')
7 | await asyncio.sleep(1)
8 | result = random.randint(1, 10)
9 | print('Worker - Done it')
10 | return result
11 |
12 |
13 | async def do_something():
14 | print('do_something - will wait for worker')
15 | # Run three calls to worker concurrently and collect results
16 | results = await asyncio.gather(worker(), worker(), worker())
17 | print('results from calls:', results)
18 |
19 |
20 | def main():
21 | print('Main - Starting')
22 | asyncio.run(do_something())
23 | print('Main - Done')
24 |
25 |
26 | if __name__ == '__main__':
27 | main()
28 |
--------------------------------------------------------------------------------
/chapter32/asyncioapp4.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import random
3 |
4 |
5 | async def worker(label):
6 | print('Worker - will take some time')
7 | await asyncio.sleep(1)
8 | result = random.randint(1, 10)
9 | print('Worker - Done it')
10 | return label + str(result)
11 |
12 |
13 | async def do_something():
14 | print('do_something - will wait for worker')
15 | # Run three calls to worker concurrently and collect results
16 | for async_func in asyncio.as_completed((worker('A'), worker('B'), worker('C'))):
17 | result = await async_func
18 | print('do_something - result:', result)
19 |
20 |
21 | def main():
22 | print('Main - Starting')
23 | asyncio.run(do_something())
24 | print('Main - Done')
25 |
26 |
27 | if __name__ == '__main__':
28 | main()
29 |
--------------------------------------------------------------------------------
/chapter32/exercises/async_factorial.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 |
4 | async def factorial(num):
5 | if num == 0:
6 | return 1
7 | else:
8 | factorial_value = 1
9 | for i in range(1, num + 1):
10 | await asyncio.sleep(0.1)
11 | factorial_value = factorial_value * i
12 | return factorial_value
13 |
14 |
15 | async def calculate_factorials(data):
16 | for async_func in asyncio.as_completed([factorial(v) for v in data]):
17 | result = await async_func
18 | print('calculate_factorials - result:', result)
19 |
20 |
21 | def main():
22 | print('Main - Starting')
23 | asyncio.run(calculate_factorials([5, 7, 3, 6]))
24 | print('Main - Done')
25 |
26 |
27 | if __name__ == '__main__':
28 | main()
29 |
--------------------------------------------------------------------------------
/chapter34/reactive1.py:
--------------------------------------------------------------------------------
1 | import rx
2 |
3 | print('Create the Observable object')
4 | # Create an observable using data in a list
5 | observable = rx.from_list([2, 3, 5, 7])
6 |
7 |
8 | class PrimeNumberObserver:
9 | """ An Observer class """
10 |
11 | def on_next(self, value):
12 | print('Object Received', value)
13 |
14 | def on_completed(self):
15 | print('Data Stream Completed')
16 |
17 | def on_error(self, error):
18 | print('Error Occurred', error)
19 |
20 |
21 | def prime_number_reporter(value):
22 | print('Function Received', value)
23 |
24 |
25 | print('Set up Observers / Subscribers')
26 |
27 | # Subscribe a lambda function
28 | observable.subscribe(lambda value: print('Lambda Received', value))
29 | # Subscribe a named function
30 | observable.subscribe(prime_number_reporter)
31 | # Subscribe an Observer object
32 | observable.subscribe(PrimeNumberObserver())
33 |
34 | # Use lambdas to set up all three functions
35 | observable.subscribe(
36 | on_next=lambda value: print('Received on_next', value),
37 | on_error=lambda exp: print('Error Occurred', exp),
38 | on_completed=lambda: print('Received completed notification')
39 | )
40 |
41 | print('Done')
42 |
--------------------------------------------------------------------------------
/chapter34/reactive2.py:
--------------------------------------------------------------------------------
1 | # A subscribers example
2 |
3 | import rx
4 | from rx.subjects import Subject
5 | from datetime import datetime
6 |
7 | # You can choose which of these to use
8 | # source = rx.from_([2, 3, 5, 7])
9 | # source = rx.from_iterable([2, 3, 5, 7])
10 | source = rx.from_list([2, 3, 5, 7])
11 |
12 |
13 | class TimeStampSubject(Subject):
14 | """ Class implementing a Subject """
15 |
16 | def on_next(self, value):
17 | print('Subject Received', value)
18 | super().on_next((value, datetime.now()))
19 |
20 | def on_completed(self):
21 | print('Data Stream Completed')
22 | super().on_completed()
23 |
24 | def on_error(self, error):
25 | print('In Subject - Error Occurred', error)
26 | super().on_error(error)
27 |
28 |
29 | def prime_number_reporter(value):
30 | print('Function Received', value)
31 |
32 |
33 | print('Set up')
34 |
35 | # Create the Subject
36 | subject = TimeStampSubject()
37 |
38 | # Set up subscribers for the subject
39 | subject.subscribe(prime_number_reporter)
40 | subject.subscribe(lambda value: print('Lambda Received', value))
41 | subject.subscribe(
42 | on_next = lambda value: print('Received on_next', value),
43 | on_error = lambda exp: print('Error Occurred', exp),
44 | on_completed = lambda: print('Received completed notification')
45 | )
46 |
47 | # Subscribe the Subject to the observable source
48 | source.subscribe(subject)
49 |
50 | print('Done')
51 |
--------------------------------------------------------------------------------
/chapter34/reactive3a.py:
--------------------------------------------------------------------------------
1 | import rx
2 |
3 | # Set up an observable
4 | observable = rx.from_list([2, 3, 5])
5 |
6 | # Subscribe three observers
7 | observable.subscribe(lambda v: print('Lambda1 Received', v))
8 | observable.subscribe(lambda v: print('Lambda2 Received', v))
9 | observable.subscribe(lambda v: print('Lambda3 Received', v))
10 |
--------------------------------------------------------------------------------
/chapter34/reactive3b.py:
--------------------------------------------------------------------------------
1 | import rx
2 | from rx.concurrency import NewThreadScheduler, ThreadPoolScheduler, ImmediateScheduler
3 |
4 | observable = rx.from_list([2, 3, 5])
5 |
6 | observable.subscribe(lambda v: print('Lambda1 Received', v), scheduler=ThreadPoolScheduler(3))
7 | observable.subscribe(lambda v: print('Lambda2 Received', v), scheduler=ImmediateScheduler())
8 | observable.subscribe(lambda v: print('Lambda3 Received', v), scheduler=NewThreadScheduler())
9 |
10 | # As the observable runs in a separate thread we need
11 | # to ensure that the main thread does not terminate
12 | input('Press enter to finish')
13 |
--------------------------------------------------------------------------------
/chapter34/reactive4.py:
--------------------------------------------------------------------------------
1 | # Example of a 'cold' Observable
2 | import rx
3 | from rx.concurrency import NewThreadScheduler
4 | import time
5 |
6 |
7 | def observer_function(value):
8 | time.sleep(1)
9 | print(value * value)
10 |
11 |
12 | rx.range(1, 100000, scheduler=NewThreadScheduler())\
13 | .subscribe(observer_function)
14 |
15 | # As the observable runs in a separate thread need
16 | # ensure that the main thread does not terminate
17 | input('Press enter to finish')
--------------------------------------------------------------------------------
/chapter35/exercises/stocks.py:
--------------------------------------------------------------------------------
1 | import rx
2 | from rx import operators as op
3 |
4 | def reporter(value):
5 | print(value)
6 |
7 | stocks = (('APPL', 12.45), ('IBM', 15.55), ('MSFT', 5.66), ('APPL', 13.33))
8 |
9 | # Select only APPL
10 | source = rx.from_list(stocks).pipe(
11 | op.filter(lambda stock: stock[0] == 'APPL')
12 | ).subscribe(reporter)
13 |
14 | print('-' * 25)
15 |
16 | # ALl stocks over 15.00
17 | source = rx.from_list(stocks).pipe(
18 | op.filter(lambda stock: stock[1] > 15.00)
19 | ).subscribe(reporter)
20 |
21 | print('-' * 25)
22 |
23 | # Find the average
24 | source = rx.from_list(stocks).pipe(
25 | op.map(lambda v: v[1]),
26 | op.average()
27 | ).subscribe(reporter)
28 |
29 | print('=' * 25)
30 |
31 |
32 | stocks2 = (('GOOG', 8.95), ('APPL', 7.65), ('APPL', 12.45), ('MSFT', 5.66), ('GOOG', 7.56), ('IBM', 12.76))
33 |
34 | source1 = rx.from_list(stocks)
35 | source2 = rx.from_list(stocks2)
36 |
37 | # Find the max
38 | rx.merge(source1, source2).pipe(
39 | op.map(lambda v: v[1]),
40 | op.max()
41 | ).subscribe(reporter)
42 |
43 | print('-' * 25)
44 |
45 | # Find the min
46 | rx.merge(source1, source2).pipe(
47 | op.map(lambda v: v[1]),
48 | op.min()
49 | ).subscribe(reporter)
50 |
51 | print('-' * 25)
52 |
53 | # Only publish unique values
54 | rx.merge(source1, source2).pipe(
55 | op.distinct()
56 | ).subscribe(reporter)
--------------------------------------------------------------------------------
/chapter35/reactive_ops1.py:
--------------------------------------------------------------------------------
1 | # Apply a transformation to a data source to convert
2 | # integers into strings
3 | import rx
4 | from rx import operators as op
5 |
6 | # Set up a source with a map function
7 | source = rx.from_list([2, 3, 5, 7]).pipe(
8 | op.map(lambda value: "'" + str(value) + "'")
9 | )
10 |
11 | # Subscribe a lambda function
12 | source.subscribe(lambda value: print('Lambda Received',
13 | value,
14 | ' is a string ',
15 | isinstance(value, str)))
16 |
--------------------------------------------------------------------------------
/chapter35/reactive_ops2.py:
--------------------------------------------------------------------------------
1 | # An example illustrating how to merge two data sources
2 | import rx
3 |
4 | # Set up two sources
5 | source1 = rx.from_list([2, 3, 5, 7])
6 | source2 = rx.from_list([10, 11, 12])
7 |
8 | # Use the merge function to create a single observable data stream
9 | rx.merge(source1, source2)\
10 | .subscribe(lambda v: print(v, end=','))
--------------------------------------------------------------------------------
/chapter35/reactive_ops3.py:
--------------------------------------------------------------------------------
1 | # Filter source for even numbers
2 | import rx
3 | from rx import operators as op
4 |
5 | # Set up a source with a filter
6 | source = rx.from_list([2, 3, 5, 7, 4, 9, 8]).pipe(
7 | op.filter(lambda value: value % 2 == 0)
8 | )
9 |
10 | # Subscribe a lambda function
11 | source.subscribe(lambda value: print('Lambda Received', value))
12 |
13 | # Use distinct to suppress duplicates
14 | source = rx.from_list([2, 3, 5, 2, 4, 3, 2]).pipe(
15 | op.distinct()
16 | )
17 |
18 | # Subscribe a lambda function
19 | source.subscribe(lambda value: print('Received', value))
--------------------------------------------------------------------------------
/chapter35/reactive_ops4.py:
--------------------------------------------------------------------------------
1 | # Example of summing all the values in a data stream
2 | import rx
3 | from rx import operators as op
4 |
5 | # Set up a source
6 | observable = rx.from_list([2, 3, 5, 7])
7 | # Apply sum function to initial source
8 | observable2 = observable.pipe(
9 | op.sum()
10 | )
11 | # Subscribe to the result generated by sum
12 | observable2.subscribe(lambda v: print(v))
13 |
14 | print('-' * 20)
15 |
16 | # Rolling or incremental sum
17 | rx.from_([2, 3, 5, 7]).pipe(
18 | op.scan(lambda subtotal, i: subtotal+i)
19 | ).subscribe(lambda v: print(v))
--------------------------------------------------------------------------------
/chapter35/reactive_ops5.py:
--------------------------------------------------------------------------------
1 | # Example of chaining operators together
2 | import rx
3 | from rx import operators as op
4 |
5 | # Set up a source with a filter and a map
6 | source = rx.from_list([2, 3, 5, 7, 4, 9, 8])
7 | pipe = source.pipe(
8 | op.filter(lambda value: value % 2 == 0),
9 | op.map(lambda value: "'" + str(value) + "'")
10 | )
11 |
12 | # Subscribe a lambda function
13 | pipe.subscribe(lambda value: print('Received', value))
14 |
--------------------------------------------------------------------------------
/chapter37/BasicTCPIPSocketServer.py:
--------------------------------------------------------------------------------
1 | import socket
2 |
3 |
4 | def main():
5 | # Setup names and offices
6 | addresses = {'JOHN': 'C45',
7 | 'DENISE': 'C44',
8 | 'PHOEBE': 'D52',
9 | 'ADAM': 'B23'}
10 |
11 | print('Starting Server')
12 | print('Create the socket')
13 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
14 |
15 | print('Bind the socket to the port')
16 | server_address = (socket.gethostname(), 8084)
17 | print('Starting up on', server_address)
18 | sock.bind(server_address)
19 |
20 | # specifies the number of connections
21 | # before refusing new connections.
22 | print('Listen for incoming connections')
23 | sock.listen(1)
24 | while True:
25 | print('Waiting for a connection')
26 | connection, client_address = sock.accept()
27 | try:
28 | print('Connection from', client_address)
29 | while True:
30 | data = connection.recv(1024).decode()
31 | print('Received: ', data)
32 | if data:
33 | key = str(data).upper()
34 | response = addresses[key]
35 | print('sending data back to the client: ',
36 | response)
37 | connection.sendall(response.encode())
38 | else:
39 | print('No more data from', client_address)
40 | break
41 | finally:
42 | connection.close()
43 |
44 |
45 | if __name__ == '__main__':
46 | main()
47 |
--------------------------------------------------------------------------------
/chapter37/BroadcastClient.py:
--------------------------------------------------------------------------------
1 | import socket
2 | import sys
3 |
4 | # Create a UDP socket - note use of socket.SOCK_DGRAM
5 | # Indicates braodcast datagram
6 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7 |
8 | # Set the server address
9 | server_address = ('localhost', 10000)
10 | message = b'This is the message. It will be repeated.'
11 |
12 | try:
13 |
14 | # Send data
15 | print('sending {!r}'.format(message))
16 | sent = sock.sendto(message, server_address)
17 |
18 | # Receive response
19 | print('waiting to receive')
20 | data, server = sock.recvfrom(4096)
21 | print('received {!r}'.format(data))
22 |
23 | finally:
24 | print('closing socket')
25 | sock.close()
26 |
--------------------------------------------------------------------------------
/chapter37/BroadcastServer.py:
--------------------------------------------------------------------------------
1 | import socket
2 | import sys
3 |
4 | # Create a UDP socket - note use of socket.SOCK_DGRAM
5 | # this indicaztes its a broadcast datagram socket not a TCP/IP socket
6 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7 |
8 | # Bind the socket to the port
9 | server_address = ('localhost', 10000)
10 | print('starting up on {} port {}'.format(*server_address))
11 | sock.bind(server_address)
12 |
13 | while True:
14 | print('\nwaiting to receive message')
15 | data, address = sock.recvfrom(4096)
16 |
17 | print('received {} bytes from {}'.format(
18 | len(data), address))
19 | print(data)
20 |
21 | if data:
22 | sent = sock.sendto(data, address)
23 | print('sent {} bytes back to {}'.format(
24 | sent, address))
25 |
--------------------------------------------------------------------------------
/chapter37/MyHttpServer.py:
--------------------------------------------------------------------------------
1 | from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
2 | from socketserver import ThreadingMixIn
3 | from datetime import datetime
4 |
5 |
6 | # class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
7 | # """Simple multi-threaded HTTP server """
8 | # pass
9 |
10 |
11 | class MyHttpRequestHandler(BaseHTTPRequestHandler):
12 | """Very simple request handler. Only supports GET."""
13 |
14 | def do_GET(self):
15 | print("do_GET() starting to process request")
16 | welcome_msg = 'Hello From Server at ' + str(datetime.today())
17 | byte_msg = bytes(welcome_msg, 'utf-8')
18 | self.send_response(200)
19 | self.send_header("Content-type", 'text/plain; charset-utf-8')
20 | self.send_header('Content-length', str(len(byte_msg)))
21 | self.end_headers()
22 | print('do_GET() replying with message')
23 | self.wfile.write(byte_msg)
24 |
25 |
26 | def main():
27 | print('Setting up server')
28 | server_address = ('localhost', 8080)
29 | httpd = ThreadingHTTPServer(server_address, MyHttpRequestHandler)
30 | print('Activating HTTP server')
31 | httpd.serve_forever()
32 |
33 |
34 | if __name__ == '__main__':
35 | main()
36 |
--------------------------------------------------------------------------------
/chapter37/MyTCPHandler.py:
--------------------------------------------------------------------------------
1 | import socketserver
2 |
3 |
4 | class MyTCPHandler(socketserver.BaseRequestHandler):
5 | """
6 | The RequestHandler class for the server.
7 | """
8 |
9 | def __init__(self, request, client_address, server):
10 | print('Setup names and offices')
11 | self.addresses = {'JOHN': 'C45',
12 | 'DENISE': 'C44',
13 | 'PHOEBE': 'D52',
14 | 'ADAM': 'B23'}
15 | super().__init__(request, client_address, server)
16 |
17 | def handle(self):
18 | print('In Handle')
19 | # self.request is the TCP socket connected to the client
20 | data = self.request.recv(1024).decode()
21 | print('data received:', data)
22 | key = str(data).upper()
23 | response = self.addresses[key]
24 | print('response:', response)
25 | # Send the result back to the client
26 | self.request.sendall(response.encode())
27 |
28 |
29 | def main():
30 | print('Setting up server')
31 | server_address = ('localhost', 8084)
32 | print('Creating server')
33 | server = socketserver.TCPServer(server_address,
34 | MyTCPHandler)
35 | print('Activating server')
36 | server.serve_forever()
37 |
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/chapter37/TCPIPSocketClient.py:
--------------------------------------------------------------------------------
1 | import socket
2 |
3 |
4 | def main():
5 | print('Starting Client')
6 | print('Create a TCP/IP socket')
7 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8 | print('Connect the socket to the server port')
9 | server_address = ('localhost', 8084)
10 | print('Connecting to: ', server_address)
11 | sock.connect(server_address)
12 | print('Connected to server')
13 | try:
14 | print('Send data')
15 | message = 'John'
16 | print('Sending: ', message)
17 | sock.send(message.encode())
18 | data = sock.recv(1024).decode()
19 | print('Received from server: ', data)
20 | finally:
21 | print('Closing socket')
22 | sock.close()
23 |
24 |
25 | if __name__ == '__main__':
26 | main()
27 |
--------------------------------------------------------------------------------
/chapter37/exercises/SimpleClient.py:
--------------------------------------------------------------------------------
1 | import socket
2 |
3 |
4 | def get_input():
5 | message = 'Please provide an input (Date, Time, DataAndTime or -1 to exit): '
6 | return input(message)
7 |
8 |
9 | def main():
10 | print('Starting Client')
11 | user_input = get_input()
12 | while user_input != '-1':
13 | try:
14 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15 | sock.connect(('localhost', 8080))
16 | print('Connected to server')
17 | print('Sending data')
18 | sock.send(user_input.encode())
19 | data = sock.recv(1024).decode()
20 | print('Received from server: ', data)
21 | finally:
22 | print('Closing socket')
23 | sock.close()
24 | user_input = get_input()
25 |
26 |
27 | if __name__ == '__main__':
28 | main()
29 |
--------------------------------------------------------------------------------
/chapter37/exercises/SimpleServer.py:
--------------------------------------------------------------------------------
1 | import socketserver
2 | from datetime import datetime, date
3 |
4 |
5 | class MyTCPHandler(socketserver.BaseRequestHandler):
6 |
7 | def handle(self):
8 | print('In Handle')
9 | # Obtain inpout data
10 | data = self.request.recv(1024).decode()
11 | print('data received:', data)
12 | request = str(data).upper()
13 | if request == 'DATE':
14 | response = str(date.today())
15 | elif request == 'TIME':
16 | now = datetime.now()
17 | response = now.strftime("%H:%M:%S")
18 | elif request == 'DATEANDTIME':
19 | response = str(datetime.today())
20 | else:
21 | response = 'UNKNOWN OPTION:' + request
22 |
23 | print('response:', response)
24 |
25 | # Send the result back to the client
26 | self.request.sendall(response.encode())
27 |
28 |
29 | def main():
30 | print('Starting')
31 | address = ('localhost', 8080)
32 | server = socketserver.ThreadingTCPServer(address,
33 | MyTCPHandler)
34 | print('Activating server')
35 | server.serve_forever()
36 |
37 |
38 | if __name__ == '__main__':
39 | main()
40 |
--------------------------------------------------------------------------------
/chapter38/hello_flask_world.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, jsonify
2 |
3 | # Initialise Flask
4 | app = Flask(__name__)
5 |
6 |
7 | # Create a mapping from URL to function
8 | @app.route('/hello', methods=['GET'])
9 | def welcome():
10 | return jsonify({'msg': 'Hello Flask World'})
11 |
12 |
13 | # Start up the web service
14 | app.run(debug=True)
15 |
--------------------------------------------------------------------------------
/chapter38/hello_flask_world2.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, jsonify, url_for
2 |
3 |
4 | def create_service():
5 | app = Flask(__name__)
6 |
7 | @app.route('/hello', methods=['GET'])
8 | def welcome():
9 | return jsonify({'msg': 'Hello Flask World'})
10 |
11 | with app.test_request_context():
12 | print(url_for('welcome'))
13 |
14 | return app
15 |
16 | if __name__ == '__main__':
17 | app = create_service()
18 | app.run(debug=True)
19 |
--------------------------------------------------------------------------------
/chapter39/bookshop_service1.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, jsonify, abort
2 |
3 |
4 | class Book:
5 | """ Represents a book in the bookshop"""
6 |
7 | def __init__(self, isbn, title, author, price):
8 | self.isbn = isbn
9 | self.title = title
10 | self.author = author
11 | self.price = price
12 |
13 | def __str__(self):
14 | return self.title + ' by ' + self.author + ' @ ' + str(self.price)
15 |
16 | def to_json(self):
17 | return {
18 | 'isbn': self.isbn,
19 | 'title': self.title,
20 | 'author': self.author,
21 | 'price': self.price
22 | }
23 |
24 |
25 | class Bookshop:
26 | """Represents the bookshop within the service"""
27 |
28 | def __init__(self, books):
29 | self.books = books
30 |
31 | def get(self, isbn):
32 | if isbn > len(self.books):
33 | abort(404)
34 | return list(filter(lambda b: b.isbn == isbn, self.books))[0]
35 |
36 | def add_book(self, book):
37 | self.books.append(book)
38 |
39 | def delete_book(self, isbn):
40 | self.books = list(filter(lambda b: b.isbn != isbn, self.books))
41 |
42 |
43 | # Global value used to hold the Bookshop object
44 | bookshop = Bookshop([Book(1, 'XML', 'Gryff Smith', 10.99),
45 | Book(2, 'Java', 'Phoebe Cooke', 12.99),
46 | Book(3, 'Scala', 'Adam Davies', 11.99),
47 | Book(4, 'Python', 'Jasmine Byrne', 15.99)])
48 |
49 |
50 | def configure_bookshop_service():
51 | """Configures the Flask Application Object
52 | for the bookshop service"""
53 | app = Flask(__name__)
54 |
55 | @app.route('/book/list', methods=['GET'])
56 | def get_books():
57 | return jsonify({'books': [b.to_json() for b in bookshop.books]})
58 |
59 | @app.route('/book/', methods=['GET'])
60 | def get_book(isbn):
61 | book = bookshop.get(isbn)
62 | return jsonify({'book': book.to_json()})
63 |
64 | return app
65 |
66 |
67 | if __name__ == '__main__':
68 | app = configure_bookshop_service()
69 | app.run(debug=True)
70 |
--------------------------------------------------------------------------------
/chapter39/bookshop_service2.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, jsonify, request, abort, make_response
2 |
3 | from flask.json import JSONEncoder
4 |
5 |
6 | class Book:
7 | def __init__(self, isbn, title, author, price):
8 | self.isbn = isbn
9 | self.title = title
10 | self.author = author
11 | self.price = price
12 |
13 | def __str__(self):
14 | return self.title + ' by ' + self.author + ' @ ' + str(self.price)
15 |
16 |
17 | class BookJSONEncoder(JSONEncoder):
18 | def default(self, obj):
19 | if isinstance(obj, Book):
20 | return {
21 | 'isbn': obj.isbn,
22 | 'title': obj.title,
23 | 'author': obj.author,
24 | 'price': obj.price
25 | }
26 | else:
27 | return super(BookJSONEncoder, self).default(obj)
28 |
29 |
30 | class Bookshop:
31 | def __init__(self, books):
32 | self.books = books
33 |
34 | def get(self, isbn):
35 | if int(isbn) > len(self.books):
36 | abort(404)
37 | return list(filter(lambda b: b.isbn == isbn, self.books))[0]
38 |
39 | def add_book(self, book):
40 | self.books.append(book)
41 |
42 | def delete_book(self, isbn):
43 | self.books = list(filter(lambda b: b.isbn != isbn, self.books))
44 |
45 |
46 | bookshop = Bookshop([Book(1, 'XML', 'Gryff Smith', 10.99),
47 | Book(2, 'Java', 'Phoebe Cooke', 12.99),
48 | Book(3, 'Scala', 'Adam Davies', 11.99),
49 | Book(4, 'Python', 'Jasmine Byrne', 15.99)])
50 |
51 | def create_bookshop_service():
52 | app = Flask(__name__)
53 | app.json_encoder = BookJSONEncoder
54 |
55 |
56 | @app.route('/book/list', methods=['GET'])
57 | def get_books():
58 | return jsonify({'books': bookshop.books})
59 |
60 |
61 | @app.route('/book/', methods=['GET'])
62 | def get_book(isbn):
63 | book = bookshop.get(isbn)
64 | return jsonify({'book': book})
65 |
66 |
67 | @app.route('/book', methods=['POST'])
68 | def create_book():
69 | print('create book')
70 | if not request.json or not 'isbn' in request.json:
71 | abort(400)
72 | book = Book(request.json['isbn'],
73 | request.json['title'],
74 | request.json.get('author', ""),
75 | float(request.json['price']))
76 | bookshop.add_book(book)
77 | return jsonify({'book': book}), 201
78 |
79 |
80 | @app.route('/book', methods=['PUT'])
81 | def update_book():
82 | if not request.json or not 'isbn' in request.json:
83 | abort(400)
84 | isbn = request.json['isbn']
85 | book = bookshop.get(isbn)
86 | book.title = request.json['title']
87 | book.author = request.json['author']
88 | book.price = request.json['price']
89 | return jsonify({'book': book}), 201
90 |
91 |
92 | @app.route('/book/', methods=['DELETE'])
93 | def delete_book(isbn):
94 | bookshop.delete_book(isbn)
95 | return jsonify({'result': True})
96 |
97 |
98 | @app.errorhandler(400)
99 | def not_found(error):
100 | return make_response(jsonify({'book': 'Not found'}), 400)
101 |
102 | return app
103 |
104 | if __name__ == '__main__':
105 | app = create_bookshop_service()
106 | app.run(debug=True)
107 |
--------------------------------------------------------------------------------
/chapter39/bookshop_service3.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, jsonify, request, abort, make_response
2 | from flask.json import JSONEncoder
3 | import pymysql
4 |
5 | class Room:
6 | def __init__(self, id, name, description):
7 | self.id = id
8 | self.name = name
9 | self.description = description
10 |
11 | def __str__(self):
12 | return self.id + ' ' + self.name + ' ( ' + self.description + ')'
13 |
14 |
15 | class BookJSONEncoder(JSONEncoder):
16 | def default(self, obj):
17 | if isinstance(obj, Room):
18 | return {
19 | 'id': obj.id,
20 | 'name': obj.name,
21 | 'description': obj.description
22 | }
23 | else:
24 | return super(BookJSONEncoder, self).default(obj)
25 |
26 |
27 | class RoomService:
28 | def __init__(self, rooms=[]):
29 | self.rooms = rooms
30 |
31 | def get(self, id):
32 | if int(id) > len(self.rooms):
33 | abort(404)
34 | return list(filter(lambda b: b.isbn == id, self.rooms))[0]
35 |
36 | def add_room(self, room):
37 | self.rooms.append(room)
38 |
39 | def delete_room(self, id):
40 | self.rooms = list(filter(lambda b: b.isbn != id, self.rooms))
41 |
42 |
43 | room_service = RoomService()
44 | connection = None
45 |
46 |
47 | def setup_database_connection():
48 | global connection
49 | # Open database connection
50 | connection = pymysql.connect('localhost', 'user', 'user123', 'room_monitoring')
51 |
52 |
53 | def load_rooms_from_db():
54 | # prepare a cursor object using cursor() method
55 | cursor = connection.cursor()
56 | # execute SQL query using execute() method.
57 | cursor.execute('SELECT * FROM rooms')
58 |
59 | data = cursor.fetchall()
60 | for row in data:
61 | print(row)
62 | room_service.add_room(Room(int(row[0]), row[1], row[2]))
63 |
64 | # disconnect from server
65 | connection.close()
66 |
67 |
68 | def update_room_in_db(room):
69 | # prepare a cursor object using cursor() method
70 | connection.autocommit(False)
71 | cursor = connection.cursor()
72 | try:
73 | update_string = "UPDATE rooms "
74 | update_string = update_string + "SET name = '" + str(room.name) + "' "
75 | update_string = update_string + "SET description = '" + str(room.description) + "' "
76 | update_string = update_string + "WHERE id = " + str(room.id)
77 | cursor.execute(update_string)
78 | connection.commit()
79 | except:
80 | # Something went wrong
81 | # rollback the changes
82 | connection.rollback()
83 |
84 |
85 | def save_room_in_db(room):
86 | # prepare a cursor object using cursor() method
87 | connection.autocommit(False)
88 | cursor = connection.cursor()
89 | try:
90 | insert_string = "INSERT INTO rooms (id, name, description) VALUES ("
91 | insert_string = insert_string + "'" + str(room.id) + "', "
92 | insert_string = insert_string + "'" + str(room.name) + "', "
93 | insert_string = insert_string + "'" + str(room.description) + "')"
94 | cursor.execute(insert_string)
95 | connection.commit()
96 | except:
97 | # Something went wrong
98 | # rollback the changes
99 | connection.rollback()
100 |
101 |
102 | def delete_room_in_db(room):
103 | connection.autocommit(False)
104 | cursor = connection.cursor()
105 | try:
106 | delete_string = "DELETE FROM students WHERE id = " + str(room.id)
107 | cursor.execute(delete_string)
108 | connection.commit()
109 | except:
110 | # Something went wrong
111 | # rollback the changes
112 | connection.rollback()
113 |
114 |
115 | def create_rooms_service():
116 | app = Flask(__name__)
117 | app.json_encoder = BookJSONEncoder
118 |
119 |
120 | @app.route('/room/list', methods=['GET'])
121 | def get_rooms():
122 | return jsonify({'rooms': room_service.rooms})
123 |
124 |
125 | @app.route('/room/', methods=['GET'])
126 | def get_room(isbn):
127 | room = room_service.get(isbn)
128 | return jsonify({'room': room})
129 |
130 |
131 | @app.route('/room', methods=['POST'])
132 | def create_room():
133 | print('create room')
134 | if not request.json or not 'id' in request.json:
135 | abort(400)
136 | room = Room(request.json['id'],
137 | request.json['name'],
138 | request.json.get('description', ""))
139 | # Add the room the cache
140 | room_service.add_room(room)
141 | # Permanently save it to the database
142 | save_room_in_db(room)
143 | return jsonify({'room': room}), 201
144 |
145 |
146 | @app.route('/room', methods=['PUT'])
147 | def update_room():
148 | if not request.json or not 'id' in request.json:
149 | abort(400)
150 | id = request.json['id']
151 | room = room_service.get(id)
152 | room.title = request.json['name']
153 | room.author = request.json['description']
154 | update_room(room)
155 | return jsonify({'room': room}), 201
156 |
157 |
158 | @app.route('/room/', methods=['DELETE'])
159 | def delete_room(id):
160 | delete_room(room_service.get(id))
161 | room_service.delete_room(id)
162 | return jsonify({'result': True})
163 |
164 |
165 | @app.errorhandler(400)
166 | def not_found(error):
167 | return make_response(jsonify({'room': 'Not found'}), 400)
168 |
169 | return app
170 |
171 |
172 | if __name__ == '__main__':
173 | setup_database_connection()
174 | load_rooms_from_db()
175 | app = create_rooms_service()
176 | app.run(debug=True)
177 |
--------------------------------------------------------------------------------
/chapter39/image_service4.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from flask import Flask, jsonify, request, send_from_directory, make_response
4 | from werkzeug.utils import secure_filename
5 |
6 | PROJECT_HOME = os.path.dirname(os.path.realpath(__file__))
7 | UPLOAD_FOLDER = '{}/uploads/'.format(PROJECT_HOME)
8 |
9 |
10 | def create_new_folder(local_dir):
11 | new_path = local_dir
12 | if not os.path.exists(new_path):
13 | os.makedirs(new_path)
14 | return new_path
15 |
16 |
17 | def create_image_service():
18 | app = Flask(__name__)
19 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
20 | app.config['UPLOAD_EXTENSIONS'] = ['.jpg', '.png', '.gif']
21 |
22 |
23 | @app.route('/api/image/', methods=['GET'])
24 | def get_image(file):
25 | img_name = secure_filename(file)
26 | return send_from_directory(app.config['UPLOAD_FOLDER'], img_name, as_attachment=True)
27 |
28 |
29 | @app.route('/api/image', methods=['POST'])
30 | def upload_image():
31 | print('upload_image()')
32 | if request.files['file']:
33 | print(app.config['UPLOAD_FOLDER'])
34 | img = request.files['file']
35 | img_name = secure_filename(img.filename)
36 | print('Secure version of image name ', img_name)
37 | create_new_folder(app.config['UPLOAD_FOLDER'])
38 | saved_path = os.path.join(app.config['UPLOAD_FOLDER'], img_name)
39 | print("saving to " + str(saved_path))
40 | img.save(saved_path)
41 | # Return a url to the image
42 | # return send_from_directory(app.config['UPLOAD_FOLDER'], img_name, as_attachment=True)
43 | return 'Success'
44 | else:
45 | return "Where is the image?"
46 |
47 | @app.errorhandler(400)
48 | def not_found(error):
49 | return make_response(jsonify({'file': 'Error'}), 400)
50 |
51 | return app
52 |
53 |
54 | if __name__ == '__main__':
55 | app = create_image_service()
56 | app.run(debug=True)
57 |
--------------------------------------------------------------------------------
/chapter4/circles-picture.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | WIDTH = 640
4 | HEIGHT = 360
5 |
6 |
7 | def setup_window():
8 | # Set up the window
9 | turtle.title('Circles in My Mind')
10 | turtle.setup(WIDTH, HEIGHT, 0, 0)
11 | turtle.colormode(255) # Indicates RGB numbers will be in the range 0 to 255
12 | turtle.hideturtle()
13 | # Batch drawing to the screen for faster rendering
14 | turtle.tracer(2000)
15 |
16 | # Speed up drawing process
17 | turtle.speed(10)
18 | turtle.penup()
19 |
20 |
21 | def draw_circle(x, y, radius, red=50, green=255, blue=10, width=7):
22 | """ Draw a circle at a specific x, y location.
23 | Then draw four smaller circles recursively"""
24 | colour = (red, green, blue)
25 |
26 | # Recursively drawn smaller circles
27 | if radius > 50:
28 | # Calculate colours and line width for smaller circles
29 | if red < 216:
30 | red = red + 33
31 | green = green - 42
32 | blue = blue + 10
33 | width -= 1
34 | else:
35 | red = 0
36 | green = 255
37 | # Calculate the radius for the smaller circles
38 | new_radius = int(radius / 1.3)
39 | # Drawn four circles
40 | draw_circle(int(x + new_radius), y, new_radius, red, green, blue, width)
41 | draw_circle(x - new_radius, y, new_radius, red, green, blue, width)
42 | draw_circle(x, int(y + new_radius), new_radius, red, green, blue, width)
43 | draw_circle(x, int(y - new_radius), new_radius, red, green, blue, width)
44 |
45 | # Draw the original circle
46 | turtle.goto(x, y)
47 | turtle.color(colour)
48 | turtle.width(width)
49 | turtle.pendown()
50 | turtle.circle(radius)
51 | turtle.penup()
52 |
53 |
54 | # Run the program
55 | print('Starting')
56 | setup_window()
57 | draw_circle(25, -100, 200)
58 |
59 | # Ensure that all the drawing is rendered
60 | turtle.update()
61 | print('Done')
62 | turtle.done()
63 |
--------------------------------------------------------------------------------
/chapter4/exercises/fractal_trees.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | # Set up 'constants'
4 |
5 | # image size
6 | IMAGE_SIZE_X = 500
7 | IMAGE_SIZE_Y = 500
8 | # Determines depth of tree - try 2 and 1.25 as alternatives
9 | FACTOR = 1.45
10 |
11 |
12 | def draw_tree(length, width=9):
13 | color = 'brown'
14 | if length < 1:
15 | return
16 | elif length < 3:
17 | color = 'green'
18 |
19 | if width < 1:
20 | width = 1
21 |
22 | turtle.color(color)
23 | turtle.width(width)
24 | turtle.forward(length)
25 | turtle.left(30)
26 | draw_tree(length / FACTOR, width - 1)
27 | turtle.right(60)
28 | draw_tree(length / FACTOR, width - 1)
29 | turtle.left(30)
30 | turtle.color(color)
31 | turtle.width(width)
32 | turtle.backward(length)
33 |
34 |
35 | def setup_screen(title, background='white', screen_size_x=640, screen_size_y=320, tracer_size=200):
36 | """ Sets up Turtle screen with useful defaults """
37 | print('Set up Screen')
38 | turtle.title(title)
39 | turtle.setup(screen_size_x, screen_size_y)
40 | turtle.hideturtle()
41 | turtle.penup()
42 | turtle.backward(240)
43 | turtle.tracer(tracer_size)
44 | turtle.bgcolor(background) # Set the background colour of the screen
45 |
46 |
47 | print("Starting ...")
48 | setup_screen('Fractal Tree', screen_size_x=IMAGE_SIZE_X, screen_size_y=IMAGE_SIZE_Y, tracer_size=2000)
49 |
50 | # Ensure tree is centred and pointing in the right direction
51 | turtle.setposition(-50, -140)
52 | turtle.left(90)
53 | turtle.down()
54 |
55 | # Draw the tree
56 | draw_tree(100)
57 |
58 | # Ensure that all the drawing is rendered
59 | turtle.update()
60 |
61 | print('Done')
62 | turtle.done()
63 |
--------------------------------------------------------------------------------
/chapter4/mandelbrot.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | # Set up constants
4 | SCREEN_OFFSET_X = 250
5 | SCREEN_OFFSET_Y = 240
6 |
7 | # max iterations allowed
8 | MAX_ITERATIONS = 255
9 |
10 | # image size
11 | IMAGE_SIZE_X = 512
12 | IMAGE_SIZE_Y = 512
13 |
14 | # Drawing area
15 | MIN_X = -2.0
16 | MAX_X = 1.0
17 | MIN_Y = -1.5
18 | MAX_Y = 1.5
19 |
20 |
21 | def setup_screen(title, background='white', screen_size_x=640, screen_size_y=320, tracer_size=200):
22 | print('Set up Screen')
23 | turtle.title(title)
24 | turtle.setup(screen_size_x, screen_size_y)
25 | turtle.hideturtle()
26 | turtle.penup()
27 | turtle.backward(240)
28 | turtle.tracer(tracer_size)
29 | turtle.bgcolor(background) # Set the background colour of the screen
30 |
31 |
32 | setup_screen('Mandelbrot', screen_size_x=IMAGE_SIZE_X, screen_size_y=IMAGE_SIZE_Y, tracer_size=20000)
33 | turtle.colormode(255) # Indicates RGB numbers will be in the range 0 to 255
34 |
35 | # Generate Mandelbrot
36 | for y in range(IMAGE_SIZE_Y):
37 | zy = y * (MAX_Y - MIN_Y) / (IMAGE_SIZE_Y - 1) + MIN_Y
38 | for x in range(IMAGE_SIZE_X):
39 | zx = x * (MAX_X - MIN_X) / (IMAGE_SIZE_Y - 1) + MIN_X
40 | z = zx + zy * 1j
41 | c = z
42 | for i in range(MAX_ITERATIONS):
43 | if abs(z) > 2.0:
44 | break
45 | z = z * z + c
46 | turtle.color((i % 4 * 64, i % 8 * 32, i % 16 * 16))
47 | turtle.setposition(x - SCREEN_OFFSET_X, y - SCREEN_OFFSET_Y)
48 | turtle.pendown()
49 | turtle.dot(1)
50 | turtle.penup()
51 |
52 | # Ensure that all the drawing is rendered
53 | turtle.update()
54 |
55 | print('Done')
56 | turtle.done()
57 |
--------------------------------------------------------------------------------
/chapter4/snowflake.py:
--------------------------------------------------------------------------------
1 | import turtle
2 | from random import randint
3 |
4 |
5 | def generate_random_colour():
6 | """Generates an R,G,B values randomly in range
7 | 0 to 255 """
8 | r = randint(0, 255)
9 | g = randint(0, 255)
10 | b = randint(0, 255)
11 | return r, g, b
12 |
13 | def setup_screen(title, background = 'white'):
14 | print('Set up Screen')
15 | turtle.title(title)
16 | turtle.setup(640, 600)
17 | turtle.hideturtle()
18 | turtle.penup()
19 | turtle.tracer(200)
20 | turtle.bgcolor(background) # Set the background colour of the screen
21 |
22 | def draw_snowflake(size):
23 | """ Draw a picture of a snowflake """
24 | turtle.penup()
25 | turtle.forward(10 * size)
26 | turtle.left(45)
27 | turtle.pendown()
28 | turtle.color(generate_random_colour())
29 |
30 | # draw branch 8 times to make a snowflake
31 | for _ in range(8):
32 | draw_branch(size)
33 | turtle.forward(size)
34 | turtle.left(45)
35 |
36 | turtle.penup()
37 |
38 | def draw_branch(size):
39 | """ Draw an individual branch on a snowflake """
40 | side_branch_size = size / 3
41 | for _ in range(3):
42 | for i in range(3):
43 | turtle.forward(side_branch_size)
44 | turtle.backward(side_branch_size)
45 | turtle.right(45)
46 | turtle.left(90)
47 | turtle.backward(side_branch_size)
48 | turtle.left(45)
49 | turtle.right(90)
50 |
51 |
52 | setup_screen('Snowflakes')
53 | turtle.colormode(255) # Indicates RGB numbers will be in the range 0 to 255
54 |
55 | print("Drawing snowflakes at random locations")
56 | for _ in range(30):
57 | x = randint(-320, 100)
58 | y = randint(-320, 80)
59 | snowflake_size = randint(1, 5) * 10
60 | turtle.goto(x, y)
61 | turtle.right(15)
62 | draw_snowflake(snowflake_size)
63 |
64 | turtle.update()
65 |
66 | print('Done')
67 | turtle.done()
68 |
--------------------------------------------------------------------------------
/chapter4/snowflake_koch.py:
--------------------------------------------------------------------------------
1 | import turtle
2 |
3 | # Set up Constants
4 | ANGLES = [60, -120, 60, 0]
5 | SIZE_OF_SNOWFLAKE = 300
6 |
7 |
8 | def get_input_depth():
9 | """ Obtain input from user and convert to an int"""
10 | message = 'Please provide the depth (0 or a positive interger):'
11 | value_as_string = input(message)
12 | while not value_as_string.isnumeric():
13 | print('The input must be an integer!')
14 | value_as_string = input(message)
15 | return int(value_as_string)
16 |
17 |
18 | def setup_screen(title, background='white', screen_size_x=640, screen_size_y=320, tracer_size=800):
19 | print('Set up Screen')
20 | turtle.title(title)
21 | turtle.setup(screen_size_x, screen_size_y)
22 | turtle.hideturtle()
23 | turtle.penup()
24 | turtle.backward(240)
25 | # Batch drawing to the screen for faster rendering
26 | turtle.tracer(tracer_size)
27 | turtle.bgcolor(background) # Set the background colour of the screen
28 |
29 |
30 | def draw_koch(size, depth):
31 | if depth > 0:
32 | for angle in ANGLES:
33 | draw_koch(size / 3, depth - 1)
34 | turtle.left(angle)
35 | else:
36 | turtle.forward(size)
37 |
38 | depth = get_input_depth()
39 |
40 | setup_screen('Koch Snowflake (depth ' + str(depth) + ')',
41 | background='black',
42 | screen_size_x=420, screen_size_y=420)
43 | # Set foreground colours
44 | turtle.color('sky blue')
45 |
46 | # Ensure snowflake is centred
47 | turtle.penup()
48 | turtle.setposition(-180,0)
49 | turtle.left(30)
50 | turtle.pendown()
51 |
52 | # Draw three sides of snowflake
53 | for _ in range(3):
54 | draw_koch(SIZE_OF_SNOWFLAKE, depth)
55 | turtle.right(120)
56 |
57 | # Ensure that all the drawing is rendered
58 | turtle.update()
59 | print('Done')
60 | turtle.done()
61 |
--------------------------------------------------------------------------------
/chapter5/bar_chart8a.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Set up the data
4 | labels = ('Python', 'Scala', 'C#', 'Java', 'PHP')
5 | index = (1, 2, 3, 4, 5)
6 | sizes = [45, 10, 15, 30, 22]
7 |
8 | # Set up the bar chart
9 | pyplot.bar(index, sizes, tick_label=labels)
10 |
11 | # Configure the layout
12 | pyplot.ylabel('Usage')
13 | pyplot.xlabel('Programming Languages')
14 |
15 | # Display the chart
16 | pyplot.show()
17 |
--------------------------------------------------------------------------------
/chapter5/bar_chart8b.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Set up the data
4 | labels = ('Python', 'Scala', 'C#', 'Java', 'PHP')
5 | index = (1, 2, 3, 4, 5)
6 | sizes = [45, 10, 15, 30, 22]
7 |
8 | # Set up the horizontal bar chart
9 | pyplot.barh(index, sizes, tick_label=labels)
10 |
11 | # Configure the layout
12 | pyplot.ylabel('Usage')
13 | pyplot.xlabel('Programming Languages')
14 |
15 | # Display the chart
16 | pyplot.show()
--------------------------------------------------------------------------------
/chapter5/bar_chart8c.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Set up the data
4 | labels = ('Python', 'Scala', 'C#', 'Java', 'PHP')
5 | index = (1, 2, 3, 4, 5)
6 | sizes = [45, 10, 15, 30, 22]
7 |
8 | # Set up the multi-coloured bar chart
9 | pyplot.bar(index, sizes, tick_label=labels, color=('red', 'green', 'blue', 'yellow', 'orange'))
10 |
11 | # Configure the layout
12 | pyplot.ylabel('Usage')
13 | pyplot.xlabel('Programming Languages')
14 |
15 | # Display the chart
16 | pyplot.show()
17 |
--------------------------------------------------------------------------------
/chapter5/bar_chart8d.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Set up the data
4 | labels = ('Python', 'Scala', 'C#', 'Java', 'PHP')
5 | index = (1, 2, 3, 4, 5)
6 | web_usage = [20, 2, 5, 10, 14]
7 | data_science_usage = [15, 8, 5, 15, 2]
8 | games_usage = [10, 1, 5, 5, 4]
9 |
10 | # Set up the bar chart
11 | pyplot.bar(index, web_usage, tick_label=labels, label='web')
12 | pyplot.bar(index, data_science_usage, tick_label=labels, label='data science', bottom=web_usage)
13 |
14 | web_and_games_usage = [web_usage[i] + data_science_usage[i] for i in range(0, len(web_usage))]
15 | pyplot.bar(index, games_usage, tick_label=labels, label='games', bottom=web_and_games_usage)
16 |
17 | # Configure the layout
18 | pyplot.ylabel('Usage')
19 | pyplot.xlabel('Programming Languages')
20 | pyplot.legend()
21 |
22 | # Display the chart
23 | pyplot.show()
--------------------------------------------------------------------------------
/chapter5/bar_chart8e.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | BAR_WIDTH = 0.35
4 |
5 | # set up grouped bar charts
6 | teama_results = (60, 75, 56, 62, 58)
7 | teamb_results = (55, 68, 80, 73, 55)
8 | # Set up the index for each bar
9 | index_teama = (1, 2, 3, 4, 5)
10 | index_teamb = [i + BAR_WIDTH for i in index_teama]
11 |
12 | # Determine the mid point for the ticks
13 | ticks = [i + BAR_WIDTH / 2 for i in index_teama]
14 | tick_labels = ('Lab 1', 'Lab 2', 'Lab 3', 'Lab 4', 'Lab 5')
15 |
16 | # Plot the bar charts
17 | pyplot.bar(index_teama, teama_results, BAR_WIDTH, color='b', label='Team A')
18 | pyplot.bar(index_teamb, teamb_results, BAR_WIDTH, color='g', label='Team B')
19 |
20 | # Set up the graph
21 | pyplot.xlabel('Labs')
22 | pyplot.ylabel('Scores')
23 | pyplot.title('Scores by Lab')
24 | pyplot.xticks(ticks, tick_labels)
25 | pyplot.legend()
26 |
27 | # Display the graph
28 | pyplot.show()
29 |
--------------------------------------------------------------------------------
/chapter5/configuringaplot4.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | x = range(1, 11)
4 | y = [3, 4, 6, 9, 11, 12, 10, 11, 14, 16]
5 |
6 | # Set the axes headings
7 | plt.ylabel('y values', fontsize=12)
8 | plt.xlabel('x values', fontsize=12)
9 |
10 | # Set the title
11 | plt.title("Sample Graph")
12 |
13 | plt.plot(x, y, linewidth=2.0, label="samples", color='blue', linestyle='--')
14 | plt.plot(y, x, label='inverse', color='green')
15 | plt.plot(x, range(2, 12), 'bo', label='ranged', linestyle=':', color='red')
16 |
17 | plt.legend()
18 |
19 | plt.show()
20 |
21 | # Can also write it to a file
22 | # plt.savefig("foo.png")
--------------------------------------------------------------------------------
/chapter5/figure_example7.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 | import numpy as np
3 |
4 | # Data for plotting
5 | t = np.arange(0.0, 2.0, 0.01)
6 | s = 1 + np.sin(2 * np.pi * t)
7 |
8 | # Initialize a Figure
9 | figure = pyplot.figure()
10 |
11 | # Add Axes to the Figure
12 | axis = figure.add_subplot(111)
13 | axis.plot(t, s, color='green', label='yyy')
14 | axis.set(xlabel='time (s)', ylabel='voltage (mV)', title='Simple Plot')
15 |
16 | # Show the grid
17 | axis.grid(linestyle='dashed')
18 |
19 | # Display the Legend
20 | axis.legend()
21 |
22 | # Generate the plot
23 | pyplot.show()
24 |
25 |
--------------------------------------------------------------------------------
/chapter5/line_graph3.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Set up the data
4 | x = [0, 1, 2, 3, 4, 5, 6]
5 | y = [0, 2, 6, 14, 30, 43, 75]
6 |
7 | # Set the axes headings
8 | pyplot.ylabel('Speed', fontsize=12)
9 | pyplot.xlabel('Time', fontsize=12)
10 |
11 | # Set the title
12 | pyplot.title("Speed v Time")
13 |
14 | # Plot and display the graph
15 | # Using blue circles for markers ('bo')
16 | # and a solid line ('-')
17 | pyplot.plot(x, y, 'bo-')
18 | pyplot.show()
19 |
--------------------------------------------------------------------------------
/chapter5/matplotlib2.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 | import numpy as np
3 |
4 | # Data for plotting
5 | t = np.arange(0.0, 2.0, 0.01)
6 | s = 1 + np.sin(2 * np.pi * t)
7 |
8 | # Initialize a Figure
9 | figure = pyplot.figure()
10 |
11 | # Add Axes to the Figure
12 | axis = figure.add_subplot(111)
13 | axis.plot(t, s, color='green', label='yyy')
14 | axis.set(xlabel='time (s)', ylabel='voltage (mV)', title='Simple Plot')
15 |
16 | x = 2.25 * np.random.rand(10)
17 | y = 2.25 * np.random.rand(10)
18 | axis.scatter(x, y, marker='o', label='xxx')
19 |
20 | # Show the grid
21 | axis.grid(linestyle='dashed')
22 |
23 | # Display the Legend
24 | axis.legend()
25 |
26 | # Generate the plot
27 | pyplot.show()
28 |
29 |
--------------------------------------------------------------------------------
/chapter5/pie_chart5.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | labels = ('Python', 'Java', 'Scala', 'C#')
4 | sizes = [45, 30, 15, 10]
5 |
6 | pyplot.pie(sizes,
7 | labels=labels,
8 | autopct='%1.f%%',
9 | counterclock=False,
10 | startangle=90)
11 |
12 | pyplot.show()
13 |
--------------------------------------------------------------------------------
/chapter5/pie_chart_5a.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | labels = ('Python', 'Java', 'Scala', 'C#')
4 | sizes = [45, 30, 15, 10]
5 |
6 | # only "explode" the 1st slice (i.e. 'Python')
7 | explode = (0.1, 0, 0, 0)
8 |
9 | pyplot.pie(sizes,
10 | explode=explode,
11 | labels=labels,
12 | autopct='%1.f%%',
13 | shadow=True,
14 | counterclock=False,
15 | startangle=90)
16 |
17 | pyplot.show()
18 |
--------------------------------------------------------------------------------
/chapter5/scatter_plot6.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Create data
4 | riding = ((17, 18, 21, 22, 19, 21, 25, 22, 25, 24),
5 | (3, 6, 3.5, 4, 5, 6.3, 4.5, 5, 4.5, 4))
6 | swimming = ((17, 18, 20, 19, 22, 21, 23, 19, 21, 24),
7 | (8, 9, 7, 10, 7.5, 9, 8, 7, 8.5, 9))
8 | sailing = ((31, 28, 29, 36, 27, 32, 34, 35, 33, 39),
9 | (4, 6.3, 6, 3, 5, 7.5, 2, 5, 7, 4))
10 |
11 | # Plot the data
12 | pyplot.scatter(x=riding[0], y=riding[1], c='red', marker='o', label='riding')
13 | pyplot.scatter(x=swimming[0], y=swimming[1], c='green', marker='^', label='swimming')
14 | pyplot.scatter(x=sailing[0], y=sailing[1], c='blue', marker='*', label='sailing')
15 |
16 | # Configure graph
17 | pyplot.xlabel('Age')
18 | pyplot.ylabel('Hours')
19 | pyplot.title('Activities Scatter Graph')
20 | pyplot.legend()
21 |
22 | # Display the chart
23 | pyplot.show()
24 |
--------------------------------------------------------------------------------
/chapter5/scatter_plot_trendline6.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as pyplot
3 |
4 | x = (5, 5.5, 6, 6.5, 7, 8, 9, 10)
5 | y = (120, 115, 100, 112, 80, 85, 69, 65)
6 |
7 | # Generate the scatter plot
8 | pyplot.scatter(x, y)
9 |
10 | # Generate the trend line
11 | z = np.polyfit(x, y, 1)
12 | p = np.poly1d(z)
13 | pyplot.plot(x, p(x), 'r')
14 |
15 | # Display the figure
16 | pyplot.show()
17 |
--------------------------------------------------------------------------------
/chapter5/simple_plot1.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | # Plot a sequence of values
4 | pyplot.plot([1, 0.25, 0.5, 2, 3, 3.75, 3.5])
5 |
6 | # Display the chart in a window
7 | pyplot.show()
8 |
--------------------------------------------------------------------------------
/chapter5/sub_plots9.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 |
3 | t = range(0, 20)
4 | s = range(30, 10, -1)
5 | # Set up the grid of subplots to be 2 by 2
6 | grid_size='22'
7 |
8 | # Initialize a Figure
9 | figure = pyplot.figure()
10 |
11 | # Add first subplot
12 | position = grid_size + '1'
13 | print('Adding first subplot to position', position)
14 | axis1 = figure.add_subplot(position)
15 | axis1.set(title='subplot(2,2,1)')
16 | axis1.plot(t, s)
17 |
18 | # Add second subplot
19 | position = grid_size + '2'
20 | print('Adding second subplot to position', position)
21 | axis2 = figure.add_subplot(position)
22 | axis2.set(title='subplot(2,2,2)')
23 | axis2.plot(t, s, 'r-')
24 |
25 | # Add third subplot
26 | position = grid_size + '3'
27 | print('Adding third subplot to position', position)
28 | axis3 = figure.add_subplot(position)
29 | axis3.set(title='subplot(2,2,3)')
30 | axis3.plot(t, s, 'g-')
31 |
32 | # Add fourth subplot
33 | position = grid_size + '4'
34 | print('Adding fourth subplot to position', position)
35 | axis4 = figure.add_subplot(position)
36 | axis4.set(title='subplot(2,2,4)')
37 | axis4.plot(t, s, 'y-')
38 |
39 | # Display the chart
40 | pyplot.show()
41 |
--------------------------------------------------------------------------------
/chapter5/three-d-plot10.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as pyplot
2 | # Import matplotlib colour map
3 | from matplotlib import cm as colourmap
4 | # Required for 3D Projections
5 | from mpl_toolkits.mplot3d import Axes3D
6 | # Provide access to numpy functions
7 | import numpy as np
8 |
9 | # Make the data to be displayed
10 | x_values = np.arange(-6, 6, 0.3)
11 | y_values = np.arange(-6, 6, 0.3)
12 |
13 | # Generate coordinate matrices from coordinate vectors
14 | x_values, y_values = np.meshgrid(x_values, y_values)
15 |
16 | # Generate Z values as sin of x plus y values
17 | z_values = np.sin(x_values + y_values)
18 |
19 | # Obtain the figure object
20 | figure = pyplot.figure()
21 |
22 | # Get the axes object for the 3D graph
23 | axes = figure.gca(projection='3d')
24 |
25 | # Plot the surface.
26 | surf = axes.plot_surface(x_values,
27 | y_values,
28 | z_values,
29 | cmap=colourmap.coolwarm)
30 |
31 | # Add a color bar which maps values to colors.
32 | figure.colorbar(surf)
33 |
34 | # Add labels to the graph
35 | pyplot.title("3D Graph")
36 | axes.set_ylabel('y values', fontsize=8)
37 | axes.set_xlabel('x values', fontsize=8)
38 | axes.set_zlabel('z values', fontsize=8)
39 |
40 | # Display the graph
41 | pyplot.show()
42 |
--------------------------------------------------------------------------------
/chapter7/FrameAndPanelApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 |
4 | class SampleFrame(wx.Frame):
5 |
6 | def __init__(self):
7 | super().__init__(parent=None,
8 | title='Sample App',
9 | size=(300, 300))
10 |
11 | # Set up the first Panel to be at position 1, 1
12 | # and of size 300 by 100 with a blue background
13 | self.panel1 = wx.Panel(self)
14 | self.panel1.SetSize(300, 100)
15 | self.panel1.SetBackgroundColour(wx.Colour(0, 0, 255))
16 |
17 | # Set up the second Panel to be at position 1, 110
18 | # and of size 300 by 100 with a red background
19 | self.panel2 = wx.Panel(self)
20 | self.panel2.SetSize(1, 110, 300, 100)
21 | self.panel2.SetBackgroundColour(wx.Colour(255, 0, 0))
22 |
23 |
24 | class MainApp(wx.App):
25 |
26 | def OnInit(self):
27 | """ Initialise the main GUI Application"""
28 | frame = SampleFrame()
29 | frame.Show()
30 | return True
31 |
32 |
33 | # Run the GUI application
34 | app = MainApp()
35 | app.MainLoop()
36 |
--------------------------------------------------------------------------------
/chapter7/SampleDCApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 |
4 | class DrawingFrame(wx.Frame):
5 |
6 | def __init__(self, title):
7 | super().__init__(None,
8 | title=title,
9 | size=(300, 200))
10 |
11 | self.Bind(wx.EVT_PAINT, self.on_paint)
12 |
13 | def on_paint(self, event):
14 | """set up the device context (DC) for painting"""
15 | dc = wx.PaintDC(self)
16 | dc.DrawLine(10, 10, 60, 20)
17 | dc.DrawRectangle(20, 40, 40, 20)
18 | dc.DrawText("Hello World", 30, 70)
19 | dc.DrawCircle(130, 40, radius=15)
20 |
21 |
22 | class GraphicApp(wx.App):
23 |
24 | def OnInit(self):
25 | """ Initialise the GUI display"""
26 | frame = DrawingFrame(title='PyDraw')
27 | frame.Show()
28 | return True
29 |
30 |
31 | # Run the GUI application
32 | app = GraphicApp()
33 | app.MainLoop()
34 |
--------------------------------------------------------------------------------
/chapter7/SimpleHelloWorldApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | # Create the Application Object
4 | app = wx.App()
5 |
6 | # Now create a Frame (representing the window)
7 | frame = wx.Frame(parent=None, title='Simple Hello World')
8 | # And add a text label to it
9 | text = wx.StaticText(parent=frame, label='Hello Python')
10 |
11 | # Display the window (frame)
12 | frame.Show()
13 |
14 | # Start the event loop
15 | app.MainLoop()
--------------------------------------------------------------------------------
/chapter8/HelloNamedApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 |
4 | class HelloFrame(wx.Frame):
5 |
6 | def __init__(self, title):
7 | super().__init__(None,
8 | title=title,
9 | size=(300, 200))
10 |
11 | self.name = ''
12 |
13 | # Create the BoxSizer to use for the Frame
14 | vertical_box_sizer = wx.BoxSizer(wx.VERTICAL)
15 | self.SetSizer(vertical_box_sizer)
16 |
17 | # Create the panel to contain the widgets
18 | panel = wx.Panel(self)
19 | # Add the Panel to the Frames Sizer
20 | vertical_box_sizer.Add(panel,
21 | wx.ID_ANY,
22 | wx.EXPAND | wx.ALL,
23 | 20)
24 |
25 | # Create the GridSizer to use with the Panel
26 | grid = wx.GridSizer(4, 1, 5, 5)
27 |
28 | # Set up the input field
29 | self.text = wx.TextCtrl(panel, size=(150, -1))
30 |
31 | # Now configure the enter button
32 | enter_button = wx.Button(panel, label='Enter')
33 | enter_button.Bind(wx.EVT_BUTTON, self.set_name)
34 |
35 | # Next set up the text label
36 | self.label = wx.StaticText(panel,
37 | label='Welcome',
38 | style=wx.ALIGN_LEFT)
39 |
40 | # Now configure the Show Message button
41 | message_button = wx.Button(panel, label='Show Message')
42 | message_button.Bind(wx.EVT_BUTTON, self.show_message)
43 |
44 | # Add all the widgets to the grid sizer to handle layout
45 | grid.AddMany([self.text, enter_button, self.label, message_button])
46 |
47 | # Set the sizer on the panel
48 | panel.SetSizer(grid)
49 |
50 | # Centre the Frame on the Computer Screen
51 | self.Centre()
52 |
53 | def show_message(self, event):
54 | """ Event Handler to display the Message Dialog
55 | using the current value of the name attribute. """
56 | dialog = wx.MessageDialog(None,
57 | message='Welcome To Python ' + self.name,
58 | caption='Hello',
59 | style=wx.OK)
60 | dialog.ShowModal()
61 |
62 | def set_name(self, event):
63 | """ Event Handler for the Enter button.
64 | Retrieves the text entered into the input field
65 | and sets the self.name attribute. This is then
66 | used to set the text label """
67 | self.name = self.text.GetLineText(0)
68 | self.label.SetLabelText('Welcome ' + self.name)
69 |
70 |
71 | class MainApp(wx.App):
72 |
73 | def OnInit(self):
74 | """ Initialise the GUI display"""
75 | frame = HelloFrame(title='Sample App')
76 | frame.Show()
77 | # Indicate whether processing should continue or not
78 | return True
79 |
80 | def OnExit(self):
81 | """ Executes when the GUI application shuts down"""
82 | print('Goodbye')
83 | # Need to indicate success or failure
84 | return True
85 |
86 |
87 | # Run the GUI application
88 | app = MainApp()
89 | app.MainLoop()
90 |
--------------------------------------------------------------------------------
/chapter8/SimpleEventHandlerApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 |
4 | class WelcomeFrame(wx.Frame):
5 | """ The Main Window / Frame of the application """
6 |
7 | def __init__(self):
8 | super().__init__(parent=None,
9 | title='Sample App',
10 | size=(300, 200))
11 |
12 | # Set up panel within the frame and text label
13 | self.panel = wx.Panel(self)
14 | self.text = wx.StaticText(self.panel, label='Hello')
15 |
16 | # Bind the on_mouse_click method to the Mouse Event via the
17 | # left mouse click binder
18 | self.panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_click)
19 |
20 | def on_mouse_click(self, mouse_event):
21 | """ When the left mouse button is clicked this
22 | method is called. It will obtain the current
23 | mouse coordinates, and reposition the text label
24 | to this position. """
25 | x, y = mouse_event.GetPosition()
26 | print(x, y)
27 | self.text.SetPosition(wx.Point(x, y))
28 |
29 |
30 | class MainApp(wx.App):
31 |
32 | def OnInit(self):
33 | """ Initialise the main GUI Application"""
34 | frame = WelcomeFrame()
35 | frame.Show()
36 | # Indicate whether processing should continue or not
37 | return True
38 |
39 |
40 | # Run the GUI application
41 | app = MainApp()
42 | app.MainLoop()
43 |
--------------------------------------------------------------------------------
/chapter8/exercises/BirthdayGUIApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 |
4 | class BirthdayFrame(wx.Frame):
5 |
6 | def __init__(self):
7 | super().__init__(parent=None,
8 | title='Happy Birthday App',
9 | size=(300, 200))
10 |
11 | self.name = '