simo 2.7.11__py3-none-any.whl → 2.7.13__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.
- simo/core/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/core/__pycache__/forms.cpython-38.pyc +0 -0
- simo/core/__pycache__/models.cpython-38.pyc +0 -0
- simo/core/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/core/__pycache__/signal_receivers.cpython-38.pyc +0 -0
- simo/core/__pycache__/views.cpython-38.pyc +0 -0
- simo/core/auto_urls.py +3 -2
- simo/core/forms.py +7 -2
- simo/core/migrations/0048_publicfile_privatefile.py +35 -0
- simo/core/migrations/__pycache__/0048_publicfile_privatefile.cpython-38.pyc +0 -0
- simo/core/models.py +32 -0
- simo/core/serializers.py +1 -0
- simo/core/signal_receivers.py +13 -2
- simo/core/views.py +16 -2
- simo/generic/__pycache__/forms.cpython-38.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/generic/forms.py +54 -15
- simo/generic/gateways.py +11 -12
- simo/multimedia/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/multimedia/controllers.py +3 -3
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/METADATA +1 -1
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/RECORD +26 -24
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/LICENSE.md +0 -0
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/WHEEL +0 -0
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/entry_points.txt +0 -0
- {simo-2.7.11.dist-info → simo-2.7.13.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/core/auto_urls.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from django.urls import path
|
|
2
2
|
from .views import (
|
|
3
|
-
get_timestamp, upgrade, restart, reboot, set_instance
|
|
3
|
+
get_timestamp, upgrade, restart, reboot, set_instance, delete_instance
|
|
4
4
|
)
|
|
5
5
|
from .autocomplete_views import (
|
|
6
6
|
IconModelAutocomplete,
|
|
@@ -33,5 +33,6 @@ urlpatterns = [
|
|
|
33
33
|
path('set-instance/<slug:instance_slug>/', set_instance, name='set-instance'),
|
|
34
34
|
path('upgrade/', upgrade, name='upgrade'),
|
|
35
35
|
path('restart/', restart, name='restart'),
|
|
36
|
-
path('reboot/', reboot, name='reboot')
|
|
36
|
+
path('reboot/', reboot, name='reboot'),
|
|
37
|
+
path('delete-instance/', delete_instance, name='delete-instance')
|
|
37
38
|
]
|
simo/core/forms.py
CHANGED
|
@@ -272,9 +272,9 @@ class ComponentAdminForm(forms.ModelForm):
|
|
|
272
272
|
self.instance.config = self.controller.default_config
|
|
273
273
|
self.instance.meta = self.controller.default_meta
|
|
274
274
|
|
|
275
|
-
self.cleanup_missing_keys(kwargs.get("data"))
|
|
275
|
+
self.cleanup_missing_keys(kwargs.get("data"), kwargs.get("files"))
|
|
276
276
|
|
|
277
|
-
def cleanup_missing_keys(self, data):
|
|
277
|
+
def cleanup_missing_keys(self, data, files=None):
|
|
278
278
|
"""
|
|
279
279
|
Removes missing keys from fields on form submission.
|
|
280
280
|
This avoids resetting fields that are not present in
|
|
@@ -289,6 +289,11 @@ class ComponentAdminForm(forms.ModelForm):
|
|
|
289
289
|
return
|
|
290
290
|
|
|
291
291
|
got_keys = list(data.keys())
|
|
292
|
+
if files:
|
|
293
|
+
try:
|
|
294
|
+
got_keys += list(files.keys())
|
|
295
|
+
except:
|
|
296
|
+
pass
|
|
292
297
|
formset_fields = set()
|
|
293
298
|
for key in got_keys:
|
|
294
299
|
if key.endswith('-TOTAL_FORMS'):
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-12-13 09:44
|
|
2
|
+
|
|
3
|
+
import django.core.files.storage
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
('core', '0047_alter_component_value_translation'),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.CreateModel(
|
|
16
|
+
name='PublicFile',
|
|
17
|
+
fields=[
|
|
18
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
19
|
+
('file', models.FileField(storage=django.core.files.storage.FileSystemStorage(base_url='/public_media/', location='/home/simanas/Projects/SIMO/_var/public_media'), upload_to='public_files')),
|
|
20
|
+
('date_uploaded', models.DateTimeField(auto_now_add=True)),
|
|
21
|
+
('meta', models.JSONField(default=dict)),
|
|
22
|
+
('component', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='public_files', to='core.component')),
|
|
23
|
+
],
|
|
24
|
+
),
|
|
25
|
+
migrations.CreateModel(
|
|
26
|
+
name='PrivateFile',
|
|
27
|
+
fields=[
|
|
28
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
29
|
+
('file', models.FileField(upload_to='private_files')),
|
|
30
|
+
('date_uploaded', models.DateTimeField(auto_now_add=True)),
|
|
31
|
+
('meta', models.JSONField(default=dict)),
|
|
32
|
+
('component', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='private_files', to='core.component')),
|
|
33
|
+
],
|
|
34
|
+
),
|
|
35
|
+
]
|
simo/core/models.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import time
|
|
3
|
+
import os
|
|
3
4
|
from collections.abc import Iterable
|
|
4
5
|
from django.utils.text import slugify
|
|
5
6
|
from django.utils.functional import cached_property
|
|
@@ -9,6 +10,8 @@ from django.db import models
|
|
|
9
10
|
from django.db.models.signals import post_delete
|
|
10
11
|
from django.dispatch import receiver
|
|
11
12
|
from django.template.loader import render_to_string
|
|
13
|
+
from django.conf import settings
|
|
14
|
+
from django.core.files.storage import FileSystemStorage
|
|
12
15
|
from timezone_utils.choices import ALL_TIMEZONES_CHOICES
|
|
13
16
|
from location_field.models.plain import PlainLocationField
|
|
14
17
|
from model_utils import FieldTracker
|
|
@@ -602,6 +605,35 @@ def is_in_alarm(self):
|
|
|
602
605
|
return c_methods
|
|
603
606
|
|
|
604
607
|
|
|
608
|
+
class PublicFile(models.Model):
|
|
609
|
+
component = models.ForeignKey(
|
|
610
|
+
Component, on_delete=models.CASCADE, related_name='public_files'
|
|
611
|
+
)
|
|
612
|
+
file = models.FileField(
|
|
613
|
+
upload_to='public_files', storage=FileSystemStorage(
|
|
614
|
+
location=os.path.join(settings.VAR_DIR, 'public_media'),
|
|
615
|
+
base_url='/public_media/'
|
|
616
|
+
)
|
|
617
|
+
)
|
|
618
|
+
date_uploaded = models.DateTimeField(auto_now_add=True)
|
|
619
|
+
meta = models.JSONField(default=dict)
|
|
620
|
+
|
|
621
|
+
def get_absolute_url(self):
|
|
622
|
+
return self.file.url
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
class PrivateFile(models.Model):
|
|
626
|
+
component = models.ForeignKey(
|
|
627
|
+
Component, on_delete=models.CASCADE, related_name='private_files'
|
|
628
|
+
)
|
|
629
|
+
file = models.FileField(upload_to='private_files')
|
|
630
|
+
date_uploaded = models.DateTimeField(auto_now_add=True)
|
|
631
|
+
meta = models.JSONField(default=dict)
|
|
632
|
+
|
|
633
|
+
def get_absolute_url(self):
|
|
634
|
+
return self.file.url
|
|
635
|
+
|
|
636
|
+
|
|
605
637
|
class ComponentHistory(models.Model):
|
|
606
638
|
component = models.ForeignKey(
|
|
607
639
|
Component, on_delete=models.CASCADE, related_name='history'
|
simo/core/serializers.py
CHANGED
|
@@ -311,6 +311,7 @@ class ComponentSerializer(FormSerializer):
|
|
|
311
311
|
Select2ListMultipleChoiceField: ComponentManyToManyRelatedField,
|
|
312
312
|
Select2ModelMultipleChoiceField: ComponentManyToManyRelatedField,
|
|
313
313
|
FormsetField: ComponentFormsetField,
|
|
314
|
+
SoundField: SoundSerializer
|
|
314
315
|
}
|
|
315
316
|
|
|
316
317
|
|
simo/core/signal_receivers.py
CHANGED
|
@@ -8,7 +8,9 @@ from django.conf import settings
|
|
|
8
8
|
from django.template.loader import render_to_string
|
|
9
9
|
from actstream import action
|
|
10
10
|
from simo.users.models import PermissionsRole
|
|
11
|
-
from .models import
|
|
11
|
+
from .models import (
|
|
12
|
+
Instance, Gateway, Component, Icon, Zone, Category, PublicFile, PrivateFile
|
|
13
|
+
)
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
@receiver(post_save, sender=Instance)
|
|
@@ -192,4 +194,13 @@ def gateway_post_save(sender, instance, created, *args, **kwargs):
|
|
|
192
194
|
|
|
193
195
|
@receiver(post_delete, sender=Gateway)
|
|
194
196
|
def gateway_post_delete(sender, instance, *args, **kwargs):
|
|
195
|
-
instance.stop()
|
|
197
|
+
instance.stop()
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@receiver(post_delete, sender=PublicFile)
|
|
201
|
+
@receiver(post_delete, sender=PrivateFile)
|
|
202
|
+
def delete_file_itself(sender, instance, *args, **kwargs):
|
|
203
|
+
try:
|
|
204
|
+
os.remove(instance.file.path)
|
|
205
|
+
except:
|
|
206
|
+
pass
|
simo/core/views.py
CHANGED
|
@@ -2,9 +2,11 @@ import time
|
|
|
2
2
|
import re
|
|
3
3
|
from django.contrib.auth.decorators import login_required
|
|
4
4
|
from django.urls import reverse
|
|
5
|
-
from django.shortcuts import redirect
|
|
5
|
+
from django.shortcuts import redirect, get_object_or_404
|
|
6
6
|
from django.views.decorators.csrf import csrf_exempt
|
|
7
|
-
from django.http import
|
|
7
|
+
from django.http import (
|
|
8
|
+
HttpResponse, Http404, JsonResponse, HttpResponseForbidden
|
|
9
|
+
)
|
|
8
10
|
from django.contrib import messages
|
|
9
11
|
from simo.conf import dynamic_settings
|
|
10
12
|
from .models import Instance
|
|
@@ -69,6 +71,18 @@ def set_instance(request, instance_slug):
|
|
|
69
71
|
return redirect(reverse('admin:index'))
|
|
70
72
|
|
|
71
73
|
|
|
74
|
+
@login_required
|
|
75
|
+
@csrf_exempt
|
|
76
|
+
def delete_instance(request):
|
|
77
|
+
if request.method != 'POST':
|
|
78
|
+
raise Http404()
|
|
79
|
+
if not request.user.is_master:
|
|
80
|
+
return HttpResponseForbidden()
|
|
81
|
+
instance = get_object_or_404(Instance, uid=request.GET['uid'])
|
|
82
|
+
instance.delete()
|
|
83
|
+
return HttpResponse('success')
|
|
84
|
+
|
|
85
|
+
|
|
72
86
|
def hub_info(request):
|
|
73
87
|
data = {"hub_uid": dynamic_settings['core__hub_uid']}
|
|
74
88
|
if not Instance.objects.filter(is_active=True).count():
|
|
Binary file
|
|
Binary file
|
simo/generic/forms.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import librosa
|
|
3
|
+
import tempfile
|
|
1
4
|
from django import forms
|
|
2
5
|
from django.forms import formset_factory
|
|
3
6
|
from django.db.models import Q
|
|
4
7
|
from django.utils.translation import gettext_lazy as _
|
|
5
8
|
from simo.core.forms import HiddenField, BaseComponentForm
|
|
6
|
-
from simo.core.models import Icon, Component
|
|
9
|
+
from simo.core.models import Icon, Component, PublicFile
|
|
7
10
|
from simo.core.controllers import (
|
|
8
11
|
NumericSensor, MultiSensor, Switch, Dimmer
|
|
9
12
|
)
|
|
@@ -18,7 +21,6 @@ from simo.core.form_fields import (
|
|
|
18
21
|
)
|
|
19
22
|
from simo.core.forms import DimmerConfigForm, SwitchForm
|
|
20
23
|
from simo.core.form_fields import SoundField
|
|
21
|
-
from simo.multimedia.models import Sound
|
|
22
24
|
|
|
23
25
|
ACTION_METHODS = (
|
|
24
26
|
('turn_on', "Turn ON"), ('turn_off', "Turn OFF"),
|
|
@@ -618,7 +620,7 @@ class AlarmClockConfigForm(BaseComponentForm):
|
|
|
618
620
|
|
|
619
621
|
|
|
620
622
|
class AudioAlertConfigForm(BaseComponentForm):
|
|
621
|
-
sound = SoundField()
|
|
623
|
+
sound = SoundField(required=False)
|
|
622
624
|
loop = forms.BooleanField(initial=False, required=False)
|
|
623
625
|
volume = forms.IntegerField(initial=30, min_value=2, max_value=100)
|
|
624
626
|
players = Select2ModelMultipleChoiceField(
|
|
@@ -630,22 +632,59 @@ class AudioAlertConfigForm(BaseComponentForm):
|
|
|
630
632
|
super().__init__(*args, **kwargs)
|
|
631
633
|
self.basic_fields.extend(['sound', 'loop', 'volume', 'players'])
|
|
632
634
|
if self.instance.id:
|
|
633
|
-
|
|
634
|
-
|
|
635
|
+
public_file = PublicFile.objects.filter(
|
|
636
|
+
component=self.instance
|
|
635
637
|
).first()
|
|
636
|
-
if
|
|
637
|
-
self.fields['sound'].
|
|
638
|
+
if public_file:
|
|
639
|
+
self.fields['sound'].help_text = f"Currently: {public_file.file}"
|
|
640
|
+
|
|
641
|
+
def clean_sound(self):
|
|
642
|
+
if not self.cleaned_data.get('sound'):
|
|
643
|
+
if not self.instance.pk:
|
|
644
|
+
raise forms.ValidationError("Please pick a sound!")
|
|
645
|
+
return
|
|
646
|
+
if self.cleaned_data['sound'].size > 1024 * 1024 * 50:
|
|
647
|
+
raise forms.ValidationError("No more than 50Mb please.")
|
|
648
|
+
temp_path = os.path.join(
|
|
649
|
+
tempfile.gettempdir(), self.cleaned_data['sound'].name
|
|
650
|
+
)
|
|
651
|
+
with open(temp_path, 'wb') as temp_file:
|
|
652
|
+
for chunk in self.cleaned_data['sound'].chunks():
|
|
653
|
+
temp_file.write(chunk)
|
|
654
|
+
|
|
655
|
+
try:
|
|
656
|
+
self.cleaned_data['sound'].duration = int(
|
|
657
|
+
librosa.core.get_duration(sr=22050, filename=temp_path)
|
|
658
|
+
)
|
|
659
|
+
except:
|
|
660
|
+
try:
|
|
661
|
+
os.remove(temp_path)
|
|
662
|
+
except:
|
|
663
|
+
pass
|
|
664
|
+
raise forms.ValidationError("This doesn't look like audio file!")
|
|
665
|
+
try:
|
|
666
|
+
os.remove(temp_path)
|
|
667
|
+
except:
|
|
668
|
+
pass
|
|
669
|
+
|
|
670
|
+
return self.cleaned_data['sound']
|
|
671
|
+
|
|
638
672
|
|
|
639
673
|
def save(self, commit=True):
|
|
640
|
-
|
|
674
|
+
obj = super().save(commit=commit)
|
|
675
|
+
if commit and self.cleaned_data.get('sound') \
|
|
641
676
|
and self.cleaned_data['sound'] != self.fields['sound'].initial:
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
)
|
|
645
|
-
sound.file.save(
|
|
677
|
+
public_file = PublicFile(component=obj)
|
|
678
|
+
public_file.file.save(
|
|
646
679
|
self.cleaned_data['sound'].name, self.cleaned_data['sound'],
|
|
647
680
|
save=True
|
|
648
681
|
)
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
682
|
+
org = PublicFile.objects.filter(
|
|
683
|
+
id=self.instance.config.get('public_file_id', 0)
|
|
684
|
+
)
|
|
685
|
+
if org:
|
|
686
|
+
org.delete()
|
|
687
|
+
self.instance.config['public_file_id'] = public_file.id
|
|
688
|
+
self.instance.config['duration'] = self.cleaned_data['sound'].duration
|
|
689
|
+
self.instance.save()
|
|
690
|
+
return obj
|
simo/generic/gateways.py
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
import logging
|
|
3
2
|
import pytz
|
|
4
3
|
import json
|
|
5
4
|
import time
|
|
6
|
-
import multiprocessing
|
|
7
5
|
import threading
|
|
8
6
|
import traceback
|
|
9
7
|
from django.conf import settings
|
|
10
8
|
from django.utils import timezone
|
|
11
|
-
from django.db import connection as db_connection
|
|
12
|
-
from django.db.models import Q
|
|
13
9
|
import paho.mqtt.client as mqtt
|
|
14
|
-
from simo.core.
|
|
10
|
+
from simo.core.utils.helpers import get_self_ip
|
|
11
|
+
from simo.core.models import Component, PublicFile
|
|
15
12
|
from simo.core.middleware import introduce_instance, drop_current_instance
|
|
16
13
|
from simo.core.gateways import BaseObjectCommandsGatewayHandler
|
|
17
14
|
from simo.core.forms import BaseGatewayForm
|
|
18
|
-
from simo.core.utils.logs import StreamToLogger
|
|
19
15
|
from simo.core.events import GatewayObjectCommand, get_event_obj
|
|
20
16
|
from simo.core.loggers import get_gw_logger, get_component_logger
|
|
21
17
|
|
|
@@ -138,12 +134,12 @@ class AudioAlertsHandler:
|
|
|
138
134
|
|
|
139
135
|
def control_audio_alert(self, component, val):
|
|
140
136
|
if val:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
id=component.config.get('sound_id')
|
|
137
|
+
public_file = PublicFile.objects.filter(
|
|
138
|
+
component=component
|
|
144
139
|
).first()
|
|
145
|
-
if not
|
|
140
|
+
if not public_file:
|
|
146
141
|
return
|
|
142
|
+
uri = f"http://{get_self_ip()}{public_file.get_absolute_url()}"
|
|
147
143
|
loop = component.config.get('loop', False)
|
|
148
144
|
for pl_id in component.config.get('players', []):
|
|
149
145
|
player = Component.objects.filter(
|
|
@@ -152,14 +148,17 @@ class AudioAlertsHandler:
|
|
|
152
148
|
if not player:
|
|
153
149
|
continue
|
|
154
150
|
player.play_alert(
|
|
155
|
-
|
|
151
|
+
uri,
|
|
156
152
|
component.config.get('loop', False),
|
|
157
153
|
component.config.get('volume', 50)
|
|
158
154
|
)
|
|
159
155
|
if not loop:
|
|
160
156
|
def set_done(comp):
|
|
161
157
|
comp.set(False)
|
|
162
|
-
threading.Timer(
|
|
158
|
+
threading.Timer(
|
|
159
|
+
component.config.get('duration', 1),
|
|
160
|
+
set_done, args=[component]
|
|
161
|
+
)
|
|
163
162
|
component.set(True)
|
|
164
163
|
else:
|
|
165
164
|
for pl_id in component.config.get('players', []):
|
|
Binary file
|
simo/multimedia/controllers.py
CHANGED
|
@@ -92,15 +92,15 @@ class BasePlayer(Switch):
|
|
|
92
92
|
def play_alert(self, val, loop=False, volume=None):
|
|
93
93
|
'''
|
|
94
94
|
Plays alert and goes back to whatever was playing initially
|
|
95
|
-
:param val:
|
|
95
|
+
:param val: uri
|
|
96
96
|
:param loop: Repeat infinitely
|
|
97
97
|
:param volume: volume at which to play
|
|
98
98
|
:return:
|
|
99
99
|
'''
|
|
100
|
-
assert type(val)
|
|
100
|
+
assert type(val) == str
|
|
101
101
|
if volume:
|
|
102
102
|
assert 0 <= volume <= 100
|
|
103
|
-
self.send({"alert": val, 'volume': volume})
|
|
103
|
+
self.send({"alert": val, 'loop': loop, 'volume': volume})
|
|
104
104
|
|
|
105
105
|
def cancel_alert(self):
|
|
106
106
|
'''Cancel alert if it's currently playing'''
|
|
@@ -66,7 +66,7 @@ simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
|
|
|
66
66
|
simo/core/api_meta.py,sha256=Bh-UOzANXl9Bg3FadFf7biM_olAr9GgjNJXu55SO6Og,5290
|
|
67
67
|
simo/core/app_widgets.py,sha256=VxZzapuc-a29wBH7JzpvNF2SK1ECrgNUySId5ke1ffc,2509
|
|
68
68
|
simo/core/apps.py,sha256=CsqpiQerhmrMsH-wGiG-gQgXd9qEkIi-LUaA9cXpKSw,425
|
|
69
|
-
simo/core/auto_urls.py,sha256=
|
|
69
|
+
simo/core/auto_urls.py,sha256=FqKhH0fF7cGO6P2YrjblwG4JA2UkVXj3lreJUOB2Jq4,1194
|
|
70
70
|
simo/core/autocomplete_views.py,sha256=x3MKOZvXYS3xVQ-V1S7Liv_U5bxr-uc0gePa85wv5nA,4561
|
|
71
71
|
simo/core/base_types.py,sha256=WypW8hTfzveuTQtruGjLYAGQZIuczxTlW-SdRk3iQug,666
|
|
72
72
|
simo/core/context.py,sha256=LKw1I4iIRnlnzoTCuSLLqDX7crHdBnMo3hjqYvVmzFc,1557
|
|
@@ -75,22 +75,22 @@ simo/core/dynamic_settings.py,sha256=bUs58XEZOCIEhg1TigR3LmYggli13KMryBZ9pC7ugAQ
|
|
|
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=Os4bLhEt6fQpQ5JWPThs5XxMI2429kQNgr7SgDDr_y0,5063
|
|
78
|
-
simo/core/forms.py,sha256=
|
|
78
|
+
simo/core/forms.py,sha256=osrwzw1nV-ObvFx7OMJaolqGU4xeZAOuhQRtirFjq6Q,22016
|
|
79
79
|
simo/core/gateways.py,sha256=Y2BME6zSyeUq_e-hzEUF6gErCUCP6nFxedkLZKiLVOo,4141
|
|
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
|
-
simo/core/models.py,sha256
|
|
83
|
+
simo/core/models.py,sha256=i7FT-y4wdvwwMbvxxDO3F9VSwLXBVcjlSFawb-V7N8w,23709
|
|
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=
|
|
87
|
-
simo/core/signal_receivers.py,sha256=
|
|
86
|
+
simo/core/serializers.py,sha256=b_38QV6LXsHZ7KfzX-h6N_-RjyV94ZDAyR6tok9lCbs,22664
|
|
87
|
+
simo/core/signal_receivers.py,sha256=5qp607PdNlRHyw88YOXu7rSznHm3upEpWLxB0lmEa0s,6527
|
|
88
88
|
simo/core/socket_consumers.py,sha256=Es_NmacQGZjsncBXDTEXR2yZbRs7mf2FKOBJjbZRGac,9607
|
|
89
89
|
simo/core/storage.py,sha256=_5igjaoWZAiExGWFEJMElxUw55DzJG1jqFty33xe8BE,342
|
|
90
90
|
simo/core/tasks.py,sha256=LMTkZQDGFus5L2Q8AGzYegjpnZKf9Klgo3V9BT5L2ng,16904
|
|
91
91
|
simo/core/todos.py,sha256=eYVXfLGiapkxKK57XuviSNe3WsUYyIWZ0hgQJk7ThKo,665
|
|
92
92
|
simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
|
|
93
|
-
simo/core/views.py,sha256=
|
|
93
|
+
simo/core/views.py,sha256=08H4Bm7KrHxB3p3ZKx1vrFR4d0DjCqMbqQosEsRWpkY,2841
|
|
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=zdegA3IsH3QhT7Hm6Aj08F2sv-3h1X7VBcwN05fhVis,14155
|
|
@@ -99,7 +99,7 @@ simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=mi3mu5qEKio_PvfQEvr3Q6AhdPL
|
|
|
99
99
|
simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=euP2EQsfTVCdvMT9NY10bK7xrz2dQouqQKZP0efN1ss,3906
|
|
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
|
-
simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=
|
|
102
|
+
simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=mwS1N-R5kcT5uoDAGraKG9MWZpCM8_SA4L4eyZsVpYk,949
|
|
103
103
|
simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=rZzjrxAir0HzN9uKPoXIY753f1CSdFWaSW7QBDen3qc,4448
|
|
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
|
|
@@ -108,21 +108,21 @@ simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=wGpnscX1DxFpRl54MQU
|
|
|
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=WJgjOqvl5BZoVAGVtxGeDOOW-jn3_fdJwVYBx1IRJlY,5886
|
|
111
|
-
simo/core/__pycache__/forms.cpython-38.pyc,sha256=
|
|
111
|
+
simo/core/__pycache__/forms.cpython-38.pyc,sha256=frvM1b9KRqsjh4YbUlV1CW8yupUyXJTb2R4sVgwy2K0,17827
|
|
112
112
|
simo/core/__pycache__/gateways.cpython-38.pyc,sha256=-_ugqnUOA1Cl6VfMqpV96n7ekVOEwYg_jNvoaZEcx9I,4815
|
|
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=SgTLFNkKxvJ62hevSAVNZHgHdG_u2p7AZBhrj-jfFPs,2649
|
|
116
|
-
simo/core/__pycache__/models.cpython-38.pyc,sha256=
|
|
116
|
+
simo/core/__pycache__/models.cpython-38.pyc,sha256=EG1RJ-kaOFupzHcrZnii6JQUuoQ1gbt6LN9xUMfHFo4,19610
|
|
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=
|
|
120
|
-
simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=
|
|
119
|
+
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=ciWQe19lrr5ImXByMZJI8JM47IlqmyAo1XcXfnVrU80,20018
|
|
120
|
+
simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=R_h1GHkoZXR-nrwiRJWQ9xE69JB1R_mP_fNYIBX4lrE,5165
|
|
121
121
|
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=Mr1-x-vGjBNffbz0S6AKpJCuzHJgRm8kXefv3qVVY_E,8397
|
|
122
122
|
simo/core/__pycache__/storage.cpython-38.pyc,sha256=9R1Xu0FJDflfRXUPsqEgt0SpwiP7FGk7HaR8s8XRyI8,721
|
|
123
123
|
simo/core/__pycache__/tasks.cpython-38.pyc,sha256=-J2is-l5XsfhamreN2TPQDTK-Jw6XGYL81bcVfjXsU8,11213
|
|
124
124
|
simo/core/__pycache__/todos.cpython-38.pyc,sha256=lOqGZ58siHM3isoJV4r7sg8igrfE9fFd-jSfeBa0AQI,253
|
|
125
|
-
simo/core/__pycache__/views.cpython-38.pyc,sha256=
|
|
125
|
+
simo/core/__pycache__/views.cpython-38.pyc,sha256=kYKvEcyKicdkTcN0iEJ4pT101-KHiZfXWkidiu82Evw,2925
|
|
126
126
|
simo/core/__pycache__/widgets.cpython-38.pyc,sha256=sR0ZeHCHrhnNDBJuRrxp3zUsfBp0xrtF0xrK2TkQv1o,3520
|
|
127
127
|
simo/core/db_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
128
|
simo/core/db_backend/base.py,sha256=wY5jsZ8hQpwot3o-7JNtDe33xy-vlfMLXa011htDojI,601
|
|
@@ -238,6 +238,7 @@ simo/core/migrations/0044_alter_gateway_type.py,sha256=xoQvOSz_JrWHECAAII83518tm
|
|
|
238
238
|
simo/core/migrations/0045_alter_instance_device_report_history_days_and_more.py,sha256=saR7gEbTDfXTcKnT1R193Aboqlg32HvDRI_JAvZ97TY,1360
|
|
239
239
|
simo/core/migrations/0046_component_value_translation_alter_gateway_type.py,sha256=SUybDSLRCGevVS9mCQGvozO8LA43tKze3R5rCf1TQ4E,1282
|
|
240
240
|
simo/core/migrations/0047_alter_component_value_translation.py,sha256=3GAgUBkZKUwWJMbDJxJJLBicC8eKkQ2ZJA__-xYpBCo,733
|
|
241
|
+
simo/core/migrations/0048_publicfile_privatefile.py,sha256=3NAP6f1ep66-CHJ7olSYOnXXeN7fTAg76lEjTJE1rL8,1601
|
|
241
242
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
242
243
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=w6GiBXVxWj30Bg4Sn_pFVeA041d-pCrkaq8mR3KuF70,5381
|
|
243
244
|
simo/core/migrations/__pycache__/0002_load_icons.cpython-38.pyc,sha256=Nb9RrPjVYo_RpZ5PmzoaEIWGCeVt4kicpmGiKlBrpIw,2123
|
|
@@ -286,6 +287,7 @@ simo/core/migrations/__pycache__/0044_alter_gateway_type.cpython-38.pyc,sha256=K
|
|
|
286
287
|
simo/core/migrations/__pycache__/0045_alter_instance_device_report_history_days_and_more.cpython-38.pyc,sha256=e1_hKjdokggnPndFkoBWrHQ18IkBi2W7WahcSjAbvKo,1278
|
|
287
288
|
simo/core/migrations/__pycache__/0046_component_value_translation_alter_gateway_type.cpython-38.pyc,sha256=0WowsGpjyPX7Z341bhU4bXErZqqFZaL1gtiusabrD0I,1445
|
|
288
289
|
simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-38.pyc,sha256=ucmaVOjI3q78vBTiEC7Aq76CklWq3fsC24EiH-mIzGc,961
|
|
290
|
+
simo/core/migrations/__pycache__/0048_publicfile_privatefile.cpython-38.pyc,sha256=Xtycj-4jvkB8UjVdgZZRzTgYl68Cr-Jj9WqCAho1Ggk,1346
|
|
289
291
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=VZmDQ57BTcebuM0KMhjiTOabgWZCBxQmSJzWZos9SO8,169
|
|
290
292
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
291
293
|
simo/core/static/admin/Img/plus.svg,sha256=2NpSFPWqGIjpAQGFI7LDQHPKagEhYkJiJX95ufCoZaI,741
|
|
@@ -10384,8 +10386,8 @@ simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
10384
10386
|
simo/generic/app_widgets.py,sha256=y8W3jR76Hh26O9pPQyg2SophMbYIOtAWD33MPKbB8Mg,856
|
|
10385
10387
|
simo/generic/base_types.py,sha256=u3SlfpNYaCwkVBwomWgso4ODzL71ay9MhiAW-bxgnDU,341
|
|
10386
10388
|
simo/generic/controllers.py,sha256=gqL1Evt-8Cq8MeHG-eV8aCtQ4St_gylE52wnXwOQUWU,46285
|
|
10387
|
-
simo/generic/forms.py,sha256=
|
|
10388
|
-
simo/generic/gateways.py,sha256=
|
|
10389
|
+
simo/generic/forms.py,sha256=VVp0IflKabObfxWPrc4Q6oEs_Z8hEvwnmNB2gZmaCGQ,25732
|
|
10390
|
+
simo/generic/gateways.py,sha256=04FKHgg3_cWjhu-bxexgRFpKRavW6_StgugFcDYwkiQ,17471
|
|
10389
10391
|
simo/generic/models.py,sha256=Adq7ipWK-renxJlNW-SZnAq2oGEOwKx8EdUWaKnfcVQ,7597
|
|
10390
10392
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10391
10393
|
simo/generic/socket_consumers.py,sha256=pyiqzfGxSKBNqfrfEJ_kCU0UbSC28XnvDn6QjKkbqyY,1767
|
|
@@ -10393,8 +10395,8 @@ simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=mLu54WS9KIl-pHwVCBKpsDFI
|
|
|
10393
10395
|
simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=D9b13pbMlirgHmjDnQhfLIDGSVINoSouHb4SWOeCRrs,1642
|
|
10394
10396
|
simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=aV5NdIuvXR-ItKpI__MwcyPZHD6Z882TFdgYkPCkr1I,493
|
|
10395
10397
|
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=jJjwKVaDYyazrRGNjUFoY74nr_jX_DEnsC9KjyxZCgc,30427
|
|
10396
|
-
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=
|
|
10397
|
-
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=
|
|
10398
|
+
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=JXaZ7iidF9GyfHY0DQSiox9rmGbEzU8c0tS9mpGNoDE,19342
|
|
10399
|
+
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=GIeMT51oZU2OCFD4eUDFdSRRYE0Qf14AcOr_gdUqG94,12705
|
|
10398
10400
|
simo/generic/__pycache__/models.cpython-38.pyc,sha256=MZpum7syAFxuulf47K7gtUlJJ7xRD-IBUBAwUM1ZRnw,5825
|
|
10399
10401
|
simo/generic/__pycache__/routing.cpython-38.pyc,sha256=xtxTUTBTdivzFyA5Wh7k-hUj1WDO_FiRq6HYXdbr9Ks,382
|
|
10400
10402
|
simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=FaVCf_uJI2uwj1Zz-jwsOXou65oV9gFCIB8e-YKquRk,1662
|
|
@@ -10435,7 +10437,7 @@ simo/multimedia/api.py,sha256=mZ5BTggWdc_kL8P70JGC3rTCiZKPnxWYoyNcAQkFnX4,285
|
|
|
10435
10437
|
simo/multimedia/app_widgets.py,sha256=g_IPx5bNmIS6JbaXXDCzYZYV2KVKAiYvWjH4oI30lWM,331
|
|
10436
10438
|
simo/multimedia/auto_urls.py,sha256=9FUwlifvAM-AJbAVK6ZCjsQdAZfREuf_sf-kSYjMu7I,204
|
|
10437
10439
|
simo/multimedia/base_types.py,sha256=dAP7_uh_b3A03yXBJZyQdRFucKIro4_RkIZ5yOaWXVE,151
|
|
10438
|
-
simo/multimedia/controllers.py,sha256=
|
|
10440
|
+
simo/multimedia/controllers.py,sha256=hEPdzVqnwzJXMYjuEsxKIYcaHK3asg3ur8m4XeEjEAA,3534
|
|
10439
10441
|
simo/multimedia/forms.py,sha256=oMCVUXRNiESrY3w_uBLRRgjMjx8BrmNeVglzorA9QtY,239
|
|
10440
10442
|
simo/multimedia/models.py,sha256=qUQaADxFegVMbcEdjyP72UCq5kkqJ5ZSe2lu9qyoom8,1169
|
|
10441
10443
|
simo/multimedia/serializers.py,sha256=9DRGsJVJLKdqmOLiVHMY06bTTYxpABhDy1JB_klzsBw,383
|
|
@@ -10446,7 +10448,7 @@ simo/multimedia/__pycache__/api.cpython-38.pyc,sha256=lFGEB74vgyEM98B42wwcN9WvH8
|
|
|
10446
10448
|
simo/multimedia/__pycache__/app_widgets.cpython-38.pyc,sha256=6pr3fz21tQ5ReC9SJ8VzheUZ0hpxDIClB0SA8YCwcPk,730
|
|
10447
10449
|
simo/multimedia/__pycache__/auto_urls.cpython-38.pyc,sha256=JNI3pZNFC3NoJV4cxsy-Oe6Vc6TA9fpPU63hjlXWINE,357
|
|
10448
10450
|
simo/multimedia/__pycache__/base_types.cpython-38.pyc,sha256=c4nmNziLs4RB3MAnxltn3W5XNW6PM5_vK_mm3Yvy42Y,324
|
|
10449
|
-
simo/multimedia/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10451
|
+
simo/multimedia/__pycache__/controllers.cpython-38.pyc,sha256=sbWvA-ro93qWxV6Qk8Pv_WPsq91tqlnFPIvCeQ0tvLA,4997
|
|
10450
10452
|
simo/multimedia/__pycache__/forms.cpython-38.pyc,sha256=99h7Yj2jim3QOrqej00wiPufrCF3F--RoYvwa6lzhPI,697
|
|
10451
10453
|
simo/multimedia/__pycache__/models.cpython-38.pyc,sha256=LmQ_XMA--wvLq11xYp24nU-y-kbx17iEZ10y9twCMJ0,1662
|
|
10452
10454
|
simo/multimedia/__pycache__/serializers.cpython-38.pyc,sha256=n86txYSrkmN0Xlrr8dMwKSY7rEzMc1iovepCZi_Fcw8,886
|
|
@@ -10616,9 +10618,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10616
10618
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10617
10619
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10618
10620
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10619
|
-
simo-2.7.
|
|
10620
|
-
simo-2.7.
|
|
10621
|
-
simo-2.7.
|
|
10622
|
-
simo-2.7.
|
|
10623
|
-
simo-2.7.
|
|
10624
|
-
simo-2.7.
|
|
10621
|
+
simo-2.7.13.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10622
|
+
simo-2.7.13.dist-info/METADATA,sha256=Dfh3VdJ-c5kB_5cRNa-EIIfN--LMdgEHt7tVD9cyDqo,1953
|
|
10623
|
+
simo-2.7.13.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
10624
|
+
simo-2.7.13.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
|
|
10625
|
+
simo-2.7.13.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10626
|
+
simo-2.7.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|