This is an automated email from the ASF dual-hosted git repository.
yasithdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git
The following commit(s) were added to refs/heads/main by this push:
new d2d8f2b0a refactor(portal): fold airavata-django-portal-commons into
django_airavata.commons (#111)
d2d8f2b0a is described below
commit d2d8f2b0ab03dc40a417059f072651e718d4f233
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Mon Jun 8 01:17:52 2026 -0400
refactor(portal): fold airavata-django-portal-commons into
django_airavata.commons (#111)
* refactor(portal): fold airavata-django-portal-commons into
django_airavata.commons
Move the standalone airavata-django-portal-commons package into the Django
portal as django_airavata.commons, dropping it as a separate PyPI distribution.
The dynamic-app loading utilities (load / merge_settings, the
custom_app_registry context processor, and the dynamic_apps URL include) are
behavior-unchanged - only the import path moves from
airavata_django_portal_commons to django_airavata.commons, with settings.py,
urls.py, the package's internal self-imports, the requirements pi [...]
* fix(portal): use stdlib importlib.metadata in folded-in commons
The standalone airavata-django-portal-commons declared the third-party
importlib_metadata backport as a dependency, but the portal's requirements
do not. Now that commons lives in the portal, import entry_points from the
stdlib importlib.metadata instead - the selectable entry_points(group=...)
API is available there on the portal's Python 3.10+ baseline - so no
backport
dependency is reintroduced. Verified with `manage.py check` on a local dev
baseline.
---
CLAUDE.md | 3 +-
README.md | 3 -
airavata-django-portal-commons/.gitignore | 7 --
airavata-django-portal-commons/MANIFEST.in | 0
airavata-django-portal-commons/README.md | 111 ---------------------
airavata-django-portal-commons/pyproject.toml | 6 --
airavata-django-portal-commons/setup.cfg | 14 ---
airavata-django-portal-commons/setup.py | 3 -
.../django_airavata/commons}/__init__.py | 0
.../commons}/dynamic_apps/__init__.py | 2 +-
.../commons}/dynamic_apps/context_processors.py | 2 +-
.../django_airavata/commons}/dynamic_apps/urls.py | 2 +-
airavata-django-portal/django_airavata/settings.py | 4 +-
airavata-django-portal/django_airavata/urls.py | 2 +-
airavata-django-portal/requirements.txt | 1 -
15 files changed, 7 insertions(+), 153 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 564e66476..9a5c09a66 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -12,7 +12,6 @@ Monorepo of web portals, SDKs, and tools built on top of
Apache Airavata. Contai
|---------|-------|---------|
| `airavata-django-portal` | Django 3.2 + Vue 2 | Reference science gateway
(main portal) |
| `airavata-django-portal-sdk` | Python | Reusable library for custom Django
app extensions (PyPI) |
-| `airavata-django-portal-commons` | Python | Dynamic app loading and shared
utilities (PyPI) |
| `airavata-research-portal` | React 19 + Vite + TypeScript | CyberShuttle
research platform (newest) |
| `airavata-custos-portal` | Django + Vue 2 | Identity, group, and permissions
management UI |
| `airavata-mft-portal` | Django + Webpack | Managed File Transfer dashboard |
@@ -71,7 +70,7 @@ Each app under `django_airavata/apps/` is self-contained with
its own frontend:
- **Backend**: Django + DRF, Thrift-based Airavata client, Wagtail CMS for
page content
- **Frontend**: Vue 2 per app, webpack/Vue CLI builds, each app has colocated
`static/` with its own build config
-- **Dynamic apps**: Plugin-style extensions discovered via Python entry points
(powered by `airavata-django-portal-commons`)
+- **Dynamic apps**: Plugin-style extensions discovered via Python entry points
(powered by `django_airavata.commons`)
- **Web components**: Workspace app builds Vue components as reusable web
components
- **No business logic** — the portal is a rendering layer. All logic lives in
the Airavata server.
diff --git a/README.md b/README.md
index 4788074d0..1efb67a88 100644
--- a/README.md
+++ b/README.md
@@ -14,9 +14,6 @@ This repository contains the following sub-projects and
templates:
- **airavata-django-portal-sdk**
A pluggable SDK enabling custom Django-based science gateways with minimal
setup.
-- **airavata-django-portal-commons**
- Shared UI components and utilities used across Django-based portals.
-
### Starter Templates
- **airavata-cookiecutter-django-app**
diff --git a/airavata-django-portal-commons/.gitignore
b/airavata-django-portal-commons/.gitignore
deleted file mode 100644
index 4f6cd5fa1..000000000
--- a/airavata-django-portal-commons/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-venv
-*.egg-info
-*.pyc
-.vscode
-build
-dist
-*.egg
diff --git a/airavata-django-portal-commons/MANIFEST.in
b/airavata-django-portal-commons/MANIFEST.in
deleted file mode 100644
index e69de29bb..000000000
diff --git a/airavata-django-portal-commons/README.md
b/airavata-django-portal-commons/README.md
deleted file mode 100644
index 282c1129a..000000000
--- a/airavata-django-portal-commons/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Airavata Django Portal Commons
-
-Utilities for working with dynamically loaded Django apps.
-
-## Getting Started
-
-Install this package with pip
-
-```
-pip install airavata-django-portal-commons
-```
-
-### Dynamically loaded Django apps
-
-1. At the end of your Django server's settings.py file add
-
-```python
-import sys
-from airavata_django_portal_commons import dynamic_apps
-
-# Add any dynamic apps installed in the virtual environment
-dynamic_apps.load(INSTALLED_APPS)
-
-# (Optional) merge WEBPACK_LOADER settings from custom Django apps
-settings_module = sys.modules[__name__]
-dynamic_apps.merge_settings(settings_module)
-```
-
-- Note: if the dynamic Django app uses WEBPACK_LOADER, keep in mind that it is
- important that the version of
-
[django-webpack-loader](https://github.com/django-webpack/django-webpack-loader)
- and the version of webpack-bundle-tracker be compatible. If you're using
- django-webpack-loader prior to version 1.0 then a known good pair of versions
- is django-webpack-loader==0.6.0 and webpack-bundle-tracker==0.4.3.
-
-2. Also add
-
`'airavata_django_portal_commons.dynamic_apps.context_processors.custom_app_registry'`
- to the context_processors list:
-
-```python
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': ...
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- ...
-
'airavata_django_portal_commons.dynamic_apps.context_processors.custom_app_registry',
- ],
- },
- },
-]
-```
-
-3. In your urls.py file add the following to the urlpatterns
-
-```python
-urlpatterns = [
- # ...
- path('', include('airavata_django_portal_commons.dynamic_apps.urls')),
-]
-```
-
-## Creating a dynamically loaded Django app
-
-See
-https://apache-airavata-django-portal.readthedocs.io/en/latest/dev/custom_django_app/
-for the latest information.
-
-Note that by default the
-[cookiecutter
template](https://github.com/machristie/cookiecutter-airavata-django-app)
-registers Django apps under the entry_point group name of `airavata.djangoapp`,
-but you can change this. Just make sure that when you call `dynamic_apps.load`
-that you pass as the second argument the name of the entry_point group.
-
-## Developing
-
-### Making a new release
-
-1. Update the version in setup.cfg.
-2. Commit the update to setup.cfg.
-3. Tag the repo with the same version, with the format `v${version_number}`.
For
- example, if the version number in setup.cfg is "1.2" then tag the repo with
- "v1.2".
-
- ```
- VERSION=...
- git tag -m $VERSION $VERSION
- git push --follow-tags
- ```
-
-4. In a clean checkout
-
- ```
- cd /tmp/
- git clone /path/to/airavata-django-portal-commons/ -b $VERSION
- cd airavata-django-portal-commons
- python3 -m venv venv
- source venv/bin/activate
- python3 -m pip install --upgrade pip build
- python3 -m build
- ```
-
-5. Push to pypi.org. Optionally can push to test.pypi.org. See
- <https://packaging.python.org/tutorials/packaging-projects/> for more info.
-
- ```
- python3 -m pip install --upgrade twine
- python3 -m twine upload dist/*
- ```
diff --git a/airavata-django-portal-commons/pyproject.toml
b/airavata-django-portal-commons/pyproject.toml
deleted file mode 100644
index 374b58cbf..000000000
--- a/airavata-django-portal-commons/pyproject.toml
+++ /dev/null
@@ -1,6 +0,0 @@
-[build-system]
-requires = [
- "setuptools>=42",
- "wheel"
-]
-build-backend = "setuptools.build_meta"
diff --git a/airavata-django-portal-commons/setup.cfg
b/airavata-django-portal-commons/setup.cfg
deleted file mode 100644
index 4e82a46e5..000000000
--- a/airavata-django-portal-commons/setup.cfg
+++ /dev/null
@@ -1,14 +0,0 @@
-[metadata]
-name = airavata-django-portal-commons
-version = 1.0.3
-description = Utilities for working with dynamically loaded Django apps.
-long_description = file: README.md
-long_description_content_type = text/markdown
-
-[options]
-packages = find:
-# Include data files as specified in MANIFEST.in
-include_package_data = True
-install_requires =
- django
- importlib_metadata
diff --git a/airavata-django-portal-commons/setup.py
b/airavata-django-portal-commons/setup.py
deleted file mode 100644
index b908cbe55..000000000
--- a/airavata-django-portal-commons/setup.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import setuptools
-
-setuptools.setup()
diff --git
a/airavata-django-portal-commons/airavata_django_portal_commons/__init__.py
b/airavata-django-portal/django_airavata/commons/__init__.py
similarity index 100%
rename from
airavata-django-portal-commons/airavata_django_portal_commons/__init__.py
rename to airavata-django-portal/django_airavata/commons/__init__.py
diff --git
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/__init__.py
b/airavata-django-portal/django_airavata/commons/dynamic_apps/__init__.py
similarity index 97%
rename from
airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/__init__.py
rename to
airavata-django-portal/django_airavata/commons/dynamic_apps/__init__.py
index 1ba67e3c8..d0b9a8a1e 100644
---
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/__init__.py
+++ b/airavata-django-portal/django_airavata/commons/dynamic_apps/__init__.py
@@ -1,6 +1,6 @@
import logging
from importlib import import_module
-from importlib_metadata import entry_points
+from importlib.metadata import entry_points
# AppConfig instances from custom Django apps
diff --git
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/context_processors.py
b/airavata-django-portal/django_airavata/commons/dynamic_apps/context_processors.py
similarity index 98%
rename from
airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/context_processors.py
rename to
airavata-django-portal/django_airavata/commons/dynamic_apps/context_processors.py
index 438016553..f43cfe9f7 100644
---
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/context_processors.py
+++
b/airavata-django-portal/django_airavata/commons/dynamic_apps/context_processors.py
@@ -3,7 +3,7 @@ from importlib import import_module
import logging
import re
-from airavata_django_portal_commons import dynamic_apps
+from django_airavata.commons import dynamic_apps
logger = logging.getLogger(__name__)
diff --git
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/urls.py
b/airavata-django-portal/django_airavata/commons/dynamic_apps/urls.py
similarity index 88%
rename from
airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/urls.py
rename to airavata-django-portal/django_airavata/commons/dynamic_apps/urls.py
index 256a6f88c..6ce60020f 100644
---
a/airavata-django-portal-commons/airavata_django_portal_commons/dynamic_apps/urls.py
+++ b/airavata-django-portal/django_airavata/commons/dynamic_apps/urls.py
@@ -1,4 +1,4 @@
-from airavata_django_portal_commons import dynamic_apps
+from django_airavata.commons import dynamic_apps
from django.conf.urls import include
from django.urls import path
diff --git a/airavata-django-portal/django_airavata/settings.py
b/airavata-django-portal/django_airavata/settings.py
index df495996a..81de01b9b 100644
--- a/airavata-django-portal/django_airavata/settings.py
+++ b/airavata-django-portal/django_airavata/settings.py
@@ -13,7 +13,7 @@ https://docs.djangoproject.com/en/1.10/ref/settings/
import os
import sys
-from airavata_django_portal_commons import dynamic_apps
+from django_airavata.commons import dynamic_apps
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -118,7 +118,7 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django_airavata.context_processors.airavata_app_registry',
-
'airavata_django_portal_commons.dynamic_apps.context_processors.custom_app_registry',
+
'django_airavata.commons.dynamic_apps.context_processors.custom_app_registry',
'django_airavata.context_processors.get_notifications',
'django_airavata.context_processors.user_session_data',
'django_airavata.context_processors.google_analytics_tracking_id',
diff --git a/airavata-django-portal/django_airavata/urls.py
b/airavata-django-portal/django_airavata/urls.py
index 5c0dcf78d..5f6a043b8 100644
--- a/airavata-django-portal/django_airavata/urls.py
+++ b/airavata-django-portal/django_airavata/urls.py
@@ -41,7 +41,7 @@ urlpatterns = [
re_path(r'^403/', views.error403),
re_path(r'^404/', views.error404),
re_path(r'^500/', views.error500),
- path('', include('airavata_django_portal_commons.dynamic_apps.urls')),
+ path('', include('django_airavata.commons.dynamic_apps.urls')),
path('', include(wagtail_urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/airavata-django-portal/requirements.txt
b/airavata-django-portal/requirements.txt
index 2ef07015d..35109faeb 100644
--- a/airavata-django-portal/requirements.txt
+++ b/airavata-django-portal/requirements.txt
@@ -26,6 +26,5 @@ grpcio==1.53.2 ; python_version >= "3.7"
airavata-django-portal-sdk==1.8.4
airavata-python-sdk==2.2.7
-airavata-django-portal-commons==1.0.0
-e "."