Mercurial > personal > weather-server
annotate weather_server/locations.py @ 22:e229afdd447b
locations.py: store location name into the right place.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Fri, 01 Nov 2019 00:48:56 -0400 |
| parents | beb42c835c52 |
| children | 20c8ec56e447 |
| 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 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
23 def __init__(self, root: pathlib.Path): |
|
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 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
26 config_file = root / CONFIG_FILE |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
27 try: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
28 with open(config_file, 'r') as infile: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
29 parser.read_file(infile) |
|
22
e229afdd447b
locations.py: store location name into the right place.
Paul Fisher <paul@pfish.zone>
parents:
21
diff
changeset
|
30 self.name = parser.get( |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
31 'location', 'name', fallback='Weather station') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
32 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
|
33 self.password = parser.get('location', 'password') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
34 self.logger = logfile.Logger.create( |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
35 str(root / LOG), sample_field='sample_time') |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
36 except (IOError, KeyError, configparser.Error): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
37 raise ConfigError("Couldn't load location info.") |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
38 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
39 def record( |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
40 self, |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
41 entries: t.Iterable[t.Dict[str, object]], |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
42 timestamp: datetime.datetime, |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
43 ) -> None: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
44 for e in entries: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
45 e['ingest_time'] = timestamp |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
46 self.logger.write_rows(entries) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
47 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
48 @property |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
49 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
|
50 return self.logger.data |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
51 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
52 def latest(self) -> t.Optional[types.Reading]: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
53 most_recent = reversed(self.logger.data) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
54 for entry in most_recent: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
55 try: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
56 return types.Reading.from_dict(entry) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
57 except KeyError: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
58 pass # go to the older one. |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
59 return None |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
60 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
61 def timezone(self) -> datetime.tzinfo: |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
62 try: |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
63 return pytz.timezone(self.tz_name) |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
64 except pytz.UnknownTimeZoneError: |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
65 return pytz.UTC |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
66 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
67 def __repr__(self) -> str: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
68 return '<Location in %r>'.format(self.root) |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
69 |
|
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
70 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
71 class LocationFolder: |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
72 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
73 def __init__(self, root: pathlib.Path): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
74 self.root = root |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
75 # locations, mtime |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
76 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
|
77 self._maybe_reload() |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
78 |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
79 def get(self, name: str) -> Location: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
80 self._maybe_reload() |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
81 locs, _ = self.info |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
82 return locs[name] |
|
1
f66df122f18d
get the skeleton of a webserver up?
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
83 |
|
21
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
84 def _maybe_reload(self) -> None: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
85 new_mtime = self.root.stat().st_mtime_ns |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
86 _, old_mtime = self.info |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
87 if old_mtime == new_mtime: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
88 return |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
89 locations = {} |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
90 for child in self.root.iterdir(): |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
91 try: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
92 locations[child.name] = Location(child) |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
93 except ConfigError: |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
94 pass # It's OK. Skip this. |
|
beb42c835c52
Make weather server handle arbitrary data:
Paul Fisher <paul@pfish.zone>
parents:
9
diff
changeset
|
95 self.info = locations, new_mtime |
