simo 2.0.2__py3-none-any.whl → 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of simo might be problematic. Click here for more details.
- simo/core/controllers.py +16 -1
- simo/core/socket_consumers.py +5 -0
- simo/core/utils/logs.py +34 -0
- simo/fleet/models.py +8 -7
- simo/fleet/socket_consumers.py +99 -92
- {simo-2.0.2.dist-info → simo-2.0.3.dist-info}/METADATA +1 -1
- {simo-2.0.2.dist-info → simo-2.0.3.dist-info}/RECORD +10 -10
- {simo-2.0.2.dist-info → simo-2.0.3.dist-info}/LICENSE.md +0 -0
- {simo-2.0.2.dist-info → simo-2.0.3.dist-info}/WHEEL +0 -0
- {simo-2.0.2.dist-info → simo-2.0.3.dist-info}/top_level.txt +0 -0
simo/core/controllers.py
CHANGED
|
@@ -762,6 +762,12 @@ class Lock(Switch):
|
|
|
762
762
|
app_widget = LockWidget
|
|
763
763
|
admin_widget_template = 'admin/controller_widgets/lock.html'
|
|
764
764
|
|
|
765
|
+
UNLOCKED = 0
|
|
766
|
+
LOCKED = 1
|
|
767
|
+
LOCKING = 2
|
|
768
|
+
UNLOCKING = 3
|
|
769
|
+
FAULT = 4
|
|
770
|
+
|
|
765
771
|
def lock(self):
|
|
766
772
|
self.turn_on()
|
|
767
773
|
|
|
@@ -769,11 +775,20 @@ class Lock(Switch):
|
|
|
769
775
|
self.turn_off()
|
|
770
776
|
|
|
771
777
|
def _receive_from_device(self, value, is_alive=True):
|
|
772
|
-
if type(value)
|
|
778
|
+
if type(value) == bool:
|
|
773
779
|
if value:
|
|
774
780
|
value = 'locked'
|
|
775
781
|
else:
|
|
776
782
|
value = 'unlocked'
|
|
783
|
+
if type(value) == int:
|
|
784
|
+
values_map = {
|
|
785
|
+
self.UNLOCKED: 'unlocked',
|
|
786
|
+
self.LOCKED: 'locked',
|
|
787
|
+
self.LOCKING: 'locking',
|
|
788
|
+
self.UNLOCKING: 'unlocking',
|
|
789
|
+
self.FAULT: 'fault'
|
|
790
|
+
}
|
|
791
|
+
value = values_map.get(value, 'fault')
|
|
777
792
|
return super()._receive_from_device(value, is_alive=is_alive)
|
|
778
793
|
|
|
779
794
|
def _validate_val(self, value, occasion=None):
|
simo/core/socket_consumers.py
CHANGED
|
@@ -7,6 +7,7 @@ from django.conf import settings
|
|
|
7
7
|
from django.contrib.contenttypes.models import ContentType
|
|
8
8
|
from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer
|
|
9
9
|
from simo.core.events import ObjectChangeEvent, get_event_obj
|
|
10
|
+
from simo.core.utils.logs import capture_socket_errors
|
|
10
11
|
import paho.mqtt.client as mqtt
|
|
11
12
|
from simo.users.middleware import introduce
|
|
12
13
|
from simo.core.models import Component, Gateway
|
|
@@ -14,6 +15,7 @@ from simo.core.utils.model_helpers import get_log_file_path
|
|
|
14
15
|
from simo.core.middleware import introduce_instance
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
@capture_socket_errors
|
|
17
19
|
class SIMOWebsocketConsumer(WebsocketConsumer):
|
|
18
20
|
headers = {}
|
|
19
21
|
|
|
@@ -24,6 +26,7 @@ class SIMOWebsocketConsumer(WebsocketConsumer):
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
|
|
29
|
+
@capture_socket_errors
|
|
27
30
|
class LogConsumer(AsyncWebsocketConsumer):
|
|
28
31
|
log_file = None
|
|
29
32
|
in_error = False
|
|
@@ -123,6 +126,7 @@ class LogConsumer(AsyncWebsocketConsumer):
|
|
|
123
126
|
self.log_file = None
|
|
124
127
|
|
|
125
128
|
|
|
129
|
+
@capture_socket_errors
|
|
126
130
|
class GatewayController(SIMOWebsocketConsumer):
|
|
127
131
|
gateway = None
|
|
128
132
|
_mqtt_client = None
|
|
@@ -178,6 +182,7 @@ class GatewayController(SIMOWebsocketConsumer):
|
|
|
178
182
|
pass
|
|
179
183
|
|
|
180
184
|
|
|
185
|
+
@capture_socket_errors
|
|
181
186
|
class ComponentController(SIMOWebsocketConsumer):
|
|
182
187
|
component = None
|
|
183
188
|
send_value = False
|
simo/core/utils/logs.py
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from inspect import iscoroutinefunction
|
|
4
|
+
from logging import getLogger
|
|
5
|
+
from channels.exceptions import AcceptConnection, DenyConnection, StopConsumer
|
|
6
|
+
|
|
7
|
+
logger = getLogger()
|
|
2
8
|
|
|
3
9
|
|
|
4
10
|
class StreamToLogger(object):
|
|
@@ -28,3 +34,31 @@ class StreamToLogger(object):
|
|
|
28
34
|
if self.linebuf != '':
|
|
29
35
|
self.logger.log(self.log_level, self.linebuf.rstrip())
|
|
30
36
|
self.linebuf = ''
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def propagate_exceptions(func):
|
|
42
|
+
async def wrapper(*args, **kwargs): # we're wrapping an async function
|
|
43
|
+
try:
|
|
44
|
+
return await func(*args, **kwargs)
|
|
45
|
+
except (AcceptConnection, DenyConnection, StopConsumer): # these are handled by channels
|
|
46
|
+
raise
|
|
47
|
+
except Exception as exception: # any other exception
|
|
48
|
+
# avoid logging the same exception multiple times
|
|
49
|
+
if not getattr(exception, "caught", False):
|
|
50
|
+
setattr(exception, "caught", True)
|
|
51
|
+
logger.error(
|
|
52
|
+
"Exception occurred in {}:".format(func.__qualname__),
|
|
53
|
+
exc_info=exception,
|
|
54
|
+
)
|
|
55
|
+
raise # propagate the exception
|
|
56
|
+
return wraps(func)(wrapper)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def capture_socket_errors(consumer_class):
|
|
60
|
+
for method_name, method in list(consumer_class.__dict__.items()):
|
|
61
|
+
if iscoroutinefunction(method): # an async method
|
|
62
|
+
# wrap the method with a decorator that propagate exceptions
|
|
63
|
+
setattr(consumer_class, method_name, propagate_exceptions(method))
|
|
64
|
+
return consumer_class
|
simo/fleet/models.py
CHANGED
|
@@ -82,10 +82,12 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
82
82
|
occupied_pins = models.JSONField(default=dict, blank=True)
|
|
83
83
|
|
|
84
84
|
logs_stream = models.BooleanField(
|
|
85
|
-
default=False, help_text="ATENTION! Causes serious overhead
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
85
|
+
default=False, help_text="ATENTION! Causes serious overhead and "
|
|
86
|
+
"significantly degrades the lifespan of a chip "
|
|
87
|
+
"due to a lot of writes to the memory. "
|
|
88
|
+
"It also causes Colonel websocket to run out of memory "
|
|
89
|
+
"and reset if a lot of data is being transmitted. "
|
|
90
|
+
"Leave this off, unleess you know what you are doing!"
|
|
89
91
|
)
|
|
90
92
|
pwm_frequency = models.IntegerField(default=1, choices=(
|
|
91
93
|
(0, "3kHz"), (1, "22kHz")
|
|
@@ -196,9 +198,6 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
196
198
|
self.components.remove(component)
|
|
197
199
|
other_colonel.components.add(component)
|
|
198
200
|
|
|
199
|
-
self.rebuild_occupied_pins()
|
|
200
|
-
other_colonel.rebuild_occupied_pins()
|
|
201
|
-
|
|
202
201
|
other_colonel.i2c_interfaces.all().delete()
|
|
203
202
|
|
|
204
203
|
for i2c_interface in self.i2c_interfaces.all():
|
|
@@ -214,6 +213,8 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
214
213
|
),
|
|
215
214
|
)
|
|
216
215
|
|
|
216
|
+
self.rebuild_occupied_pins()
|
|
217
|
+
other_colonel.rebuild_occupied_pins()
|
|
217
218
|
self.update_config()
|
|
218
219
|
other_colonel.update_config()
|
|
219
220
|
|
simo/fleet/socket_consumers.py
CHANGED
|
@@ -13,15 +13,18 @@ import paho.mqtt.client as mqtt
|
|
|
13
13
|
from channels.generic.websocket import AsyncWebsocketConsumer
|
|
14
14
|
from asgiref.sync import sync_to_async
|
|
15
15
|
from simo.core.utils.model_helpers import get_log_file_path
|
|
16
|
+
from simo.core.utils.logs import capture_socket_errors
|
|
16
17
|
from simo.core.events import GatewayObjectCommand, get_event_obj
|
|
17
18
|
from simo.core.models import Gateway, Instance, Component
|
|
18
19
|
from simo.conf import dynamic_settings
|
|
19
20
|
from simo.users.models import Fingerprint
|
|
21
|
+
|
|
20
22
|
from .gateways import FleetGatewayHandler
|
|
21
23
|
from .models import Colonel
|
|
22
24
|
from .controllers import TTLock
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
@capture_socket_errors
|
|
25
28
|
class FleetConsumer(AsyncWebsocketConsumer):
|
|
26
29
|
colonel = None
|
|
27
30
|
colonel_logger = None
|
|
@@ -345,106 +348,110 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
345
348
|
|
|
346
349
|
|
|
347
350
|
async def receive(self, text_data=None, bytes_data=None):
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
351
|
+
try:
|
|
352
|
+
if text_data:
|
|
353
|
+
print(f"{self.colonel}: {text_data}")
|
|
354
|
+
data = json.loads(text_data)
|
|
355
|
+
if 'get_config' in data:
|
|
356
|
+
config = await self.get_config_data()
|
|
357
|
+
print("Send config: ", config)
|
|
358
|
+
await self.send_data({
|
|
359
|
+
'command': 'set_config', 'data': config
|
|
360
|
+
}, compress=True)
|
|
361
|
+
elif 'comp' in data:
|
|
359
362
|
try:
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
await sync_to_async(
|
|
379
|
-
receive_val, thread_sensitive=True
|
|
380
|
-
)(data['val'])
|
|
381
|
-
|
|
382
|
-
if 'options' in data:
|
|
383
|
-
def receive_options(val):
|
|
384
|
-
component.meta['options'] = val
|
|
385
|
-
component.save()
|
|
386
|
-
await sync_to_async(
|
|
387
|
-
receive_options, thread_sensitive=True
|
|
388
|
-
)(data['options'])
|
|
389
|
-
|
|
390
|
-
if 'codes' in data and component.controller_uid == TTLock.uid:
|
|
391
|
-
def save_codes(codes):
|
|
392
|
-
component.meta['codes'] = codes
|
|
393
|
-
for code in codes:
|
|
394
|
-
Fingerprint.objects.get_or_create(
|
|
395
|
-
value=f"ttlock-{component.id}-code-{str(code)}",
|
|
396
|
-
defaults={'type': "TTLock code"}
|
|
397
|
-
)
|
|
398
|
-
component.save()
|
|
399
|
-
await sync_to_async(
|
|
400
|
-
save_codes, thread_sensitive=True
|
|
401
|
-
)(data['codes'])
|
|
402
|
-
if 'fingerprints' in data and component.controller_uid == TTLock.uid:
|
|
403
|
-
def save_codes(codes):
|
|
404
|
-
component.meta['fingerprints'] = codes
|
|
405
|
-
for code in codes:
|
|
406
|
-
Fingerprint.objects.get_or_create(
|
|
407
|
-
value=f"ttlock-{component.id}-finger-{str(code)}",
|
|
408
|
-
defaults={'type': "TTLock Fingerprint"}
|
|
363
|
+
try:
|
|
364
|
+
id=int(data['comp'])
|
|
365
|
+
except:
|
|
366
|
+
return
|
|
367
|
+
|
|
368
|
+
component = await sync_to_async(
|
|
369
|
+
Component.objects.get, thread_sensitive=True
|
|
370
|
+
)(id=id)
|
|
371
|
+
|
|
372
|
+
if 'val' in data:
|
|
373
|
+
def receive_val(val):
|
|
374
|
+
if data.get('actor'):
|
|
375
|
+
fingerprint = Fingerprint.objects.filter(
|
|
376
|
+
value=f"ttlock-{component.id}-{data.get('actor')}",
|
|
377
|
+
).first()
|
|
378
|
+
component.change_init_fingerprint = fingerprint
|
|
379
|
+
component.controller._receive_from_device(
|
|
380
|
+
val, bool(data.get('alive'))
|
|
409
381
|
)
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
382
|
+
await sync_to_async(
|
|
383
|
+
receive_val, thread_sensitive=True
|
|
384
|
+
)(data['val'])
|
|
385
|
+
|
|
386
|
+
if 'options' in data:
|
|
387
|
+
def receive_options(val):
|
|
388
|
+
component.meta['options'] = val
|
|
389
|
+
component.save()
|
|
390
|
+
await sync_to_async(
|
|
391
|
+
receive_options, thread_sensitive=True
|
|
392
|
+
)(data['options'])
|
|
393
|
+
|
|
394
|
+
if 'codes' in data and component.controller_uid == TTLock.uid:
|
|
395
|
+
def save_codes(codes):
|
|
396
|
+
component.meta['codes'] = codes
|
|
397
|
+
for code in codes:
|
|
398
|
+
Fingerprint.objects.get_or_create(
|
|
399
|
+
value=f"ttlock-{component.id}-code-{str(code)}",
|
|
400
|
+
defaults={'type': "TTLock code"}
|
|
401
|
+
)
|
|
402
|
+
component.save()
|
|
403
|
+
await sync_to_async(
|
|
404
|
+
save_codes, thread_sensitive=True
|
|
405
|
+
)(data['codes'])
|
|
406
|
+
if 'fingerprints' in data and component.controller_uid == TTLock.uid:
|
|
407
|
+
def save_codes(codes):
|
|
408
|
+
component.meta['fingerprints'] = codes
|
|
409
|
+
for code in codes:
|
|
410
|
+
Fingerprint.objects.get_or_create(
|
|
411
|
+
value=f"ttlock-{component.id}-finger-{str(code)}",
|
|
412
|
+
defaults={'type': "TTLock Fingerprint"}
|
|
413
|
+
)
|
|
414
|
+
component.save()
|
|
415
|
+
await sync_to_async(
|
|
416
|
+
save_codes, thread_sensitive=True
|
|
417
|
+
)(data['fingerprints'])
|
|
418
|
+
|
|
427
419
|
except Exception as e:
|
|
428
420
|
print(traceback.format_exc(), file=sys.stderr)
|
|
429
|
-
self.gateway.finish_discovery()
|
|
430
421
|
|
|
431
|
-
|
|
432
|
-
process_discovery_result
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
422
|
+
elif 'discover-ttlock' in data:
|
|
423
|
+
def process_discovery_result():
|
|
424
|
+
self.gateway.refresh_from_db()
|
|
425
|
+
if self.gateway.discovery.get('finished'):
|
|
426
|
+
return Component.objects.filter(
|
|
427
|
+
meta__finalization_data__temp_id=data['result']['id']
|
|
428
|
+
).first()
|
|
429
|
+
try:
|
|
430
|
+
self.gateway.process_discovery(data)
|
|
431
|
+
except Exception as e:
|
|
432
|
+
print(traceback.format_exc(), file=sys.stderr)
|
|
433
|
+
self.gateway.finish_discovery()
|
|
434
|
+
|
|
435
|
+
finished_comp = await sync_to_async(
|
|
436
|
+
process_discovery_result, thread_sensitive=True
|
|
437
|
+
)()
|
|
438
|
+
if finished_comp:
|
|
439
|
+
await self.send_data({
|
|
440
|
+
'command': 'finalize',
|
|
441
|
+
'data': finished_comp.meta['finalization_data']
|
|
442
|
+
})
|
|
439
443
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
444
|
+
elif bytes_data:
|
|
445
|
+
if not self.colonel_logger:
|
|
446
|
+
await self.start_logger()
|
|
443
447
|
|
|
444
|
-
|
|
445
|
-
|
|
448
|
+
for logline in bytes_data.decode(errors='replace').split('\n'):
|
|
449
|
+
self.colonel_logger.log(logging.INFO, logline)
|
|
450
|
+
|
|
451
|
+
await self.log_colonel_connected()
|
|
452
|
+
except Exception as e:
|
|
453
|
+
print(traceback.format_exc(), file=sys.stderr)
|
|
446
454
|
|
|
447
|
-
await self.log_colonel_connected()
|
|
448
455
|
|
|
449
456
|
|
|
450
457
|
async def log_colonel_connected(self):
|
|
@@ -34,7 +34,7 @@ simo/core/auto_urls.py,sha256=0gu-IL7PHobrmKW6ksffiOkAYu-aIorykWdxRNtwGYo,1194
|
|
|
34
34
|
simo/core/autocomplete_views.py,sha256=JT5LA2_Wtr60XYSAIqaXFKFYPjrmkEf6yunXD9y2zco,4022
|
|
35
35
|
simo/core/base_types.py,sha256=yqbIZqBksrAkEuHRbt6iExwPDDy0K5II2NzRCkmOvMU,589
|
|
36
36
|
simo/core/context.py,sha256=98PXAMie43faRVBFkOG22uNpvGRNprcGhzjBFkrxaRY,1367
|
|
37
|
-
simo/core/controllers.py,sha256=
|
|
37
|
+
simo/core/controllers.py,sha256=7M28j0I2Eh-Q7jIXZ7FMkNQoA7xluu67NSXhJXaW4gs,27018
|
|
38
38
|
simo/core/dynamic_settings.py,sha256=U2WNL96JzVXdZh0EqMPWrxqO6BaRR2Eo5KTDqz7MC4o,1943
|
|
39
39
|
simo/core/events.py,sha256=LvtonJGNyCb6HLozs4EG0WZItnDwNdtnGQ4vTcnKvUs,4438
|
|
40
40
|
simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
|
|
@@ -48,7 +48,7 @@ simo/core/permissions.py,sha256=UmFjGPDWtAUbaWxJsWORb2q6BREHqndv9mkSIpnmdLk,1379
|
|
|
48
48
|
simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
|
|
49
49
|
simo/core/serializers.py,sha256=bkfXZgUzbXZOrJY69VIevBHNLWRd7DmgyFRh4arr-gs,15810
|
|
50
50
|
simo/core/signal_receivers.py,sha256=EZ8NSYZxUgSaLS16YZdK7T__l8dl0joMRllOxx5PUt4,2809
|
|
51
|
-
simo/core/socket_consumers.py,sha256=
|
|
51
|
+
simo/core/socket_consumers.py,sha256=n7VE2Fvqt4iEAYLTRbTPOcI-7tszMAADu7gimBxB-Fg,9635
|
|
52
52
|
simo/core/storage.py,sha256=YlxmdRs-zhShWtFKgpJ0qp2NDBuIkJGYC1OJzqkbttQ,572
|
|
53
53
|
simo/core/tasks.py,sha256=se27V-noW02v4ZY2PMv0AJkXNsY3NtJ4G43__KLW7Kg,11005
|
|
54
54
|
simo/core/todos.py,sha256=eYVXfLGiapkxKK57XuviSNe3WsUYyIWZ0hgQJk7ThKo,665
|
|
@@ -10110,7 +10110,7 @@ simo/core/utils/form_fields.py,sha256=UOzYdPd71qgCw1H3qH01u85YjrOlETPJAHOJrZKhyD
|
|
|
10110
10110
|
simo/core/utils/form_widgets.py,sha256=Zxn9jJqPle9Q_BKNJnyTDn7MosYwNp1TFu5LoKs0bfc,408
|
|
10111
10111
|
simo/core/utils/formsets.py,sha256=1u34QGZ2P67cxZD2uUJS3lAf--E8XsiiqFmZ4P41Vw4,6463
|
|
10112
10112
|
simo/core/utils/helpers.py,sha256=TOWy3slspaEYEhe9zDcb0RgzHUYslF6LZDlrWPGSqUI,3791
|
|
10113
|
-
simo/core/utils/logs.py,sha256=
|
|
10113
|
+
simo/core/utils/logs.py,sha256=Zn9JQxqCH9Odx2J1BWT84nFCfkJ4Z4p5X8psdll7hNc,2366
|
|
10114
10114
|
simo/core/utils/mixins.py,sha256=X6kUPKAi_F-uw7tgm8LEaYalBXpvDA-yrLNFCGr2rks,259
|
|
10115
10115
|
simo/core/utils/model_helpers.py,sha256=3IzJeOvBoYdUJVXCJkY20npOZXPjNPAiEFvuT0OPhwA,884
|
|
10116
10116
|
simo/core/utils/relay.py,sha256=i1xy_nPTgY5Xn0l2W4lNI3xeVUpDQTUUfV3M8h2DeBg,457
|
|
@@ -10128,10 +10128,10 @@ simo/fleet/controllers.py,sha256=N8Qzdp2RPFrpZ_l9O4u8VjHWoY_WTWGg76s3V3oJqEs,139
|
|
|
10128
10128
|
simo/fleet/forms.py,sha256=UGj1mK2Zbl2LRlvLtEDObeGfC2wcuHleRbePo1_Vx6I,34972
|
|
10129
10129
|
simo/fleet/gateways.py,sha256=xFsmF_SXYXK_kMJOCHkiInPJ_0VcPWz-kJDoMup2lT8,1576
|
|
10130
10130
|
simo/fleet/managers.py,sha256=kpfvvfdH4LDxddIBDpdAb5gsVk8Gb0-L9biFcj9OFPs,807
|
|
10131
|
-
simo/fleet/models.py,sha256=
|
|
10131
|
+
simo/fleet/models.py,sha256=Ro0ZkYB3a7ZhczVQOxjAobCRECIdN0Nj0yb5EBybvW0,12809
|
|
10132
10132
|
simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
|
|
10133
10133
|
simo/fleet/serializers.py,sha256=zEpXAXxjk4Rf1JhlNnLTrs20qJggqjvIySbeHVo4Tt4,1505
|
|
10134
|
-
simo/fleet/socket_consumers.py,sha256=
|
|
10134
|
+
simo/fleet/socket_consumers.py,sha256=o8yr27AYxKFStQGyXZrk7PP1P2fUgSjsWp76DojWqbM,19415
|
|
10135
10135
|
simo/fleet/utils.py,sha256=D0EGFbDmW8zyhyxf5ozGtRpo4Sy5Ov6ZixukBK_e2Do,3462
|
|
10136
10136
|
simo/fleet/views.py,sha256=PbdZpsM_7-oyKzuDX1A5WULNABA1_B7ISF70UJX97FE,1662
|
|
10137
10137
|
simo/fleet/__pycache__/__init__.cpython-38.pyc,sha256=pIZE7EL6-cuJ3pQtaSwjKLrKLsTYelp1k9sRhXKLh6s,159
|
|
@@ -10343,8 +10343,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10343
10343
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10344
10344
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10345
10345
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10346
|
-
simo-2.0.
|
|
10347
|
-
simo-2.0.
|
|
10348
|
-
simo-2.0.
|
|
10349
|
-
simo-2.0.
|
|
10350
|
-
simo-2.0.
|
|
10346
|
+
simo-2.0.3.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10347
|
+
simo-2.0.3.dist-info/METADATA,sha256=kIgoVnqVIeZ9Paw4f7G6PA41Nwe3dafpPmpEbRV5JU4,1669
|
|
10348
|
+
simo-2.0.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
10349
|
+
simo-2.0.3.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10350
|
+
simo-2.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|