simo 2.6.6__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.

Files changed (35) hide show
  1. simo/automation/__pycache__/controllers.cpython-38.pyc +0 -0
  2. simo/automation/__pycache__/forms.cpython-38.pyc +0 -0
  3. simo/automation/__pycache__/gateways.cpython-38.pyc +0 -0
  4. simo/automation/controllers.py +9 -4
  5. simo/automation/forms.py +7 -1
  6. simo/automation/gateways.py +1 -0
  7. simo/core/__pycache__/api.cpython-38.pyc +0 -0
  8. simo/core/__pycache__/api_meta.cpython-38.pyc +0 -0
  9. simo/core/__pycache__/autocomplete_views.cpython-38.pyc +0 -0
  10. simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
  11. simo/core/__pycache__/gateways.cpython-38.pyc +0 -0
  12. simo/core/__pycache__/serializers.cpython-38.pyc +0 -0
  13. simo/core/api.py +34 -0
  14. simo/core/api_meta.py +3 -1
  15. simo/core/autocomplete_views.py +13 -4
  16. simo/core/controllers.py +25 -9
  17. simo/core/gateways.py +7 -1
  18. simo/core/serializers.py +19 -8
  19. simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
  20. simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
  21. simo/fleet/__pycache__/gateways.cpython-38.pyc +0 -0
  22. simo/fleet/__pycache__/views.cpython-38.pyc +0 -0
  23. simo/fleet/controllers.py +4 -4
  24. simo/fleet/forms.py +1 -1
  25. simo/fleet/gateways.py +2 -0
  26. simo/fleet/migrations/0043_auto_20241203_0930.py +28 -0
  27. simo/fleet/views.py +27 -7
  28. simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
  29. simo/generic/gateways.py +5 -0
  30. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/METADATA +1 -1
  31. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/RECORD +35 -34
  32. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/LICENSE.md +0 -0
  33. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/WHEEL +0 -0
  34. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/entry_points.txt +0 -0
  35. {simo-2.6.6.dist-info → simo-2.6.8.dist-info}/top_level.txt +0 -0
@@ -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
@@ -79,6 +79,7 @@ class SIMOAPIMetadata(SimpleMetadata):
79
79
  field_info['autocomplete_url'] = reverse(form_field.url)
80
80
  field_info['forward'] = form_field.forward
81
81
 
82
+
82
83
  attrs = [
83
84
  'read_only', 'label', 'help_text',
84
85
  'min_length', 'max_length',
@@ -94,6 +95,7 @@ class SIMOAPIMetadata(SimpleMetadata):
94
95
  if getattr(field, 'child', None):
95
96
  field_info['child'] = self.get_field_info(field.child)
96
97
  elif getattr(field, 'fields', None):
98
+ field.Meta.form = form_field.formset_cls.form
97
99
  field_info['children'] = self.get_serializer_info(field)
98
100
 
99
101
  if form_field and hasattr(form_field, 'queryset'):
@@ -113,7 +115,7 @@ class SIMOAPIMetadata(SimpleMetadata):
113
115
  zone__instance=self.instance
114
116
  )
115
117
 
116
- 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'):
117
119
  field_info['choices'] = [
118
120
  {
119
121
  'value': choice_value,
@@ -1,4 +1,5 @@
1
1
  from dal import autocomplete
2
+ from dal.views import BaseQuerySetView
2
3
  from django.db.models import Q
3
4
  from django.template.loader import render_to_string
4
5
  from simo.core.utils.helpers import search_queryset
@@ -13,7 +14,9 @@ class IconModelAutocomplete(autocomplete.Select2QuerySetView):
13
14
  if self.forwarded.get("id"):
14
15
  return qs.filter(pk=self.forwarded.get("id"))
15
16
 
16
- if self.q:
17
+ if self.request.GET.get('value'):
18
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
19
+ elif self.q:
17
20
  qs = search_queryset(qs, self.q, ('slug', 'keywords'))
18
21
  return qs.distinct()
19
22
 
@@ -56,7 +59,9 @@ class CategoryAutocomplete(autocomplete.Select2QuerySetView):
56
59
  return qs.filter(pk=self.forwarded.get("id"))
57
60
 
58
61
  qs = qs.filter(all=False)
59
- if self.q:
62
+ if self.request.GET.get('value'):
63
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
64
+ elif self.q:
60
65
  qs = search_queryset(qs, self.q, ('name'))
61
66
  return qs.distinct()
62
67
 
@@ -79,7 +84,9 @@ class ZoneAutocomplete(autocomplete.Select2QuerySetView):
79
84
  if self.forwarded.get("id"):
80
85
  return qs.filter(pk=self.forwarded.get("id"))
81
86
 
82
- if self.q:
87
+ if self.request.GET.get('value'):
88
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
89
+ elif self.q:
83
90
  qs = search_queryset(qs, self.q, ('name',))
84
91
  return qs.distinct()
85
92
 
@@ -116,7 +123,9 @@ class ComponentAutocomplete(autocomplete.Select2QuerySetView):
116
123
  Q(alarm_category__in=self.forwarded['alarm_category'])
117
124
  )
118
125
 
119
- if self.q:
126
+ if self.request.GET.get('value'):
127
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
128
+ elif self.q:
120
129
  qs = search_queryset(qs, self.q, ('zone__name', 'name',))
121
130
  return qs.distinct()
122
131
 
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
@@ -4,6 +4,7 @@ import re
4
4
  from django import forms
5
5
  from collections import OrderedDict
6
6
  from django.conf import settings
7
+ from django.forms.utils import pretty_name
7
8
  from collections.abc import Iterable
8
9
  from easy_thumbnails.files import get_thumbnailer
9
10
  from simo.core.middleware import get_current_request
@@ -130,7 +131,6 @@ class ComponentManyToManyRelatedField(serializers.Field):
130
131
  return self.queryset.filter(pk__in=data)
131
132
 
132
133
 
133
-
134
134
  class ComponentFormsetField(FormSerializer):
135
135
 
136
136
  class Meta:
@@ -151,9 +151,20 @@ class ComponentFormsetField(FormSerializer):
151
151
  }
152
152
 
153
153
  def __init__(self, formset_field, *args, **kwargs):
154
- self.Meta.form = formset_field.formset_cls.form
154
+ self.form = formset_field.formset_cls.form
155
155
  super().__init__(*args, **kwargs)
156
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
+
157
168
  def get_fields(self):
158
169
  ret = super(FormSerializerBase, self).get_fields()
159
170
 
@@ -163,7 +174,7 @@ class ComponentFormsetField(FormSerializer):
163
174
  FORM_SERIALIZER_FIELD_MAPPING
164
175
  )
165
176
 
166
- form = self.Meta.form
177
+ form = self.form
167
178
  for field_name, form_field in getattr(form, 'all_base_fields', form.base_fields).items():
168
179
 
169
180
  if field_name in getattr(self.Meta, 'exclude', []):
@@ -193,6 +204,9 @@ class ComponentFormsetField(FormSerializer):
193
204
  ret[field_name] = self._get_field(form_field, serializer_field_class)
194
205
  ret[field_name].initial = form_field.initial
195
206
  ret[field_name].default = form_field.initial
207
+ ret[field_name].label = form_field.label
208
+ if not ret[field_name].label:
209
+ ret[field_name].label = pretty_name(field_name)
196
210
 
197
211
  return ret
198
212
 
@@ -245,11 +259,6 @@ class ComponentFormsetField(FormSerializer):
245
259
 
246
260
  return ret
247
261
 
248
- def get_form(self, data=None, **kwargs):
249
- form = super().get_form(data=data, **kwargs)
250
- form.prefix = ''
251
- return form
252
-
253
262
  def create(self, validated_data):
254
263
  return validated_data
255
264
 
@@ -360,6 +369,8 @@ class ComponentSerializer(FormSerializer):
360
369
  )
361
370
  ret[field_name].initial = form_field.initial
362
371
  ret[field_name].default = form_field.initial
372
+ if not ret[field_name].label:
373
+ ret[field_name].label = pretty_name(field_name)
363
374
 
364
375
  for name, field in super(FormSerializerBase, self).get_fields().items():
365
376
  if name in ret:
Binary file
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/fleet/views.py CHANGED
@@ -40,7 +40,10 @@ class PinsSelectAutocomplete(autocomplete.Select2QuerySetView):
40
40
  if self.forwarded.get('filters'):
41
41
  qs = qs.filter(**self.forwarded.get('filters'))
42
42
 
43
- if self.q:
43
+
44
+ if self.request.GET.get('value'):
45
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
46
+ elif self.q:
44
47
  qs = search_queryset(qs, self.q, ('label', ))
45
48
 
46
49
  return qs
@@ -59,7 +62,9 @@ class InterfaceSelectAutocomplete(autocomplete.Select2QuerySetView):
59
62
 
60
63
  qs = Interface.objects.filter(colonel=colonel)
61
64
 
62
- if self.forwarded.get('filters'):
65
+ if self.request.GET.get('value'):
66
+ qs = qs.filter(pk__in=self.request.GET['value'].split(','))
67
+ elif self.forwarded.get('filters'):
63
68
  qs = qs.filter(**self.forwarded.get('filters'))
64
69
 
65
70
  return qs
@@ -81,15 +86,12 @@ class ControlInputSelectAutocomplete(autocomplete.Select2ListView):
81
86
  pins_qs = pins_qs.filter(
82
87
  Q(occupied_by_id=None) | Q(id=int(self.forwarded['self'][4:]))
83
88
  )
84
- else:
89
+ elif 'value' not in self.request.GET:
85
90
  pins_qs = pins_qs.filter(occupied_by_id=None)
86
91
 
87
92
  if self.forwarded.get('pin_filters'):
88
93
  pins_qs = pins_qs.filter(**self.forwarded.get('pin_filters'))
89
94
 
90
- if self.q:
91
- pins_qs = search_queryset(pins_qs, self.q, ('label',))
92
-
93
95
  buttons_qs = Component.objects.filter(
94
96
  base_type='button'
95
97
  ).select_related('zone')
@@ -97,10 +99,28 @@ class ControlInputSelectAutocomplete(autocomplete.Select2ListView):
97
99
  if self.forwarded.get('button_filters'):
98
100
  buttons_qs = buttons_qs.filter(**self.forwarded.get('button_filters'))
99
101
 
100
- if self.q:
102
+ if self.request.GET.get('value'):
103
+ pin_ids = []
104
+ button_ids = []
105
+ for v in self.request.GET['value'].split(','):
106
+ try:
107
+ t, id = v.split('-')
108
+ id = int(id)
109
+ except:
110
+ continue
111
+ if t == 'pin':
112
+ pin_ids.append(id)
113
+ elif t == 'button':
114
+ button_ids.append(id)
115
+ buttons_qs = buttons_qs.filter(id__in=button_ids)
116
+ pins_qs = pins_qs.filter(id__in=pin_ids)
117
+
118
+ elif self.q:
101
119
  buttons_qs = search_queryset(
102
120
  buttons_qs, self.q, ('name', 'zone__name', 'category__name')
103
121
  )
122
+ pins_qs = search_queryset(pins_qs, self.q, ('label',))
123
+
104
124
 
105
125
  return [(f'pin-{pin.id}', str(pin)) for pin in pins_qs] + \
106
126
  [(f'button-{button.id}',
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.6
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=EaiY-dCADP__9MvLpoHvhjytFT92IrxPZDv95xgqasU,4955
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
- simo/core/autocomplete_views.py,sha256=Nu9sgc0X5OspRkJnpomeO2XdHCOg9ii9v4ZkGecCNjQ,3860
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=NgqZhBjY0or6dfN-N_EaaygR_EUoUBryuK1DbD4R3Fg,21810
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=VYx5ZeDyNBI4B_CBEIhV5B3GnLsMOx9s3rNZTSMODco,3703
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
- simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=Of2ZFdN8XF1I4TmAUwqZonHqZd8O9CpX_DqIQMU_rdc,3967
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=QvlVp7m13i3Vn1FOmjV-y_IpLfmcSIy74jhb66ecJbo,19403
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
@@ -10263,16 +10263,16 @@ simo/fleet/serializers.py,sha256=PQnjp7LaEpMts-om2OPV5XOU9ut6KFWiePPDCXK0M98,267
10263
10263
  simo/fleet/socket_consumers.py,sha256=4hVSvFNq9Hi44R7JmaujFoEtgmH5YBST2cFYtIiMDRA,18840
10264
10264
  simo/fleet/tasks.py,sha256=NX_opj-rbkK9eeQMeRNwHj_ZJ0LC4rYOZovMg9_r0kA,904
10265
10265
  simo/fleet/utils.py,sha256=wNJvURzLP3-aho3D3rfg07N9kWCaMIw5gOsmeeO9Nlg,4740
10266
- simo/fleet/views.py,sha256=jT3GcGv_JEj3dqyfHH2whCnGqwT8YEAuFxRgIX4Dk9w,3237
10266
+ simo/fleet/views.py,sha256=jK5ajYTIPhz8ODgeHxHgZ9aWicWOD2D6PFJ_iq9B_ug,4051
10267
10267
  simo/fleet/__pycache__/__init__.cpython-38.pyc,sha256=pIZE7EL6-cuJ3pQtaSwjKLrKLsTYelp1k9sRhXKLh6s,159
10268
10268
  simo/fleet/__pycache__/admin.cpython-38.pyc,sha256=iweeu5AkaggBhQntP6-VF_eEodkNc6E7zKy0VjfwC2o,6652
10269
10269
  simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rZ1mkfkaMBEXhi9sw_jTKdk2CPJhBNxoImtjQ3Rf1VY,4016
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
@@ -10280,7 +10280,7 @@ simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=l_FzORWCM1hcSZV0AaGRO-p
10280
10280
  simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=m8sJWln-uyjeTD-alyoNikEJcHCxZGTe2vXnMGVNZog,14170
10281
10281
  simo/fleet/__pycache__/tasks.cpython-38.pyc,sha256=RoNxL2WUiW67s9O9DjaYVVjCBSZu2nje0Qn9FJkWVS0,1116
10282
10282
  simo/fleet/__pycache__/utils.cpython-38.pyc,sha256=obUd-X2Y-ybx4icqUWq_qwIxrP9yyarJjexWAfO4MTI,3344
10283
- simo/fleet/__pycache__/views.cpython-38.pyc,sha256=wilxSvZliSKQ5qC7JjWneYBSdbeZeTsF5uDrOQVmvms,3181
10283
+ simo/fleet/__pycache__/views.cpython-38.pyc,sha256=jffuwjfsNGY8EJchA6lnSBUXkDQkIqoov6DhWAO4yCA,3623
10284
10284
  simo/fleet/migrations/0001_initial.py,sha256=lce8nkD8Sz6pYr-XJSpDm4CMDuB6TA__WtnHpIp-eA4,1326
10285
10285
  simo/fleet/migrations/0002_auto_20220422_0743.py,sha256=sFOfAjnQOzcJjE8lHrrHgTaGilJNYswMdXphgVzUZqY,825
10286
10286
  simo/fleet/migrations/0003_auto_20220422_0752.py,sha256=VcH7DyMAniEwT76hDVofS8FTNpM3nxz_J9AC2zKHDSA,543
@@ -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.6.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10603
- simo-2.6.6.dist-info/METADATA,sha256=U_rJSOAn0Y32OcYjYKHpnflh2C1SLDSmOxb5f6rWXXM,1952
10604
- simo-2.6.6.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10605
- simo-2.6.6.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10606
- simo-2.6.6.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10607
- simo-2.6.6.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