diff --git a/pdm.lock b/pdm.lock index 58ead28a30d4e7f10561ecaa48d2a74c33ad95a2..d74b5f1625891e6aeb84ad493db5a3a54ce25a8b 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "dev", "lint", "local"] +groups = ["default", "dev", "lint", "local", "typing"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:a7320608dc0e3c00f197dee7ada9261e62bd35dd235e56b9532d22126d225946" +content_hash = "sha256:1a9697a08aa14dbec10f593156b8222ce9b548a907c96e9d60c8874dadcccb5c" [[metadata.targets]] requires_python = "==3.13.*" @@ -32,7 +32,7 @@ name = "asgiref" version = "3.8.1" requires_python = ">=3.8" summary = "ASGI specs, helper code, and adapters" -groups = ["default"] +groups = ["default", "typing"] dependencies = [ "typing-extensions>=4; python_version < \"3.11\"", ] @@ -393,7 +393,7 @@ name = "django" version = "5.1.2" requires_python = ">=3.10" summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." -groups = ["default"] +groups = ["default", "typing"] dependencies = [ "asgiref<4,>=3.8.1", "sqlparse>=0.3.1", @@ -530,6 +530,55 @@ files = [ {file = "django_storages-1.14.4-py3-none-any.whl", hash = "sha256:d61930acb4a25e3aebebc6addaf946a3b1df31c803a6bf1af2f31c9047febaa3"}, ] +[[package]] +name = "django-stubs" +version = "5.1.1" +requires_python = ">=3.8" +summary = "Mypy stubs for Django" +groups = ["typing"] +dependencies = [ + "asgiref", + "django", + "django-stubs-ext>=5.1.1", + "tomli; python_version < \"3.11\"", + "types-PyYAML", + "typing-extensions>=4.11.0", +] +files = [ + {file = "django_stubs-5.1.1-py3-none-any.whl", hash = "sha256:c4dc64260bd72e6d32b9e536e8dd0d9247922f0271f82d1d5132a18f24b388ac"}, + {file = "django_stubs-5.1.1.tar.gz", hash = "sha256:126d354bbdff4906c4e93e6361197f6fbfb6231c3df6def85a291dae6f9f577b"}, +] + +[[package]] +name = "django-stubs-ext" +version = "5.1.1" +requires_python = ">=3.8" +summary = "Monkey-patching and extensions for django-stubs" +groups = ["typing"] +dependencies = [ + "django", + "typing-extensions", +] +files = [ + {file = "django_stubs_ext-5.1.1-py3-none-any.whl", hash = "sha256:3907f99e178c93323e2ce908aef8352adb8c047605161f8d9e5e7b4efb5a6a9c"}, + {file = "django_stubs_ext-5.1.1.tar.gz", hash = "sha256:db7364e4f50ae7e5360993dbd58a3a57ea4b2e7e5bab0fbd525ccdb3e7975d1c"}, +] + +[[package]] +name = "django-stubs" +version = "5.1.1" +extras = ["mypy-compatible"] +requires_python = ">=3.8" +summary = "Mypy stubs for Django" +groups = ["typing"] +dependencies = [ + "django-stubs==5.1.1", +] +files = [ + {file = "django_stubs-5.1.1-py3-none-any.whl", hash = "sha256:c4dc64260bd72e6d32b9e536e8dd0d9247922f0271f82d1d5132a18f24b388ac"}, + {file = "django_stubs-5.1.1.tar.gz", hash = "sha256:126d354bbdff4906c4e93e6361197f6fbfb6231c3df6def85a291dae6f9f577b"}, +] + [[package]] name = "django-timezone-field" version = "7.0" @@ -1698,7 +1747,7 @@ name = "sqlparse" version = "0.5.1" requires_python = ">=3.8" summary = "A non-validating SQL parser." -groups = ["default"] +groups = ["default", "typing"] files = [ {file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"}, {file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"}, @@ -1780,12 +1829,23 @@ files = [ {file = "truststore-0.9.2.tar.gz", hash = "sha256:a1dee0d0575ff22d2875476343783a5d64575419974e228f3248772613c3d993"}, ] +[[package]] +name = "types-pyyaml" +version = "6.0.12.20240917" +requires_python = ">=3.8" +summary = "Typing stubs for PyYAML" +groups = ["typing"] +files = [ + {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"}, + {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"}, +] + [[package]] name = "typing-extensions" version = "4.12.2" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["default"] +groups = ["default", "typing"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1796,7 +1856,7 @@ name = "tzdata" version = "2024.2" requires_python = ">=2" summary = "Provider of IANA time zone data" -groups = ["default"] +groups = ["default", "typing"] files = [ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, diff --git a/pyproject.toml b/pyproject.toml index ce737d4e3f11d3e6ef3c777d2a38263fbf0c1762..48ea6537b9ebe084c687ad6d9fb95178edd0fc25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,9 @@ dev = [ "pre-commit>=3.6.0", "docutils>=0.21.2", ] +typing = [ + "django-stubs[mypy-compatible]>=5.1.1", +] [tool.pdm.scripts] # Generic scripts @@ -107,3 +110,10 @@ output = ".tools/coverage/coverage.xml" [tool.coverage.html] directory = ".tools/coverage/html_report" + + +[tool.mypy] +plugins=["mypy_django_plugin.main"] + +[tool.django-stubs] +django_settings_module="hub.settings.base" diff --git a/requirements.dev.txt b/requirements.dev.txt index da13333eeabfcc34a0ea3697db434cabd74c7543..8f0630377cc004f2a709cfaeed831b082c3b7a50 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -35,6 +35,8 @@ django-oauth-toolkit==3.0.1 django-ratelimit==4.1.0 django-redis==5.4.0 django-storages==1.14.4 +django-stubs-ext==5.1.1 +django-stubs[mypy-compatible]==5.1.1 django-timezone-field==7.0 django-widget-tweaks==1.5.0 djangorestframework==3.15.2 @@ -117,6 +119,7 @@ tox==4.23.0 tox-pdm==0.7.2 tqdm==4.66.5 truststore==0.9.2; python_version >= "3.10" +types-pyyaml==6.0.12.20240917 typing-extensions==4.12.2 tzdata==2024.2 unearth==0.17.2 diff --git a/src/backoffice/templates/backoffice/project/create_edit.html b/src/backoffice/templates/backoffice/project/create_edit.html index d074807db26896da7a60f34dbf32152cf37f7a27..2a59c4f6bc965f0f8ef6ca7658d5e824b999e5f0 100644 --- a/src/backoffice/templates/backoffice/project/create_edit.html +++ b/src/backoffice/templates/backoffice/project/create_edit.html @@ -142,7 +142,7 @@ </div> </div> {% include 'backoffice/link/link_display.html' with links=project.links %} - {% trans 'Project__submit' as button_text%} + {% trans 'Project__submit' as button_text %} <div class="card-footer"> {% bootstrap_button button_text button_type="submit" button_class="btn-primary float-end" %} </div> diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index e4b583c81fd42c99c87f1aed20066c1d1ccb8d4d..6931b8b45b50914fa3098b95e62e79e1bb2a060a 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -1,6 +1,15 @@ from django.urls import path, re_path from django.views.generic import RedirectView +from backoffice.views.map import ( + FloorCreateView, + FloorListView, + FloorUpdateView, + POICreateView, + POIListView, + POIUpdateView, +) + from .views import ( assemblies, assemblyteam, @@ -8,7 +17,6 @@ from .views import ( badges, channelteam, events, - map, misc, moderation, profile, @@ -94,12 +102,12 @@ urlpatterns = [ path('assembly/<uuid:assembly>/r/<uuid:room>/new_link', assemblies.CreateRoomLinkView.as_view(), name='roomlink-create'), path('assembly/<uuid:assembly>/r/<uuid:room>/remove_link', assemblies.RemoveRoomLinkView.as_view(), name='roomlink-remove'), path('assembly/<uuid:assembly>/r/<uuid:room>/remove', assemblies.RemoveRoomView.as_view(), name='assembly-remove-room'), - path('map/floors', map.FloorListView.as_view(), name='map-floor-list'), - path('map/floor/new', map.FloorCreateView.as_view(), name='map-floor-create'), - path('map/floor/<uuid:pk>', map.FloorUpdateView.as_view(), name='map-floor-edit'), - path('map/pois', map.POIListView.as_view(), name='map-poi-list'), - path('map/poi/new', map.POICreateView.as_view(), name='map-poi-create'), - path('map/poi/<uuid:pk>', map.POIUpdateView.as_view(), name='map-poi-edit'), + path('map/floors', FloorListView.as_view(), name='map-floor-list'), + path('map/floor/new', FloorCreateView.as_view(), name='map-floor-create'), + path('map/floor/<uuid:pk>', FloorUpdateView.as_view(), name='map-floor-edit'), + path('map/pois', POIListView.as_view(), name='map-poi-list'), + path('map/poi/new', POICreateView.as_view(), name='map-poi-create'), + path('map/poi/<uuid:pk>', POIUpdateView.as_view(), name='map-poi-edit'), path('moderation', moderation.IndexView.as_view(), name='moderation'), path('moderation/assemblies', moderation.ModerationAssemblyListView.as_view(), name='moderation-assembly-list'), path('moderation/assembly/<uuid:pk>', moderation.ModerationAssemblyDetailView.as_view(), name='moderation-assembly-detail'), diff --git a/src/backoffice/views/projects.py b/src/backoffice/views/projects.py index 76aa2df895158207c699cf1f426faad2a0f4a6bd..c38dccb6ace2522f131c3bfcdec9f48dffab1b47 100644 --- a/src/backoffice/views/projects.py +++ b/src/backoffice/views/projects.py @@ -124,7 +124,7 @@ class ProjectFormMixin(ConferenceLoginRequiredMixin, FormView): def get_context_data(self, *args, **kwargs): ctx = super().get_context_data(*args, **kwargs) - if 'form' not in kwargs: + if 'form' not in kwargs and 'form' not in ctx: ctx['form'] = self.get_form() if 'link_forms' not in kwargs: ctx['link_forms'] = self.get_links_formset() @@ -187,24 +187,12 @@ class CreateProjectView(SoProjectFormMixin, CreateView): self.object = None return super().post(request, *args, **kwargs) - def get_form_kwargs(self) -> dict[str, Any]: - return { - **super().get_form_kwargs(), - 'create': True, - } - class AssemblyCreateProjectView(AssemblyProjectFormMixin, CreateView): def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: self.object = None return super().post(request, *args, **kwargs) - def get_form_kwargs(self) -> dict[str, Any]: - return { - **super().get_form_kwargs(), - 'create': True, - } - class ProjectView(SoProjectFormMixin, UpdateView): def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: diff --git a/src/core/forms.py b/src/core/forms.py index 5e4f619ec4710069f8c62e6d42c82a1a0615ed45..86a57d08fd577dec00ac0f9b1a3bafcba8ac42d7 100644 --- a/src/core/forms.py +++ b/src/core/forms.py @@ -270,16 +270,16 @@ class ProjectForm(TranslatedFieldsForm): conference, assembly: Assembly | None = None, owner: PlatformUser | None = None, - create: bool = False, + instance: Project | None = None, publish: bool = False, **kwargs, ): self.conference = conference - self.create = create self.assembly = assembly self.owner = owner self.publish = publish - super().__init__(*args, **kwargs) + self.create = instance is None + super().__init__(*args, instance=instance, **kwargs) if self.instance.pk: self.initial['tags_list'] = ', '.join(self.instance.sorted_tags) diff --git a/src/hub/settings/base.py b/src/hub/settings/base.py index 458d9f8e1d4c66f8054c91d15a58dfae8127358e..634517dd042300c7ac9b7c2a0ee29c25687e8528 100644 --- a/src/hub/settings/base.py +++ b/src/hub/settings/base.py @@ -212,6 +212,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'django.template.context_processors.i18n', ], }, },