constec 0.5.2__py3-none-any.whl → 0.6.0__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.
@@ -0,0 +1,91 @@
1
+ # Generated manually for constec automation organization support
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+ from django.db.models import Q
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('constec_db', '0006_automation_trigger_action_executionlog_notificationtemplate'),
12
+ ]
13
+
14
+ operations = [
15
+ # Add organization field to Automation
16
+ migrations.AddField(
17
+ model_name='automation',
18
+ name='organization',
19
+ field=models.ForeignKey(
20
+ blank=True,
21
+ db_index=True,
22
+ help_text='Organization para automations compartidas (opcional si se define company)',
23
+ null=True,
24
+ on_delete=django.db.models.deletion.CASCADE,
25
+ to='constec_db.organization'
26
+ ),
27
+ ),
28
+ # Make company field nullable in Automation
29
+ migrations.AlterField(
30
+ model_name='automation',
31
+ name='company',
32
+ field=models.ForeignKey(
33
+ blank=True,
34
+ db_index=True,
35
+ help_text='Company específica (opcional si se define organization)',
36
+ null=True,
37
+ on_delete=django.db.models.deletion.CASCADE,
38
+ to='constec_db.company'
39
+ ),
40
+ ),
41
+ # Add organization field to NotificationTemplate
42
+ migrations.AddField(
43
+ model_name='notificationtemplate',
44
+ name='organization',
45
+ field=models.ForeignKey(
46
+ blank=True,
47
+ db_index=True,
48
+ help_text='Organization para templates compartidos (opcional si se define company)',
49
+ null=True,
50
+ on_delete=django.db.models.deletion.CASCADE,
51
+ to='constec_db.organization'
52
+ ),
53
+ ),
54
+ # Make company field nullable in NotificationTemplate
55
+ migrations.AlterField(
56
+ model_name='notificationtemplate',
57
+ name='company',
58
+ field=models.ForeignKey(
59
+ blank=True,
60
+ db_index=True,
61
+ help_text='Company específica (opcional si se define organization)',
62
+ null=True,
63
+ on_delete=django.db.models.deletion.CASCADE,
64
+ to='constec_db.company'
65
+ ),
66
+ ),
67
+ # Add indexes for organization
68
+ migrations.AddIndex(
69
+ model_name='automation',
70
+ index=models.Index(fields=['organization', 'status'], name='automations_org_status_idx'),
71
+ ),
72
+ migrations.AddIndex(
73
+ model_name='notificationtemplate',
74
+ index=models.Index(fields=['organization', 'channel', 'is_active'], name='templates_org_channel_active_idx'),
75
+ ),
76
+ # Add constraint: at least one of company or organization must be set
77
+ migrations.AddConstraint(
78
+ model_name='automation',
79
+ constraint=models.CheckConstraint(
80
+ check=Q(company__isnull=False) | Q(organization__isnull=False),
81
+ name='automation_requires_company_or_organization'
82
+ ),
83
+ ),
84
+ migrations.AddConstraint(
85
+ model_name='notificationtemplate',
86
+ constraint=models.CheckConstraint(
87
+ check=Q(company__isnull=False) | Q(organization__isnull=False),
88
+ name='template_requires_company_or_organization'
89
+ ),
90
+ ),
91
+ ]
@@ -0,0 +1,173 @@
1
+ # Generated manually - Refactor creator fields to support User and OrganizationUser
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ def migrate_creator_data(apps, schema_editor):
8
+ """Migrate existing created_by data to created_by_user."""
9
+ Automation = apps.get_model('constec_db', 'Automation')
10
+ NotificationTemplate = apps.get_model('constec_db', 'NotificationTemplate')
11
+
12
+ # Migrate Automation creators
13
+ for automation in Automation.objects.all():
14
+ if automation.created_by:
15
+ automation.created_by_user = automation.created_by
16
+ automation.save(update_fields=['created_by_user'])
17
+
18
+ # Migrate NotificationTemplate creators
19
+ for template in NotificationTemplate.objects.all():
20
+ if template.created_by:
21
+ template.created_by_user = template.created_by
22
+ template.save(update_fields=['created_by_user'])
23
+
24
+
25
+ class Migration(migrations.Migration):
26
+
27
+ dependencies = [
28
+ ('constec_db', '0007_add_organization_to_automations'),
29
+ ]
30
+
31
+ operations = [
32
+ # 1. Add new creator fields to Automation (nullable temporarily for data migration)
33
+ migrations.AddField(
34
+ model_name='automation',
35
+ name='created_by_user',
36
+ field=models.ForeignKey(
37
+ blank=True,
38
+ help_text='User creator (company-level)',
39
+ null=True,
40
+ on_delete=django.db.models.deletion.CASCADE,
41
+ related_name='created_automations',
42
+ to='constec_db.user'
43
+ ),
44
+ ),
45
+ migrations.AddField(
46
+ model_name='automation',
47
+ name='created_by_org_user',
48
+ field=models.ForeignKey(
49
+ blank=True,
50
+ help_text='OrganizationUser creator (org-level)',
51
+ null=True,
52
+ on_delete=django.db.models.deletion.CASCADE,
53
+ related_name='created_automations',
54
+ to='constec_db.organizationuser'
55
+ ),
56
+ ),
57
+
58
+ # 2. Add new creator fields to NotificationTemplate (nullable temporarily for data migration)
59
+ migrations.AddField(
60
+ model_name='notificationtemplate',
61
+ name='created_by_user',
62
+ field=models.ForeignKey(
63
+ blank=True,
64
+ help_text='User creator (company-level)',
65
+ null=True,
66
+ on_delete=django.db.models.deletion.CASCADE,
67
+ related_name='created_templates',
68
+ to='constec_db.user'
69
+ ),
70
+ ),
71
+ migrations.AddField(
72
+ model_name='notificationtemplate',
73
+ name='created_by_org_user',
74
+ field=models.ForeignKey(
75
+ blank=True,
76
+ help_text='OrganizationUser creator (org-level)',
77
+ null=True,
78
+ on_delete=django.db.models.deletion.CASCADE,
79
+ related_name='created_templates',
80
+ to='constec_db.organizationuser'
81
+ ),
82
+ ),
83
+
84
+ # 3. Add triggered_by_org_user to ExecutionLog
85
+ migrations.AddField(
86
+ model_name='executionlog',
87
+ name='triggered_by_org_user',
88
+ field=models.ForeignKey(
89
+ blank=True,
90
+ help_text='OrganizationUser who triggered execution (org-level)',
91
+ null=True,
92
+ on_delete=django.db.models.deletion.SET_NULL,
93
+ related_name='triggered_executions',
94
+ to='constec_db.organizationuser'
95
+ ),
96
+ ),
97
+
98
+ # 4. Update existing triggered_by_user field help text
99
+ migrations.AlterField(
100
+ model_name='executionlog',
101
+ name='triggered_by_user',
102
+ field=models.ForeignKey(
103
+ blank=True,
104
+ help_text='User who triggered execution (company-level)',
105
+ null=True,
106
+ on_delete=django.db.models.deletion.SET_NULL,
107
+ related_name='triggered_executions',
108
+ to='constec_db.user'
109
+ ),
110
+ ),
111
+
112
+ # 5. Migrate data from old created_by to new created_by_user
113
+ migrations.RunPython(migrate_creator_data, reverse_code=migrations.RunPython.noop),
114
+
115
+ # 6. Remove old created_by fields
116
+ migrations.RemoveField(
117
+ model_name='automation',
118
+ name='created_by',
119
+ ),
120
+ migrations.RemoveField(
121
+ model_name='notificationtemplate',
122
+ name='created_by',
123
+ ),
124
+
125
+ # 7. Add constraints for Automation
126
+ migrations.AddConstraint(
127
+ model_name='automation',
128
+ constraint=models.CheckConstraint(
129
+ check=models.Q(
130
+ ('created_by_user__isnull', False),
131
+ ('created_by_org_user__isnull', True)
132
+ ) | models.Q(
133
+ ('created_by_user__isnull', True),
134
+ ('created_by_org_user__isnull', False)
135
+ ),
136
+ name='automation_single_creator'
137
+ ),
138
+ ),
139
+ migrations.AddConstraint(
140
+ model_name='automation',
141
+ constraint=models.CheckConstraint(
142
+ check=models.Q(('created_by_user__isnull', False)) | models.Q(('created_by_org_user__isnull', False)),
143
+ name='automation_requires_creator'
144
+ ),
145
+ ),
146
+
147
+ # 8. Add constraints for NotificationTemplate
148
+ migrations.AddConstraint(
149
+ model_name='notificationtemplate',
150
+ constraint=models.CheckConstraint(
151
+ check=models.Q(
152
+ ('created_by_user__isnull', False),
153
+ ('created_by_org_user__isnull', True)
154
+ ) | models.Q(
155
+ ('created_by_user__isnull', True),
156
+ ('created_by_org_user__isnull', False)
157
+ ),
158
+ name='template_single_creator'
159
+ ),
160
+ ),
161
+ migrations.AddConstraint(
162
+ model_name='notificationtemplate',
163
+ constraint=models.CheckConstraint(
164
+ check=models.Q(('created_by_user__isnull', False)) | models.Q(('created_by_org_user__isnull', False)),
165
+ name='template_requires_creator'
166
+ ),
167
+ ),
168
+
169
+ # 9. Delete deprecated Event model
170
+ migrations.DeleteModel(
171
+ name='Event',
172
+ ),
173
+ ]
@@ -42,7 +42,7 @@ from .flow import FlowTemplate, Flow
42
42
  from .session import Session, Message
43
43
 
44
44
  # Automations models (automations schema)
45
- from .automation import Event, Automation, Trigger, Action, ExecutionLog, NotificationTemplate
45
+ from .automation import Automation, Trigger, Action, ExecutionLog, NotificationTemplate
46
46
 
47
47
 
48
48
  __all__ = [
@@ -93,7 +93,6 @@ __all__ = [
93
93
  'Session',
94
94
  'Message',
95
95
  # Automations (automations schema)
96
- 'Event',
97
96
  'Automation',
98
97
  'Trigger',
99
98
  'Action',
@@ -2,9 +2,11 @@
2
2
 
3
3
  import uuid
4
4
  from django.db import models
5
+ from django.db.models import Q
5
6
  from django.core.exceptions import ValidationError
6
7
  from .base import UUIDModel
7
8
  from .company import Company
9
+ from .organization import Organization, OrganizationUser
8
10
  from .user import User
9
11
 
10
12
 
@@ -34,12 +36,40 @@ class Automation(UUIDModel):
34
36
  ('retry', 'Retry'),
35
37
  ]
36
38
 
37
- # FKs
38
- company = models.ForeignKey(Company, on_delete=models.CASCADE, db_index=True)
39
- created_by = models.ForeignKey(
39
+ # FKs - Al menos uno debe estar presente
40
+ company = models.ForeignKey(
41
+ Company,
42
+ on_delete=models.CASCADE,
43
+ null=True,
44
+ blank=True,
45
+ db_index=True,
46
+ help_text="Company específica (opcional si se define organization)"
47
+ )
48
+ organization = models.ForeignKey(
49
+ Organization,
50
+ on_delete=models.CASCADE,
51
+ null=True,
52
+ blank=True,
53
+ db_index=True,
54
+ help_text="Organization para automations compartidas (opcional si se define company)"
55
+ )
56
+
57
+ # Creator - only ONE of these should be filled (XOR)
58
+ created_by_user = models.ForeignKey(
40
59
  User,
41
60
  on_delete=models.CASCADE,
42
- related_name='created_automations'
61
+ null=True,
62
+ blank=True,
63
+ related_name='created_automations',
64
+ help_text="User creator (company-level)"
65
+ )
66
+ created_by_org_user = models.ForeignKey(
67
+ OrganizationUser,
68
+ on_delete=models.CASCADE,
69
+ null=True,
70
+ blank=True,
71
+ related_name='created_automations',
72
+ help_text="OrganizationUser creator (org-level)"
43
73
  )
44
74
 
45
75
  # Info básica
@@ -82,13 +112,34 @@ class Automation(UUIDModel):
82
112
  app_label = 'constec_db'
83
113
  indexes = [
84
114
  models.Index(fields=['company', 'status']),
115
+ models.Index(fields=['organization', 'status']),
85
116
  models.Index(fields=['status', 'next_execution_at']),
86
117
  ]
87
118
  ordering = ['-created_at']
119
+ constraints = [
120
+ models.CheckConstraint(
121
+ check=Q(company__isnull=False) | Q(organization__isnull=False),
122
+ name='automation_requires_company_or_organization'
123
+ ),
124
+ models.CheckConstraint(
125
+ check=Q(created_by_user__isnull=False) | Q(created_by_org_user__isnull=False),
126
+ name='automation_requires_creator'
127
+ ),
128
+ models.CheckConstraint(
129
+ check=Q(created_by_user__isnull=False, created_by_org_user__isnull=True) |
130
+ Q(created_by_user__isnull=True, created_by_org_user__isnull=False),
131
+ name='automation_single_creator'
132
+ ),
133
+ ]
88
134
 
89
135
  def __str__(self):
90
136
  return f"{self.name} ({self.status})"
91
137
 
138
+ @property
139
+ def creator(self):
140
+ """Helper to access creator regardless of type."""
141
+ return self.created_by_user or self.created_by_org_user
142
+
92
143
 
93
144
  class Trigger(UUIDModel):
94
145
  """
@@ -270,7 +321,16 @@ class ExecutionLog(UUIDModel):
270
321
  on_delete=models.SET_NULL,
271
322
  null=True,
272
323
  blank=True,
273
- related_name='triggered_executions'
324
+ related_name='triggered_executions',
325
+ help_text="User who triggered execution (company-level)"
326
+ )
327
+ triggered_by_org_user = models.ForeignKey(
328
+ OrganizationUser,
329
+ on_delete=models.SET_NULL,
330
+ null=True,
331
+ blank=True,
332
+ related_name='triggered_executions',
333
+ help_text="OrganizationUser who triggered execution (org-level)"
274
334
  )
275
335
 
276
336
  # Estado
@@ -317,6 +377,11 @@ class ExecutionLog(UUIDModel):
317
377
  def __str__(self):
318
378
  return f"{self.automation.name} - {self.status} ({self.started_at})"
319
379
 
380
+ @property
381
+ def trigger_user(self):
382
+ """Helper to access trigger user regardless of type."""
383
+ return self.triggered_by_user or self.triggered_by_org_user
384
+
320
385
 
321
386
  class NotificationTemplate(UUIDModel):
322
387
  """
@@ -333,12 +398,40 @@ class NotificationTemplate(UUIDModel):
333
398
  ('push', 'Push Notification'),
334
399
  ]
335
400
 
336
- # FKs
337
- company = models.ForeignKey(Company, on_delete=models.CASCADE, db_index=True)
338
- created_by = models.ForeignKey(
401
+ # FKs - Al menos uno debe estar presente
402
+ company = models.ForeignKey(
403
+ Company,
404
+ on_delete=models.CASCADE,
405
+ null=True,
406
+ blank=True,
407
+ db_index=True,
408
+ help_text="Company específica (opcional si se define organization)"
409
+ )
410
+ organization = models.ForeignKey(
411
+ Organization,
412
+ on_delete=models.CASCADE,
413
+ null=True,
414
+ blank=True,
415
+ db_index=True,
416
+ help_text="Organization para templates compartidos (opcional si se define company)"
417
+ )
418
+
419
+ # Creator - only ONE of these should be filled (XOR)
420
+ created_by_user = models.ForeignKey(
339
421
  User,
340
422
  on_delete=models.CASCADE,
341
- related_name='created_templates'
423
+ null=True,
424
+ blank=True,
425
+ related_name='created_templates',
426
+ help_text="User creator (company-level)"
427
+ )
428
+ created_by_org_user = models.ForeignKey(
429
+ OrganizationUser,
430
+ on_delete=models.CASCADE,
431
+ null=True,
432
+ blank=True,
433
+ related_name='created_templates',
434
+ help_text="OrganizationUser creator (org-level)"
342
435
  )
343
436
 
344
437
  # Info básica
@@ -367,100 +460,29 @@ class NotificationTemplate(UUIDModel):
367
460
  app_label = 'constec_db'
368
461
  indexes = [
369
462
  models.Index(fields=['company', 'channel', 'is_active']),
463
+ models.Index(fields=['organization', 'channel', 'is_active']),
370
464
  ]
371
465
  ordering = ['name']
466
+ constraints = [
467
+ models.CheckConstraint(
468
+ check=Q(company__isnull=False) | Q(organization__isnull=False),
469
+ name='template_requires_company_or_organization'
470
+ ),
471
+ models.CheckConstraint(
472
+ check=Q(created_by_user__isnull=False) | Q(created_by_org_user__isnull=False),
473
+ name='template_requires_creator'
474
+ ),
475
+ models.CheckConstraint(
476
+ check=Q(created_by_user__isnull=False, created_by_org_user__isnull=True) |
477
+ Q(created_by_user__isnull=True, created_by_org_user__isnull=False),
478
+ name='template_single_creator'
479
+ ),
480
+ ]
372
481
 
373
482
  def __str__(self):
374
483
  return f"{self.channel}: {self.name}"
375
484
 
376
-
377
- class Event(UUIDModel):
378
- """
379
- Evento programado con soporte para múltiples tipos y recurrencia flexible.
380
-
381
- Tipos soportados:
382
- - notification: Notificaciones programadas
383
- - automation: Automatizaciones programadas (acciones HTTP, workflows, etc.)
384
- """
385
-
386
- EVENT_TYPE_CHOICES = [
387
- ('notification', 'Notification'),
388
- ('automation', 'Automation'),
389
- ]
390
-
391
- STATUS_CHOICES = [
392
- ('active', 'Active'), # Activo y programado
393
- ('paused', 'Paused'), # Pausado temporalmente
394
- ('completed', 'Completed'), # Completado (para puntuales)
395
- ('failed', 'Failed'), # Falló la última ejecución
396
- ('cancelled', 'Cancelled'), # Cancelado permanentemente
397
- ]
398
-
399
- RECURRENCE_TYPE_CHOICES = [
400
- ('punctual', 'Punctual'), # Una o más veces en fechas específicas
401
- ('periodic', 'Periodic'), # Recurrente
402
- ]
403
-
404
- # FKs
405
- company = models.ForeignKey(Company, on_delete=models.CASCADE, db_index=True)
406
-
407
- # Tipo de evento
408
- event_type = models.CharField(max_length=50, choices=EVENT_TYPE_CHOICES)
409
-
410
- # Info básica
411
- title = models.CharField(max_length=255)
412
- description = models.TextField(blank=True)
413
- status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
414
-
415
- # Recurrencia
416
- recurrence_type = models.CharField(
417
- max_length=20,
418
- choices=RECURRENCE_TYPE_CHOICES,
419
- help_text="Tipo de recurrencia: puntual (fechas específicas) o periódico"
420
- )
421
- recurrence_config = models.JSONField(
422
- help_text="Configuración de recurrencia en formato JSON"
423
- )
424
-
425
- # Configuración específica del tipo de evento
426
- config = models.JSONField(
427
- default=dict,
428
- help_text="Configuración específica según event_type (mensaje, URL, etc.)"
429
- )
430
-
431
- # Control de ejecución
432
- next_execution_at = models.DateTimeField(
433
- null=True,
434
- blank=True,
435
- db_index=True,
436
- help_text="Próxima fecha/hora de ejecución calculada"
437
- )
438
- last_executed_at = models.DateTimeField(
439
- null=True,
440
- blank=True,
441
- help_text="Última vez que se ejecutó"
442
- )
443
- execution_count = models.IntegerField(
444
- default=0,
445
- help_text="Cantidad de veces que se ha ejecutado"
446
- )
447
-
448
- # Auditoría
449
- created_by = models.ForeignKey(
450
- User,
451
- on_delete=models.CASCADE,
452
- related_name='created_events'
453
- )
454
-
455
- class Meta:
456
- db_table = '"automations"."events"'
457
- app_label = 'constec_db'
458
- indexes = [
459
- models.Index(fields=['company', 'event_type']),
460
- models.Index(fields=['status', 'next_execution_at']),
461
- models.Index(fields=['recurrence_type']),
462
- ]
463
- ordering = ['next_execution_at']
464
-
465
- def __str__(self):
466
- return f"{self.event_type}: {self.title}"
485
+ @property
486
+ def creator(self):
487
+ """Helper to access creator regardless of type."""
488
+ return self.created_by_user or self.created_by_org_user
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: constec
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Base library for the Constec ecosystem - shared utilities, models, and namespace foundation
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/TpmyCT/constec-python
@@ -7,9 +7,11 @@ constec/db/migrations/0003_remove_module_level.py,sha256=3GX-VDLSZqqxaZf6KFtuc7U
7
7
  constec/db/migrations/0004_rename_entities_company_cuit_idx_entities_company_e2c50f_idx_and_more.py,sha256=TCkutatVjJhVKxiQwp-RLhBlbOo5rtwSV1qQqao1qCI,11874
8
8
  constec/db/migrations/0005_event.py,sha256=kyvEFOAbOJj3daDzOWcIhfXD8gl5EpIHYvRy3880cZc,2892
9
9
  constec/db/migrations/0006_automation_trigger_action_executionlog_notificationtemplate.py,sha256=sfh1YTRPqUiBb5FIxRNJm_BnlYkDonwm7FEEihgtSe0,13628
10
+ constec/db/migrations/0007_add_organization_to_automations.py,sha256=08yDuetrA4WWwqNriyewr0qCpesLo_9x5YD36CDScj4,3467
11
+ constec/db/migrations/0008_refactor_creator_fields.py,sha256=O_bcChxFR_IPw1BV_1NDbsIdrzhlj4MfpdhPXnhdau4,6381
10
12
  constec/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- constec/db/models/__init__.py,sha256=tzeMhD6Bxs8Z8dBHEGBeIBm1ZrMKk66TlZEOD92InKU,2463
12
- constec/db/models/automation.py,sha256=_toRKPIGeTd54aLSnEsRUkCH42md18gXrj-xnnmTv-g,13712
13
+ constec/db/models/__init__.py,sha256=4ZU-4bnCxQrTMWKkt5e97lthHS0wQ0EWIy8GUOYBeqw,2443
14
+ constec/db/models/automation.py,sha256=4llvmthh5OzbUXue3pC_QlptfFNIGXC1LEpqRtIVSXU,14999
13
15
  constec/db/models/base.py,sha256=Urbz9iyOtSxdTfgtEYbtBLmTiea2QAcLq0L40tAzEq8,736
14
16
  constec/db/models/company.py,sha256=APYsbiNoqQ-73wxFP0jq3AByHNHn3Jjbe_J_iwpD9gM,1047
15
17
  constec/db/models/contact.py,sha256=VJ66YgzCqp09dzYM5IK9rZZV1jqBepJQO8YK28gA98k,2106
@@ -30,8 +32,8 @@ constec/shared/exceptions.py,sha256=8Bih40RWoH0gVhto09mH2ppSQV_drHPnGWITcoD-0J0,
30
32
  constec/utils/__init__.py,sha256=brf-G4UvU-3CK_rKNPTaHwsVsxnoJSbml_QTZJSM7d0,458
31
33
  constec/utils/cuit.py,sha256=dQKGlA4pRQ5DyR-N4BiV8ZsvAle2Vgjif7PU72zHx_A,2753
32
34
  constec/utils/password.py,sha256=XNpTJ9xZQSoZNjXEAnexAEZuYkwW1dFgX4AY-B5Q0gA,1462
33
- constec-0.5.2.dist-info/licenses/LICENSE,sha256=a1R51ONDGq0UQfV-n3ybsNL7EGhcC2sQ1sXvRANaFVI,1064
34
- constec-0.5.2.dist-info/METADATA,sha256=mbHsxNllNA8FUJYkiB7bAW6e_C85bj4kGs9ua2ZzOXU,2954
35
- constec-0.5.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
- constec-0.5.2.dist-info/top_level.txt,sha256=bQ9AydOLlthShsr7tA7t7ivbLvlLPdhHOo0BdWgnh_Y,8
37
- constec-0.5.2.dist-info/RECORD,,
35
+ constec-0.6.0.dist-info/licenses/LICENSE,sha256=a1R51ONDGq0UQfV-n3ybsNL7EGhcC2sQ1sXvRANaFVI,1064
36
+ constec-0.6.0.dist-info/METADATA,sha256=E559HBZj2gR3sB4FRynHSDs-SmBqv-hgu_eLBKB_aMs,2954
37
+ constec-0.6.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
38
+ constec-0.6.0.dist-info/top_level.txt,sha256=bQ9AydOLlthShsr7tA7t7ivbLvlLPdhHOo0BdWgnh_Y,8
39
+ constec-0.6.0.dist-info/RECORD,,