Mercurial > personal > weather-server
annotate weather_server/locations.py @ 26:7def5611895b
Add support for an index page displaying all locations.
This seems as good a time as any to declare 0.1.0.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sun, 10 Nov 2019 23:46:51 -0500 |
| parents | 20c8ec56e447 |
| children | 9bc3687e1e5e |
| rev | line source |
|---|---|
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
1 """Manages the directory containing the various logs.""" |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
2 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
3 import configparser |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
4 import datetime |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
5 import pathlib |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
6 import typing as t |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
7 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
8 import pytz |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
9 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
10 from . import logfile |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
11 from . import types |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
12 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
13 CONFIG_FILE = 'config.ini' |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
14 LOG = 'log.bson' |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
15 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
16 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
17 class ConfigError(Exception): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
18 """Raised when a location can't be loaded.""" |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
19 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
20 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
21 class Location: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
22 |
|
26
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
23 def __init__(self, root: pathlib.Path, key: str): |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
24 parser = configparser.ConfigParser(interpolation=None) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
25 self.root = root |
|
26
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
26 self.key = key |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
27 config_file = root / CONFIG_FILE |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
28 try: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
29 with open(config_file, 'r') as infile: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
30 parser.read_file(infile) |
|
22
e229afdd447b
locations.py: store location name into the right place.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
31 self.name = parser.get( |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
32 'location', 'name', fallback='Weather station') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
33 self.tz_name = parser.get('location', 'timezone', fallback='UTC') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
34 self.password = parser.get('location', 'password') |
|
24
20c8ec56e447
logfile: Pull logfile thread out of Logger.
Paul Fisher <paul@pfish.zone>
parents:
22
diff
changeset
|
35 self.logger = logfile.Logger( |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
36 str(root / LOG), sample_field='sample_time') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
37 except (IOError, KeyError, configparser.Error): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
38 raise ConfigError("Couldn't load location info.") |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
39 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
40 def record( |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
41 self, |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
42 entries: t.Iterable[t.Dict[str, object]], |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
43 timestamp: datetime.datetime, |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
44 ) -> None: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
45 for e in entries: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
46 e['ingest_time'] = timestamp |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
47 self.logger.write_rows(entries) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
48 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
49 @property |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
50 def entries(self) -> t.Iterable[t.Dict[str, object]]: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
51 return self.logger.data |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
52 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
53 def latest(self) -> t.Optional[types.Reading]: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
54 most_recent = reversed(self.logger.data) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
55 for entry in most_recent: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
56 try: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
57 return types.Reading.from_dict(entry) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
58 except KeyError: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
59 pass # go to the older one. |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
60 return None |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
61 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
62 def timezone(self) -> datetime.tzinfo: |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
63 try: |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
64 return pytz.timezone(self.tz_name) |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
65 except pytz.UnknownTimeZoneError: |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
66 return pytz.UTC |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
67 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
68 def __repr__(self) -> str: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
69 return '<Location in %r>'.format(self.root) |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
70 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
71 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
72 class LocationFolder: |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
73 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
74 def __init__(self, root: pathlib.Path): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
75 self.root = root |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
76 # locations, mtime |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
77 self.info: t.Tuple[t.Dict[str, Location], t.Optional[int]] = ({}, None) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
78 self._maybe_reload() |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
79 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
80 def get(self, name: str) -> Location: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
81 self._maybe_reload() |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
82 locs, _ = self.info |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
83 return locs[name] |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
84 |
|
26
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
85 def locations(self) -> t.Dict[str, Location]: |
|
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
86 return self.info[0] |
|
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
87 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
88 def _maybe_reload(self) -> None: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
89 new_mtime = self.root.stat().st_mtime_ns |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
90 _, old_mtime = self.info |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
91 if old_mtime == new_mtime: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
92 return |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
93 locations = {} |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
94 for child in self.root.iterdir(): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
95 try: |
|
26
7def5611895b
Add support for an index page displaying all locations.
Paul Fisher <paul@pfish.zone>
parents:
24
diff
changeset
|
96 locations[child.name] = Location(child, child.name) |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
97 except ConfigError: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
98 pass # It's OK. Skip this. |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
99 self.info = locations, new_mtime |
