simo 2.0.22__py3-none-any.whl → 2.0.23__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
Binary file
simo/core/api.py CHANGED
@@ -5,7 +5,7 @@ import time
5
5
  from django.db.models import Q, Prefetch
6
6
  from django.utils.translation import gettext_lazy as _
7
7
  from django.utils import timezone
8
- from django.shortcuts import get_object_or_404
8
+ from django.http import HttpResponse, Http404
9
9
  from simo.core.utils.helpers import get_self_ip, search_queryset
10
10
  from rest_framework.pagination import PageNumberPagination
11
11
  from rest_framework import viewsets
@@ -14,7 +14,6 @@ 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
18
17
  from .models import (
19
18
  Instance, Category, Zone, Component, Icon, ComponentHistory,
20
19
  HistoryAggregate, Gateway
@@ -23,7 +22,9 @@ from .serializers import (
23
22
  IconSerializer, CategorySerializer, ZoneSerializer,
24
23
  ComponentSerializer, ComponentHistorySerializer
25
24
  )
26
- from .permissions import IsInstanceSuperuser, InstanceSuperuserCanEdit
25
+ from .permissions import (
26
+ IsInstanceSuperuser, InstanceSuperuserCanEdit, ComponentPermission
27
+ )
27
28
 
28
29
 
29
30
  class InstanceMixin:
@@ -34,10 +35,10 @@ class InstanceMixin:
34
35
  slug=self.request.resolver_match.kwargs.get('instance_slug')
35
36
  )
36
37
  except Instance.DoesNotExist:
37
- raise APIValidationError(
38
+ return HttpResponse(
38
39
  f"Instance {self.request.resolver_match.kwargs.get('instance_slug')} "
39
40
  "is not found on this SIMO.io hub!",
40
- code=400
41
+ status=400
41
42
  )
42
43
  return super().dispatch(request, *args, **kwargs)
43
44
 
@@ -165,6 +166,7 @@ class ComponentViewSet(InstanceMixin, viewsets.ModelViewSet):
165
166
 
166
167
  def get_permissions(self):
167
168
  permissions = super().get_permissions()
169
+ permissions.append(ComponentPermission())
168
170
  permissions.append(InstanceSuperuserCanEdit())
169
171
  return permissions
170
172
 
@@ -210,7 +212,6 @@ class ComponentViewSet(InstanceMixin, viewsets.ModelViewSet):
210
212
  @action(detail=True, methods=['post'])
211
213
  def subcomponent(self, request, pk=None, *args, **kwargs):
212
214
  component = self.get_object()
213
- self.check_object_permissions(request, component)
214
215
  json_data = request.data
215
216
  subcomponent_id = json_data.pop('id', -1)
216
217
  try:
@@ -228,37 +229,16 @@ class ComponentViewSet(InstanceMixin, viewsets.ModelViewSet):
228
229
  self.check_object_permissions(self.request, subcomponent)
229
230
  return self.perform_controller_method(json_data, subcomponent)
230
231
 
231
-
232
- def check_object_permissions(self, request, component):
233
- super().check_object_permissions(request, component)
234
-
235
- if not component.controller:
236
- raise APIValidationError(
237
- _('Component has no controller assigned.'),
238
- code=400
239
- )
240
- if request.user.is_master:
241
- return
242
- user_role = request.user.get_role(self.instance)
243
- if user_role.is_superuser:
244
- return
245
- if not user_role.component_permissions.filter(
246
- write=True, component=component
247
- ).count():
248
- raise APIValidationError(
249
- _('You do not have permission to write to this component.'),
250
- code=403
251
- )
252
-
253
232
  @action(detail=True, methods=['post'])
254
233
  def controller(self, request, pk=None, *args, **kwargs):
255
234
  component = self.get_object()
256
- self.check_object_permissions(self.request, component)
257
235
  return self.perform_controller_method(request.data, component)
258
236
 
259
237
  @action(detail=False, methods=['post'])
260
238
  def control(self, request, *args, **kwargs):
261
- component = get_object_or_404(Component, id=request.data.pop('id', 0))
239
+ component = self.get_queryset().filter(id=request.data.pop('id', 0))
240
+ if not component:
241
+ raise Http404()
262
242
  self.check_object_permissions(self.request, component)
263
243
  return self.perform_controller_method(request.data, component)
264
244
 
simo/core/models.py CHANGED
@@ -163,7 +163,7 @@ class Category(DirtyFieldsMixin, models.Model, SimoAdminMixin):
163
163
  help_text=_("All components automatically belongs to this category")
164
164
  )
165
165
  order = models.PositiveIntegerField(
166
- default=0, blank=False, null=False, db_index=True
166
+ blank=False, null=False, db_index=True
167
167
  )
168
168
  objects = CategoriesManager()
169
169
 
@@ -175,8 +175,13 @@ class Category(DirtyFieldsMixin, models.Model, SimoAdminMixin):
175
175
  def __str__(self):
176
176
  return self.name
177
177
 
178
-
179
178
  def save(self, *args, **kwargs):
179
+ if self.order is None:
180
+ last_cat = Category.objects.filter(instance=self.instance).last()
181
+ if last_cat:
182
+ self.order = last_cat.order + 1
183
+ else:
184
+ self.order = 0
180
185
  dirty_fields = self.get_dirty_fields()
181
186
  if 'all' in dirty_fields:
182
187
  if self.all:
simo/core/permissions.py CHANGED
@@ -1,11 +1,9 @@
1
- from rest_framework.permissions import BasePermission, SAFE_METHODS
1
+ from rest_framework.permissions import BasePermission, SAFE_METHODS, IsAuthenticated
2
2
  from .models import Instance, Category, Zone
3
3
 
4
4
 
5
5
  class InstancePermission(BasePermission):
6
- """
7
- Allows access only to user instances
8
- """
6
+ message = "You have no role in this SIMO.io instance."
9
7
 
10
8
  def has_permission(self, request, view):
11
9
  if not request.user.is_active:
@@ -24,6 +22,7 @@ class InstancePermission(BasePermission):
24
22
 
25
23
 
26
24
  class IsInstanceSuperuser(BasePermission):
25
+ message = "Only superusers are allowed to do this."
27
26
 
28
27
  def has_permission(self, request, view):
29
28
  if request.user.is_master:
@@ -33,6 +32,7 @@ class IsInstanceSuperuser(BasePermission):
33
32
 
34
33
 
35
34
  class InstanceSuperuserCanEdit(BasePermission):
35
+ message = "Only superusers are allowed to perform this action."
36
36
 
37
37
  def has_object_permission(self, request, view, obj):
38
38
 
@@ -47,3 +47,28 @@ class InstanceSuperuserCanEdit(BasePermission):
47
47
  if user_role.is_superuser:
48
48
  return True
49
49
  return request.method in SAFE_METHODS
50
+
51
+
52
+ class ComponentPermission(BasePermission):
53
+ message = "You do not have permission to do this on this component."
54
+
55
+ # TODO: clean this up once the app is tested and running 100% correctly for at least 6 months.
56
+ def has_object_permission(self, request, view, obj):
57
+ print(f"Check permission of {request.user} on {obj}")
58
+ if request.method in SAFE_METHODS:
59
+ print("THIS IS SAFE METHOD!")
60
+ return True
61
+ if request.user.is_master:
62
+ print("USER IS MASTER!")
63
+ return True
64
+ user_role = request.user.get_role(view.instance)
65
+ if user_role.is_superuser:
66
+ print("USER IS SUPERUSER!")
67
+ return True
68
+ if request.method == 'POST' and user_role.component_permissions.filter(
69
+ write=True, component=obj
70
+ ).count():
71
+ print("USER HAS RIGHT TO DO THIS!")
72
+ return True
73
+ print("USER IS NOT ALLOWED TO DO THIS!")
74
+ return False
simo/core/serializers.py CHANGED
@@ -243,6 +243,7 @@ class ComponentSerializer(FormSerializer):
243
243
  meta = ObjectSerializerMethodField()
244
244
  arm_status = ObjectSerializerMethodField()
245
245
  battery_level = ObjectSerializerMethodField()
246
+ controller_methods = serializers.SerializerMethodField()
246
247
 
247
248
  class Meta:
248
249
  form = ComponentAdminForm
@@ -287,7 +288,6 @@ class ComponentSerializer(FormSerializer):
287
288
  cls = form_field.field.__class__
288
289
  if field_name == 'notes':
289
290
  serializer_field_class = TextAreaSerializerField
290
- print("TEXTAREA!~!!!")
291
291
  else:
292
292
  try:
293
293
  serializer_field_class = field_mapping[cls]
Binary file
simo/fleet/forms.py CHANGED
@@ -573,12 +573,6 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
573
573
  ]
574
574
  )
575
575
  )
576
- frequency = forms.IntegerField(
577
- min_value=30, max_value=100000, required=True, initial=3000,
578
- help_text="PWM signal frequency in Hz. Works only with GPIO ports."
579
- "3000 Hz offers great performance in most use cases."
580
-
581
- )
582
576
  min = forms.FloatField(
583
577
  required=True, initial=0,
584
578
  help_text="Minimum component value"
@@ -723,9 +717,9 @@ class ColonelRGBLightConfigForm(ColonelComponentForm):
723
717
  return custom_timing
724
718
  custom_timing = custom_timing.strip().\
725
719
  strip('(').strip('[').rstrip(')').rstrip(']').split(',')
726
- if len(custom_timing.split(',')) != 4:
720
+ if len(custom_timing) != 4:
727
721
  raise forms.ValidationError("Tuple of 4 integers please.")
728
- for t in custom_timing.split(','):
722
+ for t in custom_timing:
729
723
  try:
730
724
  t = int(t)
731
725
  except:
@@ -734,7 +728,7 @@ class ColonelRGBLightConfigForm(ColonelComponentForm):
734
728
  raise forms.ValidationError(f"Intervals must be greater than 0.")
735
729
  if t > 100000:
736
730
  raise forms.ValidationError(f"{t} seems way to much!")
737
- return f"({custom_timing})"
731
+ return f"({','.join(custom_timing)})"
738
732
 
739
733
  def clean(self):
740
734
  super().clean()
simo/fleet/models.py CHANGED
@@ -327,10 +327,20 @@ def post_i2c_interface_delete(sender, instance, *args, **kwargs):
327
327
  pin.occupied_by_content_type = None
328
328
  pin.occupied_by_content_id = None
329
329
  pin.save()
330
- instance.scl_pin.occupied_by = instance
331
- instance.scl_pin.save()
332
- instance.sda_pin.occupied_by = instance
333
- instance.sda_pin.save()
330
+
331
+ # In an event of colonel deletion these pin no longer exist
332
+ # at this point, therefore this trhows irrelevant exceptions
333
+ # that we want to fail silenty
334
+ try:
335
+ instance.scl_pin.occupied_by = instance
336
+ instance.scl_pin.save()
337
+ except ColonelPin.DoesNotExist:
338
+ pass
339
+ try:
340
+ instance.sda_pin.occupied_by = instance
341
+ instance.sda_pin.save()
342
+ except ColonelPin.DoesNotExist:
343
+ pass
334
344
 
335
345
 
336
346
  class Interface(models.Model):
simo/settings.py CHANGED
@@ -176,7 +176,6 @@ REST_FRAMEWORK = {
176
176
  'simo.core.api_auth.IsAuthenticated',
177
177
  ],
178
178
  'DEFAULT_PERMISSION_CLASSES': [
179
- 'rest_framework.permissions.IsAuthenticated',
180
179
  'simo.users.permissions.IsActivePermission',
181
180
  'simo.core.permissions.InstancePermission'
182
181
  ],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.0.22
3
+ Version: 2.0.23
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
@@ -6,7 +6,7 @@ simo/cli.py,sha256=kB1dhZ30Pnq7mDawWGbX5WnCuoZ6qNMcnWH-c8XxcaU,2233
6
6
  simo/conf.py,sha256=H2BhXAV8MEDVXF8AbkaLSfR4ULd-9_bS4bnhE5sE5fg,112
7
7
  simo/on_http_start.py,sha256=PJQlKYeZbtGCxRjDV6zcCqyA5Ns9d5NND30Tb6vIav4,2358
8
8
  simo/scripting.py,sha256=PVIkGsiMDWj4CNTbOM3rq7pJ6ruavuns-ZMU7VudLa4,923
9
- simo/settings.py,sha256=hFXlZYuMSxlEVHuU19uJ0t4mK--70Zf3GOujVIUkurA,6894
9
+ simo/settings.py,sha256=yezM7QleJv73IFWMsPyGxqoI_c3JV21R1RsDcgweIfU,6840
10
10
  simo/urls.py,sha256=PgKGCZON3SAL3Hh9vVDWVJ9zDQO5ZPsRQLz_s5GWSV0,2328
11
11
  simo/wsgi.py,sha256=ci7BK1zCuqTwCUQi29su7xKeGEJHk0N3Oc8jGJRO6EY,165
12
12
  simo/__pycache__/__init__.cpython-38.pyc,sha256=j81de0BqHMr6bs0C7cuYrXl7HwtK_vv8hDEtAdSwDJc,153
@@ -14,7 +14,7 @@ simo/__pycache__/asgi.cpython-38.pyc,sha256=OemZ2InNbZCiJtD3MWSO8IiDSqp-LUyTLFjM
14
14
  simo/__pycache__/celeryc.cpython-38.pyc,sha256=eSRoaKwfYlxVaxAiwqpQ2ndEcx7W-VpZtbxRFSV8UYg,1653
15
15
  simo/__pycache__/conf.cpython-38.pyc,sha256=MYP2yk3ULxiYwZsZR6tCLjKnU-z03A3avzQzIn66y3k,273
16
16
  simo/__pycache__/on_http_start.cpython-38.pyc,sha256=cjgntuqsmandjyNtJoqch0LpxA-BNF3UR8vUxufYn9g,2067
17
- simo/__pycache__/settings.cpython-38.pyc,sha256=rWI5C5rSlAaDif8BtxwQ6vEww1YaU9xwR753YF8Y4xI,6132
17
+ simo/__pycache__/settings.cpython-38.pyc,sha256=m9O2hfu1sVkYxi9-MzM2D4DzOHL7ea9LOt1AJlV4LdI,6084
18
18
  simo/__pycache__/urls.cpython-38.pyc,sha256=sqfstQthcjXtv31Tad0RAlWWI2A0HH6HN0fW0VmmWQw,2050
19
19
  simo/__pycache__/wsgi.cpython-38.pyc,sha256=Wt9kKkH2Sg5LRL4NrVQQDYPIoDyTvnXwm6jZjnG3kIc,322
20
20
  simo/_hub_template/hub/asgi.py,sha256=ElN_fdeSkf0Ysa7pS9rJVmZ1HmLhFxb8jFaMLqe1220,126
@@ -26,7 +26,7 @@ simo/_hub_template/hub/supervisor.conf,sha256=IY3fdK0fDD2eAothB0n54xhjQj8LYoXIR9
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=cPOC2x45Gjf0T8MKtmE2wJZk7DAuHMsvvy5Nk3YUIG8,17675
29
- simo/core/api.py,sha256=H4KJBiU377zEj8dJGSnBUKgyeyA2512WmSh9I0nH4WM,23760
29
+ simo/core/api.py,sha256=bAX-DXG5aJr3VvjqGKGtjVzel0E7Cp3l5tkA3uLhnFw,22969
30
30
  simo/core/api_auth.py,sha256=_3hG4e1eLKrcRnSAOB_xTL6cwtOJ2_7JS7GZU_iqTgA,1251
31
31
  simo/core/api_meta.py,sha256=ySmmhtVrWatI3yqnYPuP5ipapmJfyfEbl32w-7_W5O4,3551
32
32
  simo/core/app_widgets.py,sha256=EEQOto3fGR0syDqpJE38tQrx8DoTTyg26nF5kYzHY38,2018
@@ -43,10 +43,10 @@ simo/core/gateways.py,sha256=s_c2W0v2_te89i6LS4Nj7F2wn9UwjZXPT7pfy6SToVo,3714
43
43
  simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
44
44
  simo/core/managers.py,sha256=WoQ4OX3akIvoroSYji-nLVqXBSJzCiC1u_IiWkKbKmA,2413
45
45
  simo/core/middleware.py,sha256=64PYjnyRnYf4sgMvPfR0oQqf9UEtxUwnhJe3RV6z_HI,2040
46
- simo/core/models.py,sha256=c_MnZO-h02qYEu_6vnhkuW6l2OuYuKuUqlE5bc2CB_0,19453
47
- simo/core/permissions.py,sha256=UmFjGPDWtAUbaWxJsWORb2q6BREHqndv9mkSIpnmdLk,1379
46
+ simo/core/models.py,sha256=zqbPDYLHOsavrBzw5uOmUgcWBnBbjGLvezgETX-pD_E,19672
47
+ simo/core/permissions.py,sha256=b2qO_kNaCgWcv2VJbOp6AUXOc_cup7fOT3Up16rn77M,2495
48
48
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
49
- simo/core/serializers.py,sha256=KVkp4u_FEnNySDlwO-3bDe4l_cdBJBV6Di8Smi1fNFk,17541
49
+ simo/core/serializers.py,sha256=kmja52o-BUOcUTX2ZsKWixvKRZSXB7lGe866Q1ajlmo,17563
50
50
  simo/core/signal_receivers.py,sha256=EZ8NSYZxUgSaLS16YZdK7T__l8dl0joMRllOxx5PUt4,2809
51
51
  simo/core/socket_consumers.py,sha256=n7VE2Fvqt4iEAYLTRbTPOcI-7tszMAADu7gimBxB-Fg,9635
52
52
  simo/core/storage.py,sha256=YlxmdRs-zhShWtFKgpJ0qp2NDBuIkJGYC1OJzqkbttQ,572
@@ -57,7 +57,7 @@ simo/core/views.py,sha256=hlAKpAbCbqI3a-uL5tDp532T2oLFiF0MBzKUJ_SNzo0,5833
57
57
  simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
58
58
  simo/core/__pycache__/__init__.cpython-38.pyc,sha256=y0IW37wBUIGa3Eh_ZG28pRqHKoLiPyTgUX2OnbkEPlc,158
59
59
  simo/core/__pycache__/admin.cpython-38.pyc,sha256=EqwHQhU8qQrjfSChyCZXN6J-1Eira9alYIqR45-3OnE,13475
60
- simo/core/__pycache__/api.cpython-38.pyc,sha256=kH2ORVfI8xtwe7M1wdOEtaqJR_SqKR8V1wrCdhazVhc,18883
60
+ simo/core/__pycache__/api.cpython-38.pyc,sha256=l3BUnLGBsM-FzqdaKi__1R9Z5DJnhgJrkmXQ2XQetT0,18372
61
61
  simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=5UTBr3rDMERAfc0OuOVDwGeQkt6Q7GLBtZJAMBse1sg,1712
62
62
  simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=94T3_rybn2T1_bkaDQnQRyjy21LBaGOnz-mmkJ6T0N8,2840
63
63
  simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=9Es2wZNduzUJv-jZ_HX0-L3vqwpXWBbseEwoC5K6b-w,3465
@@ -74,10 +74,10 @@ simo/core/__pycache__/gateways.cpython-38.pyc,sha256=XBiwMfBkjoQ2re6jvADJOwK0_0A
74
74
  simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
75
75
  simo/core/__pycache__/managers.cpython-38.pyc,sha256=5vstOMfm997CZBBkaSiaS7EojhLTWZlbeA_EQ8u-yfg,2554
76
76
  simo/core/__pycache__/middleware.cpython-38.pyc,sha256=bGOFJNEhJeLbpsZp8LYn1VA3paLF5HULHQ6IFKa7Juc,2022
77
- simo/core/__pycache__/models.cpython-38.pyc,sha256=Nz3g-p6PIKDgOdreXyjurfKXsBhmTh1P3MnqbZPKfRc,17029
78
- simo/core/__pycache__/permissions.cpython-38.pyc,sha256=uygjPbfRQiEzyo5-McCxsuMDJLbDYO_TLu55U7bJbR0,1809
77
+ simo/core/__pycache__/models.cpython-38.pyc,sha256=meQeK2mVoSDP9cTMSZDW-Ofi53QzwjfHSUlAGlnhyfs,17127
78
+ simo/core/__pycache__/permissions.cpython-38.pyc,sha256=7iz0o_jIEhDM2FQd-P-3Y6sm4GQ0MRy4a5biBNkngOA,2680
79
79
  simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
80
- simo/core/__pycache__/serializers.cpython-38.pyc,sha256=1-Xs9UtjmUZ8YCh7zkKqmet7XRpy06W1HLijyqluMTk,16871
80
+ simo/core/__pycache__/serializers.cpython-38.pyc,sha256=x-obnrdPnoYRhriP_51_Jy_0saCsasWdFQSH1kalVqo,16869
81
81
  simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=sgjH_wv-1U99auH5uHb3or0qettPeHAlsz8P7B03ajY,2430
82
82
  simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=NJUr7nRyHFvmAumxxWpsod5wzVVZM99rCEuJs1utHA4,8432
83
83
  simo/core/__pycache__/storage.cpython-38.pyc,sha256=BTkYH8QQyjqI0WOtJC8fHNtgu0YA1vjqZclXjC2vCVI,1116
@@ -10171,10 +10171,10 @@ simo/fleet/auto_urls.py,sha256=X04oKJWA48wFW5iXg3PPROY2KDdHn_a99orQSE28QC4,518
10171
10171
  simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
10172
10172
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10173
10173
  simo/fleet/controllers.py,sha256=rTxRFf-LKWAZxzixrsLZHHm51BmMx9a1PLdgf6inlNM,20533
10174
- simo/fleet/forms.py,sha256=ucH9mkwHDA8iUaxVP5W9O8tyoKUb7N2V0KCVSD-oCWI,38237
10174
+ simo/fleet/forms.py,sha256=SOz0CnaRJ1jOOJLzvL2kOfacuaE7nOVlc6NtScSaR1Y,37965
10175
10175
  simo/fleet/gateways.py,sha256=KV5i5fxXIrlK-k6zyEkk83x11GJt-ELQ0npb4Ac83cM,3693
10176
10176
  simo/fleet/managers.py,sha256=XOpDOA9L-f_550TNSyXnJbun2EmtGz1TenVTMlUSb8E,807
10177
- simo/fleet/models.py,sha256=1Wb9xPc61OtoiYu9aS4KezchPGZTC4CDxa2dqVhltqM,14161
10177
+ simo/fleet/models.py,sha256=ve-97F1cwGt-AmwfSJK0d-57pP3NyZpeu0XlHu2oK28,14494
10178
10178
  simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
10179
10179
  simo/fleet/serializers.py,sha256=LgSTnSI_sUhFXmW9-669keM6gmaSI_teaqMHEab4aL4,1972
10180
10180
  simo/fleet/socket_consumers.py,sha256=Z-MooNN2HQccdhkynADJks5slbK9mGsnEpMLuA51H3I,18534
@@ -10188,10 +10188,10 @@ simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=SqyTuaz_kEBvx-bL46SclsZEE
10188
10188
  simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
10189
10189
  simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
10190
10190
  simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=l9bz18Qp33C12TJOKPSn9vIXnlBKnBusODNk7Fg64qA,18103
10191
- simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=vFMihKqwLKQRO9GoErkNZwGmDPQd6OYywh9iiZ8rf84,27566
10191
+ simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=0HmLdm3-2_4Zy_lIjUnGpnjf_gFz_KmmTFS1Vt4SY48,27398
10192
10192
  simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=YAcgTOqJbtjGI03lvEcU6keFfrwAHkObVmErYzfRvjk,3569
10193
10193
  simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=8uz-xpUiqbGDgXIZ_XRZtFb-Tju6NGxflGg-Ee4Yo6k,1310
10194
- simo/fleet/__pycache__/models.cpython-38.pyc,sha256=DQtRR6kI9bt3atgJ0pArCVfSyuutqb6SpxYrsBg10cM,12277
10194
+ simo/fleet/__pycache__/models.cpython-38.pyc,sha256=pHNRUiPRjH0SLp14pzbSIxHi_-27SpZFgSh_7lzA8Wo,12359
10195
10195
  simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
10196
10196
  simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=gwLIoLQJwkFoDCjKC_ikksNCYea3-mF8hVHFeKlOkbc,3098
10197
10197
  simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=RjzPD580096fby0HYLzZorm61zdZNOq5AHXmNAC4Yd8,13764
@@ -10448,8 +10448,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10448
10448
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10449
10449
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10450
10450
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10451
- simo-2.0.22.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10452
- simo-2.0.22.dist-info/METADATA,sha256=FwvdMlZV2ue45i8GkzfigcN5aynl1_HPlxcxQnXO5hc,1730
10453
- simo-2.0.22.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10454
- simo-2.0.22.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10455
- simo-2.0.22.dist-info/RECORD,,
10451
+ simo-2.0.23.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10452
+ simo-2.0.23.dist-info/METADATA,sha256=n65-Fcht6N4VSA8W5igDDeUKN7Hq5YgU8XMTb5pmUcw,1730
10453
+ simo-2.0.23.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10454
+ simo-2.0.23.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10455
+ simo-2.0.23.dist-info/RECORD,,
File without changes