arthexis 0.1.4__tar.gz → 0.1.5__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.

Files changed (125) hide show
  1. {arthexis-0.1.4 → arthexis-0.1.5}/PKG-INFO +2 -2
  2. {arthexis-0.1.4 → arthexis-0.1.5}/README.md +1 -1
  3. {arthexis-0.1.4 → arthexis-0.1.5}/arthexis.egg-info/PKG-INFO +2 -2
  4. {arthexis-0.1.4 → arthexis-0.1.5}/core/admin.py +23 -9
  5. {arthexis-0.1.4 → arthexis-0.1.5}/core/models.py +4 -3
  6. {arthexis-0.1.4 → arthexis-0.1.5}/core/views.py +4 -1
  7. {arthexis-0.1.4 → arthexis-0.1.5}/pyproject.toml +1 -1
  8. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_package_release_admin_actions.py +19 -6
  9. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_release_fixture_cleanup.py +5 -0
  10. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_release_progress.py +33 -1
  11. {arthexis-0.1.4 → arthexis-0.1.5}/LICENSE +0 -0
  12. {arthexis-0.1.4 → arthexis-0.1.5}/arthexis.egg-info/SOURCES.txt +0 -0
  13. {arthexis-0.1.4 → arthexis-0.1.5}/arthexis.egg-info/dependency_links.txt +0 -0
  14. {arthexis-0.1.4 → arthexis-0.1.5}/arthexis.egg-info/requires.txt +0 -0
  15. {arthexis-0.1.4 → arthexis-0.1.5}/arthexis.egg-info/top_level.txt +0 -0
  16. {arthexis-0.1.4 → arthexis-0.1.5}/config/__init__.py +0 -0
  17. {arthexis-0.1.4 → arthexis-0.1.5}/config/active_app.py +0 -0
  18. {arthexis-0.1.4 → arthexis-0.1.5}/config/asgi.py +0 -0
  19. {arthexis-0.1.4 → arthexis-0.1.5}/config/auth_app.py +0 -0
  20. {arthexis-0.1.4 → arthexis-0.1.5}/config/celery.py +0 -0
  21. {arthexis-0.1.4 → arthexis-0.1.5}/config/context_processors.py +0 -0
  22. {arthexis-0.1.4 → arthexis-0.1.5}/config/loadenv.py +0 -0
  23. {arthexis-0.1.4 → arthexis-0.1.5}/config/logging.py +0 -0
  24. {arthexis-0.1.4 → arthexis-0.1.5}/config/middleware.py +0 -0
  25. {arthexis-0.1.4 → arthexis-0.1.5}/config/offline.py +0 -0
  26. {arthexis-0.1.4 → arthexis-0.1.5}/config/settings.py +0 -0
  27. {arthexis-0.1.4 → arthexis-0.1.5}/config/urls.py +0 -0
  28. {arthexis-0.1.4 → arthexis-0.1.5}/config/wsgi.py +0 -0
  29. {arthexis-0.1.4 → arthexis-0.1.5}/core/__init__.py +0 -0
  30. {arthexis-0.1.4 → arthexis-0.1.5}/core/apps.py +0 -0
  31. {arthexis-0.1.4 → arthexis-0.1.5}/core/backends.py +0 -0
  32. {arthexis-0.1.4 → arthexis-0.1.5}/core/entity.py +0 -0
  33. {arthexis-0.1.4 → arthexis-0.1.5}/core/environment.py +0 -0
  34. {arthexis-0.1.4 → arthexis-0.1.5}/core/fields.py +0 -0
  35. {arthexis-0.1.4 → arthexis-0.1.5}/core/lcd_screen.py +0 -0
  36. {arthexis-0.1.4 → arthexis-0.1.5}/core/middleware.py +0 -0
  37. {arthexis-0.1.4 → arthexis-0.1.5}/core/notifications.py +0 -0
  38. {arthexis-0.1.4 → arthexis-0.1.5}/core/release.py +0 -0
  39. {arthexis-0.1.4 → arthexis-0.1.5}/core/system.py +0 -0
  40. {arthexis-0.1.4 → arthexis-0.1.5}/core/tasks.py +0 -0
  41. {arthexis-0.1.4 → arthexis-0.1.5}/core/tests.py +0 -0
  42. {arthexis-0.1.4 → arthexis-0.1.5}/core/urls.py +0 -0
  43. {arthexis-0.1.4 → arthexis-0.1.5}/core/user_data.py +0 -0
  44. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/__init__.py +0 -0
  45. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/actions.py +0 -0
  46. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/admin.py +0 -0
  47. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/apps.py +0 -0
  48. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/lcd.py +0 -0
  49. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/models.py +0 -0
  50. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/tasks.py +0 -0
  51. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/tests.py +0 -0
  52. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/urls.py +0 -0
  53. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/utils.py +0 -0
  54. {arthexis-0.1.4 → arthexis-0.1.5}/nodes/views.py +0 -0
  55. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/__init__.py +0 -0
  56. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/admin.py +0 -0
  57. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/apps.py +0 -0
  58. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/consumers.py +0 -0
  59. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/evcs.py +0 -0
  60. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/models.py +0 -0
  61. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/routing.py +0 -0
  62. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/simulator.py +0 -0
  63. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/store.py +0 -0
  64. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/tasks.py +0 -0
  65. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/test_export_import.py +0 -0
  66. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/test_rfid.py +0 -0
  67. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/tests.py +0 -0
  68. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/transactions_io.py +0 -0
  69. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/urls.py +0 -0
  70. {arthexis-0.1.4 → arthexis-0.1.5}/ocpp/views.py +0 -0
  71. {arthexis-0.1.4 → arthexis-0.1.5}/pages/__init__.py +0 -0
  72. {arthexis-0.1.4 → arthexis-0.1.5}/pages/admin.py +0 -0
  73. {arthexis-0.1.4 → arthexis-0.1.5}/pages/apps.py +0 -0
  74. {arthexis-0.1.4 → arthexis-0.1.5}/pages/checks.py +0 -0
  75. {arthexis-0.1.4 → arthexis-0.1.5}/pages/context_processors.py +0 -0
  76. {arthexis-0.1.4 → arthexis-0.1.5}/pages/models.py +0 -0
  77. {arthexis-0.1.4 → arthexis-0.1.5}/pages/tests.py +0 -0
  78. {arthexis-0.1.4 → arthexis-0.1.5}/pages/urls.py +0 -0
  79. {arthexis-0.1.4 → arthexis-0.1.5}/pages/utils.py +0 -0
  80. {arthexis-0.1.4 → arthexis-0.1.5}/pages/views.py +0 -0
  81. {arthexis-0.1.4 → arthexis-0.1.5}/setup.cfg +0 -0
  82. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_acronym_capitalization.py +0 -0
  83. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_admin_history.py +0 -0
  84. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_admin_index_actions.py +0 -0
  85. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_awg_admin.py +0 -0
  86. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_csrf_failure.py +0 -0
  87. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_csrf_origin_subnet.py +0 -0
  88. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_email_collector.py +0 -0
  89. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_email_inbox.py +0 -0
  90. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_email_inbox_admin.py +0 -0
  91. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_email_inbox_search_action.py +0 -0
  92. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_env_refresh_clean.py +0 -0
  93. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_env_refresh_unlink.py +0 -0
  94. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_footer_admin_link.py +0 -0
  95. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_footer_no_references.py +0 -0
  96. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_footer_presence.py +0 -0
  97. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_footer_render.py +0 -0
  98. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_github_token.py +0 -0
  99. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_install_script.py +0 -0
  100. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_language_switch.py +0 -0
  101. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_lcd_smbus2.py +0 -0
  102. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_localhost_admin_backend.py +0 -0
  103. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_model_verbose_name_capitalization.py +0 -0
  104. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_notifications_fallback.py +0 -0
  105. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_notify_command.py +0 -0
  106. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_odoo_profile.py +0 -0
  107. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_odoo_profile_admin.py +0 -0
  108. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_offline.py +0 -0
  109. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_pypi_token.py +0 -0
  110. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_readme_language.py +0 -0
  111. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_reference_qr_code.py +0 -0
  112. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_reference_transaction_uuid.py +0 -0
  113. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_register_site_apps_command.py +0 -0
  114. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_release_logs.py +0 -0
  115. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_release_mapping.py +0 -0
  116. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_release_tasks.py +0 -0
  117. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_rfid_admin_reference_clear.py +0 -0
  118. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_rfid_admin_scan_csrf.py +0 -0
  119. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_rfid_background_reader.py +0 -0
  120. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_save_as_copy.py +0 -0
  121. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_seed_data.py +0 -0
  122. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_sigil_resolution.py +0 -0
  123. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_urls_autodiscover.py +0 -0
  124. {arthexis-0.1.4 → arthexis-0.1.5}/tests/test_user_datum_admin.py +0 -0
  125. {arthexis-0.1.4 → arthexis-0.1.5}/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.4
3
+ Version: 0.1.5
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 https://www.gelectriic.com/ for professional services and commercial support.
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 https://www.gelectriic.com/ for professional services and commercial support.
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.4
3
+ Version: 0.1.5
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 https://www.gelectriic.com/ for professional services and commercial support.
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."
@@ -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
@@ -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(DjangoObjectActions, admin.ModelAdmin):
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"]
@@ -755,7 +769,7 @@ class RFIDAdmin(ImportExportModelAdmin):
755
769
 
756
770
 
757
771
  @admin.register(PackageRelease)
758
- class PackageReleaseAdmin(DjangoObjectActions, admin.ModelAdmin):
772
+ class PackageReleaseAdmin(SaveBeforeChangeAction, admin.ModelAdmin):
759
773
  list_display = (
760
774
  "version",
761
775
  "package",
@@ -808,18 +822,18 @@ class PackageReleaseAdmin(DjangoObjectActions, admin.ModelAdmin):
808
822
  publish_release_action.short_description = "Publish this release"
809
823
 
810
824
  @staticmethod
811
- def _checkbox(value: bool) -> str:
812
- return format_html(
813
- '<input type="checkbox"{} disabled>', " checked" if value else ""
814
- )
825
+ def _boolean_icon(value: bool) -> str:
826
+ icon = static("admin/img/icon-yes.svg" if value else "admin/img/icon-no.svg")
827
+ alt = "True" if value else "False"
828
+ return format_html('<img src="{}" alt="{}">', icon, alt)
815
829
 
816
830
  @admin.display(description="Published")
817
831
  def published_status(self, obj):
818
- return self._checkbox(obj.is_published)
832
+ return self._boolean_icon(obj.is_published)
819
833
 
820
834
  @admin.display(description="Is current")
821
835
  def is_current(self, obj):
822
- return self._checkbox(obj.is_current)
836
+ return self._boolean_icon(obj.is_current)
823
837
 
824
838
  def pr_link(self, obj):
825
839
  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 _delete_release_fixture(sender, instance, **kwargs) -> None:
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 = ctx.get("log") or f"{identifier}.log"
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
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "arthexis"
7
- version = "0.1.4"
7
+ version = "0.1.5"
8
8
  description = "Django-based MESH system"
9
9
  requires-python = ">=3.10"
10
10
  license = "MIT"
@@ -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(resp, action_url)
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('<input type="checkbox" checked disabled>', content)
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()
@@ -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