Skip to content

Commit 9e52e13

Browse files
committed
added chapter 5 code
1 parent cba324e commit 9e52e13

File tree

7 files changed

+1000
-0
lines changed

7 files changed

+1000
-0
lines changed

Chapter05/DateEntry.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import tkinter as tk
2+
from tkinter import ttk
3+
from datetime import datetime
4+
5+
class DateEntry(ttk.Entry):
6+
"""An Entry for ISO-style dates (Year-month-day)"""
7+
8+
def __init__(self, parent, *args, **kwargs):
9+
super().__init__(parent, *args, **kwargs)
10+
self.configure(
11+
validate='all',
12+
validatecommand=(self.register(self._validate), '%S', '%i', '%V', '%d'),
13+
invalidcommand=(self.register(self._on_invalid), '%V')
14+
)
15+
self.error = tk.StringVar()
16+
17+
def _toggle_error(self, error=''):
18+
self.error.set(error)
19+
if error:
20+
self.config(foreground='red')
21+
else:
22+
self.config(foreground='black')
23+
24+
def _validate(self, char, index, event, action):
25+
26+
# reset error state
27+
self._toggle_error()
28+
valid = True
29+
30+
# ISO dates only need digits and hyphens
31+
if event == 'key':
32+
if action == '0':
33+
valid = True
34+
elif index in ('0', '1', '2', '3', '5', '6', '8', '9'):
35+
valid = char.isdigit()
36+
elif index in ('4', '7'):
37+
valid = char == '-'
38+
else:
39+
valid = False
40+
elif event == 'focusout':
41+
try:
42+
datetime.strptime(self.get(), '%Y-%m-%d')
43+
except ValueError:
44+
valid = False
45+
return valid
46+
47+
def _on_invalid(self, event):
48+
if event != 'key':
49+
self._toggle_error('Not a valid date')
50+
51+
if __name__ == '__main__':
52+
root = tk.Tk()
53+
entry = DateEntry(root)
54+
entry.pack()
55+
ttk.Label(
56+
textvariable=entry.error, foreground='red'
57+
).pack()
58+
59+
# add this so we can unfocus the DateEntry
60+
ttk.Entry(root).pack()
61+
root.mainloop()

Chapter05/MixinExample.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""This example shows the use of a mixin class"""
2+
3+
class Fruit():
4+
5+
_taste = 'sweet'
6+
7+
def taste(self):
8+
print(f'It tastes {self._taste}')
9+
10+
class PeelableMixin():
11+
12+
def __init__(self, *args, **kwargs):
13+
super().__init__(*args, **kwargs)
14+
self._peeled = False
15+
16+
def peel(self):
17+
self._peeled = True
18+
19+
def taste(self):
20+
if not self._peeled:
21+
print('I will peel it first')
22+
self.peel()
23+
super().taste()
24+
25+
class Plantain(PeelableMixin, Fruit):
26+
27+
_taste = 'starchy'
28+
29+
def peel(self):
30+
print('It has a tough peel!')
31+
super().peel()
32+
33+
plantain = Plantain()
34+
plantain.taste()

Chapter05/abq_data_entry_spec.rst

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
======================================
2+
ABQ Data Entry Program specification
3+
======================================
4+
5+
6+
Description
7+
-----------
8+
The program is being created to minimize data entry errors for laboratory measurements.
9+
10+
Functionality Required
11+
----------------------
12+
13+
The program must:
14+
15+
* allow all relevant, valid data to be entered, as per the field chart
16+
* append entered data to a CSV file
17+
- The CSV file must have a filename of abq_data_record_CURRENTDATE.csv,
18+
where CURRENTDATE is the date of the checks in ISO format (Year-month-day)
19+
- The CSV file must have all the fields as per the chart
20+
* enforce correct datatypes per field
21+
* have inputs that:
22+
- ignore meaningless keystrokes
23+
- display an error if the value is invalid on focusout
24+
- display an error if a required field is empty on focusout
25+
* prevent saving the record when errors are present
26+
27+
The program should try, whenever possible, to:
28+
29+
* enforce reasonable limits on data entered
30+
* Auto-fill data
31+
* Suggest likely correct values
32+
* Provide a smooth and efficient workflow
33+
34+
Functionality Not Required
35+
--------------------------
36+
37+
The program does not need to:
38+
39+
* Allow editing of data. This can be done in LibreOffice if necessary.
40+
* Allow deletion of data.
41+
42+
Limitations
43+
-----------
44+
45+
The program must:
46+
47+
* Be efficiently operable by keyboard-only users.
48+
* Be accessible to color blind users.
49+
* Run on Debian Linux.
50+
* Run acceptably on a low-end PC.
51+
52+
Data Dictionary
53+
---------------
54+
+------------+----------+------+-------------+------------------------+
55+
|Field | Datatype | Units| Range |Descripton |
56+
+============+==========+======+=============+========================+
57+
|Date |Date | | |Date of record |
58+
+------------+----------+------+-------------+------------------------+
59+
|Time |Time | |8:00, 12:00, |Time period |
60+
| | | |16:00, 20:00 | |
61+
+------------+----------+------+-------------+------------------------+
62+
|Lab |String | | A - C |Lab ID |
63+
+------------+----------+------+-------------+------------------------+
64+
|Technician |String | | |Technician name |
65+
+------------+----------+------+-------------+------------------------+
66+
|Plot |Int | | 1 - 20 |Plot ID |
67+
+------------+----------+------+-------------+------------------------+
68+
|Seed |String | | |Seed sample ID |
69+
|sample | | | | |
70+
+------------+----------+------+-------------+------------------------+
71+
|Fault |Bool | | |Fault on environmental |
72+
| | | | |sensor |
73+
+------------+----------+------+-------------+------------------------+
74+
|Light |Decimal |klx | 0 - 100 |Light at plot |
75+
+------------+----------+------+-------------+------------------------+
76+
|Humidity |Decimal |g/m³ | 0.5 - 52.0 |Abs humidity at plot |
77+
+------------+----------+------+-------------+------------------------+
78+
|Temperature |Decimal |°C | 4 - 40 |Temperature at plot |
79+
+------------+----------+------+-------------+------------------------+
80+
|Blossoms |Int | | 0 - 1000 |Num of blossoms in plot |
81+
+------------+----------+------+-------------+------------------------+
82+
|Fruit |Int | | 0 - 1000 |Num of fruits in plot |
83+
+------------+----------+------+-------------+------------------------+
84+
|Plants |Int | | 0 - 20 |Num of plants in plot |
85+
+------------+----------+------+-------------+------------------------+
86+
|Max height |Decimal |cm | 0 - 1000 |Height of tallest |
87+
| | | | |plant in plot |
88+
+------------+----------+------+-------------+------------------------+
89+
|Min height |Decimal |cm | 0 - 1000 |Height of shortest |
90+
| | | | |plant in plot |
91+
+------------+----------+------+-------------+------------------------+
92+
|Median |Decimal |cm | 0 - 1000 |Median height of |
93+
|height | | | |plants in plot |
94+
+------------+----------+------+-------------+------------------------+
95+
|Notes |String | | |Miscellaneous notes |
96+
+------------+----------+------+-------------+------------------------+

0 commit comments

Comments
 (0)