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

@@ -156,6 +156,11 @@ class PresenceLighting(Script):
156
156
  ).first()
157
157
  if comp:
158
158
  condition['component'] = comp
159
+ condition['condition_value'] = \
160
+ comp.controller._string_to_vals(condition['value'])
161
+ if condition['op'] != 'in':
162
+ condition['condition_value'] = \
163
+ condition['condition_value'][0]
159
164
  self.conditions.append(condition)
160
165
  comp.on_change(self._on_condition)
161
166
  self.condition_comps[comp.id] = comp
@@ -203,20 +208,20 @@ class PresenceLighting(Script):
203
208
  continue
204
209
 
205
210
  if condition['op'] == 'in':
206
- if comp.value not in self._string_to_vals(condition['value']):
211
+ if comp.value not in condition['condition_value']:
207
212
  if must_on and on_sensor:
208
213
  print(
209
214
  f"Condition not met: [{comp} value:{comp.value} "
210
- f"{condition['op']} {condition['value']}]"
215
+ f"{condition['op']} {condition['condition_value']}]"
211
216
  )
212
217
  additional_conditions_met = False
213
218
  break
214
219
 
215
- if not op(comp.value, condition['value']):
220
+ if not op(comp.value, condition['condition_value']):
216
221
  if must_on and on_sensor:
217
222
  print(
218
223
  f"Condition not met: [{comp} value:{comp.value} "
219
- f"{condition['op']} {condition['value']}]"
224
+ f"{condition['op']} {condition['condition_value']}]"
220
225
  )
221
226
  additional_conditions_met = False
222
227
  break
simo/automation/forms.py CHANGED
@@ -150,7 +150,7 @@ class ConditionForm(forms.Form):
150
150
  for val in values:
151
151
  val = val.strip()
152
152
  if controller_val_type == bool:
153
- if val.lower() in ('0', 'false', 'none', 'null'):
153
+ if val.lower() in ('0', 'false', 'none', 'null', 'off'):
154
154
  final_val = False
155
155
  else:
156
156
  final_val = True
@@ -169,6 +169,12 @@ class ConditionForm(forms.Form):
169
169
  'value', f"{val} is not compatible with selected component."
170
170
  )
171
171
  continue
172
+
173
+ if final_val == True:
174
+ final_val = 'ON'
175
+ elif final_val == False:
176
+ final_val = 'OFF'
177
+
172
178
  final_values.append(final_val)
173
179
 
174
180
  if self.cleaned_data['op'] == 'in':
@@ -80,6 +80,7 @@ class ScriptRunHandler(multiprocessing.Process):
80
80
  class AutomationsGatewayHandler(BaseObjectCommandsGatewayHandler):
81
81
  name = "Automation"
82
82
  config_form = BaseGatewayForm
83
+ info = "Provides various types of automation capabilities"
83
84
 
84
85
  running_scripts = {}
85
86
  periodic_tasks = (
Binary file
simo/core/api.py CHANGED
@@ -716,6 +716,7 @@ class StatesViewSet(InstanceMixin, viewsets.GenericViewSet):
716
716
  })
717
717
 
718
718
 
719
+ # Legacy.
719
720
  class ControllerTypes(InstanceMixin, viewsets.GenericViewSet):
720
721
  url = 'core/controller-types'
721
722
  basename = 'controller-types'
@@ -745,6 +746,39 @@ class ControllerTypes(InstanceMixin, viewsets.GenericViewSet):
745
746
  return RESTResponse(data)
746
747
 
747
748
 
749
+ class GWControllerTypes(InstanceMixin, viewsets.GenericViewSet):
750
+ url = 'core/gw-controller-types'
751
+ basename = 'gw-controller-types'
752
+ queryset = []
753
+
754
+ def get_permissions(self):
755
+ permissions = super().get_permissions()
756
+ permissions.append(IsInstanceSuperuser())
757
+ return permissions
758
+
759
+ def list(self, request, *args, **kwargs):
760
+ from .utils.type_constants import get_controller_types_map
761
+ data = {}
762
+
763
+ for uid, cls in get_controller_types_map(user=request.user).items():
764
+ if cls.gateway_class.uid not in data:
765
+ data[cls.gateway_class.uid] = {
766
+ 'name': cls.gateway_class.name,
767
+ 'info': cls.gateway_class.info,
768
+ 'controllers': []
769
+ }
770
+ data[cls.gateway_class.uid]['controllers'].append({
771
+ 'uid': uid,
772
+ 'name': cls.name,
773
+ 'is_discoverable': cls.is_discoverable,
774
+ 'manual_add': cls.manual_add,
775
+ 'discovery_msg': cls.discovery_msg,
776
+ 'info': cls.info(cls)
777
+ })
778
+
779
+ return RESTResponse(data)
780
+
781
+
748
782
  class RunningDiscoveries(InstanceMixin, viewsets.GenericViewSet):
749
783
  url = 'core/discoveries'
750
784
  basename = 'discoveries'
simo/core/api_meta.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from collections import OrderedDict
2
2
  from django.urls import reverse
3
3
  from django.utils.encoding import force_str
4
- from django.forms.utils import pretty_name
5
4
  from rest_framework.metadata import SimpleMetadata
6
5
  from rest_framework import serializers
7
6
  from rest_framework.utils.field_mapping import ClassLookupDict
@@ -97,7 +96,7 @@ class SIMOAPIMetadata(SimpleMetadata):
97
96
  field_info['child'] = self.get_field_info(field.child)
98
97
  elif getattr(field, 'fields', None):
99
98
  field.Meta.form = form_field.formset_cls.form
100
- field_info['children'] = self.get_formset_serializer_info(field)
99
+ field_info['children'] = self.get_serializer_info(field)
101
100
 
102
101
  if form_field and hasattr(form_field, 'queryset'):
103
102
  if form_field.queryset.model == Icon:
@@ -116,7 +115,7 @@ class SIMOAPIMetadata(SimpleMetadata):
116
115
  zone__instance=self.instance
117
116
  )
118
117
 
119
- if not field_info.get('read_only') and hasattr(field, 'choices'):
118
+ if not field_info.get('read_only') and hasattr(field, 'choices'):# and not hasattr(form_field, 'forward'):
120
119
  field_info['choices'] = [
121
120
  {
122
121
  'value': choice_value,
@@ -125,20 +124,4 @@ class SIMOAPIMetadata(SimpleMetadata):
125
124
  for choice_value, choice_name in field.choices.items()
126
125
  ]
127
126
 
128
- return field_info
129
-
130
-
131
- def get_formset_serializer_info(self, serializer):
132
- """
133
- Given an instance of a serializer, return a dictionary of metadata
134
- about its fields.
135
- """
136
- if hasattr(serializer, 'child'):
137
- # If this is a `ListSerializer` then we want to examine the
138
- # underlying child serializer instance instead.
139
- serializer = serializer.child
140
- return OrderedDict([
141
- (field_name, self.get_field_info(field))
142
- for field_name, field in serializer.get_fields().items()
143
- if not isinstance(field, serializers.HiddenField)
144
- ])
127
+ return field_info
simo/core/controllers.py CHANGED
@@ -40,6 +40,7 @@ class ControllerBase(ABC):
40
40
  manual_add = True # Can be added manually
41
41
  family = None
42
42
  masters_only = False # component can be created/modified by hub masters only
43
+ info_template_path = None
43
44
 
44
45
  @property
45
46
  @abstractmethod
@@ -76,11 +77,6 @@ class ControllerBase(ABC):
76
77
  :return: Default value of this base component type
77
78
  """
78
79
 
79
- @property
80
- def info_template_path(self) -> str:
81
- return f"{self.__class__.__module__.split('.')[-2]}/" \
82
- f"controllers_info/{self.__class__.__name__}.md"
83
-
84
80
  @abstractmethod
85
81
  def _validate_val(self, value, occasion=None):
86
82
  """
@@ -121,7 +117,8 @@ class ControllerBase(ABC):
121
117
  cls, '_process_discovery'
122
118
  )
123
119
 
124
- def info(self):
120
+ @classmethod
121
+ def info(cls, component=None):
125
122
  '''
126
123
  Override this to give users help on how to use this component type,
127
124
  after you do that, include any component instance specific information
@@ -130,10 +127,13 @@ class ControllerBase(ABC):
130
127
  along with any other relative information,
131
128
  regarding this particular component instance
132
129
  '''
130
+ if not cls.info_template_path:
131
+ cls.info_template_path = f"{cls.__module__.split('.')[-2]}/" \
132
+ f"controllers_info/{cls.__name__}.md"
133
133
  try:
134
134
  return render_to_string(
135
- self.info_template_path, {
136
- 'component': self.component if hasattr(self, 'component') else None
135
+ cls.info_template_path, {
136
+ 'component': component
137
137
  }
138
138
  )
139
139
  except:
@@ -214,7 +214,23 @@ class ControllerBase(ABC):
214
214
  '''
215
215
  val_type = type(self.default_value)
216
216
  v = str(v).strip('(').strip('[').rstrip(')').rstrip(']')
217
- return [val_type(val.strip()) for val in v.split(',')]
217
+ vals = []
218
+ for val in v.split(','):
219
+ val = val.strip()
220
+ if val.lower() in ('none', 'null'):
221
+ val = None
222
+ elif val_type == bool:
223
+ if val.lower() in ('0', 'false', 'off'):
224
+ val = False
225
+ else:
226
+ val = True
227
+ else:
228
+ try:
229
+ val = val_type(val)
230
+ except:
231
+ continue
232
+ vals.append(val)
233
+ return vals
218
234
 
219
235
  def send(self, value):
220
236
  self.component.refresh_from_db()
simo/core/gateways.py CHANGED
@@ -3,7 +3,7 @@ import time
3
3
  import json
4
4
  import paho.mqtt.client as mqtt
5
5
  from django.conf import settings
6
- from django.db import close_old_connections
6
+ from django.template.loader import render_to_string
7
7
  from abc import ABC, abstractmethod
8
8
  from simo.core.utils.helpers import classproperty
9
9
  from simo.core.events import GatewayObjectCommand, get_event_obj
@@ -33,6 +33,12 @@ class BaseGatewayHandler(ABC):
33
33
  def uid(cls):
34
34
  return ".".join([cls.__module__, cls.__name__])
35
35
 
36
+
37
+ @classproperty
38
+ @classmethod
39
+ def info(cls):
40
+ return
41
+
36
42
  def __init__(self, gateway_instance):
37
43
  self.gateway_instance = gateway_instance
38
44
  super().__init__()
simo/core/serializers.py CHANGED
@@ -131,7 +131,6 @@ class ComponentManyToManyRelatedField(serializers.Field):
131
131
  return self.queryset.filter(pk__in=data)
132
132
 
133
133
 
134
-
135
134
  class ComponentFormsetField(FormSerializer):
136
135
 
137
136
  class Meta:
@@ -152,9 +151,20 @@ class ComponentFormsetField(FormSerializer):
152
151
  }
153
152
 
154
153
  def __init__(self, formset_field, *args, **kwargs):
155
- self.Meta.form = formset_field.formset_cls.form
154
+ self.form = formset_field.formset_cls.form
156
155
  super().__init__(*args, **kwargs)
157
156
 
157
+ def get_form(self, data=None, **kwargs):
158
+ form_cls = self.form
159
+ instance = form_cls(data=data, **kwargs)
160
+ # Handle partial validation on the form side
161
+ if self.partial:
162
+ set_form_partial_validation(
163
+ instance, self.Meta.minimum_required
164
+ )
165
+ instance.prefix = ''
166
+ return instance
167
+
158
168
  def get_fields(self):
159
169
  ret = super(FormSerializerBase, self).get_fields()
160
170
 
@@ -164,7 +174,7 @@ class ComponentFormsetField(FormSerializer):
164
174
  FORM_SERIALIZER_FIELD_MAPPING
165
175
  )
166
176
 
167
- form = self.Meta.form
177
+ form = self.form
168
178
  for field_name, form_field in getattr(form, 'all_base_fields', form.base_fields).items():
169
179
 
170
180
  if field_name in getattr(self.Meta, 'exclude', []):
@@ -249,11 +259,6 @@ class ComponentFormsetField(FormSerializer):
249
259
 
250
260
  return ret
251
261
 
252
- def get_form(self, data=None, **kwargs):
253
- form = super().get_form(data=data, **kwargs)
254
- form.prefix = ''
255
- return form
256
-
257
262
  def create(self, validated_data):
258
263
  return validated_data
259
264
 
Binary file
simo/fleet/controllers.py CHANGED
@@ -25,7 +25,7 @@ from .forms import (
25
25
  ColonelSwitchConfigForm, ColonelPWMOutputConfigForm, DCDriverConfigForm,
26
26
  ColonelNumericSensorConfigForm, ColonelRGBLightConfigForm,
27
27
  ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
28
- BME680SensorConfigForm, MPC9808SensorConfigForm, ENS160SensorConfigForm,
28
+ BME680SensorConfigForm, MCP9808SensorConfigForm, ENS160SensorConfigForm,
29
29
  DualMotorValveForm, BlindsConfigForm, GateConfigForm,
30
30
  BurglarSmokeDetectorConfigForm,
31
31
  TTLockConfigForm, DALIDeviceConfigForm, DaliLampForm, DaliGearGroupForm,
@@ -177,10 +177,10 @@ class BME680Sensor(FleeDeviceMixin, BaseMultiSensor):
177
177
  name = "BME680 Climate Sensor (I2C)"
178
178
 
179
179
 
180
- class MPC9808TempSensor(FleeDeviceMixin, BaseNumericSensor):
180
+ class MCP9808TempSensor(FleeDeviceMixin, BaseNumericSensor):
181
181
  gateway_class = FleetGatewayHandler
182
- config_form = MPC9808SensorConfigForm
183
- name = "MPC9808 Temperature Sensor (I2C)"
182
+ config_form = MCP9808SensorConfigForm
183
+ name = "MCP9808 Temperature Sensor (I2C)"
184
184
 
185
185
  @property
186
186
  def default_value_units(self):
simo/fleet/forms.py CHANGED
@@ -501,7 +501,7 @@ class BME680SensorConfigForm(ColonelComponentForm):
501
501
  return super().save(commit=commit)
502
502
 
503
503
 
504
- class MPC9808SensorConfigForm(ColonelComponentForm):
504
+ class MCP9808SensorConfigForm(ColonelComponentForm):
505
505
  interface = Select2ModelChoiceField(
506
506
  queryset=Interface.objects.filter(type='i2c'),
507
507
  url='autocomplete-interfaces',
simo/fleet/gateways.py CHANGED
@@ -14,6 +14,8 @@ from simo.core.utils.serialization import deserialize_form_data
14
14
  class FleetGatewayHandler(BaseObjectCommandsGatewayHandler):
15
15
  name = "SIMO.io Fleet"
16
16
  config_form = BaseGatewayForm
17
+ info = "Provides components that run on SIMO.io colonel boards " \
18
+ "like The Game Changer"
17
19
 
18
20
  periodic_tasks = (
19
21
  ('look_for_updates', 600),
@@ -0,0 +1,28 @@
1
+ # Generated by Django 4.2.10 on 2024-12-03 09:30
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ def forwards_func(apps, schema_editor):
7
+ Component = apps.get_model("core", "Component")
8
+
9
+ for comp in Component.objects.filter(
10
+ controller_uid='simo.fleet.controllers.MPC9808TempSensor'
11
+ ):
12
+ comp.controller_uid = 'simo.fleet.controllers.MCP9808TempSensor'
13
+ comp.save()
14
+
15
+
16
+ def reverse_func(apps, schema_editor):
17
+ pass
18
+
19
+
20
+ class Migration(migrations.Migration):
21
+
22
+ dependencies = [
23
+ ('fleet', '0042_auto_20241120_1028'),
24
+ ]
25
+
26
+ operations = [
27
+ migrations.RunPython(forwards_func, reverse_func, elidable=True),
28
+ ]
simo/generic/gateways.py CHANGED
@@ -62,6 +62,9 @@ class CameraWatcher(threading.Thread):
62
62
  class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
63
63
  name = "Generic"
64
64
  config_form = BaseGatewayForm
65
+ info = "Provides generic type components which use other components to operate like " \
66
+ "thermostats, alarm groups, watering programs, alarm clocks," \
67
+ "etc. "
65
68
 
66
69
  running_scripts = {}
67
70
  periodic_tasks = (
@@ -242,6 +245,8 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
242
245
  class DummyGatewayHandler(BaseObjectCommandsGatewayHandler):
243
246
  name = "Dummy"
244
247
  config_form = BaseGatewayForm
248
+ info = "Provides dummy components that do absolutely anything, " \
249
+ "but comes in super handy when configuring custom automations."
245
250
 
246
251
  def perform_value_send(self, component, value):
247
252
  component.controller.set(value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.6.7
3
+ Version: 2.6.8
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
@@ -13,18 +13,18 @@ simo/__pycache__/urls.cpython-38.pyc,sha256=u0x6EqT8S1YfDOSPgbI8Kf-RDlveY9OV-EDX
13
13
  simo/__pycache__/wsgi.cpython-38.pyc,sha256=TpRxO7VM_ql31hbKphVdanydC5RI1nHB4l0QA2pdWxo,322
14
14
  simo/automation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  simo/automation/app_widgets.py,sha256=gaqImMZjuMHm7nIb9a4D-Y3qipz_WhSPAHXcwGx4Uzs,199
16
- simo/automation/controllers.py,sha256=Py62mo8boFsreiGVAnalJt_1SJePxD67aCGma6zGjWg,10206
17
- simo/automation/forms.py,sha256=wJMaXE5ngO_o60jqxnf4Om09q48yXpWwRna0FkQCZYs,10081
18
- simo/automation/gateways.py,sha256=7r33NOAiRd_RGMMm44i0KYzuAuweQnEF4HxLo-Rpexs,9408
16
+ simo/automation/controllers.py,sha256=kk_gssVoxfkn268gAhmmSpTWnW4UnEQAVyxLHwyZYPc,10498
17
+ simo/automation/forms.py,sha256=UWnkxw8pILPK0smRPTo4SLgsZl78zOySx7JIc30Bgtk,10228
18
+ simo/automation/gateways.py,sha256=wElqHHyNd2jdpWuhO9DQ0yORIrObSzJsgZ-4dlKCLo4,9471
19
19
  simo/automation/helpers.py,sha256=iP-fxxB8HsFQy3k2CjFubu86aMqvWgmh-p24DiyOrek,4330
20
20
  simo/automation/models.py,sha256=l45FHgeKGsfpLtd1X1PVFpIjB5JI4BlvKkodpcxm6aE,927
21
21
  simo/automation/serializers.py,sha256=PjyFrjdPK1mBsgbNhyqMi9SWzcymqTa742ipy0LhAN4,1996
22
22
  simo/automation/state.py,sha256=aZZvNBae7unnux_zGHCIWCV2z47hVJc-DIL72Hqfkeo,600
23
23
  simo/automation/__pycache__/__init__.cpython-38.pyc,sha256=YmP0xAD-mxpQHgdTZeC64sXChA8TriMZD1jckNYi3xg,164
24
24
  simo/automation/__pycache__/app_widgets.cpython-38.pyc,sha256=7DfUA9V_1MiwrOe_ta-ts8dYY8xXb9UMg2_9A3XoRcs,523
25
- simo/automation/__pycache__/controllers.cpython-38.pyc,sha256=s9YqMUTCzjIxNVrk36SrIvGrXWYLc9DR80Sa3orpg1o,7936
26
- simo/automation/__pycache__/forms.cpython-38.pyc,sha256=qxQZeTafJOT_lrXOKY6134XjIrx5OzABAZdncNnRV4E,7720
27
- simo/automation/__pycache__/gateways.cpython-38.pyc,sha256=W6OrugOLOGaYbibEWSs-zBZc8jQpNlO_NmJU-rmd6fU,7558
25
+ simo/automation/__pycache__/controllers.cpython-38.pyc,sha256=YTL0-xu1CjO57mz1HKX1DIDrZeSGiGtl9-uKlokbF1Y,8024
26
+ simo/automation/__pycache__/forms.cpython-38.pyc,sha256=cpA5hA2Iz3JsPC0Dq01ki1I7S9c5DKRcXveHApI1dJo,7772
27
+ simo/automation/__pycache__/gateways.cpython-38.pyc,sha256=4gDB7AeKwumAty-1x1Uyh1dEckw-kntBafMNvayH-PA,7621
28
28
  simo/automation/__pycache__/helpers.cpython-38.pyc,sha256=4VSSarOFnUk_KExWwvDlx5dEhv8aHUCHMZDtGG--pUY,3627
29
29
  simo/automation/__pycache__/models.cpython-38.pyc,sha256=6gXdIMcrWaGACal2omj-b2if5JW8QvLIrtRfYVpDRQU,1230
30
30
  simo/automation/__pycache__/serializers.cpython-38.pyc,sha256=gWgcuPE8aY-TmuRLXCuSR74mvtKerpZ04m0MfPfw0AI,3405
@@ -61,29 +61,29 @@ simo/backups/migrations/__pycache__/0004_alter_backup_options_alter_backuplog_op
61
61
  simo/backups/migrations/__pycache__/__init__.cpython-38.pyc,sha256=Lz1fs6V05h2AoxTOLNye0do9bEMnyuaXB_hHOjG5-HU,172
62
62
  simo/core/__init__.py,sha256=_s2TjJfQImsMrTIxqLAx9AZie1Ojmm6sCHASdl3WLGU,50
63
63
  simo/core/admin.py,sha256=nmFDO57D5hXHDfl0wjJ9J5jBxyCqW4Gp_uqHhpS2uuw,18564
64
- simo/core/api.py,sha256=HWyzmFGbULndSaW3sdrQa_kw2zfjd7yzfYxErAij7cY,29070
64
+ simo/core/api.py,sha256=iipxmn7rWnK_c2JaHJ8PQ7BVAsA19VlFIM7RkU0HxNM,30232
65
65
  simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
66
- simo/core/api_meta.py,sha256=7yvarprPAHV2VP7AZV8wOqmeWsJ_UInrzKMakkeXsXU,5686
66
+ simo/core/api_meta.py,sha256=e9iqVv-3d651lMvZY-ILG4F35Puh2XunnwykiBUbl5E,5055
67
67
  simo/core/app_widgets.py,sha256=VxZzapuc-a29wBH7JzpvNF2SK1ECrgNUySId5ke1ffc,2509
68
68
  simo/core/apps.py,sha256=CsqpiQerhmrMsH-wGiG-gQgXd9qEkIi-LUaA9cXpKSw,425
69
69
  simo/core/auto_urls.py,sha256=FBDclIeRp5UVWomIUbRzUgY-AoMk-r2qC2htlwKD4Lo,1106
70
70
  simo/core/autocomplete_views.py,sha256=sQbT2g1Y9HGLLKazKaNfnZmwa6RJlTek9XzkGQcx4P8,4363
71
71
  simo/core/base_types.py,sha256=WypW8hTfzveuTQtruGjLYAGQZIuczxTlW-SdRk3iQug,666
72
72
  simo/core/context.py,sha256=LKw1I4iIRnlnzoTCuSLLqDX7crHdBnMo3hjqYvVmzFc,1557
73
- simo/core/controllers.py,sha256=vAZwtwPb259Bw-3dPSXuDxIcErMnQ6YBpBaUh4HWghM,35656
73
+ simo/core/controllers.py,sha256=xqEtTWkIJSpgez2OmsLoYImR4ZPSzY20xR-qe8eMQpo,36129
74
74
  simo/core/dynamic_settings.py,sha256=bUs58XEZOCIEhg1TigR3LmYggli13KMryBZ9pC7ugAQ,1872
75
75
  simo/core/events.py,sha256=1_KIk5pJqdLPRQlCQ9xSyALst2Cn0b2lAEAJ3QjwIjE,4801
76
76
  simo/core/filters.py,sha256=6wbn8C2WvKTTjtfMwwLBp2Fib1V0-DMpS4iqJd6jJQo,2540
77
77
  simo/core/form_fields.py,sha256=wowWocYgxkKBr0WYzpKn4UvH4ScnImus56Tg2G8OPBc,2274
78
78
  simo/core/forms.py,sha256=CCKypzX32-Mp8LpyO0ffiPcwIitaw0F03e8A9ZL0Mhw,21586
79
- simo/core/gateways.py,sha256=m0eS3XjVe34Dge6xtoCq16kFWCKJcdQrT0JW0REqoq8,3715
79
+ simo/core/gateways.py,sha256=7SvBKuVwdYYLRoAP8FXT2qz63FBpns21vlSMW1bCDFg,3795
80
80
  simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
81
81
  simo/core/managers.py,sha256=n-b3I4uXzfHKTeB1VMjSaMsDUxp8FegFJwnbV1IsWQ4,3019
82
82
  simo/core/middleware.py,sha256=eUFf6iP-Snx_0TE3MoXsSwqrd5IjlukqZk2GQGStRCo,3385
83
83
  simo/core/models.py,sha256=QNVTnWeHAW6LVrs3eaR7WNMhwjICuQpXZ8vyH_2qCBo,22834
84
84
  simo/core/permissions.py,sha256=2YNRot2qoHjHKWPGOpO4PBseecctPbTlUQpepnFkCRs,3027
85
85
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
86
- simo/core/serializers.py,sha256=JN1B2IcLkjZB3XiAetxK8Awx9WNHPOFwrCOrGqTLdbE,22118
86
+ simo/core/serializers.py,sha256=OvwFIIKHJtBuAJPhILPLx-9ENADBSz5T6dHOuKKtC3g,22326
87
87
  simo/core/signal_receivers.py,sha256=xUnQrWFBMF0Uasj6PzpERPr6h6BR-ZjUb1NSakRSzQo,9458
88
88
  simo/core/socket_consumers.py,sha256=trRZvBGTJ7xIbfdmVvn7zoiWp_qssSkMZykDrI5YQyE,9783
89
89
  simo/core/storage.py,sha256=_5igjaoWZAiExGWFEJMElxUw55DzJG1jqFty33xe8BE,342
@@ -94,29 +94,29 @@ simo/core/views.py,sha256=yx9I0byeVUa-LAOnklpWIYwpNNOf5m9fyjKBvj4YCh4,2475
94
94
  simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
95
95
  simo/core/__pycache__/__init__.cpython-38.pyc,sha256=ZJFM_XN0RmJMULQulgA_wFiOnEtsMoedcOWnXjH-Y8o,208
96
96
  simo/core/__pycache__/admin.cpython-38.pyc,sha256=WAfdq_hAdkW-_QwJ0E7NSd25yxnPRi_HjJ-uKFMJzcg,14146
97
- simo/core/__pycache__/api.cpython-38.pyc,sha256=0kALbhViLcVqxcxzc_mmT9TzZcONc0ZNzZCWscbxjWE,22459
97
+ simo/core/__pycache__/api.cpython-38.pyc,sha256=88Btwy435_Jb5bYnkuBfsrNILpdfhMTCYHuNdo1pu-8,23209
98
98
  simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=mi3mu5qEKio_PvfQEvr3Q6AhdPLAHxzxAxrMbAz_pKU,1712
99
- simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=CpiIoUPpQkX8db8o150LtGo79nHnBoEWKeRF8NoY69o,4391
99
+ simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=PrJrXcjbhXQkYrvEVG9jpRzkB8XYBMRQuKjXrgU9POA,3742
100
100
  simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=oN657XMMZ6GYN9nblv7fX3kdnTEzSP9XV6PXM6Z0wl4,4358
101
101
  simo/core/__pycache__/apps.cpython-38.pyc,sha256=JL0BEqgXcSQvMlcK48PBpPfyDEkPMdO1Y0teqMRGirs,713
102
102
  simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=ib_ns5Ko8ybfrdJJWYVV1jevihxOFs39aBF4bez6Lzs,874
103
103
  simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=Er4fS5KhE2FB9g7-ckjS_RIWOv7qysuzdt1Ab7HUL5Q,4318
104
104
  simo/core/__pycache__/base_types.cpython-38.pyc,sha256=CX-qlF7CefRi_mCE954wYa9rUFR88mOl6g7fybDRu7g,803
105
105
  simo/core/__pycache__/context.cpython-38.pyc,sha256=NlTHt2GvXxA21AhBkeyOLfRFUuXw7wmwqyNhhcDl2cw,1373
106
- simo/core/__pycache__/controllers.cpython-38.pyc,sha256=Lt9JDheLB3qgaZZ9NACAEeg43IY9XxZHN3Y0c5JavMo,30710
106
+ simo/core/__pycache__/controllers.cpython-38.pyc,sha256=X9Dd2zKebwG_I93H63uYyS1WtqZRrjX8z7dqngtbSlM,30610
107
107
  simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=wGpnscX1DxFpRl54MQURhjz2aD3NJohSzw9JCFnzh2Y,2384
108
108
  simo/core/__pycache__/events.cpython-38.pyc,sha256=1y8YaZsiDkBOeIWzH7SQz4holmMG_RLlMWi8kuSZcoE,5280
109
109
  simo/core/__pycache__/filters.cpython-38.pyc,sha256=WBBDwcDQwOmgbrRhyUxenSN80rU4Eq9jQ6RcrRGCP_o,2440
110
110
  simo/core/__pycache__/form_fields.cpython-38.pyc,sha256=phMdhDFRmaFDhJSnasAg8VKNP6PxkPjFqkLwEuWicIs,3465
111
111
  simo/core/__pycache__/forms.cpython-38.pyc,sha256=9ogrGIBTmPWXUD3qgICo2oA-pBlgO2Bqg9hRv_-IUdE,17571
112
- simo/core/__pycache__/gateways.cpython-38.pyc,sha256=D1ooHL-iSpQrxnD8uAl4xWFJmm-QWZfbkLiLlFOMtdU,4553
112
+ simo/core/__pycache__/gateways.cpython-38.pyc,sha256=MG7VHsx0DcfjTqi9efDEomnp_oz7eOC0rLdyzUw4-Wk,4694
113
113
  simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
114
114
  simo/core/__pycache__/managers.cpython-38.pyc,sha256=6RTIxyjOgpQGtAqcUyE2vFPS09w1V5Wmd_vOV7rHRRI,3370
115
115
  simo/core/__pycache__/middleware.cpython-38.pyc,sha256=g3d4L2PwxFyRKIPMP9Hkdjk1PL9NarQd4hSHS55I8n8,2649
116
116
  simo/core/__pycache__/models.cpython-38.pyc,sha256=po4B4bMyA-KDBu8qbVwGjrpUZJQPVBB6dkfncEBKYnM,18554
117
117
  simo/core/__pycache__/permissions.cpython-38.pyc,sha256=UdtxCTXPEbe99vgZOfRz9wfKSYvUn9hSRbpIV9CJSyI,2988
118
118
  simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
119
- simo/core/__pycache__/serializers.cpython-38.pyc,sha256=xSz0o7EROKp4eKbMmTwm37j9jbAuTcN8PMqluRjZucQ,19551
119
+ simo/core/__pycache__/serializers.cpython-38.pyc,sha256=SK8uPWorFZujwL4vBeLarwS5hPknoqREmDSGhX5bWO8,19616
120
120
  simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=h0AsNC33oLoADJlwUVfPB1suUYovfzjfc0SE41-3MjY,6778
121
121
  simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=KqbO1cOewodVPcy0-htVefyUjCuELKV0o7fOfYqfgPc,8490
122
122
  simo/core/__pycache__/storage.cpython-38.pyc,sha256=9R1Xu0FJDflfRXUPsqEgt0SpwiP7FGk7HaR8s8XRyI8,721
@@ -10253,9 +10253,9 @@ simo/fleet/api.py,sha256=rJwAYJvp0uslW7O6Q4XOpOa8hfCdy3keUD7b3UNL43E,3424
10253
10253
  simo/fleet/auto_urls.py,sha256=UX66eR2ykMqFgfIllW-RTdjup5-FieCWl_BVm3CcXKg,702
10254
10254
  simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
10255
10255
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10256
- simo/fleet/controllers.py,sha256=w2Zf-hFXyaaekoHbar7pIfE0iGN0S__79rANFm23hW8,29157
10257
- simo/fleet/forms.py,sha256=S0OsfQ6VOm6lox2gSTKjRrIH0mlPcsAUhaplm6Wsiuw,64772
10258
- simo/fleet/gateways.py,sha256=lKEJW0MgaOEiNnijH50DNSVChvaUT3TA3UurcI57P8k,5677
10256
+ simo/fleet/controllers.py,sha256=jz-DyWP1F-eLUl8UkbCAqiAqRUm4d_TXVuepTIe9akU,29157
10257
+ simo/fleet/forms.py,sha256=2pbX1otTb1HqJ3aksRWz-FbsJ3YIyx6weV_tMFonecY,64772
10258
+ simo/fleet/gateways.py,sha256=C7dyapWDlJ5erYPNLkSoH50I8kj0lIXicSno0_CrdXc,5783
10259
10259
  simo/fleet/managers.py,sha256=ZNeHFSkF5kzsl9E1DCBevOW6kXJlD6kw0LU4B-JMOG8,828
10260
10260
  simo/fleet/models.py,sha256=zPplx_v64nfKBmb-nCb74aCVtEeY3m3SjEy-VhbnydU,17511
10261
10261
  simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
@@ -10270,9 +10270,9 @@ simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rZ1mkfkaMBEXhi9sw_jTKdk2CPJhBNx
10270
10270
  simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=Tc6a6BCXHjijP8U2jE2ghlJwnSNrGm59-hW5t-80wF0,689
10271
10271
  simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
10272
10272
  simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
10273
- simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=jpXIYOPPQyumLwiO-PbgB8L5WYKkvd5T5GlAFnBKHp8,24906
10274
- simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=yyRnT_AU1kCLo3ISyuXonzP8hoiu8SAvRxhu9WQPIoc,43550
10275
- simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=0RKVn0ndreVKhsrukqeLPSdMnRrsQ_W7yeVeBkRLfIk,5058
10273
+ simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=C8pGEX-J8aaXsq9tNIMNAcd4Ip37--nT1V7eqXd6aQg,24906
10274
+ simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=VQqXDYGpTMMOrV3PGXFbWD_49XjglqJO2LWIHidMom0,43550
10275
+ simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=MIpXuGWitGNdsxJ99fWvMXJ6sVE96ac7iR4K4aM4Sds,5148
10276
10276
  simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=Vmm23zoQnS3-uS5_WJt2n3wtjhLiEhLWaYxXJCU6Gts,1339
10277
10277
  simo/fleet/__pycache__/models.cpython-38.pyc,sha256=WUahZgETWlem5rVXlJ_vINFRM7OZWp5xpWXGMoeBXsM,14131
10278
10278
  simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
@@ -10323,6 +10323,7 @@ simo/fleet/migrations/0039_auto_20241016_1047.py,sha256=c75iDlPH9NPQohkNBt58NPl3
10323
10323
  simo/fleet/migrations/0040_alter_colonel_pwm_frequency.py,sha256=AiiYeLXEmBAFj1O3WdJB0xQy1KqfiErYR8yPpL8W7e4,498
10324
10324
  simo/fleet/migrations/0041_alter_colonel_instance_and_more.py,sha256=r3PzZERt4kM0ul_TFl-i7qS7n0ht0G8jS83nucMxZfQ,1181
10325
10325
  simo/fleet/migrations/0042_auto_20241120_1028.py,sha256=nXyOXyTqhYfR2IDpIX0E3oIhKI7ShI7TGZ0Uf1CzR1U,715
10326
+ simo/fleet/migrations/0043_auto_20241203_0930.py,sha256=wYfYEBurHB5pGOgL6M-z9EoOZGhW9glhT3BpNiMDoH4,651
10326
10327
  simo/fleet/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10327
10328
  simo/fleet/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=9kc1UyMEYkRNVnZ7iwZbiW1t3qWXROvWrI2G1BdzIaA,1250
10328
10329
  simo/fleet/migrations/__pycache__/0002_auto_20220422_0743.cpython-38.pyc,sha256=8oxhGb7rL8QYKlBLU3pOYcd8aHeQWDB9I8awkK04mXg,841
@@ -10374,7 +10375,7 @@ simo/generic/app_widgets.py,sha256=y8W3jR76Hh26O9pPQyg2SophMbYIOtAWD33MPKbB8Mg,8
10374
10375
  simo/generic/base_types.py,sha256=u3SlfpNYaCwkVBwomWgso4ODzL71ay9MhiAW-bxgnDU,341
10375
10376
  simo/generic/controllers.py,sha256=9u6Z_69t1Pkfmbsepx4AOj3cJKrZhik2elVuZjuBYGA,41722
10376
10377
  simo/generic/forms.py,sha256=i1TDb8pvFBws2COlmLCH12dTY4MKElFlQoSu5pwdw_w,18967
10377
- simo/generic/gateways.py,sha256=apT1PxvTiciOMhAQMfIMZJJCI9r1Ke-zgoUhclqDCcA,8790
10378
+ simo/generic/gateways.py,sha256=3gvBoT4a5NuzdOX1GyzG8M462I1ScbhL8LmShcK-Vcc,9122
10378
10379
  simo/generic/models.py,sha256=Adq7ipWK-renxJlNW-SZnAq2oGEOwKx8EdUWaKnfcVQ,7597
10379
10380
  simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
10380
10381
  simo/generic/socket_consumers.py,sha256=K2OjphIhKJH48BvfFfoCOyCQZ1NmXb_phs6y1IP-qaQ,1757
@@ -10383,7 +10384,7 @@ simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=D9b13pbMlirgHmjDnQhfL
10383
10384
  simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=aV5NdIuvXR-ItKpI__MwcyPZHD6Z882TFdgYkPCkr1I,493
10384
10385
  simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=_JsNQrL8iR-SY3MlrGJqguoAYaDGg2KGL7IwA0jl3w4,27025
10385
10386
  simo/generic/__pycache__/forms.cpython-38.pyc,sha256=fm8tOkr4t0VUiwAOjibvRdh7FPPL2VNH2w78DZsMYW4,14380
10386
- simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=iTIYK_K-08-MFvz5qX1u5ITfXqopP9QkRnVdVHqE12M,7224
10387
+ simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=-sdbyRuRpngSIORp3Y94hoLzIL4nrj52HGbcDy4heSA,7507
10387
10388
  simo/generic/__pycache__/models.cpython-38.pyc,sha256=MZpum7syAFxuulf47K7gtUlJJ7xRD-IBUBAwUM1ZRnw,5825
10388
10389
  simo/generic/__pycache__/routing.cpython-38.pyc,sha256=xtxTUTBTdivzFyA5Wh7k-hUj1WDO_FiRq6HYXdbr9Ks,382
10389
10390
  simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=qJO5kvQLWhsQDOr1AtAtsAybuRWioxSkQei3Pc7rdP0,1737
@@ -10599,9 +10600,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10599
10600
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10600
10601
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10601
10602
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10602
- simo-2.6.7.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10603
- simo-2.6.7.dist-info/METADATA,sha256=Jar59TxU2gPodg0J4-1cPqMgEgAOOSb_Bfh9Hs_Qxuk,1952
10604
- simo-2.6.7.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10605
- simo-2.6.7.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10606
- simo-2.6.7.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10607
- simo-2.6.7.dist-info/RECORD,,
10603
+ simo-2.6.8.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10604
+ simo-2.6.8.dist-info/METADATA,sha256=oLE9PcdmNJtUr78LOvEltMytRMStMXtcPoWCS7O4Y-E,1952
10605
+ simo-2.6.8.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10606
+ simo-2.6.8.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10607
+ simo-2.6.8.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10608
+ simo-2.6.8.dist-info/RECORD,,
File without changes