arthexis 0.1.4__tar.gz → 0.1.6__tar.gz
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 arthexis might be problematic. Click here for more details.
- {arthexis-0.1.4 → arthexis-0.1.6}/PKG-INFO +2 -2
- {arthexis-0.1.4 → arthexis-0.1.6}/README.md +1 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/arthexis.egg-info/PKG-INFO +2 -2
- {arthexis-0.1.4 → arthexis-0.1.6}/arthexis.egg-info/SOURCES.txt +1 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/admin.py +37 -11
- {arthexis-0.1.4 → arthexis-0.1.6}/core/models.py +4 -3
- {arthexis-0.1.4 → arthexis-0.1.6}/core/views.py +4 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/admin.py +13 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/tests.py +0 -5
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/views.py +0 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/pyproject.toml +1 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_email_inbox_search_action.py +5 -3
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_package_release_admin_actions.py +19 -6
- arthexis-0.1.6/tests/test_post_office_admin_group.py +33 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_release_fixture_cleanup.py +5 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_release_progress.py +33 -1
- {arthexis-0.1.4 → arthexis-0.1.6}/LICENSE +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/arthexis.egg-info/dependency_links.txt +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/arthexis.egg-info/requires.txt +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/arthexis.egg-info/top_level.txt +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/__init__.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/active_app.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/asgi.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/auth_app.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/celery.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/context_processors.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/loadenv.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/logging.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/middleware.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/offline.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/settings.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/urls.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/config/wsgi.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/__init__.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/apps.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/backends.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/entity.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/environment.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/fields.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/lcd_screen.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/middleware.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/notifications.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/release.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/system.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/tasks.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/tests.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/urls.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/core/user_data.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/__init__.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/actions.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/apps.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/lcd.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/models.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/tasks.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/urls.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/nodes/utils.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/__init__.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/apps.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/consumers.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/evcs.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/models.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/routing.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/simulator.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/store.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/tasks.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/test_export_import.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/test_rfid.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/tests.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/transactions_io.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/urls.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/ocpp/views.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/__init__.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/apps.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/checks.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/context_processors.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/models.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/tests.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/urls.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/utils.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/pages/views.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/setup.cfg +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_acronym_capitalization.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_admin_history.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_admin_index_actions.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_awg_admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_csrf_failure.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_csrf_origin_subnet.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_email_collector.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_email_inbox.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_email_inbox_admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_env_refresh_clean.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_env_refresh_unlink.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_footer_admin_link.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_footer_no_references.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_footer_presence.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_footer_render.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_github_token.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_install_script.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_language_switch.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_lcd_smbus2.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_localhost_admin_backend.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_model_verbose_name_capitalization.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_notifications_fallback.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_notify_command.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_odoo_profile.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_odoo_profile_admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_offline.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_pypi_token.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_readme_language.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_reference_qr_code.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_reference_transaction_uuid.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_register_site_apps_command.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_release_logs.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_release_mapping.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_release_tasks.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_rfid_admin_reference_clear.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_rfid_admin_scan_csrf.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_rfid_background_reader.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_save_as_copy.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_seed_data.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_sigil_resolution.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_urls_autodiscover.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_user_datum_admin.py +0 -0
- {arthexis-0.1.4 → arthexis-0.1.6}/tests/test_vscode_manage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arthexis
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Django-based MESH system
|
|
5
5
|
Author-email: "Rafael J. Guillén-Osorio" <tecnologia@gelectriic.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -118,7 +118,7 @@ Arthexis Constellation is a narrative-driven Django-based suite that centralizes
|
|
|
118
118
|
- Single codebase with special features per role
|
|
119
119
|
|
|
120
120
|
## Support
|
|
121
|
-
You may contact us at tecnologia at gelectriic dot com or visit our web page
|
|
121
|
+
You may contact us at tecnologia at gelectriic dot com or visit our [web page](https://www.gelectriic.com/) for professional services and commercial support.
|
|
122
122
|
|
|
123
123
|
## About Me
|
|
124
124
|
> "What? You want to know about me too? Well, I enjoy developing software, roleplaying games, long walks on the beach and a fourth secret thing."
|
|
@@ -10,7 +10,7 @@ Arthexis Constellation is a narrative-driven Django-based suite that centralizes
|
|
|
10
10
|
- Single codebase with special features per role
|
|
11
11
|
|
|
12
12
|
## Support
|
|
13
|
-
You may contact us at tecnologia at gelectriic dot com or visit our web page
|
|
13
|
+
You may contact us at tecnologia at gelectriic dot com or visit our [web page](https://www.gelectriic.com/) for professional services and commercial support.
|
|
14
14
|
|
|
15
15
|
## About Me
|
|
16
16
|
> "What? You want to know about me too? Well, I enjoy developing software, roleplaying games, long walks on the beach and a fourth secret thing."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arthexis
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Django-based MESH system
|
|
5
5
|
Author-email: "Rafael J. Guillén-Osorio" <tecnologia@gelectriic.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -118,7 +118,7 @@ Arthexis Constellation is a narrative-driven Django-based suite that centralizes
|
|
|
118
118
|
- Single codebase with special features per role
|
|
119
119
|
|
|
120
120
|
## Support
|
|
121
|
-
You may contact us at tecnologia at gelectriic dot com or visit our web page
|
|
121
|
+
You may contact us at tecnologia at gelectriic dot com or visit our [web page](https://www.gelectriic.com/) for professional services and commercial support.
|
|
122
122
|
|
|
123
123
|
## About Me
|
|
124
124
|
> "What? You want to know about me too? Well, I enjoy developing software, roleplaying games, long walks on the beach and a fourth secret thing."
|
|
@@ -102,6 +102,7 @@ tests/test_odoo_profile.py
|
|
|
102
102
|
tests/test_odoo_profile_admin.py
|
|
103
103
|
tests/test_offline.py
|
|
104
104
|
tests/test_package_release_admin_actions.py
|
|
105
|
+
tests/test_post_office_admin_group.py
|
|
105
106
|
tests/test_pypi_token.py
|
|
106
107
|
tests/test_readme_language.py
|
|
107
108
|
tests/test_reference_qr_code.py
|
|
@@ -3,7 +3,7 @@ from django.contrib import admin
|
|
|
3
3
|
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
|
|
4
4
|
from django.urls import path, reverse
|
|
5
5
|
from django.shortcuts import redirect, render
|
|
6
|
-
from django.http import JsonResponse
|
|
6
|
+
from django.http import JsonResponse, HttpResponseBase
|
|
7
7
|
from django.template.response import TemplateResponse
|
|
8
8
|
from django.views.decorators.csrf import csrf_exempt
|
|
9
9
|
from django.core.exceptions import ValidationError
|
|
@@ -17,6 +17,7 @@ from import_export import resources, fields
|
|
|
17
17
|
from import_export.admin import ImportExportModelAdmin
|
|
18
18
|
from import_export.widgets import ForeignKeyWidget
|
|
19
19
|
from django.contrib.auth.models import Group
|
|
20
|
+
from django.templatetags.static import static
|
|
20
21
|
from django.utils.html import format_html
|
|
21
22
|
import json
|
|
22
23
|
import uuid
|
|
@@ -37,7 +38,7 @@ from .models import (
|
|
|
37
38
|
Reference,
|
|
38
39
|
OdooProfile,
|
|
39
40
|
FediverseProfile,
|
|
40
|
-
EmailInbox,
|
|
41
|
+
EmailInbox as CoreEmailInbox,
|
|
41
42
|
Package,
|
|
42
43
|
PackageRelease,
|
|
43
44
|
ReleaseManager,
|
|
@@ -49,6 +50,19 @@ from .user_data import UserDatumAdminMixin
|
|
|
49
50
|
admin.site.unregister(Group)
|
|
50
51
|
|
|
51
52
|
|
|
53
|
+
class SaveBeforeChangeAction(DjangoObjectActions):
|
|
54
|
+
def response_change(self, request, obj):
|
|
55
|
+
action = request.POST.get("_action")
|
|
56
|
+
if action:
|
|
57
|
+
allowed = self.get_change_actions(request, str(obj.pk), None)
|
|
58
|
+
if action in allowed and hasattr(self, action):
|
|
59
|
+
response = getattr(self, action)(request, obj)
|
|
60
|
+
if isinstance(response, HttpResponseBase):
|
|
61
|
+
return response
|
|
62
|
+
return redirect(request.path)
|
|
63
|
+
return super().response_change(request, obj)
|
|
64
|
+
|
|
65
|
+
|
|
52
66
|
@admin.register(Reference)
|
|
53
67
|
class ReferenceAdmin(admin.ModelAdmin):
|
|
54
68
|
list_display = (
|
|
@@ -131,7 +145,7 @@ class ReleaseManagerAdmin(admin.ModelAdmin):
|
|
|
131
145
|
|
|
132
146
|
|
|
133
147
|
@admin.register(Package)
|
|
134
|
-
class PackageAdmin(
|
|
148
|
+
class PackageAdmin(SaveBeforeChangeAction, admin.ModelAdmin):
|
|
135
149
|
list_display = ("name", "description", "homepage_url", "release_manager")
|
|
136
150
|
actions = ["prepare_next_release"]
|
|
137
151
|
change_actions = ["prepare_next_release_action"]
|
|
@@ -366,6 +380,14 @@ class FediverseProfileAdmin(admin.ModelAdmin):
|
|
|
366
380
|
self.message_user(request, f"{profile}: {exc}", level=messages.ERROR)
|
|
367
381
|
|
|
368
382
|
|
|
383
|
+
class EmailInbox(CoreEmailInbox):
|
|
384
|
+
class Meta:
|
|
385
|
+
proxy = True
|
|
386
|
+
app_label = "post_office"
|
|
387
|
+
verbose_name = CoreEmailInbox._meta.verbose_name
|
|
388
|
+
verbose_name_plural = CoreEmailInbox._meta.verbose_name_plural
|
|
389
|
+
|
|
390
|
+
|
|
369
391
|
class EmailInboxAdminForm(forms.ModelForm):
|
|
370
392
|
"""Admin form for :class:`core.models.EmailInbox` with hidden password."""
|
|
371
393
|
|
|
@@ -376,7 +398,7 @@ class EmailInboxAdminForm(forms.ModelForm):
|
|
|
376
398
|
)
|
|
377
399
|
|
|
378
400
|
class Meta:
|
|
379
|
-
model =
|
|
401
|
+
model = CoreEmailInbox
|
|
380
402
|
fields = "__all__"
|
|
381
403
|
|
|
382
404
|
def __init__(self, *args, **kwargs):
|
|
@@ -431,6 +453,10 @@ class EmailInboxAdmin(admin.ModelAdmin):
|
|
|
431
453
|
),
|
|
432
454
|
)
|
|
433
455
|
|
|
456
|
+
def save_model(self, request, obj, form, change):
|
|
457
|
+
super().save_model(request, obj, form, change)
|
|
458
|
+
obj.__class__ = EmailInbox
|
|
459
|
+
|
|
434
460
|
@admin.action(description="Test selected inboxes")
|
|
435
461
|
def test_connection(self, request, queryset):
|
|
436
462
|
for inbox in queryset:
|
|
@@ -755,7 +781,7 @@ class RFIDAdmin(ImportExportModelAdmin):
|
|
|
755
781
|
|
|
756
782
|
|
|
757
783
|
@admin.register(PackageRelease)
|
|
758
|
-
class PackageReleaseAdmin(
|
|
784
|
+
class PackageReleaseAdmin(SaveBeforeChangeAction, admin.ModelAdmin):
|
|
759
785
|
list_display = (
|
|
760
786
|
"version",
|
|
761
787
|
"package",
|
|
@@ -808,18 +834,18 @@ class PackageReleaseAdmin(DjangoObjectActions, admin.ModelAdmin):
|
|
|
808
834
|
publish_release_action.short_description = "Publish this release"
|
|
809
835
|
|
|
810
836
|
@staticmethod
|
|
811
|
-
def
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
)
|
|
837
|
+
def _boolean_icon(value: bool) -> str:
|
|
838
|
+
icon = static("admin/img/icon-yes.svg" if value else "admin/img/icon-no.svg")
|
|
839
|
+
alt = "True" if value else "False"
|
|
840
|
+
return format_html('<img src="{}" alt="{}">', icon, alt)
|
|
815
841
|
|
|
816
842
|
@admin.display(description="Published")
|
|
817
843
|
def published_status(self, obj):
|
|
818
|
-
return self.
|
|
844
|
+
return self._boolean_icon(obj.is_published)
|
|
819
845
|
|
|
820
846
|
@admin.display(description="Is current")
|
|
821
847
|
def is_current(self, obj):
|
|
822
|
-
return self.
|
|
848
|
+
return self._boolean_icon(obj.is_current)
|
|
823
849
|
|
|
824
850
|
def pr_link(self, obj):
|
|
825
851
|
if obj.pr_url:
|
|
@@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
|
|
10
10
|
from django.core.validators import RegexValidator
|
|
11
11
|
from django.core.exceptions import ValidationError
|
|
12
12
|
from django.apps import apps
|
|
13
|
-
from django.db.models.signals import m2m_changed, post_delete
|
|
13
|
+
from django.db.models.signals import m2m_changed, post_delete, post_save
|
|
14
14
|
from django.dispatch import receiver
|
|
15
15
|
from datetime import timedelta
|
|
16
16
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -1257,8 +1257,9 @@ class PackageRelease(Entity):
|
|
|
1257
1257
|
return self.revision[-6:] if self.revision else ""
|
|
1258
1258
|
|
|
1259
1259
|
|
|
1260
|
-
@receiver(post_delete, sender=PackageRelease)
|
|
1261
|
-
def
|
|
1260
|
+
@receiver([post_save, post_delete], sender=PackageRelease)
|
|
1261
|
+
def _update_release_fixture(sender, instance, **kwargs) -> None:
|
|
1262
|
+
"""Keep the release fixture in sync with the database."""
|
|
1262
1263
|
PackageRelease.dump_fixture()
|
|
1263
1264
|
|
|
1264
1265
|
# Ensure each RFID can only be linked to one energy account
|
|
@@ -399,7 +399,10 @@ def release_progress(request, pk: int, action: str):
|
|
|
399
399
|
identifier = f"{release.package.name}-{release.version}"
|
|
400
400
|
if release.revision:
|
|
401
401
|
identifier = f"{identifier}-{release.revision[:7]}"
|
|
402
|
-
log_name =
|
|
402
|
+
log_name = f"{identifier}.log"
|
|
403
|
+
if ctx.get("log") != log_name:
|
|
404
|
+
ctx = {"step": 0, "log": log_name}
|
|
405
|
+
step_count = 0
|
|
403
406
|
log_path = Path("logs") / log_name
|
|
404
407
|
ctx.setdefault("log", log_name)
|
|
405
408
|
|
|
@@ -18,7 +18,7 @@ from .actions import NodeAction
|
|
|
18
18
|
|
|
19
19
|
from .models import (
|
|
20
20
|
Node,
|
|
21
|
-
EmailOutbox,
|
|
21
|
+
EmailOutbox as NodeEmailOutbox,
|
|
22
22
|
NodeRole,
|
|
23
23
|
ContentSample,
|
|
24
24
|
NodeTask,
|
|
@@ -181,10 +181,22 @@ class NodeAdmin(admin.ModelAdmin):
|
|
|
181
181
|
return redirect(reverse("admin:nodes_node_change", args=[node_id]))
|
|
182
182
|
|
|
183
183
|
|
|
184
|
+
class EmailOutbox(NodeEmailOutbox):
|
|
185
|
+
class Meta:
|
|
186
|
+
proxy = True
|
|
187
|
+
app_label = "post_office"
|
|
188
|
+
verbose_name = NodeEmailOutbox._meta.verbose_name
|
|
189
|
+
verbose_name_plural = NodeEmailOutbox._meta.verbose_name_plural
|
|
190
|
+
|
|
191
|
+
|
|
184
192
|
@admin.register(EmailOutbox)
|
|
185
193
|
class EmailOutboxAdmin(admin.ModelAdmin):
|
|
186
194
|
list_display = ("node", "host", "port", "username", "use_tls", "use_ssl")
|
|
187
195
|
|
|
196
|
+
def save_model(self, request, obj, form, change):
|
|
197
|
+
super().save_model(request, obj, form, change)
|
|
198
|
+
obj.__class__ = EmailOutbox
|
|
199
|
+
|
|
188
200
|
|
|
189
201
|
class NodeRoleAdminForm(forms.ModelForm):
|
|
190
202
|
nodes = forms.ModelMultipleChoiceField(
|
|
@@ -560,11 +560,6 @@ class NetMessageAdminTests(TransactionTestCase):
|
|
|
560
560
|
class LastNetMessageViewTests(TestCase):
|
|
561
561
|
def setUp(self):
|
|
562
562
|
self.client = Client()
|
|
563
|
-
User = get_user_model()
|
|
564
|
-
self.user = User.objects.create_user(
|
|
565
|
-
username="lastmsg", password="pwd"
|
|
566
|
-
)
|
|
567
|
-
self.client.force_login(self.user)
|
|
568
563
|
NodeRole.objects.get_or_create(name="Terminal")
|
|
569
564
|
|
|
570
565
|
def test_returns_latest_message(self):
|
|
@@ -4,7 +4,7 @@ from unittest.mock import patch
|
|
|
4
4
|
from django.contrib.admin.sites import AdminSite
|
|
5
5
|
from django.test import TestCase, RequestFactory
|
|
6
6
|
|
|
7
|
-
from core.admin import EmailInboxAdmin
|
|
7
|
+
from core.admin import EmailInboxAdmin, EmailInbox as AdminEmailInbox
|
|
8
8
|
from core.models import EmailInbox, User
|
|
9
9
|
|
|
10
10
|
|
|
@@ -93,11 +93,13 @@ class EmailInboxSearchTests(TestCase):
|
|
|
93
93
|
use_ssl=True,
|
|
94
94
|
)
|
|
95
95
|
site = AdminSite()
|
|
96
|
-
ma = EmailInboxAdmin(
|
|
96
|
+
ma = EmailInboxAdmin(AdminEmailInbox, site)
|
|
97
97
|
factory = RequestFactory()
|
|
98
98
|
request = factory.post("/", {"apply": "yes", "subject": "S"})
|
|
99
99
|
request.user = admin
|
|
100
|
-
response = ma.search_inbox(
|
|
100
|
+
response = ma.search_inbox(
|
|
101
|
+
request, AdminEmailInbox.objects.filter(id=inbox.id)
|
|
102
|
+
)
|
|
101
103
|
self.assertEqual(response.status_code, 200)
|
|
102
104
|
content = response.render().content.decode()
|
|
103
105
|
self.assertIn("S", content)
|
|
@@ -28,12 +28,10 @@ class PackageReleaseAdminActionsTests(TestCase):
|
|
|
28
28
|
|
|
29
29
|
def test_change_page_contains_publish_action(self):
|
|
30
30
|
change_url = reverse("admin:core_packagerelease_change", args=[self.release.pk])
|
|
31
|
-
action_url = reverse(
|
|
32
|
-
"admin:core_packagerelease_actions",
|
|
33
|
-
args=[self.release.pk, "publish_release_action"],
|
|
34
|
-
)
|
|
35
31
|
resp = self.client.get(change_url)
|
|
36
|
-
self.assertContains(
|
|
32
|
+
self.assertContains(
|
|
33
|
+
resp, 'name="_action" value="publish_release_action"'
|
|
34
|
+
)
|
|
37
35
|
|
|
38
36
|
def test_publish_action_redirects(self):
|
|
39
37
|
url = reverse(
|
|
@@ -45,6 +43,21 @@ class PackageReleaseAdminActionsTests(TestCase):
|
|
|
45
43
|
resp, reverse("release-progress", args=[self.release.pk, "publish"])
|
|
46
44
|
)
|
|
47
45
|
|
|
46
|
+
def test_publish_action_saves_changes_before_execution(self):
|
|
47
|
+
change_url = reverse("admin:core_packagerelease_change", args=[self.release.pk])
|
|
48
|
+
data = {
|
|
49
|
+
"package": self.package.pk,
|
|
50
|
+
"release_manager": "",
|
|
51
|
+
"version": "1.0.1",
|
|
52
|
+
"_action": "publish_release_action",
|
|
53
|
+
}
|
|
54
|
+
resp = self.client.post(change_url, data)
|
|
55
|
+
self.assertRedirects(
|
|
56
|
+
resp, reverse("release-progress", args=[self.release.pk, "publish"])
|
|
57
|
+
)
|
|
58
|
+
self.release.refresh_from_db()
|
|
59
|
+
self.assertEqual(self.release.version, "1.0.1")
|
|
60
|
+
|
|
48
61
|
def test_change_page_pypi_url_readonly(self):
|
|
49
62
|
change_url = reverse("admin:core_packagerelease_change", args=[self.release.pk])
|
|
50
63
|
resp = self.client.get(change_url)
|
|
@@ -77,7 +90,7 @@ class PackageReleaseAdminActionsTests(TestCase):
|
|
|
77
90
|
resp = self.client.get(list_url)
|
|
78
91
|
content = resp.content.decode()
|
|
79
92
|
self.assertIn("Is current", content)
|
|
80
|
-
self.assertIn('
|
|
93
|
+
self.assertIn('icon-yes.svg', content)
|
|
81
94
|
|
|
82
95
|
def test_release_revision_defaults_to_repo_revision(self):
|
|
83
96
|
expected = revision_utils.get_revision()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from django.test import TestCase
|
|
2
|
+
from django.contrib.auth import get_user_model
|
|
3
|
+
from django.urls import reverse
|
|
4
|
+
from django.contrib.admin.sites import site
|
|
5
|
+
|
|
6
|
+
from core.admin import EmailInbox as PostOfficeEmailInbox
|
|
7
|
+
from nodes.admin import EmailOutbox as PostOfficeEmailOutbox
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PostOfficeAdminGroupTests(TestCase):
|
|
11
|
+
def setUp(self):
|
|
12
|
+
User = get_user_model()
|
|
13
|
+
self.admin = User.objects.create_superuser(
|
|
14
|
+
username="po-admin", password="pwd", email="admin@example.com"
|
|
15
|
+
)
|
|
16
|
+
self.client.force_login(self.admin)
|
|
17
|
+
|
|
18
|
+
def test_models_registered(self):
|
|
19
|
+
registry = site._registry
|
|
20
|
+
self.assertIn(PostOfficeEmailInbox, registry)
|
|
21
|
+
self.assertIn(PostOfficeEmailOutbox, registry)
|
|
22
|
+
self.assertEqual(
|
|
23
|
+
registry[PostOfficeEmailInbox].model._meta.app_label, "post_office"
|
|
24
|
+
)
|
|
25
|
+
self.assertEqual(
|
|
26
|
+
registry[PostOfficeEmailOutbox].model._meta.app_label, "post_office"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def test_admin_index_shows_post_office_group(self):
|
|
30
|
+
response = self.client.get(reverse("admin:index"))
|
|
31
|
+
self.assertContains(response, "Post Office")
|
|
32
|
+
self.assertContains(response, "Email Inboxes")
|
|
33
|
+
self.assertContains(response, "Email Outboxes")
|
|
@@ -30,3 +30,8 @@ class ReleaseFixtureCleanupTests(TestCase):
|
|
|
30
30
|
data = self.fixture_path.read_text()
|
|
31
31
|
self.assertNotIn("1.0.0", data)
|
|
32
32
|
|
|
33
|
+
def test_create_updates_fixture(self):
|
|
34
|
+
PackageRelease.objects.create(package=self.package, version="2.0.0")
|
|
35
|
+
data = self.fixture_path.read_text()
|
|
36
|
+
self.assertIn("2.0.0", data)
|
|
37
|
+
|
|
@@ -62,7 +62,12 @@ class ReleaseProgressTests(TestCase):
|
|
|
62
62
|
self.assertContains(resp, "All steps completed")
|
|
63
63
|
self.assertContains(
|
|
64
64
|
resp,
|
|
65
|
-
'<a href="http://example.com/pr/1" target="_blank">http://example.com/pr/1</a>',
|
|
65
|
+
'<a href="http://example.com/pr/1" target="_blank" rel="noopener">http://example.com/pr/1</a>',
|
|
66
|
+
html=True,
|
|
67
|
+
)
|
|
68
|
+
self.assertContains(
|
|
69
|
+
resp,
|
|
70
|
+
'<a href="https://pypi.org/project/pkg/1.0.0/" target="_blank" rel="noopener">https://pypi.org/project/pkg/1.0.0/</a>',
|
|
66
71
|
html=True,
|
|
67
72
|
)
|
|
68
73
|
release.refresh_from_db()
|
|
@@ -94,6 +99,11 @@ class ReleaseProgressTests(TestCase):
|
|
|
94
99
|
self.assertEqual(resp.status_code, 200)
|
|
95
100
|
self.assertContains(resp, "All steps completed")
|
|
96
101
|
self.assertIsNone(resp.context["pr_url"])
|
|
102
|
+
self.assertContains(
|
|
103
|
+
resp,
|
|
104
|
+
'<a href="https://pypi.org/project/pkg/1.1.0/" target="_blank" rel="noopener">https://pypi.org/project/pkg/1.1.0/</a>',
|
|
105
|
+
html=True,
|
|
106
|
+
)
|
|
97
107
|
release.refresh_from_db()
|
|
98
108
|
self.assertTrue(release.is_published)
|
|
99
109
|
pub.assert_called_once()
|
|
@@ -131,3 +141,25 @@ class ReleaseProgressTests(TestCase):
|
|
|
131
141
|
resp = self.client.get(f"{url}?step=0")
|
|
132
142
|
self.assertEqual(resp.context["error"], "Version 2.0.0 is older than existing 3.0.0")
|
|
133
143
|
self.assertEqual(self.version_path.read_text().strip(), "3.0.0")
|
|
144
|
+
|
|
145
|
+
def test_session_resets_when_version_changes(self):
|
|
146
|
+
release = PackageRelease.objects.create(package=self.package, version="1.2.0")
|
|
147
|
+
url = reverse("release-progress", args=[release.pk, "publish"])
|
|
148
|
+
self.client.get(url)
|
|
149
|
+
with patch("core.views.release_utils.network_available", return_value=False):
|
|
150
|
+
self.client.get(f"{url}?step=0")
|
|
151
|
+
|
|
152
|
+
release.version = "1.3.0"
|
|
153
|
+
release.save()
|
|
154
|
+
|
|
155
|
+
resp = self.client.get(url)
|
|
156
|
+
expected_log = f"logs/pkg-1.3.0-{release.revision[:7]}.log"
|
|
157
|
+
self.assertEqual(resp.context["log_path"], expected_log)
|
|
158
|
+
self.assertEqual(resp.context["current_step"], 0)
|
|
159
|
+
|
|
160
|
+
with patch("core.views.release_utils.network_available", return_value=False):
|
|
161
|
+
self.client.get(f"{url}?step=0")
|
|
162
|
+
|
|
163
|
+
log_content = Path(expected_log).read_text()
|
|
164
|
+
self.assertIn("Checking if version 1.3.0 exists on PyPI", log_content)
|
|
165
|
+
self.assertNotIn("1.2.0", log_content)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|