simo 2.0.3__py3-none-any.whl → 2.0.5__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/_hub_template/hub/nginx.conf +2 -2
- simo/core/api.py +1 -0
- simo/core/api_auth.py +4 -2
- simo/core/controllers.py +9 -4
- simo/fleet/forms.py +3 -1
- simo/fleet/models.py +9 -32
- simo/fleet/socket_consumers.py +11 -10
- simo/users/middleware.py +2 -4
- {simo-2.0.3.dist-info → simo-2.0.5.dist-info}/METADATA +2 -1
- {simo-2.0.3.dist-info → simo-2.0.5.dist-info}/RECORD +13 -13
- {simo-2.0.3.dist-info → simo-2.0.5.dist-info}/LICENSE.md +0 -0
- {simo-2.0.3.dist-info → simo-2.0.5.dist-info}/WHEEL +0 -0
- {simo-2.0.3.dist-info → simo-2.0.5.dist-info}/top_level.txt +0 -0
simo/core/api.py
CHANGED
|
@@ -14,6 +14,7 @@ from rest_framework.decorators import action
|
|
|
14
14
|
from rest_framework.response import Response as RESTResponse
|
|
15
15
|
from rest_framework.exceptions import ValidationError as APIValidationError
|
|
16
16
|
from simo.core.utils.config_values import ConfigException
|
|
17
|
+
from simo.users.middleware import introduce as introduce_user
|
|
17
18
|
from .models import (
|
|
18
19
|
Instance, Category, Zone, Component, Icon, ComponentHistory,
|
|
19
20
|
HistoryAggregate, Gateway
|
simo/core/api_auth.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
|
|
3
2
|
from rest_framework import HTTP_HEADER_ENCODING, exceptions
|
|
4
3
|
from simo.users.models import User
|
|
4
|
+
from simo.users.middleware import introduce as introduce_user
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class SecretKeyAuth(BasicAuthentication):
|
|
@@ -15,7 +15,7 @@ class SecretKeyAuth(BasicAuthentication):
|
|
|
15
15
|
|
|
16
16
|
if not user or not user.is_active:
|
|
17
17
|
return
|
|
18
|
-
|
|
18
|
+
introduce_user(user)
|
|
19
19
|
return (user, None)
|
|
20
20
|
|
|
21
21
|
def authenticate_header(self, request):
|
|
@@ -35,6 +35,8 @@ class IsAuthenticated(SessionAuthentication):
|
|
|
35
35
|
if not user.is_authenticated:
|
|
36
36
|
raise exceptions.NotAuthenticated()
|
|
37
37
|
|
|
38
|
+
introduce_user(user)
|
|
39
|
+
|
|
38
40
|
return (user, None)
|
|
39
41
|
|
|
40
42
|
def authenticate_header(self, request):
|
simo/core/controllers.py
CHANGED
|
@@ -222,13 +222,14 @@ class ControllerBase(ABC):
|
|
|
222
222
|
if value != self.component.value:
|
|
223
223
|
self.component.value_previous = self.component.value
|
|
224
224
|
self.component.value = value
|
|
225
|
+
|
|
225
226
|
self.component.change_init_by = None
|
|
226
227
|
self.component.change_init_date = None
|
|
227
228
|
self.component.change_init_to = None
|
|
228
229
|
self.component.change_init_fingerprint = None
|
|
229
230
|
self.component.save()
|
|
230
231
|
|
|
231
|
-
def _receive_from_device(self, value, is_alive=True):
|
|
232
|
+
def _receive_from_device(self, value, is_alive=True, battery_level=None):
|
|
232
233
|
value = self._prepare_for_set(value)
|
|
233
234
|
actor = self._get_actor(value)
|
|
234
235
|
|
|
@@ -241,7 +242,9 @@ class ControllerBase(ABC):
|
|
|
241
242
|
# in relation to the change of this component
|
|
242
243
|
introduce(actor)
|
|
243
244
|
self.component.alive = is_alive
|
|
244
|
-
|
|
245
|
+
if battery_level:
|
|
246
|
+
self.battery_level = battery_level
|
|
247
|
+
self.component.save(update_fields=['alive', 'battery_level'])
|
|
245
248
|
self.set(value, actor)
|
|
246
249
|
|
|
247
250
|
if init_by_device and self.component.slaves.count():
|
|
@@ -774,7 +777,7 @@ class Lock(Switch):
|
|
|
774
777
|
def unlock(self):
|
|
775
778
|
self.turn_off()
|
|
776
779
|
|
|
777
|
-
def _receive_from_device(self, value, is_alive=True):
|
|
780
|
+
def _receive_from_device(self, value, is_alive=True, battery_level=None):
|
|
778
781
|
if type(value) == bool:
|
|
779
782
|
if value:
|
|
780
783
|
value = 'locked'
|
|
@@ -789,7 +792,9 @@ class Lock(Switch):
|
|
|
789
792
|
self.FAULT: 'fault'
|
|
790
793
|
}
|
|
791
794
|
value = values_map.get(value, 'fault')
|
|
792
|
-
return super()._receive_from_device(
|
|
795
|
+
return super()._receive_from_device(
|
|
796
|
+
value, is_alive=is_alive, battery_level=battery_level
|
|
797
|
+
)
|
|
793
798
|
|
|
794
799
|
def _validate_val(self, value, occasion=None):
|
|
795
800
|
if occasion == BEFORE_SEND:
|
simo/fleet/forms.py
CHANGED
|
@@ -106,6 +106,8 @@ class ColonelComponentForm(BaseComponentForm):
|
|
|
106
106
|
)
|
|
107
107
|
|
|
108
108
|
def clean_colonel(self):
|
|
109
|
+
if not self.instance.pk:
|
|
110
|
+
return self.cleaned_data['colonel']
|
|
109
111
|
org = self.instance.config.get('colonel')
|
|
110
112
|
if org and org != self.cleaned_data['colonel'].id:
|
|
111
113
|
raise forms.ValidationError(
|
|
@@ -618,7 +620,7 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
|
|
|
618
620
|
help_text="easeOutSine - offers most naturally looking effect."
|
|
619
621
|
)
|
|
620
622
|
inverse = forms.BooleanField(
|
|
621
|
-
label=_("Inverse dimmer signal"), required=False
|
|
623
|
+
label=_("Inverse dimmer signal"), required=False, initial=True
|
|
622
624
|
)
|
|
623
625
|
on_value = forms.FloatField(
|
|
624
626
|
required=True, initial=100,
|
simo/fleet/models.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import requests
|
|
2
|
+
import time
|
|
2
3
|
from django.db import transaction
|
|
3
4
|
from django.db import models
|
|
4
5
|
from django.db.models.signals import post_save, pre_delete, post_delete
|
|
@@ -165,7 +166,8 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
165
166
|
@transaction.atomic
|
|
166
167
|
def rebuild_occupied_pins(self):
|
|
167
168
|
for pin in ColonelPin.objects.filter(colonel=self):
|
|
168
|
-
pin.
|
|
169
|
+
pin.occupied_by_id = None
|
|
170
|
+
pin.occupied_by_content_type = None
|
|
169
171
|
pin.save()
|
|
170
172
|
|
|
171
173
|
for component in self.components.all():
|
|
@@ -185,38 +187,13 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
185
187
|
interface.scl_pin.save()
|
|
186
188
|
|
|
187
189
|
|
|
188
|
-
@transaction.atomic()
|
|
189
190
|
def move_to(self, other_colonel):
|
|
190
|
-
|
|
191
|
-
other_colonel.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
component.config['colonel'] = other_colonel.id
|
|
197
|
-
component.save()
|
|
198
|
-
self.components.remove(component)
|
|
199
|
-
other_colonel.components.add(component)
|
|
200
|
-
|
|
201
|
-
other_colonel.i2c_interfaces.all().delete()
|
|
202
|
-
|
|
203
|
-
for i2c_interface in self.i2c_interfaces.all():
|
|
204
|
-
I2CInterface.objects.create(
|
|
205
|
-
no=i2c_interface.no,
|
|
206
|
-
colonel=other_colonel, name=i2c_interface.name,
|
|
207
|
-
freq=i2c_interface.freq,
|
|
208
|
-
scl_pin=ColonelPin.objects.get(
|
|
209
|
-
colonel=other_colonel, no=i2c_interface.scl_pin.no,
|
|
210
|
-
),
|
|
211
|
-
sda_pin=ColonelPin.objects.get(
|
|
212
|
-
colonel=other_colonel, no=i2c_interface.sda_pin.no,
|
|
213
|
-
),
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
self.rebuild_occupied_pins()
|
|
217
|
-
other_colonel.rebuild_occupied_pins()
|
|
218
|
-
self.update_config()
|
|
219
|
-
other_colonel.update_config()
|
|
191
|
+
self.restart()
|
|
192
|
+
other_colonel.restart()
|
|
193
|
+
time.sleep(1)
|
|
194
|
+
self.uid = other_colonel.uid
|
|
195
|
+
other_colonel.delete()
|
|
196
|
+
self.save()
|
|
220
197
|
|
|
221
198
|
|
|
222
199
|
class ColonelPin(models.Model):
|
simo/fleet/socket_consumers.py
CHANGED
|
@@ -46,6 +46,8 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
async def connect(self):
|
|
49
|
+
print("Fleet Socket Connect with headers:", self.scope.get('headers'))
|
|
50
|
+
await self.accept()
|
|
49
51
|
|
|
50
52
|
headers = {
|
|
51
53
|
item[0].decode().lower(): item[1].decode() for item in self.scope['headers']
|
|
@@ -91,7 +93,8 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
91
93
|
'name': headers.get('colonel-name'),
|
|
92
94
|
'type': headers['colonel-type'],
|
|
93
95
|
'firmware_version': headers['firmware-version'],
|
|
94
|
-
'last_seen': timezone.now()
|
|
96
|
+
'last_seen': timezone.now(),
|
|
97
|
+
'enabled': True
|
|
95
98
|
}
|
|
96
99
|
with transaction.atomic():
|
|
97
100
|
colonel, new = Colonel.objects.get_or_create(
|
|
@@ -99,10 +102,10 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
99
102
|
)
|
|
100
103
|
if not new:
|
|
101
104
|
for key, val in defaults.items():
|
|
105
|
+
if key in ('new', ):
|
|
106
|
+
continue
|
|
102
107
|
setattr(colonel, key, val)
|
|
103
|
-
|
|
104
|
-
colonel.enabled = True
|
|
105
|
-
colonel.save()
|
|
108
|
+
colonel.save()
|
|
106
109
|
|
|
107
110
|
return colonel, new
|
|
108
111
|
|
|
@@ -113,7 +116,6 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
113
116
|
print(f"Colonel {self.colonel} connected!")
|
|
114
117
|
if not self.colonel.enabled:
|
|
115
118
|
print("Colonel %s drop, it's not enabled!" % str(self.colonel))
|
|
116
|
-
await self.accept()
|
|
117
119
|
return await self.close()
|
|
118
120
|
|
|
119
121
|
if headers.get('instance-uid') != self.colonel.instance.uid \
|
|
@@ -123,8 +125,6 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
123
125
|
|
|
124
126
|
self.connected = True
|
|
125
127
|
|
|
126
|
-
await self.accept()
|
|
127
|
-
|
|
128
128
|
await self.log_colonel_connected()
|
|
129
129
|
|
|
130
130
|
|
|
@@ -370,18 +370,19 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
370
370
|
)(id=id)
|
|
371
371
|
|
|
372
372
|
if 'val' in data:
|
|
373
|
-
def receive_val(
|
|
373
|
+
def receive_val(data):
|
|
374
374
|
if data.get('actor'):
|
|
375
375
|
fingerprint = Fingerprint.objects.filter(
|
|
376
376
|
value=f"ttlock-{component.id}-{data.get('actor')}",
|
|
377
377
|
).first()
|
|
378
378
|
component.change_init_fingerprint = fingerprint
|
|
379
379
|
component.controller._receive_from_device(
|
|
380
|
-
val, bool(data.get('alive'))
|
|
380
|
+
data['val'], bool(data.get('alive')),
|
|
381
|
+
data.get('battery_level')
|
|
381
382
|
)
|
|
382
383
|
await sync_to_async(
|
|
383
384
|
receive_val, thread_sensitive=True
|
|
384
|
-
)(data
|
|
385
|
+
)(data)
|
|
385
386
|
|
|
386
387
|
if 'options' in data:
|
|
387
388
|
def receive_options(val):
|
simo/users/middleware.py
CHANGED
|
@@ -11,9 +11,8 @@ import threading
|
|
|
11
11
|
|
|
12
12
|
# We use daphne for asgi, which seems to be working fine for what we have already
|
|
13
13
|
# observed. However, this is a good candidate for reworking it in to something
|
|
14
|
-
# more
|
|
14
|
+
# more robust.
|
|
15
15
|
|
|
16
|
-
# TODO: rework this in to something more roboust
|
|
17
16
|
|
|
18
17
|
_thread_locals = threading.local()
|
|
19
18
|
|
|
@@ -39,7 +38,6 @@ class IntroduceUser:
|
|
|
39
38
|
self.get_response = get_response
|
|
40
39
|
|
|
41
40
|
def __call__(self, request):
|
|
42
|
-
response = self.get_response(request)
|
|
43
41
|
if request.user.is_authenticated:
|
|
44
42
|
introduce(request.user)
|
|
45
|
-
return
|
|
43
|
+
return self.get_response(request)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simo
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
4
4
|
Summary: Smart Home on Steroids!
|
|
5
5
|
Author-email: Simanas Venčkauskas <simanas@simo.io>
|
|
6
6
|
Project-URL: Homepage, https://simo.io
|
|
@@ -43,4 +43,5 @@ Requires-Dist: ansi2html ==1.7.0
|
|
|
43
43
|
Requires-Dist: slugify ==0.0.1
|
|
44
44
|
Requires-Dist: django-countries ==7.5.1
|
|
45
45
|
Requires-Dist: librosa ==0.10.1
|
|
46
|
+
Requires-Dist: daphne ==4.1.0
|
|
46
47
|
|
|
@@ -20,21 +20,21 @@ simo/__pycache__/wsgi.cpython-38.pyc,sha256=Wt9kKkH2Sg5LRL4NrVQQDYPIoDyTvnXwm6jZ
|
|
|
20
20
|
simo/_hub_template/hub/asgi.py,sha256=ElN_fdeSkf0Ysa7pS9rJVmZ1HmLhFxb8jFaMLqe1220,126
|
|
21
21
|
simo/_hub_template/hub/celeryc.py,sha256=3ksDXftIZKJ4Cq9WNKJERdZdQlDEnjTQXycweRFmsSQ,27
|
|
22
22
|
simo/_hub_template/hub/manage.py,sha256=PNNlw3EVeIJDgkG0l-klqoxsKWfTYWG9jzRG0upmAaI,620
|
|
23
|
-
simo/_hub_template/hub/nginx.conf,sha256=
|
|
23
|
+
simo/_hub_template/hub/nginx.conf,sha256=MOJljsz_symwQF_L7ubp2ZnhkE7BrvkzIxZPtd1sWw0,2000
|
|
24
24
|
simo/_hub_template/hub/settings.py,sha256=4QhvhbtLRxHvAntwqG_qeAAtpDUqKvN4jzw9u3vqff8,361
|
|
25
25
|
simo/_hub_template/hub/supervisor.conf,sha256=IY3fdK0fDD2eAothB0n54xhjQj8LYoXIR96-Adda5Z8,1353
|
|
26
26
|
simo/_hub_template/hub/urls.py,sha256=Ydm-1BkYAzWeEF-MKSDIFf-7aE4qNLPm48-SA51XgJQ,25
|
|
27
27
|
simo/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
simo/core/admin.py,sha256=SXZlKI2aiEscDS12qXdkxDa30GNkFsgnJMT711S1wuw,17525
|
|
29
|
-
simo/core/api.py,sha256=
|
|
30
|
-
simo/core/api_auth.py,sha256=
|
|
29
|
+
simo/core/api.py,sha256=D2uX25Do7UkKaYNNY5ZIMtuet8r-_XgoEzK9324smkw,23695
|
|
30
|
+
simo/core/api_auth.py,sha256=_3hG4e1eLKrcRnSAOB_xTL6cwtOJ2_7JS7GZU_iqTgA,1251
|
|
31
31
|
simo/core/api_meta.py,sha256=li4KLFl6xTYOoD8pgS8PYcjqTZlzhXI0reAkt06PZFA,3404
|
|
32
32
|
simo/core/app_widgets.py,sha256=EEQOto3fGR0syDqpJE38tQrx8DoTTyg26nF5kYzHY38,2018
|
|
33
33
|
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=paeZU6Ky2LgRTwj9nFqrgfeJ4kxWPcl95WDTf6P7jOo,27200
|
|
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
|
|
@@ -10125,13 +10125,13 @@ simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
|
|
|
10125
10125
|
simo/fleet/auto_urls.py,sha256=gAXTWUvsWkQHRdZGM_W_5iJBEsM4lY063kIx3f5LUqs,578
|
|
10126
10126
|
simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
|
|
10127
10127
|
simo/fleet/controllers.py,sha256=N8Qzdp2RPFrpZ_l9O4u8VjHWoY_WTWGg76s3V3oJqEs,13999
|
|
10128
|
-
simo/fleet/forms.py,sha256=
|
|
10128
|
+
simo/fleet/forms.py,sha256=HpvcdFyMl9dLNx1sEOkAkXOkYht6ku2HwWWga-PJzZQ,35067
|
|
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=O0lsXRmTgPyOhpcwWeJ-2GHTNe2uFhiJy4FTW9Ljz-c,11830
|
|
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=xNeR1IuaBTiHO2GEXwB1_4CJ29uMlqBycIUdxGT96E8,19578
|
|
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
|
|
@@ -10276,7 +10276,7 @@ simo/users/api.py,sha256=xJCCj75eQXdaYfiCxxG_rMDKzEZuYuCadOhOutqX2YY,9053
|
|
|
10276
10276
|
simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
|
|
10277
10277
|
simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
|
|
10278
10278
|
simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
|
|
10279
|
-
simo/users/middleware.py,sha256=
|
|
10279
|
+
simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
|
|
10280
10280
|
simo/users/models.py,sha256=f59mkQBpq_fFLDUa-44b1qWleB-TvGdC1M0G67huJMg,18498
|
|
10281
10281
|
simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
|
|
10282
10282
|
simo/users/serializers.py,sha256=yrWghK7ONxfzkjO3LbDLK1WPxsPBMYUegdm29qovjjo,2486
|
|
@@ -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.5.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10347
|
+
simo-2.0.5.dist-info/METADATA,sha256=aQw7niHw3pcQrYlEkzWz-SoLhr68a4It838k65sh08Q,1699
|
|
10348
|
+
simo-2.0.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
10349
|
+
simo-2.0.5.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10350
|
+
simo-2.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|