simo 2.5.39__py3-none-any.whl → 2.5.41__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.

Binary file
Binary file
simo/core/api.py CHANGED
@@ -12,6 +12,7 @@ from actstream.models import Action
12
12
  from rest_framework.pagination import PageNumberPagination
13
13
  from rest_framework import viewsets
14
14
  from django_filters.rest_framework import DjangoFilterBackend
15
+ from django.core.cache import cache
15
16
  from rest_framework.decorators import action
16
17
  from rest_framework.response import Response as RESTResponse
17
18
  from rest_framework.exceptions import ValidationError as APIValidationError
@@ -143,43 +144,55 @@ class ZoneViewSet(InstanceMixin, viewsets.ModelViewSet):
143
144
  return RESTResponse({'status': 'success'})
144
145
 
145
146
 
146
- def get_components_queryset(instance, user):
147
- qs = Component.objects.filter(zone__instance=instance)
148
- if user.is_superuser:
149
- return qs
150
-
151
- c_ids = set()
147
+ def get_main_components_ids(instance):
148
+ cache_key = f"main-components-{instance.id}"
149
+ ids = cache.get(cache_key)
150
+ if ids:
151
+ return ids
152
152
 
153
+ ids = []
153
154
  from simo.generic.controllers import Weather
154
155
 
155
156
  if instance.indoor_climate_sensor:
156
- c_ids.add(instance.indoor_climate_sensor.id)
157
+ ids.append(instance.indoor_climate_sensor.id)
157
158
  wf_c = Component.objects.filter(
158
159
  zone__instance=instance,
159
160
  controller_uid=Weather.uid, config__is_main=True
160
161
  ).values('id').first()
161
162
  if wf_c:
162
- c_ids.add(wf_c['id'])
163
+ ids.append(wf_c['id'])
163
164
  main_alarm_group = Component.objects.filter(
164
165
  zone__instance=instance,
165
166
  base_type='alarm-group', config__is_main=True
166
167
  ).values('id').first()
167
168
  if main_alarm_group:
168
- c_ids.add(main_alarm_group['id'])
169
+ ids.append(main_alarm_group['id'])
169
170
  state = Component.objects.filter(
170
171
  zone__instance=instance,
171
172
  base_type='state-select', config__is_main=True
172
173
  ).values('id').first()
173
174
  if state:
174
- c_ids.add(state['id'])
175
+ ids.append(state['id'])
175
176
 
176
- user_role = user.get_role(instance)
177
- if user_role:
178
- for cp in user_role.component_permissions.all():
179
- if cp.read:
180
- c_ids.add(cp.component.id)
177
+ cache.set(cache_key, ids, 30)
178
+ return ids
181
179
 
182
- return qs.filter(id__in=c_ids).select_related(
180
+
181
+ def get_components_queryset(instance, user):
182
+ qs = Component.objects.filter(zone__instance=instance)
183
+ if user.is_master or user.is_superuser:
184
+ pass
185
+ else:
186
+ c_ids = get_main_components_ids(instance)
187
+
188
+ user_role = user.get_role(instance)
189
+ if user_role:
190
+ for cp in user_role.component_permissions.all():
191
+ if cp.read:
192
+ c_ids.append(cp.component.id)
193
+ qs = qs.filter(id__in=c_ids)
194
+
195
+ return qs.select_related(
183
196
  'zone', 'category', 'icon'
184
197
  ).prefetch_related('slaves')
185
198
 
@@ -318,12 +331,11 @@ class ComponentHistoryViewSet(InstanceMixin, viewsets.ReadOnlyModelViewSet):
318
331
  )
319
332
  if self.request.user.is_superuser:
320
333
  return qs
321
- c_ids = [
322
- cp.component.id for cp in
323
- self.request.user.get_role(self.instance).component_permissions.filter(
324
- read=True
325
- ).select_related('component')
326
- ]
334
+ role = self.request.user.get_role(self.instance)
335
+ c_ids = []
336
+ for p in role.component_permissions.all():
337
+ if p.read:
338
+ c_ids.append(p.component.id)
327
339
  qs = qs.filter(component__id__in=c_ids)
328
340
  return qs
329
341
 
simo/core/models.py CHANGED
@@ -580,22 +580,19 @@ def is_in_alarm(self):
580
580
  return bool(self.value)
581
581
 
582
582
  def can_read(self, user):
583
- if user.is_superuser:
583
+ if user.is_master:
584
584
  return True
585
- perm = user.component_permissions.filter(component=self).first()
586
- if not perm:
585
+ from .middleware import get_current_instance
586
+ instance = get_current_instance()
587
+ if instance:
588
+ role = user.get_role(instance)
589
+ if not role:
590
+ return False
591
+ for perm in role.component_permissions.all():
592
+ if perm.component.id == self.id:
593
+ return any([perm.write, perm.read])
587
594
  return False
588
- if perm.write:
589
- return True
590
- return perm.read
591
-
592
- def can_write(self, user):
593
- if user.is_superuser:
594
- return True
595
- perm = user.component_permissions.filter(component=self).first()
596
- if not perm:
597
- return False
598
- return perm.write
595
+ return False
599
596
 
600
597
  def get_controller_methods(self):
601
598
  c_methods = []
simo/core/permissions.py CHANGED
@@ -80,7 +80,7 @@ class ComponentPermission(BasePermission):
80
80
  return True
81
81
  if request.user.is_master:
82
82
  return True
83
- if obj.controller.masters_only:
83
+ if obj.controller and obj.controller.masters_only:
84
84
  return False
85
85
  user_role = request.user.get_role(view.instance)
86
86
  if user_role.is_superuser:
@@ -89,6 +89,6 @@ class ComponentPermission(BasePermission):
89
89
  return True
90
90
  if request.method == 'POST':
91
91
  for perm in user_role.component_permissions.all():
92
- if perm.component == obj:
92
+ if perm.component.id == obj.id:
93
93
  return perm.write
94
94
  return False
simo/core/serializers.py CHANGED
@@ -544,7 +544,7 @@ class ComponentSerializer(FormSerializer):
544
544
  return {'type': app_widget.uid, 'size': app_widget.size}
545
545
 
546
546
  def get_slaves(self, obj):
547
- return [c['id'] for c in obj.slaves.all().values('id')]
547
+ return [s.id for s in obj.slaves.all()]
548
548
 
549
549
  def get_masters_only(self, obj):
550
550
  if not obj.controller:
@@ -565,12 +565,11 @@ class ZoneSerializer(serializers.ModelSerializer):
565
565
  return qs
566
566
  user = self.context.get('request').user
567
567
  instance = self.context.get('instance')
568
- c_ids = [
569
- cp.component.id for cp in
570
- user.get_role(instance).component_permissions.filter(
571
- read=True
572
- ).select_related('component')
573
- ]
568
+ role = user.get_role(instance)
569
+ c_ids = []
570
+ for p in role.component_permissions.all():
571
+ if p.read:
572
+ c_ids.append(p.component.id)
574
573
  qs = qs.filter(id__in=c_ids)
575
574
  return qs
576
575
 
simo/users/models.py CHANGED
@@ -193,11 +193,19 @@ class User(AbstractBaseUser, SimoAdminMixin):
193
193
  USERNAME_FIELD = 'email'
194
194
  REQUIRED_FIELDS = ['name']
195
195
 
196
+
197
+
196
198
  class Meta:
197
199
  verbose_name = _('user')
198
200
  verbose_name_plural = _('users')
199
201
  abstract = False
200
202
 
203
+ def __init__(self, *args, **kwargs):
204
+ super().__init__(*args, **kwargs)
205
+ self._is_active = None
206
+ self._instances = None
207
+ self._instance_roles = {}
208
+
201
209
  def __str__(self):
202
210
  return self.name
203
211
 
@@ -240,6 +248,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
240
248
  return self.is_active and self.is_master
241
249
 
242
250
  def get_role(self, instance):
251
+ if instance.id in self._instance_roles:
252
+ return self._instance_roles[instance.id]
243
253
  cache_key = f'user-{self.id}_instance-{instance.id}_role'
244
254
  role = cache.get(cache_key)
245
255
  if role is None:
@@ -250,7 +260,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
250
260
  ).first()
251
261
  if role:
252
262
  cache.set(cache_key, role, 20)
253
- return role
263
+ self._instance_roles[instance.id] = role
264
+ return self._instance_roles[instance.id]
254
265
 
255
266
  @property
256
267
  def role_id(self):
@@ -285,12 +296,20 @@ class User(AbstractBaseUser, SimoAdminMixin):
285
296
  'role': role
286
297
  }
287
298
  )
299
+ self._role_id = None
300
+ try:
301
+ cache.delete(f'user-{self.id}_instance-{instance.id}-role-id')
302
+ except:
303
+ pass
288
304
 
289
305
  @property
290
306
  def instances(self):
291
307
  from simo.core.models import Instance
292
308
  if not self.is_active:
293
309
  return Instance.objects.none()
310
+ if self._instances != None:
311
+ return self._instances
312
+
294
313
  cache_key = f'user-{self.id}_instances'
295
314
  instances = cache.get(cache_key)
296
315
  if instances is None:
@@ -303,7 +322,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
303
322
  )
304
323
  ], is_active=True)
305
324
  cache.set(cache_key, instances, 10)
306
- return instances
325
+ self._instances = instances
326
+ return self._instances
307
327
 
308
328
  @property
309
329
  def component_permissions(self):
@@ -314,6 +334,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
314
334
 
315
335
  @property
316
336
  def is_active(self):
337
+ if self._is_active != None:
338
+ return self._is_active
317
339
  cache_key = f'user-{self.id}_is_active'
318
340
  cached_value = cache.get(cache_key)
319
341
  if cached_value is None:
@@ -339,7 +361,9 @@ class User(AbstractBaseUser, SimoAdminMixin):
339
361
  self.instance_roles.filter(is_active=True).count()
340
362
  )
341
363
  cache.set(cache_key, cached_value, 20)
342
- return cached_value
364
+
365
+ self._is_active = cached_value
366
+ return self._is_active
343
367
 
344
368
 
345
369
  @is_active.setter
@@ -359,6 +383,8 @@ class User(AbstractBaseUser, SimoAdminMixin):
359
383
 
360
384
  rebuild_authorized_keys()
361
385
 
386
+ self._is_active = None
387
+
362
388
 
363
389
  @property
364
390
  def is_superuser(self):
@@ -391,23 +417,6 @@ class User(AbstractBaseUser, SimoAdminMixin):
391
417
  def has_perms(self, perm_list, obj=None):
392
418
  return True
393
419
 
394
- def get_component_permissions(self):
395
- if not self.instances:
396
- return []
397
- components = []
398
- for instance in self.instances:
399
- for comp in instance.components.all():
400
- can_read = comp.can_read(self)
401
- can_write = comp.can_write(self)
402
- if not any([can_read, can_write]):
403
- continue
404
- components.append({
405
- 'component': comp,
406
- 'can_read': can_read,
407
- 'can_write': can_write
408
- })
409
- return components
410
-
411
420
 
412
421
  class Fingerprint(models.Model):
413
422
  value = models.CharField(max_length=200, db_index=True, unique=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.5.39
3
+ Version: 2.5.41
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
@@ -33,7 +33,7 @@ simo/backups/migrations/__pycache__/0004_alter_backup_options_alter_backuplog_op
33
33
  simo/backups/migrations/__pycache__/__init__.cpython-38.pyc,sha256=Lz1fs6V05h2AoxTOLNye0do9bEMnyuaXB_hHOjG5-HU,172
34
34
  simo/core/__init__.py,sha256=_s2TjJfQImsMrTIxqLAx9AZie1Ojmm6sCHASdl3WLGU,50
35
35
  simo/core/admin.py,sha256=T-NjMq1OxtCt-LjWL-YuuGtAi4JcvtjWhcGrLb8G5D4,18434
36
- simo/core/api.py,sha256=jFSuknrIiFhuf_Hx07GeTQ_prOG0cBJhtbcTImPVmqI,28502
36
+ simo/core/api.py,sha256=9e9q0a_Knrddx2Yt_R3r7_mYRphyUUCgxbHr8XP5m9o,28827
37
37
  simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
38
38
  simo/core/api_meta.py,sha256=EaiY-dCADP__9MvLpoHvhjytFT92IrxPZDv95xgqasU,4955
39
39
  simo/core/app_widgets.py,sha256=VxZzapuc-a29wBH7JzpvNF2SK1ECrgNUySId5ke1ffc,2509
@@ -52,10 +52,10 @@ simo/core/gateways.py,sha256=m0eS3XjVe34Dge6xtoCq16kFWCKJcdQrT0JW0REqoq8,3715
52
52
  simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
53
53
  simo/core/managers.py,sha256=n-b3I4uXzfHKTeB1VMjSaMsDUxp8FegFJwnbV1IsWQ4,3019
54
54
  simo/core/middleware.py,sha256=eUFf6iP-Snx_0TE3MoXsSwqrd5IjlukqZk2GQGStRCo,3385
55
- simo/core/models.py,sha256=1eJRIxOYtzx7JOGSAyo75QBoTEaigxjsRXIFghDSz9k,22837
56
- simo/core/permissions.py,sha256=INQPrUAIM3WXCvd7e6cmYytKaak8fMEn7VooX-fIds0,3002
55
+ simo/core/models.py,sha256=QNVTnWeHAW6LVrs3eaR7WNMhwjICuQpXZ8vyH_2qCBo,22834
56
+ simo/core/permissions.py,sha256=2YNRot2qoHjHKWPGOpO4PBseecctPbTlUQpepnFkCRs,3027
57
57
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
58
- simo/core/serializers.py,sha256=UIIKinmCICMbJZRkI6xInZau3VfkesRe_LX-GMrJYHg,21849
58
+ simo/core/serializers.py,sha256=NgqZhBjY0or6dfN-N_EaaygR_EUoUBryuK1DbD4R3Fg,21810
59
59
  simo/core/signal_receivers.py,sha256=2WfF3FI5ZmJM1S-oT_1w3TdnBUX6fjbI4Rpg-DKsuYA,8696
60
60
  simo/core/socket_consumers.py,sha256=trRZvBGTJ7xIbfdmVvn7zoiWp_qssSkMZykDrI5YQyE,9783
61
61
  simo/core/storage.py,sha256=_5igjaoWZAiExGWFEJMElxUw55DzJG1jqFty33xe8BE,342
@@ -66,7 +66,7 @@ simo/core/views.py,sha256=yx9I0byeVUa-LAOnklpWIYwpNNOf5m9fyjKBvj4YCh4,2475
66
66
  simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
67
67
  simo/core/__pycache__/__init__.cpython-38.pyc,sha256=ZJFM_XN0RmJMULQulgA_wFiOnEtsMoedcOWnXjH-Y8o,208
68
68
  simo/core/__pycache__/admin.cpython-38.pyc,sha256=mXU-u9Bl5RCa0K4Y9wJAkYns33XCByME3sb_FsMC2DI,14090
69
- simo/core/__pycache__/api.cpython-38.pyc,sha256=u4qCGX0I_IEvdVf4vzQWnGkUsNRBa7Bx2PqWCyX7aHs,21980
69
+ simo/core/__pycache__/api.cpython-38.pyc,sha256=sAVNBbjo787IfRZTWp7YMUnGmaIFPjZw0bmoWSFSkPU,22162
70
70
  simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=mi3mu5qEKio_PvfQEvr3Q6AhdPLAHxzxAxrMbAz_pKU,1712
71
71
  simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=VYx5ZeDyNBI4B_CBEIhV5B3GnLsMOx9s3rNZTSMODco,3703
72
72
  simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=oN657XMMZ6GYN9nblv7fX3kdnTEzSP9XV6PXM6Z0wl4,4358
@@ -85,10 +85,10 @@ simo/core/__pycache__/gateways.cpython-38.pyc,sha256=D1ooHL-iSpQrxnD8uAl4xWFJmm-
85
85
  simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
86
86
  simo/core/__pycache__/managers.cpython-38.pyc,sha256=6RTIxyjOgpQGtAqcUyE2vFPS09w1V5Wmd_vOV7rHRRI,3370
87
87
  simo/core/__pycache__/middleware.cpython-38.pyc,sha256=g3d4L2PwxFyRKIPMP9Hkdjk1PL9NarQd4hSHS55I8n8,2649
88
- simo/core/__pycache__/models.cpython-38.pyc,sha256=m2KdO5zWXwHT3pIDyGW9SQgnesSAGPPcttOXoKCArzM,18610
89
- simo/core/__pycache__/permissions.cpython-38.pyc,sha256=LXfbPrLm81oquflywAdK-a53-g7N1tkUuiePIdvk0ek,2974
88
+ simo/core/__pycache__/models.cpython-38.pyc,sha256=jLZXRDsR1_GJBvuDZ32KpuFz3B5qRoQmgpY6kLxxFI0,18554
89
+ simo/core/__pycache__/permissions.cpython-38.pyc,sha256=UdtxCTXPEbe99vgZOfRz9wfKSYvUn9hSRbpIV9CJSyI,2988
90
90
  simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
91
- simo/core/__pycache__/serializers.cpython-38.pyc,sha256=yBOmGPbCvfwk6j0dWN3sBuuf75ZG2FpSNWi84xLoX6Q,19577
91
+ simo/core/__pycache__/serializers.cpython-38.pyc,sha256=QvlVp7m13i3Vn1FOmjV-y_IpLfmcSIy74jhb66ecJbo,19403
92
92
  simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=Od1ejof2nHAFzTAG5vGGVjMA8WUJNVJ9o_KWGqRSR34,6669
93
93
  simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=KqbO1cOewodVPcy0-htVefyUjCuELKV0o7fOfYqfgPc,8490
94
94
  simo/core/__pycache__/storage.cpython-38.pyc,sha256=9R1Xu0FJDflfRXUPsqEgt0SpwiP7FGk7HaR8s8XRyI8,721
@@ -10456,7 +10456,7 @@ simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
10456
10456
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10457
10457
  simo/users/managers.py,sha256=OHgEP85MBtdkdYxdstBd8RavTBT8F_2WyDxUJ9aCqqM,246
10458
10458
  simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
10459
- simo/users/models.py,sha256=cmoPzz5e4Mymqf7Dwh8KBoR5D-wumHSj18rvb3LU9E4,19735
10459
+ simo/users/models.py,sha256=2c9unF8xd9kjwzwQEUEsxw79NrO1_YSJZl6h4wpNsI8,19915
10460
10460
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10461
10461
  simo/users/serializers.py,sha256=zzw1KONTnaTNBaU0r4rNVxJ827KzD6Z5LuQt27ZsQ98,2516
10462
10462
  simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
@@ -10473,7 +10473,7 @@ simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=K-3sz2h-cEitoflSmZk1t0eUg
10473
10473
  simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
10474
10474
  simo/users/__pycache__/managers.cpython-38.pyc,sha256=O0Y8ABp42RAosrbODmYsPMaj9AyOPyJ-aqzuO0Qpi2s,679
10475
10475
  simo/users/__pycache__/middleware.cpython-38.pyc,sha256=Tj4nVEAvxEW3xA63fBRiJWRJpz_M848ZOqbHioc_IPE,1149
10476
- simo/users/__pycache__/models.cpython-38.pyc,sha256=XemTxwgZMpnoAXYryfY_H-g_xhVepqOU-ddCKJyPNCE,17710
10476
+ simo/users/__pycache__/models.cpython-38.pyc,sha256=UH-lceJI5fYxYn85dIUJ8HYESwb9irIPkvu_d-vGSkA,17777
10477
10477
  simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
10478
10478
  simo/users/__pycache__/serializers.cpython-38.pyc,sha256=Dy8RAcwNkNSXoJHvLp8fozURyHCtucqpSPyqZtbnMZc,3732
10479
10479
  simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=uAwDozpOmrhUald-8tOHANILXkH7-TI8fNYXOtPkSY8,402
@@ -10579,9 +10579,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10579
10579
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10580
10580
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10581
10581
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10582
- simo-2.5.39.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10583
- simo-2.5.39.dist-info/METADATA,sha256=eJDjovPyXN783fHsdMkLjCh0MweABo21kJdAHUSvhE4,1953
10584
- simo-2.5.39.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10585
- simo-2.5.39.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10586
- simo-2.5.39.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10587
- simo-2.5.39.dist-info/RECORD,,
10582
+ simo-2.5.41.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10583
+ simo-2.5.41.dist-info/METADATA,sha256=Zv_ztSmF--6O5h2ftMUNFjKt-hjOdiBCJp3ZLBN28M0,1953
10584
+ simo-2.5.41.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10585
+ simo-2.5.41.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10586
+ simo-2.5.41.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10587
+ simo-2.5.41.dist-info/RECORD,,
File without changes