fcf22a8d2cf20d4e6a6dd83690a51de08ce2f44d
[python_utils.git] / site_config.py
1 #!/usr/bin/env python3
2
3 import logging
4 import platform
5 from dataclasses import dataclass
6 from typing import Callable, Optional
7
8 # Note: this module is fairly early loaded.  Be aware of dependencies.
9 import config
10 from type.locations import Location
11
12 logger = logging.getLogger(__name__)
13
14 args = config.add_commandline_args(
15     f'Global Site Config ({__file__})',
16     'Args related to global site-specific configuration',
17 )
18 args.add_argument(
19     '--site_config_override_location',
20     default='NONE',
21     const='NONE',
22     nargs='?',
23     choices=['HOUSE', 'CABIN', 'NONE'],
24     help='Where are we, HOUSE, CABIN?  Overrides standard detection code.',
25 )
26
27
28 @dataclass
29 class SiteConfig(object):
30     location_name: str
31     location: Location
32     network: str
33     network_netmask: str
34     network_router_ip: str
35     presence_location: Location
36     is_anyone_present: Callable
37     arper_minimum_device_count: int
38     arper_cache_file: str
39
40
41 def get_location_name():
42     """
43     Where are we?
44
45     >>> location = get_location_name()
46     >>> location == 'HOUSE' or location == 'CABIN'
47     True
48
49     """
50     return get_config().location_name
51
52
53 def get_location():
54     """
55     Returns location as an enum instead of a string.
56
57     >>> from type.locations import Location
58     >>> location = get_location()
59     >>> location == Location.HOUSE or location == Location.CABIN
60     True
61
62     """
63     return get_config().location
64
65
66 def is_anyone_present_wrapper(location: Location):
67     import base_presence
68
69     p = base_presence.PresenceDetection()
70     return p.is_anyone_in_location_now(location)
71
72
73 def other_location() -> str:
74     """
75     Returns the location where this program is _NOT_ running.
76
77     >>> x = other_location()
78     >>> x in set(['HOUSE', 'CABIN'])
79     True
80
81     """
82     hostname = platform.node()
83     if '.house' in hostname:
84         location = 'CABIN'
85     elif '.cabin' in hostname:
86         location = 'HOUSE'
87     else:
88         raise Exception(f"{hostname} doesn't help me know where I'm running?!")
89     return location
90
91
92 def this_location() -> str:
93     """
94     Returns the location where this program _IS_ running.
95
96     >>> x = this_location()
97     >>> x in set(['HOUSE', 'CABIN'])
98     True
99
100     """
101     hostname = platform.node()
102     if '.house' in hostname:
103         location = 'HOUSE'
104     elif '.cabin' in hostname:
105         location = 'CABIN'
106     else:
107         raise Exception(f"{hostname} doesn't help me know where I'm running?!")
108     return location
109
110
111 def effective_location(location_override: Optional[str] = None) -> str:
112     """Detects and returns a location taking into account two override
113     mechanisms.
114
115     >>> x = effective_location()
116     >>> x in set(['HOUSE', 'CABIN'])
117     True
118
119     >>> effective_location('HOUSE')
120     'HOUSE'
121
122     """
123     if location_override is None:
124         try:
125             location_override = config.config['site_config_override_location']
126         except KeyError:
127             location_override = None
128
129     if location_override is None or location_override == 'NONE':
130         location = this_location()
131     else:
132         logger.debug(f'site_config\'s location_override was set to: {location_override}')
133         location = location_override
134     return location
135
136
137 def get_config(location_override: Optional[str] = None):
138     """
139     Get a configuration dataclass with information that is
140     site-specific including the current running location.
141
142     >>> cfg = get_config()
143     >>> cfg.location_name == 'HOUSE' or cfg.location_name == 'CABIN'
144     True
145
146     """
147     location = effective_location(location_override)
148     if location == 'HOUSE':
149         return SiteConfig(
150             location_name='HOUSE',
151             location=Location.HOUSE,
152             network='10.0.0.0/24',
153             network_netmask='255.255.255.0',
154             network_router_ip='10.0.0.1',
155             presence_location=Location.HOUSE,
156             is_anyone_present=lambda x=Location.HOUSE: is_anyone_present_wrapper(x),
157             arper_minimum_device_count=50,
158             arper_cache_file='/home/scott/cache/.arp_table_cache_house',
159         )
160     elif location == 'CABIN':
161         return SiteConfig(
162             location_name='CABIN',
163             location=Location.CABIN,
164             network='192.168.0.0/24',
165             network_netmask='255.255.255.0',
166             network_router_ip='192.168.0.1',
167             presence_location=Location.CABIN,
168             is_anyone_present=lambda x=Location.CABIN: is_anyone_present_wrapper(x),
169             arper_minimum_device_count=15,
170             arper_cache_file='/home/scott/cache/.arp_table_cache_cabin',
171         )
172     else:
173         raise Exception(f'Unknown site location: {location}')
174
175
176 if __name__ == '__main__':
177     import doctest
178
179     doctest.testmod()