simo 2.0.35__py3-none-any.whl → 2.0.37__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/forms.py CHANGED
@@ -291,7 +291,7 @@ class ComponentAdminForm(forms.ModelForm):
291
291
 
292
292
  class Meta:
293
293
  model = Component
294
- fields = 'name', 'icon', 'zone', 'category', 'show_in_app', 'notes'
294
+ fields = 'name', 'icon', 'zone', 'category', 'show_in_app', 'notes',
295
295
  widgets = {
296
296
  'icon': autocomplete.ModelSelect2(
297
297
  url='autocomplete-icon', attrs={'data-html': True}
@@ -466,6 +466,13 @@ class NumericSensorForm(BaseComponentForm):
466
466
  ValueLimitForm, can_delete=True, can_order=True, extra=0, max_num=3
467
467
  ), label="Graph Limits"
468
468
  )
469
+ value_units = forms.CharField(required=False)
470
+
471
+
472
+ def __init__(self, *args, **kwargs):
473
+ super().__init__(*args, **kwargs)
474
+ self.fields['value_units'].initial = self.controller.default_value_units
475
+
469
476
 
470
477
 
471
478
  class MultiSensorConfigForm(BaseComponentForm):
@@ -660,6 +667,7 @@ class DimmerConfigForm(BaseComponentForm):
660
667
  max = forms.FloatField(
661
668
  initial=1.0, help_text="Maximum component value."
662
669
  )
670
+ value_units = forms.CharField(required=False)
663
671
  inverse = forms.BooleanField(
664
672
  label=_("Inverse dimmer signal"), required=False
665
673
  )
@@ -676,6 +684,7 @@ class DimmerConfigForm(BaseComponentForm):
676
684
 
677
685
  def __init__(self, *args, **kwargs):
678
686
  super().__init__(*args, **kwargs)
687
+ self.fields['value_units'].initial = self.controller.default_value_units
679
688
  if self.instance.pk:
680
689
  self.fields['slaves'].initial = self.instance.slaves.all()
681
690
 
@@ -704,6 +713,11 @@ class DimmerPlusConfigForm(BaseComponentForm):
704
713
  secondary_max = forms.FloatField(
705
714
  initial=1.0, help_text="Maximum secondary value."
706
715
  )
716
+ value_units = forms.CharField(required=False)
717
+
718
+ def __init__(self, *args, **kwargs):
719
+ super().__init__(*args, **kwargs)
720
+ self.fields['value_units'].initial = self.controller.default_value_units
707
721
 
708
722
 
709
723
  class RGBWConfigForm(BaseComponentForm):
simo/core/serializers.py CHANGED
@@ -375,7 +375,6 @@ class ComponentSerializer(FormSerializer):
375
375
  user_role = self.context['request'].user.get_role(
376
376
  self.context['instance']
377
377
  )
378
- print("FORM BASIC FIELDS: ", form.basic_fields)
379
378
  if not user_role.is_superuser and user_role.is_owner:
380
379
  for field_name in list(form.fields.keys()):
381
380
  if field_name not in form.basic_fields:
@@ -164,7 +164,10 @@ class FormsetField(forms.Field):
164
164
  elif isinstance(field, forms.fields.BooleanField):
165
165
  form_data[field_name] = form_data[field_name] == 'on'
166
166
  elif isinstance(field, forms.fields.IntegerField):
167
- form_data[field_name] = int(form_data[field_name])
167
+ try:
168
+ form_data[field_name] = int(form_data[field_name])
169
+ except:
170
+ form_data[field_name] = None
168
171
  if self.widget.formset.can_order:
169
172
  form_data['order'] = int(formset_data.get(
170
173
  '%s-%d-ORDER' % (prefix, i), 0
Binary file
simo/fleet/forms.py CHANGED
@@ -84,8 +84,7 @@ class InterfaceAdminForm(forms.ModelForm):
84
84
 
85
85
  class ColonelComponentForm(BaseComponentForm):
86
86
  colonel = forms.ModelChoiceField(
87
- label="Colonel", queryset=Colonel.objects.all(),
88
- help_text="ATENTION! Changing Colonel after component creation is not recommended!"
87
+ label="Colonel", queryset=Colonel.objects.all()
89
88
  )
90
89
 
91
90
  def clean_colonel(self):
@@ -133,6 +132,7 @@ class ColonelComponentForm(BaseComponentForm):
133
132
  updated_vals[key] = int(val)
134
133
  self.cleaned_data['controls'][i] = updated_vals
135
134
 
135
+ pins_in_use = []
136
136
  formset_errors = {}
137
137
  for i, control in enumerate(self.cleaned_data['controls']):
138
138
  if pin_instances[i].colonel != self.cleaned_data['colonel']:
@@ -144,6 +144,11 @@ class ColonelComponentForm(BaseComponentForm):
144
144
  formset_errors[i] = {
145
145
  'pin': f"{pin_instances[i]} is already occupied by {pin_instances[i].occupied_by}!"
146
146
  }
147
+ elif pin_instances[i].no in pins_in_use:
148
+ formset_errors[i] = {
149
+ 'pin': f"{pin_instances[i].no} is already in use!"
150
+ }
151
+ pins_in_use.append(pin_instances[i].no)
147
152
 
148
153
  errors_list = []
149
154
  if formset_errors:
@@ -424,6 +429,17 @@ class BME680SensorConfigForm(ColonelComponentForm):
424
429
 
425
430
  )
426
431
 
432
+ def clean(self):
433
+ if not self.cleaned_data.get('colonel'):
434
+ return self.cleaned_data
435
+ if self.cleaned_data['interface'].colonel != self.cleaned_data['colonel']:
436
+ self.add_error(
437
+ 'interface',
438
+ f"This interface is on {self.cleaned_data['interface'].colonel}, "
439
+ f"however we need an interface from {self.cleaned_data['colonel']}."
440
+ )
441
+ return self.cleaned_data
442
+
427
443
  def save(self, commit=True):
428
444
  if 'interface' in self.cleaned_data:
429
445
  self.instance.config['i2c_interface'] = self.cleaned_data['interface'].no
@@ -455,6 +471,17 @@ class MPC9808SensorConfigForm(ColonelComponentForm):
455
471
 
456
472
  )
457
473
 
474
+ def clean(self):
475
+ if not self.cleaned_data.get('colonel'):
476
+ return self.cleaned_data
477
+ if self.cleaned_data['interface'].colonel != self.cleaned_data['colonel']:
478
+ self.add_error(
479
+ 'interface',
480
+ f"This interface is on {self.cleaned_data['interface'].colonel}, "
481
+ f"however we need an interface from {self.cleaned_data['colonel']}."
482
+ )
483
+ return self.cleaned_data
484
+
458
485
  def save(self, commit=True):
459
486
  if 'interface' in self.cleaned_data:
460
487
  self.instance.config['i2c_interface'] = self.cleaned_data['interface'].no
@@ -560,6 +587,14 @@ class ColonelSwitchConfigForm(ColonelComponentForm):
560
587
  if self.cleaned_data.get('controls'):
561
588
  self._clean_controls()
562
589
 
590
+ if self.cleaned_data.get('output_pin') and self.cleaned_data.get('controls'):
591
+ for ctrl in self.cleaned_data['controls']:
592
+ if ctrl['pin'] == self.cleaned_data['output_pin']:
593
+ self.add_error(
594
+ "output_pin",
595
+ "Can't be used as control pin at the same time!"
596
+ )
597
+
563
598
  return self.cleaned_data
564
599
 
565
600
 
@@ -592,6 +627,7 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
592
627
  required=True, initial=100,
593
628
  help_text="Maximum component value"
594
629
  )
630
+ value_units = forms.CharField(required=False)
595
631
  duty_min = forms.IntegerField(
596
632
  min_value=0, max_value=1023, required=True, initial=0,
597
633
  help_text="Minumum PWM signal output duty (0 - 1023)"
@@ -621,6 +657,7 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
621
657
  required=True, initial=100,
622
658
  help_text="Component ON value when used with toggle switch"
623
659
  )
660
+
624
661
  slaves = forms.ModelMultipleChoiceField(
625
662
  required=False,
626
663
  queryset=Component.objects.filter(
@@ -639,7 +676,10 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
639
676
 
640
677
  def __init__(self, *args, **kwargs):
641
678
  super().__init__(*args, **kwargs)
642
- self.basic_fields.extend(['turn_on_time', 'turn_off_time', 'skew'])
679
+ self.fields['value_units'].initial = self.controller.default_value_units
680
+ self.basic_fields.extend(
681
+ ['value_units', 'turn_on_time', 'turn_off_time', 'skew']
682
+ )
643
683
  if self.instance.pk and 'slaves' in self.fields:
644
684
  self.fields['slaves'].initial = self.instance.slaves.all()
645
685
 
@@ -654,6 +694,13 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
654
694
  self._clean_pin('output_pin')
655
695
  if 'controls' in self.cleaned_data:
656
696
  self._clean_controls()
697
+ if self.cleaned_data.get('output_pin') and self.cleaned_data.get('controls'):
698
+ for ctrl in self.cleaned_data['controls']:
699
+ if ctrl['pin'] == self.cleaned_data['output_pin']:
700
+ self.add_error(
701
+ "output_pin",
702
+ "Can't be used as control pin at the same time!"
703
+ )
657
704
  return self.cleaned_data
658
705
 
659
706
 
@@ -754,6 +801,14 @@ class ColonelRGBLightConfigForm(ColonelComponentForm):
754
801
  if self.cleaned_data.get('controls'):
755
802
  self._clean_controls()
756
803
 
804
+ if self.cleaned_data.get('output_pin') and self.cleaned_data.get('controls'):
805
+ for ctrl in self.cleaned_data['controls']:
806
+ if ctrl['pin'] == self.cleaned_data['output_pin']:
807
+ self.add_error(
808
+ "output_pin",
809
+ "Can't be used as control pin at the same time!"
810
+ )
811
+
757
812
  if 'color_order' in self.cleaned_data:
758
813
  if self.cleaned_data.get('color_order'):
759
814
  if self.cleaned_data['has_white']:
@@ -818,6 +873,12 @@ class DualMotorValveForm(ColonelComponentForm):
818
873
  self._clean_pin('open_pin')
819
874
  if self.cleaned_data.get('close_pin'):
820
875
  self._clean_pin('close_pin')
876
+ if self.cleaned_data.get('open_pin') \
877
+ and self.cleaned_data.get('close_pin') \
878
+ and self.cleaned_data['open_pin'] == self.cleaned_data['close_pin']:
879
+ self.add_error(
880
+ 'close_pin', "Can't be the same as open pin!"
881
+ )
821
882
  return self.cleaned_data
822
883
 
823
884
  def save(self, commit=True):
@@ -905,6 +966,13 @@ class BlindsConfigForm(ColonelComponentForm):
905
966
  def clean(self):
906
967
  super().clean()
907
968
 
969
+ if self.cleaned_data.get('open_pin') \
970
+ and self.cleaned_data.get('close_pin') \
971
+ and self.cleaned_data['open_pin'] == self.cleaned_data['close_pin']:
972
+ self.add_error(
973
+ 'close_pin', "Can't be the same as open pin!"
974
+ )
975
+
908
976
  if self.cleaned_data.get('open_pin'):
909
977
  self._clean_pin('open_pin')
910
978
  if self.cleaned_data.get('close_pin'):
@@ -926,6 +994,23 @@ class BlindsConfigForm(ColonelComponentForm):
926
994
  return self.cleaned_data
927
995
 
928
996
  self._clean_controls()
997
+
998
+ if self.cleaned_data.get('open_pin'):
999
+ for ctrl in self.cleaned_data['controls']:
1000
+ if ctrl['pin'] == self.cleaned_data['output_pin']:
1001
+ self.add_error(
1002
+ "open_pin",
1003
+ "Can't be used as control pin at the same time!"
1004
+ )
1005
+
1006
+ if self.cleaned_data.get('close_pin'):
1007
+ for ctrl in self.cleaned_data['controls']:
1008
+ if ctrl['pin'] == self.cleaned_data['close_pin']:
1009
+ self.add_error(
1010
+ "close_pin",
1011
+ "Can't be used as control pin at the same time!"
1012
+ )
1013
+
929
1014
  return self.cleaned_data
930
1015
 
931
1016
  def save(self, commit=True):
@@ -974,6 +1059,13 @@ class BurglarSmokeDetectorConfigForm(ColonelComponentForm):
974
1059
  if 'power_pin' in self.cleaned_data:
975
1060
  self._clean_pin('power_pin')
976
1061
 
1062
+ if self.cleaned_data.get('sensor_pin') \
1063
+ and self.cleaned_data.get('power_pin') \
1064
+ and self.cleaned_data['sensor_pin'] == self.cleaned_data['power_pin']:
1065
+ self.add_error(
1066
+ 'power_pin', "Can't be the same as sensor pin!"
1067
+ )
1068
+
977
1069
  return self.cleaned_data
978
1070
 
979
1071
  def save(self, commit=True):
@@ -1049,6 +1141,17 @@ class DALIDeviceConfigForm(ColonelComponentForm):
1049
1141
  )
1050
1142
  return self.cleaned_data['interface']
1051
1143
 
1144
+ def clean(self):
1145
+ if not self.cleaned_data.get('colonel'):
1146
+ return self.cleaned_data
1147
+ if self.cleaned_data['interface'].colonel != self.cleaned_data['colonel']:
1148
+ self.add_error(
1149
+ 'interface',
1150
+ f"This interface is on {self.cleaned_data['interface'].colonel}, "
1151
+ f"however we need an interface from {self.cleaned_data['colonel']}."
1152
+ )
1153
+ return self.cleaned_data
1154
+
1052
1155
  def save(self, commit=True, update_colonel_config=True):
1053
1156
  if 'interface' in self.cleaned_data:
1054
1157
  self.instance.config['dali_interface'] = \
simo/generic/forms.py CHANGED
@@ -270,7 +270,6 @@ class AlarmGroupConfigForm(BaseComponentForm):
270
270
  )
271
271
  has_alarm = False
272
272
 
273
-
274
273
  def __init__(self, *args, **kwargs):
275
274
  super().__init__(*args, **kwargs)
276
275
  from .controllers import AlarmGroup
@@ -281,9 +280,10 @@ class AlarmGroupConfigForm(BaseComponentForm):
281
280
  config__is_main=True
282
281
  ).count()
283
282
  )
284
- self.fields['is_main'].initial = first_alarm_group
285
- if first_alarm_group:
286
- self.fields['is_main'].widget.attrs['disabled'] = 'disabled'
283
+ if 'is_main' in self.fields:
284
+ self.fields['is_main'].initial = first_alarm_group
285
+ if first_alarm_group:
286
+ self.fields['is_main'].widget.attrs['disabled'] = 'disabled'
287
287
  else:
288
288
  if self.instance.config.get('is_main'):
289
289
  self.fields['is_main'].widget.attrs['disabled'] = 'disabled'
simo/users/api.py CHANGED
@@ -35,7 +35,9 @@ class UsersViewSet(mixins.RetrieveModelMixin,
35
35
  email__in=('system@simo.io', 'device@simo.io')
36
36
  ) # Exclude system user
37
37
 
38
- return queryset.filter(roles__instance=self.instance)
38
+ return queryset.filter(
39
+ Q(roles__instance=self.instance) | Q(id=self.request.user.id)
40
+ )
39
41
 
40
42
 
41
43
  def check_permission_to_change(self, request, target_user):
simo/users/serializers.py CHANGED
@@ -24,11 +24,12 @@ class UserSerializer(serializers.ModelSerializer):
24
24
  class Meta:
25
25
  model = User
26
26
  fields = (
27
- 'id', 'email', 'name', 'avatar', 'role', 'is_active',
27
+ 'id', 'email', 'name', 'avatar', 'role', 'is_master', 'is_active',
28
28
  'at_home', 'last_action'
29
29
  )
30
30
  read_only_fields = (
31
- 'id', 'email', 'name', 'avatar', 'at_home', 'last_action', 'ssh_key'
31
+ 'id', 'email', 'name', 'avatar', 'at_home', 'last_action', 'ssh_key',
32
+ 'is_master'
32
33
  )
33
34
 
34
35
  def get_is_active(self, obj):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.0.35
3
+ Version: 2.0.37
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
@@ -38,7 +38,7 @@ simo/core/controllers.py,sha256=Z_sXPaehJcOS8Zz1UZZ2n7-1cjx3_B9dVjHBQHgjtTc,2728
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
41
- simo/core/forms.py,sha256=VoNKoLDR7AAJWHiEUTT8tYcNoVwZh4XxX1-lZEoRzpI,23688
41
+ simo/core/forms.py,sha256=f0_qnyrIem9yj5BKDAenzG5XK_tW7PGKWLuLKb3wPgg,24252
42
42
  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=Qdg2-Qh4dLbW0A5Dmtnpct6CUhEuuvdbIskBijQxopU,2360
@@ -46,7 +46,7 @@ simo/core/middleware.py,sha256=pO52hQOJV_JRmNyUe7zfufSnJFlRITOWX6jwkoPWJhk,2052
46
46
  simo/core/models.py,sha256=W5rShDy8l6GQzTRFiBZFAuibe_fg_LRwSNk973mv_m8,20134
47
47
  simo/core/permissions.py,sha256=yqVXq6SNZccSKcOoGdb0oh-WHsyTTtI9ovJdJyhjv28,2707
48
48
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
49
- simo/core/serializers.py,sha256=dbQ78K9ePBChFPjJHXGj8BkqXQfIFcfFpOtcupGUuz8,18337
49
+ simo/core/serializers.py,sha256=7iE5_ke56GpcQ_cV6LgQIsfG3pAQXPc3t4e60HwogUs,18277
50
50
  simo/core/signal_receivers.py,sha256=C6Jk7wVEtyo4hwcrU7L0ijtpK0wce2MNwpyBgSfSJ-U,5467
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=1OisxqtyWMbzpgeeu5vtBW3gp3Nts4Ei4ff1P-SPpq4,13545
60
- simo/core/__pycache__/api.cpython-38.pyc,sha256=RsMxUiiMEEXsSh2fBbrkjsIUOKUy81dmN9_20SB7CR8,19942
60
+ simo/core/__pycache__/api.cpython-38.pyc,sha256=YBk4BVAMxAkShEyWgeTkHtTpr4P-tMwrTQI5TTP7vFE,19968
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
@@ -77,11 +77,11 @@ simo/core/__pycache__/middleware.cpython-38.pyc,sha256=ESR5JPtITo9flczO0672sfzYU
77
77
  simo/core/__pycache__/models.cpython-38.pyc,sha256=UNX6Btm5ZnpLzSCWgevQnSYzAyDWttA2Ivy7CGPu8DU,17288
78
78
  simo/core/__pycache__/permissions.cpython-38.pyc,sha256=flJOCh94U8mFhE0XWzUD0sGR6Xe1HlfG4hQtNSnAGZ4,2788
79
79
  simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
80
- simo/core/__pycache__/serializers.cpython-38.pyc,sha256=ltj2lqyqt2ctV6svTQ_VkTmq_aOx8iPhTdu5QQhScdk,17213
80
+ simo/core/__pycache__/serializers.cpython-38.pyc,sha256=8QlBSWOtgmhTpFbMMgGoXtMoTMETSnpA37z2LBgRzNQ,17178
81
81
  simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=UcKT8RK_14CI-JEWfplnIxskmWec_w5-gqKUXITLDA4,4323
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
84
- simo/core/__pycache__/tasks.cpython-38.pyc,sha256=7qQsnj1VkWTrYQNwfXH8SKkiaXBQteibciubKWPClXU,9139
84
+ simo/core/__pycache__/tasks.cpython-38.pyc,sha256=yt2G8HPIkx1Djz4oVBfhUW9WOR9GOdxLhHFXViQJc6A,9139
85
85
  simo/core/__pycache__/todos.cpython-38.pyc,sha256=lOqGZ58siHM3isoJV4r7sg8igrfE9fFd-jSfeBa0AQI,253
86
86
  simo/core/__pycache__/views.cpython-38.pyc,sha256=YrKRZPaV_JM4VGpdhVhsK-90UwUTOqp-V-Yj0SRGZgs,4212
87
87
  simo/core/__pycache__/widgets.cpython-38.pyc,sha256=sR0ZeHCHrhnNDBJuRrxp3zUsfBp0xrtF0xrK2TkQv1o,3520
@@ -10149,7 +10149,7 @@ simo/core/utils/config_values.py,sha256=4HCQmv5wQdupd16WOp80oJSyU7EDccjUO6blX--d
10149
10149
  simo/core/utils/easing.py,sha256=N2NwD0CjLh82RGaYJKjyt-VVpVeS9z0mba8fqr8A1t0,1499
10150
10150
  simo/core/utils/form_fields.py,sha256=UOzYdPd71qgCw1H3qH01u85YjrOlETPJAHOJrZKhyD0,627
10151
10151
  simo/core/utils/form_widgets.py,sha256=Zxn9jJqPle9Q_BKNJnyTDn7MosYwNp1TFu5LoKs0bfc,408
10152
- simo/core/utils/formsets.py,sha256=1u34QGZ2P67cxZD2uUJS3lAf--E8XsiiqFmZ4P41Vw4,6463
10152
+ simo/core/utils/formsets.py,sha256=1v2folVgoOd915LMQjyb0OMBuQ535HPq6uymm5m35ZU,6573
10153
10153
  simo/core/utils/helpers.py,sha256=TOWy3slspaEYEhe9zDcb0RgzHUYslF6LZDlrWPGSqUI,3791
10154
10154
  simo/core/utils/json.py,sha256=x3kMiiK30vuyWSYfghLVsDKo0N2JlCxZ5n8cwel85Vk,464
10155
10155
  simo/core/utils/logs.py,sha256=Zn9JQxqCH9Odx2J1BWT84nFCfkJ4Z4p5X8psdll7hNc,2366
@@ -10183,7 +10183,7 @@ simo/fleet/auto_urls.py,sha256=X04oKJWA48wFW5iXg3PPROY2KDdHn_a99orQSE28QC4,518
10183
10183
  simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
10184
10184
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10185
10185
  simo/fleet/controllers.py,sha256=WCqOA5Qrn9RavdfcB8X06WwaTE-9TGUprTQHZ8V8-nA,23172
10186
- simo/fleet/forms.py,sha256=Kvw-MG-3mI4OIPwo0uiJ_1E5QX3eIr8WR1_U2ggO3U0,43697
10186
+ simo/fleet/forms.py,sha256=7MuKBfOUgXuLDsSYo0jQHYxWJxQiTB95K7ogwULmp84,48121
10187
10187
  simo/fleet/gateways.py,sha256=KV5i5fxXIrlK-k6zyEkk83x11GJt-ELQ0npb4Ac83cM,3693
10188
10188
  simo/fleet/managers.py,sha256=XOpDOA9L-f_550TNSyXnJbun2EmtGz1TenVTMlUSb8E,807
10189
10189
  simo/fleet/models.py,sha256=bD5AebGFCAYGXPYhTA2nK1X9KpMG4WK4zFk9OzBDoHI,15301
@@ -10199,11 +10199,11 @@ simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rL9fb7cCQatyFvXyKmlNOKmxVo8vHYe
10199
10199
  simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=SqyTuaz_kEBvx-bL46SclsZEEP5RFh6U6TGKyXDdiOE,565
10200
10200
  simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
10201
10201
  simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
10202
- simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=IInB1lBX4uFj1ZDyzCJEDABPXWTMwUpKBczkoJyj4SI,19842
10203
- simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=aW_L2Q8y7YACrV6wlO3_JL-Id_16biEkXT_BAPnqzHg,31617
10202
+ simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=TN3yvfZJgS7FwzgP4S1aDoaOqxbKj2oXfXOxqbkIXJU,19856
10203
+ simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=spAw3w0y42aF0driUhxT6QrDDOom3KkOrgoFYwAwqak,31698
10204
10204
  simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=YAcgTOqJbtjGI03lvEcU6keFfrwAHkObVmErYzfRvjk,3569
10205
10205
  simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=8uz-xpUiqbGDgXIZ_XRZtFb-Tju6NGxflGg-Ee4Yo6k,1310
10206
- simo/fleet/__pycache__/models.cpython-38.pyc,sha256=dQ5Fj9nXg7vgFfACzxWurhqGw8EnYa9Px7SwmGiAih4,12904
10206
+ simo/fleet/__pycache__/models.cpython-38.pyc,sha256=LjcLsSytCQd17xhH-5RrzvnZ6JYI1ilvNdCY2iUCsGc,12935
10207
10207
  simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
10208
10208
  simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=9ljhwoHkolcVrJwOVbYCbGPAUKgALRwor_M3W_K0adE,3173
10209
10209
  simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=0-WhvzVsVJ5A_AgoKnWKOJjoJioLDNsYX4C6bGJANwQ,13551
@@ -10286,7 +10286,7 @@ simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10286
10286
  simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
10287
10287
  simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
10288
10288
  simo/generic/controllers.py,sha256=WYuOUzDWvkYRaTvlbdGy_qmwp1o_ohqKDfV7OrOq2QU,52218
10289
- simo/generic/forms.py,sha256=NPHNg_8BPTIJt-DR0-GkNWgVo9bE0_50PUWSnpIE4Dg,24262
10289
+ simo/generic/forms.py,sha256=ZKK7uqSHTff_sAX7ZWZZpf5l1uvyosdXa_BCX9tLuf0,24314
10290
10290
  simo/generic/gateways.py,sha256=RcHubz3oyY_ysPLNPLRoyh8C6r-WfPzpD98OVkDvPPI,17731
10291
10291
  simo/generic/models.py,sha256=92TACMhJHadAg0TT9GnARO_R3_Sl6i-GGjhG_x7YdFI,7391
10292
10292
  simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
@@ -10372,14 +10372,14 @@ simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-38.
10372
10372
  simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=YMBRHVon2nWDtIUbghckjnC12sIg_ykPWhV5aM0tto4,178
10373
10373
  simo/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10374
10374
  simo/users/admin.py,sha256=6RKGnwcrmewJFPzpqnxYn8rxjHO4tJPVFJvA3eMum2s,6746
10375
- simo/users/api.py,sha256=FVo2bHkGA9VKavyjQm8_wfvI5rQ5KcMZliRiTJjixmI,9462
10375
+ simo/users/api.py,sha256=vf11fV8ZCao3Q2TdUO8mDTF3n0N3JYad7CUhz7_ZrZQ,9516
10376
10376
  simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
10377
10377
  simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
10378
10378
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10379
10379
  simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
10380
10380
  simo/users/models.py,sha256=I_iAa-6CLORshmGszSl021zl97oaXNIEOZYMSq5Wn5M,18902
10381
10381
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10382
- simo/users/serializers.py,sha256=e6yIUsO7BfvrZ4IQHBn-FdpAUMgic5clmGQdTtRlGRY,2515
10382
+ simo/users/serializers.py,sha256=DwbFGi4WeTYXOSnfrBfd5rC5OGtevYurn27EaTVa1EU,2553
10383
10383
  simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
10384
10384
  simo/users/sso_views.py,sha256=-XI67TvQ7SN3goU4OuAHyn84u_1vtusvpn7Pu0K97zo,4648
10385
10385
  simo/users/tasks.py,sha256=v9J7t4diB0VnqUDVZAQ8H-rlr4ZR14bgEUuEGpODyOI,854
@@ -10466,8 +10466,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10466
10466
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10467
10467
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10468
10468
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10469
- simo-2.0.35.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10470
- simo-2.0.35.dist-info/METADATA,sha256=K3eQYM55-6gro2zNR8B_egdy6IPqogizV_qnB1CTwR0,1730
10471
- simo-2.0.35.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10472
- simo-2.0.35.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10473
- simo-2.0.35.dist-info/RECORD,,
10469
+ simo-2.0.37.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10470
+ simo-2.0.37.dist-info/METADATA,sha256=xKOE5qzOHNzbeyUNG_nM_qrb0pPynAJuc-Qshb9UjUs,1730
10471
+ simo-2.0.37.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10472
+ simo-2.0.37.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10473
+ simo-2.0.37.dist-info/RECORD,,
File without changes