You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ya...@apache.org on 2026/04/08 07:02:23 UTC
(airavata-portals) 13/21: style: apply ruff formatting, upgrade Python syntax to 3.12 patterns
This is an automated email from the ASF dual-hosted git repository.
yasith pushed a commit to branch feat/sdk-facade-migration
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git
commit 5e7ef97414f736b744690fcedf4d5e3a33728473
Author: yasithdev <ya...@icloud.com>
AuthorDate: Wed Apr 8 00:56:33 2026 -0500
style: apply ruff formatting, upgrade Python syntax to 3.12 patterns
---
.../django_airavata/app_config.py | 3 +-
.../django_airavata/apps/admin/admin.py | 1 -
.../django_airavata/apps/admin/apps.py | 93 +-
.../admin/management/commands/archive_user_data.py | 76 +-
.../management/commands/unarchive_user_data.py | 17 +-
.../apps/admin/migrations/0001_initial.py | 35 +-
.../django_airavata/apps/admin/tests.py | 1 -
.../django_airavata/apps/admin/urls.py | 25 +-
.../django_airavata/apps/admin/views.py | 43 +-
.../django_airavata/apps/api/admin.py | 5 +-
.../django_airavata/apps/api/apps.py | 6 +-
.../django_airavata/apps/api/authentication.py | 10 +-
.../django_airavata/apps/api/exceptions.py | 46 +-
.../django_airavata/apps/api/helpers.py | 55 +-
.../apps/api/migrations/0001_initial.py | 12 +-
.../0001_squashed_0004_auto_20190625_1938.py | 35 +-
.../apps/api/migrations/0002_auto_20190513_2037.py | 17 +-
.../apps/api/migrations/0002_auto_20190711_1438.py | 19 +-
.../apps/api/migrations/0003_auto_20190625_1926.py | 9 +-
.../apps/api/migrations/0003_auto_20190716_1549.py | 28 +-
.../apps/api/migrations/0004_auto_20190625_1938.py | 13 +-
.../apps/api/migrations/0004_auto_20191112_2134.py | 17 +-
.../apps/api/migrations/0005_delete_user_files.py | 7 +-
...template_applicationtemplatecontextprocessor.py | 48 +-
.../api/migrations/0007_applicationsettings.py | 11 +-
.../api/migrations/0007_notificationextension.py | 13 +-
.../api/migrations/0008_merge_20220601_1951.py | 8 +-
...icationsettings_queue_settings_calculator_id.py | 7 +-
.../django_airavata/apps/api/models.py | 21 +-
.../django_airavata/apps/api/output_views.py | 216 +-
.../django_airavata/apps/api/proto_utils.py | 112 +-
.../django_airavata/apps/api/queue_settings.py | 6 +-
.../django_airavata/apps/api/serializers.py | 1112 ++--
.../django_airavata/apps/api/signals.py | 6 +-
.../django_airavata/apps/api/tests/test_views.py | 276 +-
.../django_airavata/apps/api/tus.py | 16 +-
.../django_airavata/apps/api/urls.py | 165 +-
.../django_airavata/apps/api/view_utils.py | 81 +-
.../django_airavata/apps/api/views.py | 1493 +++---
.../django_airavata/apps/auth/apps.py | 4 +-
.../django_airavata/apps/auth/backends.py | 202 +-
.../django_airavata/apps/auth/forms.py | 136 +-
.../django_airavata/apps/auth/iam_admin_client.py | 59 +-
.../django_airavata/apps/auth/middleware.py | 70 +-
.../apps/auth/migrations/0001_initial.py | 21 +-
.../apps/auth/migrations/0002_emailtemplate.py | 24 +-
.../migrations/0003_default_email_templates.py | 22 +-
.../auth/migrations/0004_password_reset_request.py | 40 +-
.../auth/migrations/0005_auto_20191211_2011.py | 29 +-
.../auth/migrations/0006_emailverification_next.py | 9 +-
.../auth/migrations/0007_auto_20200917_1610.py | 40 +-
.../auth/migrations/0008_auto_20210422_1838.py | 39 +-
.../0009_alter_emailverification_next.py | 7 +-
.../auth/migrations/0009_auto_20210625_1725.py | 38 +-
.../0010_userprofile_username_initialized.py | 7 +-
.../0011_remove_userprofile_username_locked.py | 7 +-
.../auth/migrations/0012_merge_20211210_2041.py | 8 +-
.../auth/migrations/0013_auto_20220118_1650.py | 7 +-
.../auth/migrations/0014_auto_20220217_2255.py | 13 +-
...ld_extendeduserprofilefieldlink_extendeduser.py | 186 +-
.../auth/migrations/0015_auto_20220329_1708.py | 126 +-
.../0016_extendeduserprofilefield_required.py | 7 +-
.../auth/migrations/0017_auto_20220616_1831.py | 10 +-
...4_auto_20220217_2255_0017_auto_20220616_1831.py | 8 +-
.../auth/migrations/0019_auto_20221118_1323.py | 32 +-
.../django_airavata/apps/auth/models.py | 211 +-
.../django_airavata/apps/auth/serializers.py | 319 +-
.../django_airavata/apps/auth/signals.py | 38 +-
.../apps/auth/tests/test_backends.py | 81 +-
.../apps/auth/tests/test_middleware.py | 27 +-
.../django_airavata/apps/auth/tests/test_models.py | 281 +-
.../apps/auth/tests/test_signals.py | 55 +-
.../django_airavata/apps/auth/tests/test_views.py | 196 +-
.../django_airavata/apps/auth/urls.py | 59 +-
.../django_airavata/apps/auth/utils.py | 168 +-
.../django_airavata/apps/auth/views.py | 654 ++-
.../django_airavata/apps/dataparsers/admin.py | 1 -
.../django_airavata/apps/dataparsers/apps.py | 18 +-
.../django_airavata/apps/dataparsers/tests.py | 1 -
.../django_airavata/apps/dataparsers/urls.py | 12 +-
.../django_airavata/apps/dataparsers/views.py | 46 +-
.../django_airavata/apps/groups/admin.py | 1 -
.../django_airavata/apps/groups/apps.py | 16 +-
.../django_airavata/apps/groups/forms.py | 40 +-
.../django_airavata/apps/groups/models.py | 1 -
.../django_airavata/apps/groups/tests.py | 1 -
.../django_airavata/apps/groups/urls.py | 9 +-
.../django_airavata/apps/groups/views.py | 48 +-
.../django_airavata/apps/workspace/admin.py | 1 -
.../django_airavata/apps/workspace/apps.py | 42 +-
.../apps/workspace/migrations/0001_initial.py | 14 +-
.../workspace/migrations/0002_delete_user_files.py | 7 +-
.../django_airavata/apps/workspace/models.py | 1 -
.../django_airavata/apps/workspace/tests.py | 1 -
.../django_airavata/apps/workspace/urls.py | 25 +-
.../django_airavata/apps/workspace/views.py | 193 +-
.../django_airavata/context_processors.py | 99 +-
.../django_airavata/dynamic_apps/__init__.py | 19 +-
.../dynamic_apps/context_processors.py | 22 +-
.../django_airavata/dynamic_apps/urls.py | 7 +-
.../django_airavata/middleware.py | 14 +-
.../django_airavata/proto_compat.py | 25 +-
airavata-django-portal/django_airavata/settings.py | 689 ++-
.../django_airavata/uploadhandler.py | 13 +-
airavata-django-portal/django_airavata/urls.py | 37 +-
airavata-django-portal/django_airavata/utils.py | 5 +-
airavata-django-portal/django_airavata/views.py | 63 +-
.../django_airavata/wagtailapps/base/apps.py | 6 +-
.../django_airavata/wagtailapps/base/blocks.py | 522 +-
.../wagtailapps/base/image_formats.py | 10 +-
.../commands/fix_page_revision_content_type.py | 5 +-
.../base/management/commands/load_cms_data.py | 35 +-
.../base/management/commands/set_wagtail_site.py | 26 +-
.../wagtailapps/base/migrations/0001_initial.py | 2117 +++++++-
.../base/migrations/0002_auto_20180410_2236.py | 1621 +++++-
.../base/migrations/0003_navextra_nav_logo_link.py | 11 +-
.../base/migrations/0004_auto_20180414_1852.py | 1636 +++++-
...ewayhomepage_rowcybergatewayhomepagerelation.py | 1218 ++++-
.../base/migrations/0006_auto_20180415_0040.py | 2857 +++++++++-
.../base/migrations/0007_auto_20180415_0045.py | 2722 +++++++++-
.../0008_cybergatewayhomepage_contact.py | 550 +-
.../base/migrations/0009_auto_20180415_0141.py | 583 ++-
.../base/migrations/0010_auto_20180415_0142.py | 38 +-
.../base/migrations/0011_auto_20180415_0143.py | 38 +-
.../base/migrations/0012_auto_20180415_0149.py | 49 +-
.../base/migrations/0013_auto_20180417_2034.py | 3361 +++++++++++-
.../base/migrations/0014_homepage_show_footer.py | 16 +-
...0015_cybergatewayhomepage_show_announcements.py | 16 +-
.../base/migrations/0016_auto_20180427_1755.py | 20 +-
.../migrations/0017_gatewayicon_gatewaytitle.py | 42 +-
.../base/migrations/0018_auto_20181010_0136.py | 265 +-
.../base/migrations/0019_auto_20181025_1522.py | 3553 ++++++++++++-
.../base/migrations/0020_auto_20190417_1949.py | 3852 +++++++++++++-
.../base/migrations/0021_auto_20191105_2053.py | 56 +-
.../base/migrations/0022_auto_20191106_1542.py | 3783 +++++++++++++-
.../0023_rowblankpagerelation_container.py | 75 +-
.../base/migrations/0024_auto_20200624_1925.py | 3817 +++++++++++++-
.../base/migrations/0025_auto_20210319_2247.py | 320 +-
.../base/migrations/0026_auto_20210923_2212.py | 5453 +++++++++++++++++++-
.../django_airavata/wagtailapps/base/models.py | 666 ++-
.../base/templatetags/navigation_tags.py | 100 +-
.../base/tests/management/test_set_wagtail_site.py | 37 +-
.../wagtailapps/base/wagtail_hooks.py | 49 +-
airavata-django-portal/django_airavata/wsgi.py | 4 +-
airavata-django-portal/pyproject.toml | 23 +-
145 files changed, 42569 insertions(+), 5858 deletions(-)
diff --git a/airavata-django-portal/django_airavata/app_config.py b/airavata-django-portal/django_airavata/app_config.py
index 718e851f4..2a977f85f 100644
--- a/airavata-django-portal/django_airavata/app_config.py
+++ b/airavata-django-portal/django_airavata/app_config.py
@@ -1,4 +1,3 @@
-
import logging
from abc import ABC, abstractmethod
from importlib import import_module
@@ -44,7 +43,7 @@ class AiravataAppConfig(AppConfig, ABC):
def get_url_app_name(app_config):
"""Return the urls namespace for the given AppConfig instance."""
urls = get_app_urls(app_config)
- return getattr(urls, 'app_name', None)
+ return getattr(urls, "app_name", None)
def get_app_urls(app_config):
diff --git a/airavata-django-portal/django_airavata/apps/admin/admin.py b/airavata-django-portal/django_airavata/apps/admin/admin.py
index b97a94f64..846f6b406 100644
--- a/airavata-django-portal/django_airavata/apps/admin/admin.py
+++ b/airavata-django-portal/django_airavata/apps/admin/admin.py
@@ -1,2 +1 @@
-
# Register your models here.
diff --git a/airavata-django-portal/django_airavata/apps/admin/apps.py b/airavata-django-portal/django_airavata/apps/admin/apps.py
index a9a664203..a686ad587 100644
--- a/airavata-django-portal/django_airavata/apps/admin/apps.py
+++ b/airavata-django-portal/django_airavata/apps/admin/apps.py
@@ -1,76 +1,69 @@
-
from django_airavata.app_config import AiravataAppConfig
class AdminConfig(AiravataAppConfig):
- name = 'django_airavata.apps.admin'
- label = 'django_airavata_admin'
- verbose_name = 'Settings'
+ name = "django_airavata.apps.admin"
+ label = "django_airavata_admin"
+ verbose_name = "Settings"
app_order = 100
- url_home = 'django_airavata_admin:home'
- fa_icon_class = 'fa-cog'
+ url_home = "django_airavata_admin:home"
+ fa_icon_class = "fa-cog"
app_description = """
Configure and share resources with other users.
"""
nav = [
{
- 'label': 'Application Catalog',
- 'icon': 'fa fa-cogs',
- 'url': 'django_airavata_admin:app_catalog',
- 'active_prefixes': ['applications'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin),
+ "label": "Application Catalog",
+ "icon": "fa fa-cogs",
+ "url": "django_airavata_admin:app_catalog",
+ "active_prefixes": ["applications"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
{
- 'label': 'Manage Users',
- 'icon': 'fa fa-users',
- 'url': 'django_airavata_admin:users',
- 'active_prefixes': ['users', 'extended-user-profile'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin),
+ "label": "Manage Users",
+ "icon": "fa fa-users",
+ "url": "django_airavata_admin:users",
+ "active_prefixes": ["users", "extended-user-profile"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
{
- 'label': 'Experiment Statistics',
- 'icon': 'fa fa-chart-bar',
- 'url': 'django_airavata_admin:experiment-statistics',
- 'active_prefixes': ['experiment-statistics'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin),
+ "label": "Experiment Statistics",
+ "icon": "fa fa-chart-bar",
+ "url": "django_airavata_admin:experiment-statistics",
+ "active_prefixes": ["experiment-statistics"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
{
- 'label': 'Credential Store',
- 'icon': 'fa fa-lock',
- 'url': 'django_airavata_admin:credential_store',
- 'active_prefixes': ['credentials']
+ "label": "Credential Store",
+ "icon": "fa fa-lock",
+ "url": "django_airavata_admin:credential_store",
+ "active_prefixes": ["credentials"],
},
{
- 'label': 'Group Resource Profile',
- 'icon': 'fa fa-server',
- 'url': 'django_airavata_admin:group_resource_profile',
- 'active_prefixes': ['group-resource-profiles']
+ "label": "Group Resource Profile",
+ "icon": "fa fa-server",
+ "url": "django_airavata_admin:group_resource_profile",
+ "active_prefixes": ["group-resource-profiles"],
},
{
- 'label': 'Gateway Resource Profile',
- 'icon': 'fa fa-tasks',
- 'url': 'django_airavata_admin:gateway_resource_profile',
- 'active_prefixes': ['gateway-resource-profile'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin)
+ "label": "Gateway Resource Profile",
+ "icon": "fa fa-tasks",
+ "url": "django_airavata_admin:gateway_resource_profile",
+ "active_prefixes": ["gateway-resource-profile"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
{
- 'label': 'Manage Notices',
- 'icon': 'fa fa-bell',
- 'url': 'django_airavata_admin:notices',
- 'active_prefixes': ['notices'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin)
+ "label": "Manage Notices",
+ "icon": "fa fa-bell",
+ "url": "django_airavata_admin:notices",
+ "active_prefixes": ["notices"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
{
- 'label': 'Developer Console',
- 'icon': 'fa fa-code',
- 'url': 'django_airavata_admin:developers',
- 'active_prefixes': ['developers'],
- 'enabled': lambda req: (req.is_gateway_admin or
- req.is_read_only_gateway_admin)
+ "label": "Developer Console",
+ "icon": "fa fa-code",
+ "url": "django_airavata_admin:developers",
+ "active_prefixes": ["developers"],
+ "enabled": lambda req: req.is_gateway_admin or req.is_read_only_gateway_admin,
},
]
diff --git a/airavata-django-portal/django_airavata/apps/admin/management/commands/archive_user_data.py b/airavata-django-portal/django_airavata/apps/admin/management/commands/archive_user_data.py
index bab8be533..6495e3d80 100644
--- a/airavata-django-portal/django_airavata/apps/admin/management/commands/archive_user_data.py
+++ b/airavata-django-portal/django_airavata/apps/admin/management/commands/archive_user_data.py
@@ -4,8 +4,8 @@ import os
import shutil
import tarfile
import tempfile
+from collections.abc import Iterator
from pathlib import Path
-from typing import Iterator
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
@@ -21,21 +21,27 @@ class Command(BaseCommand):
help = "Create an archive of user data directories and optionally clean them up"
def add_arguments(self, parser):
- parser.add_argument('--dry-run',
- action='store_true',
- help="Print the list of files/directories that would be archived then exit",
- default=False)
- parser.add_argument('--max-age',
- help="Max age of files/directories in days. Any that are older will be archived.",
- type=int,
- default=getattr(settings, "GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS", None))
+ parser.add_argument(
+ "--dry-run",
+ action="store_true",
+ help="Print the list of files/directories that would be archived then exit",
+ default=False,
+ )
+ parser.add_argument(
+ "--max-age",
+ help="Max age of files/directories in days. Any that are older will be archived.",
+ type=int,
+ default=getattr(settings, "GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS", None),
+ )
def handle(self, *args, **options):
try:
# Take --max-age from the command line first, then from the setting
- max_age_setting = options['max_age']
+ max_age_setting = options["max_age"]
if max_age_setting is None:
- raise CommandError("Setting GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS is not configured and --max-age option missing.")
+ raise CommandError(
+ "Setting GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS is not configured and --max-age option missing."
+ )
max_age = timezone.now() - datetime.timedelta(days=max_age_setting)
entries_to_archive = self.get_archive_entries(older_than=max_age)
@@ -49,7 +55,7 @@ class Command(BaseCommand):
archive_list_filename = f"{archive_basename}.txt"
archive_list_filepath = os.path.join(tmpdir, archive_list_filename)
entry_count = 0
- with open(archive_list_filepath, "wt") as archive_list_file:
+ with open(archive_list_filepath, "w") as archive_list_file:
for entry in entries_to_archive:
entry_count = entry_count + 1
archive_list_file.write(f"{entry.path}\n")
@@ -60,7 +66,7 @@ class Command(BaseCommand):
return
# if dry run, just print file and exit
- if options['dry_run']:
+ if options["dry_run"]:
self.stdout.write(f"DRY RUN: printing {archive_list_filename}, then exiting")
with open(os.path.join(tmpdir, archive_list_filename)) as archive_list_file:
for line in archive_list_file:
@@ -76,9 +82,13 @@ class Command(BaseCommand):
for line in archive_list_file:
tarball.add(line.strip())
- minimum_bytes_size = settings.GATEWAY_USER_DATA_ARCHIVE_MINIMUM_ARCHIVE_SIZE_GB * 1024 ** 3
+ minimum_bytes_size = settings.GATEWAY_USER_DATA_ARCHIVE_MINIMUM_ARCHIVE_SIZE_GB * 1024**3
if os.stat(archive_tarball_filepath).st_size < minimum_bytes_size:
- self.stdout.write(self.style.WARNING("Aborting, archive size is not large enough to proceed (size less than GATEWAY_USER_DATA_ARCHIVE_MINIMUM_ARCHIVE_SIZE_GB)"))
+ self.stdout.write(
+ self.style.WARNING(
+ "Aborting, archive size is not large enough to proceed (size less than GATEWAY_USER_DATA_ARCHIVE_MINIMUM_ARCHIVE_SIZE_GB)"
+ )
+ )
# Exit early
return
@@ -86,7 +96,9 @@ class Command(BaseCommand):
shutil.move(archive_list_filepath, archive_directory / archive_list_filename)
shutil.move(archive_tarball_filepath, archive_directory / archive_tarball_filename)
- self.stdout.write(self.style.SUCCESS(f"Created tarball: {archive_directory / archive_tarball_filename}"))
+ self.stdout.write(
+ self.style.SUCCESS(f"Created tarball: {archive_directory / archive_tarball_filename}")
+ )
# Now we'll remove any files/directories that were in the archive
# and create database records for the archive
@@ -96,7 +108,8 @@ class Command(BaseCommand):
user_data_archive = models.UserDataArchive(
archive_name=archive_tarball_filename,
archive_path=os.fspath(archive_directory / archive_tarball_filename),
- max_modification_time=max_age)
+ max_modification_time=max_age,
+ )
user_data_archive.save()
# delete archived entries
with open(archive_directory / archive_list_filename) as archive_list_file:
@@ -107,15 +120,26 @@ class Command(BaseCommand):
elif os.path.isdir(archive_path):
shutil.rmtree(archive_path)
else:
- self.stdout.write(self.style.WARNING(f"Cannot delete {archive_path} as it is neither a file nor directory, perhaps was already removed"))
- archive_entry = models.UserDataArchiveEntry(user_data_archive=user_data_archive, entry_path=archive_path)
+ self.stdout.write(
+ self.style.WARNING(
+ f"Cannot delete {archive_path} as it is neither a file nor directory, perhaps was already removed"
+ )
+ )
+ archive_entry = models.UserDataArchiveEntry(
+ user_data_archive=user_data_archive, entry_path=archive_path
+ )
archive_entry.save()
except Exception as e:
self.stdout.write(self.style.ERROR("Failed while deleting archived data, attempting to roll back"))
with tarfile.open(archive_directory / archive_tarball_filename) as tf:
tf.extractall(path="/")
- logger.exception(f"[archive_user_data] Failed to delete archived files, but unarchived from tarball {archive_directory / archive_tarball_filename}", exc_info=e)
- raise CommandError(f"Failed to delete archived files, but unarchived from tarball {archive_directory / archive_tarball_filename}") from e
+ logger.exception(
+ f"[archive_user_data] Failed to delete archived files, but unarchived from tarball {archive_directory / archive_tarball_filename}",
+ exc_info=e,
+ )
+ raise CommandError(
+ f"Failed to delete archived files, but unarchived from tarball {archive_directory / archive_tarball_filename}"
+ ) from e
self.stdout.write(self.style.SUCCESS("Successfully removed archived user data"))
except CommandError:
@@ -125,7 +149,7 @@ class Command(BaseCommand):
def get_archive_entries(self, older_than: datetime.datetime) -> Iterator[os.DirEntry]:
- GATEWAY_USER_DIR = settings.USER_STORAGES['default']['OPTIONS']['directory']
+ GATEWAY_USER_DIR = settings.USER_STORAGES["default"]["OPTIONS"]["directory"]
with os.scandir(GATEWAY_USER_DIR) as user_dirs:
for user_dir_entry in user_dirs:
@@ -138,10 +162,12 @@ class Command(BaseCommand):
with os.scandir(user_dir_entry.path) as project_dirs:
for project_dir_entry in project_dirs:
yield from self._scan_project_dir_for_archive_entries(
- project_dir_entry=project_dir_entry,
- older_than=older_than)
+ project_dir_entry=project_dir_entry, older_than=older_than
+ )
- def _scan_project_dir_for_archive_entries(self, project_dir_entry: os.DirEntry, older_than: datetime.datetime) -> Iterator[os.DirEntry]:
+ def _scan_project_dir_for_archive_entries(
+ self, project_dir_entry: os.DirEntry, older_than: datetime.datetime
+ ) -> Iterator[os.DirEntry]:
# archive files here but not directories
if project_dir_entry.is_file() and project_dir_entry.stat().st_mtime < older_than.timestamp():
yield project_dir_entry
diff --git a/airavata-django-portal/django_airavata/apps/admin/management/commands/unarchive_user_data.py b/airavata-django-portal/django_airavata/apps/admin/management/commands/unarchive_user_data.py
index dddb35b0d..3ba93d789 100644
--- a/airavata-django-portal/django_airavata/apps/admin/management/commands/unarchive_user_data.py
+++ b/airavata-django-portal/django_airavata/apps/admin/management/commands/unarchive_user_data.py
@@ -1,4 +1,3 @@
-
import os
import pathlib
import tarfile
@@ -12,11 +11,15 @@ class Command(BaseCommand):
help = "Unarchive a user data archive"
def add_arguments(self, parser):
- parser.add_argument('archive_file',
- help="Archive file (ending in .tgz) that was created by the archive_user_data")
- parser.add_argument('-m', '--reset-modification',
- help="Set modification timestamp to current time for all entries in archive",
- action="store_true")
+ parser.add_argument(
+ "archive_file", help="Archive file (ending in .tgz) that was created by the archive_user_data"
+ )
+ parser.add_argument(
+ "-m",
+ "--reset-modification",
+ help="Set modification timestamp to current time for all entries in archive",
+ action="store_true",
+ )
def handle(self, *args, **options):
with tarfile.open(options["archive_file"]) as tf:
@@ -32,7 +35,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.ERROR(f"Could not find UserDataArchive database record for {archive_name}"))
if options["reset_modification"]:
- root = pathlib.Path('/')
+ root = pathlib.Path("/")
with tarfile.open(options["archive_file"]) as tf:
for tarinfo in tf:
path = root / tarinfo.path
diff --git a/airavata-django-portal/django_airavata/apps/admin/migrations/0001_initial.py b/airavata-django-portal/django_airavata/apps/admin/migrations/0001_initial.py
index 6223ce73c..8f49ad459 100644
--- a/airavata-django-portal/django_airavata/apps/admin/migrations/0001_initial.py
+++ b/airavata-django-portal/django_airavata/apps/admin/migrations/0001_initial.py
@@ -1,35 +1,38 @@
# Generated by Django 3.2.18 on 2023-04-17 14:10
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='UserDataArchive',
+ name="UserDataArchive",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
- ('archive_name', models.CharField(max_length=255)),
- ('archive_path', models.TextField()),
- ('rolled_back', models.BooleanField(default=False)),
- ('max_modification_time', models.DateTimeField()),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
+ ("archive_name", models.CharField(max_length=255)),
+ ("archive_path", models.TextField()),
+ ("rolled_back", models.BooleanField(default=False)),
+ ("max_modification_time", models.DateTimeField()),
],
),
migrations.CreateModel(
- name='UserDataArchiveEntry',
+ name="UserDataArchiveEntry",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('entry_path', models.TextField()),
- ('user_data_archive', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='django_airavata_admin.userdataarchive')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("entry_path", models.TextField()),
+ (
+ "user_data_archive",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE, to="django_airavata_admin.userdataarchive"
+ ),
+ ),
],
),
]
diff --git a/airavata-django-portal/django_airavata/apps/admin/tests.py b/airavata-django-portal/django_airavata/apps/admin/tests.py
index 492902048..a39b155ac 100644
--- a/airavata-django-portal/django_airavata/apps/admin/tests.py
+++ b/airavata-django-portal/django_airavata/apps/admin/tests.py
@@ -1,2 +1 @@
-
# Create your tests here.
diff --git a/airavata-django-portal/django_airavata/apps/admin/urls.py b/airavata-django-portal/django_airavata/apps/admin/urls.py
index f52672714..a16907aed 100644
--- a/airavata-django-portal/django_airavata/apps/admin/urls.py
+++ b/airavata-django-portal/django_airavata/apps/admin/urls.py
@@ -2,19 +2,16 @@ from django.urls import path, re_path
from . import views
-app_name = 'django_airavata_admin'
+app_name = "django_airavata_admin"
urlpatterns = [
- re_path(r'^$', views.home, name='home'),
- re_path(r'^applications/', views.app_catalog, name='app_catalog'),
- re_path(r'^credentials/', views.credential_store, name='credential_store'),
- re_path(r'^experiment-statistics/', views.experiment_statistics,
- name="experiment-statistics"),
- re_path(r'^group-resource-profiles/', views.group_resource_profile,
- name='group_resource_profile'),
- re_path(r'^gateway-resource-profile/', views.gateway_resource_profile,
- name='gateway_resource_profile'),
- re_path(r'^notices/', views.notices, name='notices'),
- re_path(r'^users/', views.users, name='users'),
- path('extended-user-profile/', views.extended_user_profile, name="extended_user_profile"),
- path('developers/', views.developers, name='developers'),
+ re_path(r"^$", views.home, name="home"),
+ re_path(r"^applications/", views.app_catalog, name="app_catalog"),
+ re_path(r"^credentials/", views.credential_store, name="credential_store"),
+ re_path(r"^experiment-statistics/", views.experiment_statistics, name="experiment-statistics"),
+ re_path(r"^group-resource-profiles/", views.group_resource_profile, name="group_resource_profile"),
+ re_path(r"^gateway-resource-profile/", views.gateway_resource_profile, name="gateway_resource_profile"),
+ re_path(r"^notices/", views.notices, name="notices"),
+ re_path(r"^users/", views.users, name="users"),
+ path("extended-user-profile/", views.extended_user_profile, name="extended_user_profile"),
+ path("developers/", views.developers, name="developers"),
]
diff --git a/airavata-django-portal/django_airavata/apps/admin/views.py b/airavata-django-portal/django_airavata/apps/admin/views.py
index e8be1042c..6c37bfb36 100644
--- a/airavata-django-portal/django_airavata/apps/admin/views.py
+++ b/airavata-django-portal/django_airavata/apps/admin/views.py
@@ -6,66 +6,65 @@ from django.urls import reverse
@login_required
def home(request):
if request.is_gateway_admin or request.is_read_only_gateway_admin:
- return redirect(reverse('django_airavata_admin:app_catalog'))
+ return redirect(reverse("django_airavata_admin:app_catalog"))
else:
- return redirect(
- reverse('django_airavata_admin:group_resource_profile'))
+ return redirect(reverse("django_airavata_admin:group_resource_profile"))
@login_required
def app_catalog(request):
- request.active_nav_item = 'app_catalog'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "app_catalog"
+ return render(request, "admin/admin_base.html")
@login_required
def credential_store(request):
- request.active_nav_item = 'credential_store'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "credential_store"
+ return render(request, "admin/admin_base.html")
@login_required
def compute_resource(request):
- return render(request, 'admin/compute_resource.html')
+ return render(request, "admin/compute_resource.html")
@login_required
def group_resource_profile(request):
- request.active_nav_item = 'group_resource_profile'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "group_resource_profile"
+ return render(request, "admin/admin_base.html")
@login_required
def gateway_resource_profile(request):
- request.active_nav_item = 'gateway_resource_profile'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "gateway_resource_profile"
+ return render(request, "admin/admin_base.html")
@login_required
def notices(request):
- request.active_nav_item = 'notices'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "notices"
+ return render(request, "admin/admin_base.html")
@login_required
def users(request):
- request.active_nav_item = 'users'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "users"
+ return render(request, "admin/admin_base.html")
@login_required
def extended_user_profile(request):
- request.active_nav_item = 'users'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "users"
+ return render(request, "admin/admin_base.html")
@login_required
def experiment_statistics(request):
- request.active_nav_item = 'experiment-statistics'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "experiment-statistics"
+ return render(request, "admin/admin_base.html")
@login_required
def developers(request):
- request.active_nav_item = 'developers'
- return render(request, 'admin/admin_base.html')
+ request.active_nav_item = "developers"
+ return render(request, "admin/admin_base.html")
diff --git a/airavata-django-portal/django_airavata/apps/api/admin.py b/airavata-django-portal/django_airavata/apps/api/admin.py
index a5d03645c..a6174c060 100644
--- a/airavata-django-portal/django_airavata/apps/api/admin.py
+++ b/airavata-django-portal/django_airavata/apps/api/admin.py
@@ -1,4 +1,3 @@
-
# Register your models here.
from django.contrib import admin
@@ -12,8 +11,8 @@ class ApplicationTemplateContextProcessorInline(admin.StackedInline):
class ApplicationTemplateAdmin(admin.ModelAdmin):
- fields = ['application_module_id', 'template_path']
- list_display = ['application_module_id', 'template_path', 'updated_by', 'updated']
+ fields = ["application_module_id", "template_path"]
+ list_display = ["application_module_id", "template_path", "updated_by", "updated"]
inlines = [ApplicationTemplateContextProcessorInline]
def save_model(self, request, obj, form, change):
diff --git a/airavata-django-portal/django_airavata/apps/api/apps.py b/airavata-django-portal/django_airavata/apps/api/apps.py
index b95d88e47..22e58d435 100644
--- a/airavata-django-portal/django_airavata/apps/api/apps.py
+++ b/airavata-django-portal/django_airavata/apps/api/apps.py
@@ -3,13 +3,13 @@ from pkg_resources import iter_entry_points
class ApiConfig(AppConfig):
- name = 'django_airavata.apps.api'
- label = 'django_airavata_api'
+ name = "django_airavata.apps.api"
+ label = "django_airavata_api"
def ready(self):
from . import signals # noqa
from . import output_views
# Load and create instances of each output view provider
- for entry_point in iter_entry_points(group='airavata.output_view_providers'):
+ for entry_point in iter_entry_points(group="airavata.output_view_providers"):
output_views.OUTPUT_VIEW_PROVIDERS[entry_point.name] = entry_point.load()()
diff --git a/airavata-django-portal/django_airavata/apps/api/authentication.py b/airavata-django-portal/django_airavata/apps/api/authentication.py
index 2cf95e4d6..7c56f3efd 100644
--- a/airavata-django-portal/django_airavata/apps/api/authentication.py
+++ b/airavata-django-portal/django_airavata/apps/api/authentication.py
@@ -12,13 +12,12 @@ logger = logging.getLogger(__name__)
class OAuthAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
- if 'HTTP_AUTHORIZATION' in request.META:
+ if "HTTP_AUTHORIZATION" in request.META:
try:
user = authenticate(request=request)
if user is None:
- raise exceptions.AuthenticationFailed(
- "Token failed to authenticate")
- _, token = request.META.get('HTTP_AUTHORIZATION').split()
+ raise exceptions.AuthenticationFailed("Token failed to authenticate")
+ _, token = request.META.get("HTTP_AUTHORIZATION").split()
logger.debug(f"OAuthAuthentication authenticated user {user}")
# Set request attributes that are normally set by middleware
@@ -27,7 +26,6 @@ class OAuthAuthentication(authentication.BaseAuthentication):
set_admin_group_attributes(request)
return (user, token)
except Exception as e:
- raise exceptions.AuthenticationFailed(
- "Token failed to authenticate") from e
+ raise exceptions.AuthenticationFailed("Token failed to authenticate") from e
else:
return None
diff --git a/airavata-django-portal/django_airavata/apps/api/exceptions.py b/airavata-django-portal/django_airavata/apps/api/exceptions.py
index f4645d975..20e581fbb 100644
--- a/airavata-django-portal/django_airavata/apps/api/exceptions.py
+++ b/airavata-django-portal/django_airavata/apps/api/exceptions.py
@@ -3,11 +3,11 @@ import sys
from django.core.exceptions import ObjectDoesNotExist
from django.http import JsonResponse
+from grpc import RpcError, StatusCode
from rest_framework import status
from rest_framework.exceptions import NotAuthenticated
from rest_framework.response import Response
from rest_framework.views import exception_handler
-from grpc import RpcError, StatusCode
log = logging.getLogger(__name__)
@@ -18,56 +18,44 @@ def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if isinstance(exc, RpcError):
- code = exc.code() if hasattr(exc, 'code') else None
+ code = exc.code() if hasattr(exc, "code") else None
if code == StatusCode.PERMISSION_DENIED:
log.warning("gRPC PermissionDenied", exc_info=exc)
- return Response(
- {'detail': str(exc)},
- status=status.HTTP_403_FORBIDDEN)
+ return Response({"detail": str(exc)}, status=status.HTTP_403_FORBIDDEN)
elif code == StatusCode.NOT_FOUND:
log.warning("gRPC NotFound", exc_info=exc)
- return Response(
- {'detail': str(exc)},
- status=status.HTTP_404_NOT_FOUND)
+ return Response({"detail": str(exc)}, status=status.HTTP_404_NOT_FOUND)
elif code == StatusCode.UNAVAILABLE:
log.warning("gRPC Unavailable (API server down)", exc_info=exc)
- return Response(
- {'detail': str(exc), 'apiServerDown': True},
- status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ return Response({"detail": str(exc), "apiServerDown": True}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
else:
- log.error("gRPC error", exc_info=exc, extra={'request': context['request']})
- return Response(
- {'detail': str(exc)},
- status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ log.error("gRPC error", exc_info=exc, extra={"request": context["request"]})
+ return Response({"detail": str(exc)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if isinstance(exc, ObjectDoesNotExist):
log.warning("ObjectDoesNotExist", exc_info=exc)
- return Response(
- {'detail': str(exc)},
- status=status.HTTP_404_NOT_FOUND)
+ return Response({"detail": str(exc)}, status=status.HTTP_404_NOT_FOUND)
if isinstance(exc, NotAuthenticated):
log.debug("NotAuthenticated", exc_info=exc)
if response is not None:
- response.data['is_authenticated'] = False
+ response.data["is_authenticated"] = False
if isinstance(exc, UnicodeEncodeError):
fse = sys.getfilesystemencoding()
- if fse != 'utf-8':
- log.error(f"filesystem encoding is {fse}, not 'utf-8'. File paths with Unicode characters will produce errors.")
+ if fse != "utf-8":
+ log.error(
+ f"filesystem encoding is {fse}, not 'utf-8'. File paths with Unicode characters will produce errors."
+ )
# Generic handler
if response is None:
- log.error("API exception", exc_info=exc, extra={'request': context['request']})
- return Response(
- {'detail': str(exc)},
- status=status.HTTP_500_INTERNAL_SERVER_ERROR
- )
+ log.error("API exception", exc_info=exc, extra={"request": context["request"]})
+ return Response({"detail": str(exc)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return response
# For non-Django REST Framework error responses
-def generic_json_exception_response(
- exc, status=status.HTTP_500_INTERNAL_SERVER_ERROR):
- return JsonResponse({'detail': str(exc)}, status=status)
+def generic_json_exception_response(exc, status=status.HTTP_500_INTERNAL_SERVER_ERROR):
+ return JsonResponse({"detail": str(exc)}, status=status)
diff --git a/airavata-django-portal/django_airavata/apps/api/helpers.py b/airavata-django-portal/django_airavata/apps/api/helpers.py
index a5aa2fd34..47475efc1 100644
--- a/airavata-django-portal/django_airavata/apps/api/helpers.py
+++ b/airavata-django-portal/django_airavata/apps/api/helpers.py
@@ -1,20 +1,19 @@
import logging
-from django_airavata.proto_compat import ResourcePermissionType
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
+from django_airavata.proto_compat import ResourcePermissionType
+
from . import models
logger = logging.getLogger(__name__)
class WorkspacePreferencesHelper:
-
def get(self, request):
try:
- workspace_preferences = models.WorkspacePreferences.objects.get(
- username=request.user.username)
+ workspace_preferences = models.WorkspacePreferences.objects.get(username=request.user.username)
self._check(request, workspace_preferences)
except ObjectDoesNotExist:
workspace_preferences = self._create_default(request)
@@ -22,21 +21,18 @@ class WorkspacePreferencesHelper:
return workspace_preferences
def _create_default(self, request):
- workspace_preferences = models.WorkspacePreferences.create(
- request.user.username)
+ workspace_preferences = models.WorkspacePreferences.create(request.user.username)
most_recent_project = self._get_most_recent_project(request)
- workspace_preferences.most_recent_project_id = \
- most_recent_project.projectID
- first_grp = \
- self._get_first_group_resource_profile(request)
- workspace_preferences.most_recent_group_resource_profile_id = \
+ workspace_preferences.most_recent_project_id = most_recent_project.projectID
+ first_grp = self._get_first_group_resource_profile(request)
+ workspace_preferences.most_recent_group_resource_profile_id = (
first_grp.groupResourceProfileId if first_grp else None
+ )
return workspace_preferences
def _get_most_recent_project(self, request):
"Return most recent writeable project."
- projects = request.airavata_client.research.get_user_projects(
- settings.GATEWAY_ID, request.user.username, -1, 0)
+ projects = request.airavata_client.research.get_user_projects(settings.GATEWAY_ID, request.user.username, -1, 0)
for project in projects:
if self._can_write(request, project.projectID):
return project
@@ -45,8 +41,7 @@ class WorkspacePreferencesHelper:
def _get_first_group_resource_profile(self, request):
"Return first accessible group resource profile"
- group_resource_profiles = request.airavata_client.compute.get_group_resource_list(
- settings.GATEWAY_ID)
+ group_resource_profiles = request.airavata_client.compute.get_group_resource_list(settings.GATEWAY_ID)
if len(group_resource_profiles) > 0:
return group_resource_profiles[0]
else:
@@ -54,37 +49,29 @@ class WorkspacePreferencesHelper:
def _check(self, request, prefs):
"Validate preference values and update as needed."
- if (not prefs.most_recent_project_id or
- not self._can_write(request, prefs.most_recent_project_id)):
+ if not prefs.most_recent_project_id or not self._can_write(request, prefs.most_recent_project_id):
most_recent_project = self._get_most_recent_project(request)
if most_recent_project is not None:
- logger.info("_check: updating most_recent_project_id to {}".format(most_recent_project.projectID))
+ logger.info(f"_check: updating most_recent_project_id to {most_recent_project.projectID}")
prefs.most_recent_project_id = most_recent_project.projectID
prefs.save()
else:
logger.warning("_check: no writeable projects found, unsetting most_recent_project_id")
prefs.most_recent_project_id = None
prefs.save()
- group_resource_profiles = request.airavata_client.compute.get_group_resource_list(
- settings.GATEWAY_ID)
+ group_resource_profiles = request.airavata_client.compute.get_group_resource_list(settings.GATEWAY_ID)
group_resource_profile_ids = list(map(lambda g: g.groupResourceProfileId, group_resource_profiles))
- if (not prefs.most_recent_group_resource_profile_id or
- prefs.most_recent_group_resource_profile_id not in group_resource_profile_ids):
- first_grp_id = (group_resource_profile_ids[0]
- if len(group_resource_profile_ids) > 0
- else None)
- logger.warn(f"_check: updating "
- f"most_recent_group_resource_profile_id to "
- f"{first_grp_id}")
+ if (
+ not prefs.most_recent_group_resource_profile_id
+ or prefs.most_recent_group_resource_profile_id not in group_resource_profile_ids
+ ):
+ first_grp_id = group_resource_profile_ids[0] if len(group_resource_profile_ids) > 0 else None
+ logger.warn(f"_check: updating most_recent_group_resource_profile_id to {first_grp_id}")
prefs.most_recent_group_resource_profile_id = first_grp_id
prefs.save()
def _can_write(self, request, entity_id):
- return request.airavata_client.sharing.user_has_access(
- entity_id,
- ResourcePermissionType.WRITE)
+ return request.airavata_client.sharing.user_has_access(entity_id, ResourcePermissionType.WRITE)
def _can_read(self, request, entity_id):
- return request.airavata_client.sharing.user_has_access(
- entity_id,
- ResourcePermissionType.READ)
+ return request.airavata_client.sharing.user_has_access(entity_id, ResourcePermissionType.READ)
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0001_initial.py b/airavata-django-portal/django_airavata/apps/api/migrations/0001_initial.py
index c59bae5af..10e969689 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0001_initial.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0001_initial.py
@@ -1,23 +1,19 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-03-05 19:35
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='WorkspacePreferences',
+ name="WorkspacePreferences",
fields=[
- ('username', models.CharField(max_length=64, primary_key=True, serialize=False)),
- ('most_recent_project_id', models.CharField(max_length=64)),
+ ("username", models.CharField(max_length=64, primary_key=True, serialize=False)),
+ ("most_recent_project_id", models.CharField(max_length=64)),
],
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0001_squashed_0004_auto_20190625_1938.py b/airavata-django-portal/django_airavata/apps/api/migrations/0001_squashed_0004_auto_20190625_1938.py
index 7251fce2a..319877349 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0001_squashed_0004_auto_20190625_1938.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0001_squashed_0004_auto_20190625_1938.py
@@ -1,42 +1,43 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-06-25 19:39
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
- replaces = [('django_airavata_api', '0001_initial'), ('django_airavata_api', '0002_auto_20190513_2037'), ('django_airavata_api', '0003_auto_20190625_1926'), ('django_airavata_api', '0004_auto_20190625_1938')]
+ replaces = [
+ ("django_airavata_api", "0001_initial"),
+ ("django_airavata_api", "0002_auto_20190513_2037"),
+ ("django_airavata_api", "0003_auto_20190625_1926"),
+ ("django_airavata_api", "0004_auto_20190625_1938"),
+ ]
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='WorkspacePreferences',
+ name="WorkspacePreferences",
fields=[
- ('username', models.CharField(max_length=64, primary_key=True, serialize=False)),
- ('most_recent_project_id', models.CharField(max_length=64)),
+ ("username", models.CharField(max_length=64, primary_key=True, serialize=False)),
+ ("most_recent_project_id", models.CharField(max_length=64)),
],
),
migrations.CreateModel(
- name='User_Files',
+ name="User_Files",
fields=[
- ('username', models.CharField(max_length=64)),
- ('file_path', models.TextField()),
- ('file_dpu', models.CharField(max_length=255, primary_key=True, serialize=False)),
+ ("username", models.CharField(max_length=64)),
+ ("file_path", models.TextField()),
+ ("file_dpu", models.CharField(max_length=255, primary_key=True, serialize=False)),
],
),
migrations.AlterField(
- model_name='user_files',
- name='file_dpu',
+ model_name="user_files",
+ name="file_dpu",
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AddIndex(
- model_name='user_files',
- index=models.Index(fields=['username'], name='username_idx'),
+ model_name="user_files",
+ index=models.Index(fields=["username"], name="username_idx"),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190513_2037.py b/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190513_2037.py
index 4bd49880a..5c6fc361a 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190513_2037.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190513_2037.py
@@ -1,27 +1,24 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-05-13 20:37
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0001_initial'),
+ ("django_airavata_api", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='User_Files',
+ name="User_Files",
fields=[
- ('username', models.CharField(max_length=64)),
- ('file_path', models.TextField()),
- ('file_dpu', models.CharField(max_length=500, primary_key=True, serialize=False)),
+ ("username", models.CharField(max_length=64)),
+ ("file_path", models.TextField()),
+ ("file_dpu", models.CharField(max_length=500, primary_key=True, serialize=False)),
],
),
migrations.AddIndex(
- model_name='user_files',
- index=models.Index(fields=['username', 'file_path'], name='username_file_path_idx'),
+ model_name="user_files",
+ index=models.Index(fields=["username", "file_path"], name="username_file_path_idx"),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190711_1438.py b/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190711_1438.py
index 8b938a780..96d79f2a8 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190711_1438.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0002_auto_20190711_1438.py
@@ -1,28 +1,25 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-07-11 14:38
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0001_squashed_0004_auto_20190625_1938'),
+ ("django_airavata_api", "0001_squashed_0004_auto_20190625_1938"),
]
operations = [
migrations.CreateModel(
- name='User_Notifications',
+ name="User_Notifications",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('username', models.CharField(max_length=64)),
- ('notification_id', models.CharField(max_length=255)),
- ('is_read', models.BooleanField(default=False)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("username", models.CharField(max_length=64)),
+ ("notification_id", models.CharField(max_length=255)),
+ ("is_read", models.BooleanField(default=False)),
],
),
migrations.AlterUniqueTogether(
- name='user_notifications',
- unique_together=set([('username', 'notification_id')]),
+ name="user_notifications",
+ unique_together=set([("username", "notification_id")]),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190625_1926.py b/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190625_1926.py
index 3b639ce4a..c198ce0d9 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190625_1926.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190625_1926.py
@@ -1,20 +1,17 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-06-25 19:26
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0002_auto_20190513_2037'),
+ ("django_airavata_api", "0002_auto_20190513_2037"),
]
operations = [
migrations.AlterField(
- model_name='user_files',
- name='file_dpu',
+ model_name="user_files",
+ name="file_dpu",
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190716_1549.py b/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190716_1549.py
index 3840aab39..af7b17cec 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190716_1549.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0003_auto_20190716_1549.py
@@ -1,30 +1,32 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-07-16 15:49
-from __future__ import unicode_literals
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0002_auto_20190711_1438'),
+ ("django_airavata_api", "0002_auto_20190711_1438"),
]
operations = [
migrations.CreateModel(
- name='ApplicationPreferences',
+ name="ApplicationPreferences",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('username', models.CharField(max_length=64)),
- ('application_id', models.CharField(max_length=64)),
- ('favorite', models.BooleanField(default=False)),
- ('workspace_preferences', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='django_airavata_api.WorkspacePreferences')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("username", models.CharField(max_length=64)),
+ ("application_id", models.CharField(max_length=64)),
+ ("favorite", models.BooleanField(default=False)),
+ (
+ "workspace_preferences",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE, to="django_airavata_api.WorkspacePreferences"
+ ),
+ ),
],
),
migrations.AlterUniqueTogether(
- name='applicationpreferences',
- unique_together=set([('username', 'application_id')]),
+ name="applicationpreferences",
+ unique_together=set([("username", "application_id")]),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20190625_1938.py b/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20190625_1938.py
index 245efca84..06f1db7f2 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20190625_1938.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20190625_1938.py
@@ -1,23 +1,20 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-06-25 19:38
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0003_auto_20190625_1926'),
+ ("django_airavata_api", "0003_auto_20190625_1926"),
]
operations = [
migrations.RemoveIndex(
- model_name='user_files',
- name='username_file_path_idx',
+ model_name="user_files",
+ name="username_file_path_idx",
),
migrations.AddIndex(
- model_name='user_files',
- index=models.Index(fields=['username'], name='username_idx'),
+ model_name="user_files",
+ index=models.Index(fields=["username"], name="username_idx"),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20191112_2134.py b/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20191112_2134.py
index 994dad65a..0949b4c49 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20191112_2134.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0004_auto_20191112_2134.py
@@ -1,30 +1,27 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-11-12 21:34
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0003_auto_20190716_1549'),
+ ("django_airavata_api", "0003_auto_20190716_1549"),
]
operations = [
migrations.AddField(
- model_name='workspacepreferences',
- name='most_recent_compute_resource_id',
+ model_name="workspacepreferences",
+ name="most_recent_compute_resource_id",
field=models.CharField(max_length=255, null=True),
),
migrations.AddField(
- model_name='workspacepreferences',
- name='most_recent_group_resource_profile_id',
+ model_name="workspacepreferences",
+ name="most_recent_group_resource_profile_id",
field=models.CharField(max_length=255, null=True),
),
migrations.AlterField(
- model_name='workspacepreferences',
- name='most_recent_project_id',
+ model_name="workspacepreferences",
+ name="most_recent_project_id",
field=models.CharField(max_length=255, null=True),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0005_delete_user_files.py b/airavata-django-portal/django_airavata/apps/api/migrations/0005_delete_user_files.py
index ed22e1276..062d77797 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0005_delete_user_files.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0005_delete_user_files.py
@@ -1,18 +1,15 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2020-07-01 15:59
-from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0004_auto_20191112_2134'),
+ ("django_airavata_api", "0004_auto_20191112_2134"),
]
operations = [
migrations.DeleteModel(
- name='User_Files',
+ name="User_Files",
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0006_applicationtemplate_applicationtemplatecontextprocessor.py b/airavata-django-portal/django_airavata/apps/api/migrations/0006_applicationtemplate_applicationtemplatecontextprocessor.py
index 688cc6377..06d3ae446 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0006_applicationtemplate_applicationtemplatecontextprocessor.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0006_applicationtemplate_applicationtemplatecontextprocessor.py
@@ -1,39 +1,55 @@
# Generated by Django 2.2.17 on 2021-05-20 17:13
+import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
-import django.db.models.deletion
class Migration(migrations.Migration):
-
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('django_airavata_api', '0005_delete_user_files'),
+ ("django_airavata_api", "0005_delete_user_files"),
]
operations = [
migrations.CreateModel(
- name='ApplicationTemplate',
+ name="ApplicationTemplate",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('application_module_id', models.CharField(max_length=255, unique=True)),
- ('template_path', models.TextField()),
- ('created', models.DateTimeField(auto_now_add=True)),
- ('updated', models.DateTimeField(auto_now=True)),
- ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
- ('updated_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("application_module_id", models.CharField(max_length=255, unique=True)),
+ ("template_path", models.TextField()),
+ ("created", models.DateTimeField(auto_now_add=True)),
+ ("updated", models.DateTimeField(auto_now=True)),
+ (
+ "created_by",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE, related_name="+", to=settings.AUTH_USER_MODEL
+ ),
+ ),
+ (
+ "updated_by",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE, related_name="+", to=settings.AUTH_USER_MODEL
+ ),
+ ),
],
),
migrations.CreateModel(
- name='ApplicationTemplateContextProcessor',
+ name="ApplicationTemplateContextProcessor",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('callable_path', models.CharField(max_length=255)),
- ('application_template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='context_processors', to='django_airavata_api.ApplicationTemplate')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("callable_path", models.CharField(max_length=255)),
+ (
+ "application_template",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="context_processors",
+ to="django_airavata_api.ApplicationTemplate",
+ ),
+ ),
],
options={
- 'unique_together': {('application_template', 'callable_path')},
+ "unique_together": {("application_template", "callable_path")},
},
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0007_applicationsettings.py b/airavata-django-portal/django_airavata/apps/api/migrations/0007_applicationsettings.py
index 1266cbc48..379432b98 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0007_applicationsettings.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0007_applicationsettings.py
@@ -4,18 +4,17 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0006_applicationtemplate_applicationtemplatecontextprocessor'),
+ ("django_airavata_api", "0006_applicationtemplate_applicationtemplatecontextprocessor"),
]
operations = [
migrations.CreateModel(
- name='ApplicationSettings',
+ name="ApplicationSettings",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('application_module_id', models.CharField(max_length=255, unique=True)),
- ('show_queue_settings', models.BooleanField(default=True)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("application_module_id", models.CharField(max_length=255, unique=True)),
+ ("show_queue_settings", models.BooleanField(default=True)),
],
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0007_notificationextension.py b/airavata-django-portal/django_airavata/apps/api/migrations/0007_notificationextension.py
index 24a97f22b..fe95f0fbc 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0007_notificationextension.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0007_notificationextension.py
@@ -4,21 +4,20 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0006_applicationtemplate_applicationtemplatecontextprocessor'),
+ ("django_airavata_api", "0006_applicationtemplate_applicationtemplatecontextprocessor"),
]
operations = [
migrations.CreateModel(
- name='NotificationExtension',
+ name="NotificationExtension",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('notification_id', models.CharField(max_length=255)),
- ('showInDashboard', models.BooleanField(default=False)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("notification_id", models.CharField(max_length=255)),
+ ("showInDashboard", models.BooleanField(default=False)),
],
options={
- 'unique_together': {('notification_id',)},
+ "unique_together": {("notification_id",)},
},
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0008_merge_20220601_1951.py b/airavata-django-portal/django_airavata/apps/api/migrations/0008_merge_20220601_1951.py
index 04f0d4f25..e9a61fafc 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0008_merge_20220601_1951.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0008_merge_20220601_1951.py
@@ -4,11 +4,9 @@ from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0007_applicationsettings'),
- ('django_airavata_api', '0007_notificationextension'),
+ ("django_airavata_api", "0007_applicationsettings"),
+ ("django_airavata_api", "0007_notificationextension"),
]
- operations = [
- ]
+ operations = []
diff --git a/airavata-django-portal/django_airavata/apps/api/migrations/0009_applicationsettings_queue_settings_calculator_id.py b/airavata-django-portal/django_airavata/apps/api/migrations/0009_applicationsettings_queue_settings_calculator_id.py
index bc7bf8fbf..a1bbe20be 100644
--- a/airavata-django-portal/django_airavata/apps/api/migrations/0009_applicationsettings_queue_settings_calculator_id.py
+++ b/airavata-django-portal/django_airavata/apps/api/migrations/0009_applicationsettings_queue_settings_calculator_id.py
@@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_api', '0008_merge_20220601_1951'),
+ ("django_airavata_api", "0008_merge_20220601_1951"),
]
operations = [
migrations.AddField(
- model_name='applicationsettings',
- name='queue_settings_calculator_id',
+ model_name="applicationsettings",
+ name="queue_settings_calculator_id",
field=models.CharField(max_length=255, null=True),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/api/models.py b/airavata-django-portal/django_airavata/apps/api/models.py
index 45c881642..4fe28bd6a 100644
--- a/airavata-django-portal/django_airavata/apps/api/models.py
+++ b/airavata-django-portal/django_airavata/apps/api/models.py
@@ -6,10 +6,8 @@ from django.db import models
class WorkspacePreferences(models.Model):
username = models.CharField(max_length=64, primary_key=True)
most_recent_project_id = models.CharField(max_length=255, null=True)
- most_recent_group_resource_profile_id = models.CharField(max_length=255,
- null=True)
- most_recent_compute_resource_id = models.CharField(max_length=255,
- null=True)
+ most_recent_group_resource_profile_id = models.CharField(max_length=255, null=True)
+ most_recent_compute_resource_id = models.CharField(max_length=255, null=True)
@classmethod
def create(cls, username):
@@ -20,16 +18,15 @@ class ApplicationPreferences(models.Model):
username = models.CharField(max_length=64)
application_id = models.CharField(max_length=64)
favorite = models.BooleanField(default=False)
- workspace_preferences = models.ForeignKey(WorkspacePreferences,
- on_delete=models.CASCADE)
+ workspace_preferences = models.ForeignKey(WorkspacePreferences, on_delete=models.CASCADE)
class Meta:
- unique_together = (('username', 'application_id'),)
+ unique_together = (("username", "application_id"),)
class NotificationExtension(models.Model):
class Meta:
- unique_together = (('notification_id', ),)
+ unique_together = (("notification_id",),)
notification_id = models.CharField(max_length=255)
showInDashboard = models.BooleanField(default=False)
@@ -37,7 +34,7 @@ class NotificationExtension(models.Model):
class User_Notifications(models.Model):
class Meta:
- unique_together = (('username', 'notification_id'),)
+ unique_together = (("username", "notification_id"),)
username = models.CharField(max_length=64)
notification_id = models.CharField(max_length=255)
@@ -57,13 +54,15 @@ class ApplicationTemplate(models.Model):
class ApplicationTemplateContextProcessor(models.Model):
- application_template = models.ForeignKey(ApplicationTemplate, on_delete=models.CASCADE, related_name="context_processors")
+ application_template = models.ForeignKey(
+ ApplicationTemplate, on_delete=models.CASCADE, related_name="context_processors"
+ )
# Use django.util.module_loading.import_string to import
# https://docs.djangoproject.com/en/3.2/ref/utils/#module-django.utils.module_loading
callable_path = models.CharField(max_length=255)
class Meta:
- unique_together = (('application_template', 'callable_path'),)
+ unique_together = (("application_template", "callable_path"),)
def __str__(self):
return self.callable_path
diff --git a/airavata-django-portal/django_airavata/apps/api/output_views.py b/airavata-django-portal/django_airavata/apps/api/output_views.py
index fb6065705..341a1f5cb 100644
--- a/airavata-django-portal/django_airavata/apps/api/output_views.py
+++ b/airavata-django-portal/django_airavata/apps/api/output_views.py
@@ -7,11 +7,12 @@ from functools import partial
import nbformat
import papermill as pm
-from django_airavata.proto_compat import DataType
from airavata_django_portal_sdk import user_storage
from django.conf import settings
from nbconvert import HTMLExporter
+from django_airavata.proto_compat import DataType
+
logger = logging.getLogger(__name__)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -21,91 +22,64 @@ OUTPUT_VIEW_PROVIDERS = {}
class DefaultViewProvider:
- display_type = 'default'
+ display_type = "default"
immediate = False
name = "Default"
- def generate_data(
- self,
- request,
- experiment_output,
- experiment,
- output_file=None,
- **kwargs):
- return {
- }
+ def generate_data(self, request, experiment_output, experiment, output_file=None, **kwargs):
+ return {}
class ParameterizedNotebookViewProvider:
- display_type = 'notebook'
+ display_type = "notebook"
name = "Example Parameterized Notebook View"
# test_output_file = os.path.join(BASE_DIR, "data", "Gaussian.log")
- def generate_data(self,
- request,
- experiment_output,
- experiment,
- output_file=None,
- output_dir=None):
+ def generate_data(self, request, experiment_output, experiment, output_file=None, output_dir=None):
# use papermill to generate the output notebook
output_file_path = os.path.realpath(output_file.name)
pm.execute_notebook(
os.path.join(BASE_DIR, "path", "to", "notebook.ipynb"),
# TODO: use TemporaryFile instead
- '/tmp/output.ipynb',
- parameters=dict(
- experiment_output={},
- experiment={},
- output_file=output_file_path,
- output_dir=output_dir
- )
+ "/tmp/output.ipynb",
+ parameters=dict(experiment_output={}, experiment={}, output_file=output_file_path, output_dir=output_dir),
)
# TODO: convert the output notebook into html format
- output_notebook = nbformat.read('/tmp/output.ipynb', as_version=4)
+ output_notebook = nbformat.read("/tmp/output.ipynb", as_version=4)
html_exporter = HTMLExporter()
(body, resources) = html_exporter.from_notebook_node(output_notebook)
# TODO: return the HTML output as the output key
- return {
- 'output': body
- }
+ return {"output": body}
-DEFAULT_VIEW_PROVIDERS = {
- 'default': DefaultViewProvider()
-}
+DEFAULT_VIEW_PROVIDERS = {"default": DefaultViewProvider()}
def get_output_views(request, experiment, application_interface=None):
output_views = {}
for output in experiment.experimentOutputs:
output_views[output.name] = []
- output_view_provider_ids = _get_output_view_providers(
- output, application_interface)
+ output_view_provider_ids = _get_output_view_providers(output, application_interface)
for output_view_provider_id in output_view_provider_ids:
output_view_provider = None
if output_view_provider_id in DEFAULT_VIEW_PROVIDERS:
- output_view_provider = DEFAULT_VIEW_PROVIDERS[
- output_view_provider_id]
+ output_view_provider = DEFAULT_VIEW_PROVIDERS[output_view_provider_id]
elif output_view_provider_id in OUTPUT_VIEW_PROVIDERS:
- output_view_provider = OUTPUT_VIEW_PROVIDERS[
- output_view_provider_id]
+ output_view_provider = OUTPUT_VIEW_PROVIDERS[output_view_provider_id]
else:
- logger.warning("Unable to find output view provider with "
- "name '{}'".format(output_view_provider_id))
+ logger.warning(f"Unable to find output view provider with name '{output_view_provider_id}'")
if output_view_provider is not None:
view_config = {
- 'provider-id': output_view_provider_id,
- 'display-type': output_view_provider.display_type,
- 'name': getattr(output_view_provider, 'name',
- output_view_provider_id),
+ "provider-id": output_view_provider_id,
+ "display-type": output_view_provider.display_type,
+ "name": getattr(output_view_provider, "name", output_view_provider_id),
}
- if getattr(output_view_provider, 'immediate', False):
+ if getattr(output_view_provider, "immediate", False):
# Immediately call generate_data function
- data = _generate_data(
- request, output_view_provider, output, experiment)
- view_config['data'] = data
+ data = _generate_data(request, output_view_provider, output, experiment)
+ view_config["data"] = data
else:
- view_config['data'] = {}
+ view_config["data"] = {}
output_views[output.name].append(view_config)
return output_views
@@ -120,105 +94,76 @@ def _get_output_view_provider(output_view_provider_id):
def _get_output_view_providers(experiment_output, application_interface):
output_view_providers = []
- logger.debug("experiment_output={}".format(experiment_output))
+ logger.debug(f"experiment_output={experiment_output}")
if experiment_output.metaData:
try:
output_metadata = json.loads(experiment_output.metaData)
- logger.debug("output_metadata={}".format(output_metadata))
- if 'output-view-providers' in output_metadata:
- output_view_providers.extend(
- output_metadata['output-view-providers'])
+ logger.debug(f"output_metadata={output_metadata}")
+ if "output-view-providers" in output_metadata:
+ output_view_providers.extend(output_metadata["output-view-providers"])
except Exception:
- logger.exception(
- "Failed to parse metadata for output {}".format(
- experiment_output.name))
+ logger.exception(f"Failed to parse metadata for output {experiment_output.name}")
# Add in any output view providers defined on the application interface
if application_interface is not None:
app_output_view_providers = _get_application_output_view_providers(
- application_interface, experiment_output.name)
+ application_interface, experiment_output.name
+ )
for view_provider in app_output_view_providers:
if view_provider not in output_view_providers:
output_view_providers.append(view_provider)
- if 'default' not in output_view_providers:
- output_view_providers.insert(0, 'default')
+ if "default" not in output_view_providers:
+ output_view_providers.insert(0, "default")
return output_view_providers
def _get_application_output_view_providers(application_interface, output_name):
- app_output = [o
- for o in application_interface.applicationOutputs
- if o.name == output_name]
+ app_output = [o for o in application_interface.applicationOutputs if o.name == output_name]
if len(app_output) == 1:
- logger.debug("{}: {}".format(output_name, app_output))
+ logger.debug(f"{output_name}: {app_output}")
app_output = app_output[0]
else:
return []
if app_output.metaData:
try:
output_metadata = json.loads(app_output.metaData)
- if 'output-view-providers' in output_metadata:
- return output_metadata['output-view-providers']
+ if "output-view-providers" in output_metadata:
+ return output_metadata["output-view-providers"]
except Exception:
- logger.exception(
- "Failed to parse metadata for output {}".format(
- app_output.name))
+ logger.exception(f"Failed to parse metadata for output {app_output.name}")
return []
-def generate_data(request,
- output_view_provider_id,
- experiment_output_name,
- experiment_id,
- test_mode=False,
- **kwargs):
+def generate_data(request, output_view_provider_id, experiment_output_name, experiment_id, test_mode=False, **kwargs):
output_view_provider = _get_output_view_provider(output_view_provider_id)
# TODO if output_view_provider is None, return 404
- experiment = request.airavata_client.research.get_experiment(
- experiment_id)
- experiment_output = [o
- for o in experiment.experimentOutputs
- if o.name == experiment_output_name]
+ experiment = request.airavata_client.research.get_experiment(experiment_id)
+ experiment_output = [o for o in experiment.experimentOutputs if o.name == experiment_output_name]
# TODO: handle experiment_output not found by name
experiment_output = experiment_output[0]
# TODO: add experiment_output_dir
# convert the extra/interactive arguments to appropriate types
kwargs = _convert_params_to_type(output_view_provider, kwargs)
- return _generate_data(request,
- output_view_provider,
- experiment_output,
- experiment,
- test_mode=test_mode,
- **kwargs)
-
-
-def _generate_data(request,
- output_view_provider,
- experiment_output,
- experiment,
- test_mode=False,
- **kwargs):
+ return _generate_data(request, output_view_provider, experiment_output, experiment, test_mode=test_mode, **kwargs)
+
+
+def _generate_data(request, output_view_provider, experiment_output, experiment, test_mode=False, **kwargs):
output_files = []
# test_mode can only be used in DEBUG=True mode
if test_mode and settings.DEBUG:
- test_output_file = getattr(output_view_provider,
- 'test_output_file',
- None)
+ test_output_file = getattr(output_view_provider, "test_output_file", None)
if test_output_file is None:
raise Exception(f"test_output_file is not set on {output_view_provider}")
logger.info(f"Using {test_output_file} instead of regular output file")
- output_file = open(test_output_file, 'rb')
+ output_file = open(test_output_file, "rb")
output_files.append(output_file)
- elif (experiment_output.value and
- experiment_output.type in (DataType.URI,
- DataType.URI_COLLECTION,
- DataType.STDOUT,
- DataType.STDERR) and
- experiment_output.value.startswith("airavata-dp")):
+ elif (
+ experiment_output.value
+ and experiment_output.type in (DataType.URI, DataType.URI_COLLECTION, DataType.STDOUT, DataType.STDERR)
+ and experiment_output.value.startswith("airavata-dp")
+ ):
data_product_uris = experiment_output.value.split(",")
- data_products = map(lambda dpid:
- request.airavata_client.research.get_data_product(dpid),
- data_product_uris)
+ data_products = map(lambda dpid: request.airavata_client.research.get_data_product(dpid), data_product_uris)
for data_product in data_products:
if user_storage.exists(request, data_product):
output_file = user_storage.open_file(request, data_product)
@@ -226,37 +171,34 @@ def _generate_data(request,
generate_data_func = output_view_provider.generate_data
method_sig = inspect.signature(generate_data_func)
- if 'output_files' in method_sig.parameters:
+ if "output_files" in method_sig.parameters:
generate_data_func = partial(generate_data_func, output_files=output_files)
# TODO: convert experiment and experiment_output to dict/JSON
- data = generate_data_func(request,
- experiment_output,
- experiment,
- output_file=output_files[0] if len(output_files) > 0 else None,
- **kwargs)
+ data = generate_data_func(
+ request, experiment_output, experiment, output_file=output_files[0] if len(output_files) > 0 else None, **kwargs
+ )
_process_interactive_params(data)
return data
def _process_interactive_params(data):
- if 'interactive' in data:
+ if "interactive" in data:
_convert_options(data)
- for param in data['interactive']:
- if 'type' not in param:
- param['type'] = _infer_interactive_param_type(param)
+ for param in data["interactive"]:
+ if "type" not in param:
+ param["type"] = _infer_interactive_param_type(param)
# integer type implicitly has a step size of 1
- if param['type'] == "integer" and 'step' not in param:
- param['step'] = 1
+ if param["type"] == "integer" and "step" not in param:
+ param["step"] = 1
def _convert_options(data):
"""Convert interactive options to explicit text/value dicts."""
- for param in data['interactive']:
- if 'options' in param and isinstance(param['options'][0], str):
- param['options'] = _convert_options_strings(param['options'])
- elif 'options' in param and isinstance(
- param['options'][0], collections.Sequence):
- param['options'] = _convert_options_sequences(param['options'])
+ for param in data["interactive"]:
+ if "options" in param and isinstance(param["options"][0], str):
+ param["options"] = _convert_options_strings(param["options"])
+ elif "options" in param and isinstance(param["options"][0], collections.Sequence):
+ param["options"] = _convert_options_sequences(param["options"])
def _convert_options_strings(options):
@@ -268,7 +210,7 @@ def _convert_options_sequences(options):
def _infer_interactive_param_type(param):
- v = param['value']
+ v = param["value"]
# Boolean test must come first since bools are also integers
if isinstance(v, bool):
return "boolean"
@@ -287,24 +229,24 @@ def _convert_params_to_type(output_view_provider, params):
# parameters (will only be present if there are interactive parameters)
meta = json.loads(params.pop("_meta", "{}"))
for k, v in params.items():
- meta_type = meta[k]['type'] if k in meta else None
+ meta_type = meta[k]["type"] if k in meta else None
default_value = None
- if (k in method_params and
- method_params[k].default is not inspect.Parameter.empty and
- method_params[k].default is not None):
+ if (
+ k in method_params
+ and method_params[k].default is not inspect.Parameter.empty
+ and method_params[k].default is not None
+ ):
default_value = method_params[k].default
# TODO: handle lists?
# Handle boolean and numeric values, converting from string
- if meta_type == 'boolean' or isinstance(default_value, bool):
+ if meta_type == "boolean" or isinstance(default_value, bool):
params[k] = v == "true"
- elif meta_type == 'float' or isinstance(default_value, float):
+ elif meta_type == "float" or isinstance(default_value, float):
params[k] = float(v)
- elif meta_type == 'integer' or isinstance(default_value, int):
+ elif meta_type == "integer" or isinstance(default_value, int):
params[k] = int(v)
- elif meta_type == 'string' or isinstance(default_value, str):
+ elif meta_type == "string" or isinstance(default_value, str):
params[k] = v
else:
- logger.warning(
- f"Unrecognized type for parameter {k}: "
- f"meta_type={meta_type}, default_value={default_value}")
+ logger.warning(f"Unrecognized type for parameter {k}: meta_type={meta_type}, default_value={default_value}")
return params
diff --git a/airavata-django-portal/django_airavata/apps/api/proto_utils.py b/airavata-django-portal/django_airavata/apps/api/proto_utils.py
index 4fca3204c..add87d795 100644
--- a/airavata-django-portal/django_airavata/apps/api/proto_utils.py
+++ b/airavata-django-portal/django_airavata/apps/api/proto_utils.py
@@ -4,6 +4,7 @@ Used to create Django Rest Framework serializers for Airavata data types.
Migrated from thrift_utils.py -- now works with proto-compatible data classes
from django_airavata.proto_compat instead of Thrift-generated types.
"""
+
import copy
import datetime
import enum
@@ -21,8 +22,9 @@ from rest_framework.serializers import (
ListSerializer,
Serializer,
SerializerMetaclass,
- ValidationError
+ ValidationError,
)
+
from django_airavata.proto_compat import (
ApplicationParallelismType,
DataType,
@@ -59,7 +61,6 @@ mapping = {
class UTCPosixTimestampDateTimeField(DateTimeField):
-
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.default = self.current_time_ms
@@ -67,7 +68,7 @@ class UTCPosixTimestampDateTimeField(DateTimeField):
self.required = False
def to_representation(self, obj):
- dt = datetime.datetime.fromtimestamp(obj / 1000, datetime.timezone.utc)
+ dt = datetime.datetime.fromtimestamp(obj / 1000, datetime.UTC)
return super().to_representation(dt)
def to_internal_value(self, data):
@@ -82,7 +83,6 @@ class UTCPosixTimestampDateTimeField(DateTimeField):
class ThriftEnumField(Field):
-
def __init__(self, enumClass, *args, **kwargs):
super().__init__(*args, **kwargs)
self.enumClass = enumClass
@@ -114,22 +114,21 @@ def create_serializer(thrift_data_type, enable_date_time_conversion=False, **kwa
def create_serializer_class(thrift_data_type, enable_date_time_conversion=False):
class CustomSerializerMeta(SerializerMetaclass):
-
def __new__(cls, name, bases, attrs):
- meta = attrs.get('Meta', None)
+ meta = attrs.get("Meta", None)
thrift_spec = thrift_data_type.thrift_spec
for field in thrift_spec:
if field and field[2] not in attrs:
- required = (field[2] in meta.required
- if meta and hasattr(meta, 'required')
- else False)
- read_only = (field[2] in meta.read_only
- if meta and hasattr(meta, 'read_only')
- else False)
+ required = field[2] in meta.required if meta and hasattr(meta, "required") else False
+ read_only = field[2] in meta.read_only if meta and hasattr(meta, "read_only") else False
allow_null = not required
field_serializer = process_field(
- field, enable_date_time_conversion, required=required, read_only=read_only,
- allow_null=allow_null)
+ field,
+ enable_date_time_conversion,
+ required=required,
+ read_only=read_only,
+ allow_null=allow_null,
+ )
attrs[field[2]] = field_serializer
return super().__new__(cls, name, bases, attrs)
@@ -142,32 +141,28 @@ def create_serializer_class(thrift_data_type, enable_date_time_conversion=False)
fields = self.fields
params = copy.deepcopy(validated_data)
for field_name, serializer in fields.items():
- if (isinstance(serializer, ListField) or
- isinstance(serializer, ListSerializer)):
- if (params.get(field_name, None) is not None or
- not serializer.allow_null):
+ if isinstance(serializer, ListField) or isinstance(serializer, ListSerializer):
+ if params.get(field_name, None) is not None or not serializer.allow_null:
if isinstance(serializer.child, Serializer):
- if field_name == 'experimentInputs' and 'type' in serializer.child.fields:
- for item in params[field_name]:
- if 'type' in item and isinstance(item['type'], int):
- item['type'] = DataType(item['type'])
- elif field_name == 'experimentOutputs' and 'type' in serializer.child.fields:
+ if (
+ field_name == "experimentInputs"
+ and "type" in serializer.child.fields
+ or field_name == "experimentOutputs"
+ and "type" in serializer.child.fields
+ ):
for item in params[field_name]:
- if 'type' in item and isinstance(item['type'], int):
- item['type'] = DataType(item['type'])
- elif field_name == 'experimentStatus' and 'state' in serializer.child.fields:
+ if "type" in item and isinstance(item["type"], int):
+ item["type"] = DataType(item["type"])
+ elif field_name == "experimentStatus" and "state" in serializer.child.fields:
for item in params[field_name]:
- if 'state' in item and isinstance(item['state'], int):
- item['state'] = ExperimentState(item['state'])
- params[field_name] = [serializer.child.create(
- item) for item in params[field_name]]
+ if "state" in item and isinstance(item["state"], int):
+ item["state"] = ExperimentState(item["state"])
+ params[field_name] = [serializer.child.create(item) for item in params[field_name]]
else:
- params[field_name] = serializer.to_representation(
- params[field_name])
+ params[field_name] = serializer.to_representation(params[field_name])
elif isinstance(serializer, Serializer):
if field_name in params and params[field_name] is not None:
- params[field_name] = serializer.create(
- params[field_name])
+ params[field_name] = serializer.create(params[field_name])
return params
def create(self, validated_data):
@@ -183,13 +178,19 @@ def create_serializer_class(thrift_data_type, enable_date_time_conversion=False)
if field_name in params and params[field_name] is None:
del params[field_name]
- if (thrift_data_type.__name__ == 'ExperimentModel' and
- 'experimentType' in params and isinstance(params['experimentType'], int)):
- params['experimentType'] = ExperimentType(params['experimentType'])
+ if (
+ thrift_data_type.__name__ == "ExperimentModel"
+ and "experimentType" in params
+ and isinstance(params["experimentType"], int)
+ ):
+ params["experimentType"] = ExperimentType(params["experimentType"])
- if (thrift_data_type.__name__ == 'ApplicationDeploymentDescription' and
- 'parallelism' in params and isinstance(params['parallelism'], int)):
- params['parallelism'] = ApplicationParallelismType(params['parallelism'])
+ if (
+ thrift_data_type.__name__ == "ApplicationDeploymentDescription"
+ and "parallelism" in params
+ and isinstance(params["parallelism"], int)
+ ):
+ params["parallelism"] = ApplicationParallelismType(params["parallelism"])
return thrift_data_type(**params)
@@ -204,12 +205,17 @@ def process_field(field, enable_date_time_conversion, required=False, read_only=
field_class = mapping[field[1]]
kwargs = dict(required=required, read_only=read_only)
if field_class not in (BooleanField,):
- kwargs['allow_null'] = allow_null
+ kwargs["allow_null"] = allow_null
if field_class == CharField:
- kwargs['allow_blank'] = allow_null
+ kwargs["allow_blank"] = allow_null
thrift_model_class = mapping[field[1]]
- if thrift_model_class == IntegerField and field[3] is not None and isinstance(field[3], type) and issubclass(field[3], enum.IntEnum):
+ if (
+ thrift_model_class == IntegerField
+ and field[3] is not None
+ and isinstance(field[3], type)
+ and issubclass(field[3], enum.IntEnum)
+ ):
return ThriftEnumField(field[3], required=required, read_only=read_only, allow_null=allow_null)
if enable_date_time_conversion and thrift_model_class == IntegerField and field[2].lower().endswith("time"):
@@ -217,15 +223,9 @@ def process_field(field, enable_date_time_conversion, required=False, read_only=
return thrift_model_class(**kwargs)
elif field[1] == TTYPE_LIST:
list_field_serializer = process_list_field(field)
- return ListField(child=list_field_serializer,
- required=required,
- read_only=read_only,
- allow_null=allow_null)
+ return ListField(child=list_field_serializer, required=required, read_only=read_only, allow_null=allow_null)
elif field[1] == TTYPE_STRUCT:
- return create_serializer(field[3][0],
- required=required,
- read_only=read_only,
- allow_null=allow_null)
+ return create_serializer(field[3][0], required=required, read_only=read_only, allow_null=allow_null)
def process_list_field(field):
@@ -233,10 +233,12 @@ def process_list_field(field):
item_ttype = list_details[0]
item_type_info = list_details[1]
- if (item_ttype == TTYPE_I32 and
- item_type_info is not None and
- isinstance(item_type_info, type) and
- issubclass(item_type_info, enum.IntEnum)):
+ if (
+ item_ttype == TTYPE_I32
+ and item_type_info is not None
+ and isinstance(item_type_info, type)
+ and issubclass(item_type_info, enum.IntEnum)
+ ):
return ThriftEnumField(item_type_info)
if item_ttype in mapping:
diff --git a/airavata-django-portal/django_airavata/apps/api/queue_settings.py b/airavata-django-portal/django_airavata/apps/api/queue_settings.py
index 474089f1e..664a9dab2 100644
--- a/airavata-django-portal/django_airavata/apps/api/queue_settings.py
+++ b/airavata-django-portal/django_airavata/apps/api/queue_settings.py
@@ -4,7 +4,9 @@ Queue settings calculators — inlined from airavata_django_portal_sdk.
Provides a registry of queue settings calculator functions that can be
used to automatically compute batch queue parameters for experiments.
"""
-from typing import Callable, NamedTuple
+
+from collections.abc import Callable
+from typing import NamedTuple
QUEUE_SETTINGS_CALCULATORS = []
@@ -17,6 +19,7 @@ class QueueSettingsCalculator(NamedTuple):
def queue_settings_calculator(_func=None, *, id=None, name=None, **kwargs):
"""Decorator for registering queue settings calculator functions."""
+
def decorator(func):
name_ = name
if name_ is None:
@@ -28,6 +31,7 @@ def queue_settings_calculator(_func=None, *, id=None, name=None, **kwargs):
raise Exception(f"Duplicate queue settings calculator id: {id_}")
QUEUE_SETTINGS_CALCULATORS.append(QueueSettingsCalculator(id_, name_, func))
return func
+
if _func is None:
return decorator
else:
diff --git a/airavata-django-portal/django_airavata/apps/api/serializers.py b/airavata-django-portal/django_airavata/apps/api/serializers.py
index 3752ce667..21cbf3ffa 100644
--- a/airavata-django-portal/django_airavata/apps/api/serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/serializers.py
@@ -4,6 +4,13 @@ import json
import logging
from pathlib import Path
from urllib.parse import quote
+
+from airavata_django_portal_sdk import experiment_util, user_storage
+from django.conf import settings
+from django.contrib.auth import get_user_model
+from django.urls import reverse
+from rest_framework import serializers
+
from django_airavata.proto_compat import (
ApplicationDeploymentDescription,
ApplicationInterfaceDescription,
@@ -45,22 +52,13 @@ from django_airavata.proto_compat import (
SummaryType,
UserProfile,
)
-from airavata_django_portal_sdk import (
- experiment_util,
- user_storage
-)
-from django.conf import settings
-from django.contrib.auth import get_user_model
-from django.urls import reverse
-from rest_framework import serializers
from . import models, proto_utils, view_utils
log = logging.getLogger(__name__)
-class FullyEncodedHyperlinkedIdentityField(
- serializers.HyperlinkedIdentityField):
+class FullyEncodedHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
def get_url(self, obj, view_name, request, format):
if hasattr(obj, self.lookup_field):
lookup_value = getattr(obj, self.lookup_field)
@@ -70,21 +68,19 @@ class FullyEncodedHyperlinkedIdentityField(
encoded_lookup_value = quote(lookup_value, safe="")
except Exception:
log.warning(
- "Failed to encode lookup_value [{}] for lookup_field "
- "[{}] of object [{}]".format(
- lookup_value, self.lookup_field, obj))
+ f"Failed to encode lookup_value [{lookup_value}] for lookup_field "
+ f"[{self.lookup_field}] of object [{obj}]"
+ )
raise
# Bit of a hack. Django's URL reversing does URL encoding but it
# doesn't encode all characters including some like '/' that are used
# in URL mappings.
kwargs = {self.lookup_url_kwarg: "__PLACEHOLDER__"}
- url = self.reverse(view_name, kwargs=kwargs,
- request=request, format=format)
+ url = self.reverse(view_name, kwargs=kwargs, request=request, format=format)
return url.replace("__PLACEHOLDER__", encoded_lookup_value)
class UTCPosixTimestampDateTimeField(serializers.DateTimeField):
-
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.default = self.current_time_ms
@@ -93,7 +89,7 @@ class UTCPosixTimestampDateTimeField(serializers.DateTimeField):
def to_representation(self, obj):
# Create datetime instance from milliseconds that is aware of timezon
- dt = datetime.datetime.fromtimestamp(obj / 1000, datetime.timezone.utc)
+ dt = datetime.datetime.fromtimestamp(obj / 1000, datetime.UTC)
return super().to_representation(dt)
def to_internal_value(self, data):
@@ -124,13 +120,12 @@ class StoredJSONField(serializers.JSONField):
try:
return json.dumps(data)
except (TypeError, ValueError):
- self.fail('invalid')
+ self.fail("invalid")
class OrderedListField(serializers.ListField):
-
def __init__(self, *args, **kwargs):
- self.order_by = kwargs.pop('order_by', None)
+ self.order_by = kwargs.pop("order_by", None)
super().__init__(*args, **kwargs)
def to_representation(self, instance):
@@ -150,9 +145,8 @@ class OrderedListField(serializers.ListField):
class GroupSerializer(proto_utils.create_serializer_class(GroupModel)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:group-detail',
- lookup_field='id',
- lookup_url_kwarg='group_id')
+ view_name="django_airavata_api:group-detail", lookup_field="id", lookup_url_kwarg="group_id"
+ )
isAdmin = serializers.SerializerMethodField()
isOwner = serializers.SerializerMethodField()
isMember = serializers.SerializerMethodField()
@@ -161,90 +155,83 @@ class GroupSerializer(proto_utils.create_serializer_class(GroupModel)):
isDefaultGatewayUsersGroup = serializers.SerializerMethodField()
class Meta:
- required = ('name',)
- read_only = ('ownerId',)
+ required = ("name",)
+ read_only = ("ownerId",)
def create(self, validated_data):
group = super().create(validated_data)
- group.ownerId = self.context['request'].user.username + \
- "@" + settings.GATEWAY_ID
+ group.ownerId = self.context["request"].user.username + "@" + settings.GATEWAY_ID
return group
def update(self, instance, validated_data):
- instance.name = validated_data.get('name', instance.name)
- instance.description = validated_data.get(
- 'description', instance.description)
+ instance.name = validated_data.get("name", instance.name)
+ instance.description = validated_data.get("description", instance.description)
# Calculate added and removed members
old_members = set(instance.members)
- new_members = set(validated_data.get('members', instance.members))
+ new_members = set(validated_data.get("members", instance.members))
removed_members = old_members - new_members
added_members = new_members - old_members
instance._removed_members = list(removed_members)
instance._added_members = list(added_members)
- instance.members = validated_data.get('members', instance.members)
+ instance.members = validated_data.get("members", instance.members)
# Calculate added and removed admins
old_admins = set(instance.admins)
- new_admins = set(validated_data.get('admins', instance.admins))
+ new_admins = set(validated_data.get("admins", instance.admins))
removed_admins = old_admins - new_admins
added_admins = new_admins - old_admins
instance._removed_admins = list(removed_admins)
instance._added_admins = list(added_admins)
- instance.admins = validated_data.get('admins', instance.admins)
+ instance.admins = validated_data.get("admins", instance.admins)
# Add new admins that aren't members to the added_members list
instance._added_members.extend(list(added_admins - new_members))
instance.members.extend(list(added_admins - new_members))
return instance
def get_isAdmin(self, group):
- request = self.context['request']
+ request = self.context["request"]
return request.airavata_client.sharing.has_admin_access(
- group.id,
- request.user.username + "@" + settings.GATEWAY_ID)
+ group.id, request.user.username + "@" + settings.GATEWAY_ID
+ )
def get_isOwner(self, group):
- request = self.context['request']
- return group.ownerId == (request.user.username +
- "@" +
- settings.GATEWAY_ID)
+ request = self.context["request"]
+ return group.ownerId == (request.user.username + "@" + settings.GATEWAY_ID)
def get_isMember(self, group):
- request = self.context['request']
+ request = self.context["request"]
username = request.user.username + "@" + settings.GATEWAY_ID
return group.members and username in group.members
def get_isGatewayAdminsGroup(self, group):
- return group.id == self._gateway_groups()['adminsGroupId']
+ return group.id == self._gateway_groups()["adminsGroupId"]
def get_isReadOnlyGatewayAdminsGroup(self, group):
- return group.id == self._gateway_groups()['readOnlyAdminsGroupId']
+ return group.id == self._gateway_groups()["readOnlyAdminsGroupId"]
def get_isDefaultGatewayUsersGroup(self, group):
- return group.id == self._gateway_groups()['defaultGatewayUsersGroupId']
+ return group.id == self._gateway_groups()["defaultGatewayUsersGroupId"]
def _gateway_groups(self):
- request = self.context['request']
+ request = self.context["request"]
# gateway_groups_middleware sets this session variable
- if 'GATEWAY_GROUPS' in request.session:
- return request.session['GATEWAY_GROUPS']
+ if "GATEWAY_GROUPS" in request.session:
+ return request.session["GATEWAY_GROUPS"]
else:
gateway_groups = request.airavata_client.iam.get_gateway_groups()
return copy.deepcopy(gateway_groups.__dict__)
-class ProjectSerializer(
- proto_utils.create_serializer_class(Project)):
+class ProjectSerializer(proto_utils.create_serializer_class(Project)):
class Meta:
- required = ('name',)
- read_only = ('owner', 'gatewayId')
+ required = ("name",)
+ read_only = ("owner", "gatewayId")
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:project-detail',
- lookup_field='projectID',
- lookup_url_kwarg='project_id')
+ view_name="django_airavata_api:project-detail", lookup_field="projectID", lookup_url_kwarg="project_id"
+ )
experiments = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:project-experiments',
- lookup_field='projectID',
- lookup_url_kwarg='project_id')
+ view_name="django_airavata_api:project-experiments", lookup_field="projectID", lookup_url_kwarg="project_id"
+ )
creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
userHasWriteAccess = serializers.SerializerMethodField()
isOwner = serializers.SerializerMethodField()
@@ -253,50 +240,47 @@ class ProjectSerializer(
return Project(**validated_data)
def update(self, instance, validated_data):
- instance.name = validated_data.get('name', instance.name)
- instance.description = validated_data.get(
- 'description', instance.description)
+ instance.name = validated_data.get("name", instance.name)
+ instance.description = validated_data.get("description", instance.description)
return instance
def get_userHasWriteAccess(self, project):
- request = self.context['request']
- return request.airavata_client.sharing.user_has_access(
- project.projectID,
- ResourcePermissionType.WRITE)
+ request = self.context["request"]
+ return request.airavata_client.sharing.user_has_access(project.projectID, ResourcePermissionType.WRITE)
def get_isOwner(self, project):
- request = self.context['request']
+ request = self.context["request"]
return project.owner == request.user.username
-class ApplicationModuleSerializer(
- proto_utils.create_serializer_class(ApplicationModule)):
+class ApplicationModuleSerializer(proto_utils.create_serializer_class(ApplicationModule)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-detail',
- lookup_field='appModuleId',
- lookup_url_kwarg='app_module_id')
+ view_name="django_airavata_api:application-detail", lookup_field="appModuleId", lookup_url_kwarg="app_module_id"
+ )
applicationInterface = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-application-interface',
- lookup_field='appModuleId',
- lookup_url_kwarg='app_module_id')
+ view_name="django_airavata_api:application-application-interface",
+ lookup_field="appModuleId",
+ lookup_url_kwarg="app_module_id",
+ )
applicationDeployments = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-application-deployments',
- lookup_field='appModuleId',
- lookup_url_kwarg='app_module_id')
+ view_name="django_airavata_api:application-application-deployments",
+ lookup_field="appModuleId",
+ lookup_url_kwarg="app_module_id",
+ )
userHasWriteAccess = serializers.SerializerMethodField()
class Meta:
- required = ('appModuleName',)
+ required = ("appModuleName",)
def get_userHasWriteAccess(self, appDeployment):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
class EnumChoiceField(serializers.ChoiceField):
def __init__(self, enum_class, **kwargs):
self.enum_class = enum_class
- kwargs['choices'] = [(member.name, member.name) for member in enum_class]
+ kwargs["choices"] = [(member.name, member.name) for member in enum_class]
super().__init__(**kwargs)
def to_internal_value(self, data):
@@ -304,11 +288,11 @@ class EnumChoiceField(serializers.ChoiceField):
try:
return self.enum_class(data)
except ValueError:
- self.fail('invalid_choice', input=data)
+ self.fail("invalid_choice", input=data)
try:
return self.enum_class[data]
except KeyError:
- self.fail('invalid_choice', input=data)
+ self.fail("invalid_choice", input=data)
def to_representation(self, value):
return value.name
@@ -338,6 +322,7 @@ class InputDataObjectTypeSerializer(serializers.Serializer):
setattr(instance, attr, value)
return instance
+
class OutputDataObjectTypeSerializer(serializers.Serializer):
name = serializers.CharField()
value = serializers.CharField(allow_blank=True, allow_null=True, required=False)
@@ -360,6 +345,7 @@ class OutputDataObjectTypeSerializer(serializers.Serializer):
setattr(instance, attr, value)
return instance
+
class ApplicationInterfaceDescriptionSerializer(serializers.Serializer):
applicationInterfaceId = serializers.CharField(required=False, allow_null=True, allow_blank=True)
applicationName = serializers.CharField()
@@ -371,26 +357,28 @@ class ApplicationInterfaceDescriptionSerializer(serializers.Serializer):
hasOptionalFileInputs = serializers.BooleanField(default=False, read_only=True)
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-interface-detail',
- lookup_field='applicationInterfaceId',
- lookup_url_kwarg='app_interface_id', read_only=True)
+ view_name="django_airavata_api:application-interface-detail",
+ lookup_field="applicationInterfaceId",
+ lookup_url_kwarg="app_interface_id",
+ read_only=True,
+ )
userHasWriteAccess = serializers.SerializerMethodField()
showQueueSettings = serializers.BooleanField(required=False)
queueSettingsCalculatorId = serializers.CharField(allow_null=True, required=False)
def create(self, validated_data):
# Convert inputs/outputs from dicts to Thrift objects
- inputs_data = validated_data.pop('applicationInputs', None)
- outputs_data = validated_data.pop('applicationOutputs', None)
+ inputs_data = validated_data.pop("applicationInputs", None)
+ outputs_data = validated_data.pop("applicationOutputs", None)
# Remove Django specific fields
- validated_data.pop('showQueueSettings', None)
- validated_data.pop('queueSettingsCalculatorId', None)
- validated_data.pop('url', None)
- validated_data.pop('userHasWriteAccess', None)
+ validated_data.pop("showQueueSettings", None)
+ validated_data.pop("queueSettingsCalculatorId", None)
+ validated_data.pop("url", None)
+ validated_data.pop("userHasWriteAccess", None)
- if 'applicationInterfaceId' in validated_data and validated_data['applicationInterfaceId'] is None:
- validated_data['applicationInterfaceId'] = ""
+ if "applicationInterfaceId" in validated_data and validated_data["applicationInterfaceId"] is None:
+ validated_data["applicationInterfaceId"] = ""
application_interface = ApplicationInterfaceDescription(**validated_data)
@@ -413,8 +401,8 @@ class ApplicationInterfaceDescriptionSerializer(serializers.Serializer):
application_module_id=application_module_id, defaults=defaults
)
- inputs_data = validated_data.pop('applicationInputs', None)
- outputs_data = validated_data.pop('applicationOutputs', None)
+ inputs_data = validated_data.pop("applicationInputs", None)
+ outputs_data = validated_data.pop("applicationOutputs", None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
@@ -427,68 +415,47 @@ class ApplicationInterfaceDescriptionSerializer(serializers.Serializer):
return instance
def get_userHasWriteAccess(self, appDeployment):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
-class CommandObjectSerializer(
- proto_utils.create_serializer_class(CommandObject)):
+class CommandObjectSerializer(proto_utils.create_serializer_class(CommandObject)):
pass
-class SetEnvPathsSerializer(
- proto_utils.create_serializer_class(SetEnvPaths)):
+class SetEnvPathsSerializer(proto_utils.create_serializer_class(SetEnvPaths)):
pass
-class ApplicationDeploymentDescriptionSerializer(
- proto_utils.create_serializer_class(
- ApplicationDeploymentDescription)):
+class ApplicationDeploymentDescriptionSerializer(proto_utils.create_serializer_class(ApplicationDeploymentDescription)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-deployment-detail',
- lookup_field='appDeploymentId',
- lookup_url_kwarg='app_deployment_id')
+ view_name="django_airavata_api:application-deployment-detail",
+ lookup_field="appDeploymentId",
+ lookup_url_kwarg="app_deployment_id",
+ )
# Default values returned in these results have been overridden with app
# deployment defaults for any that exist
queues = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:application-deployment-queues',
- lookup_field='appDeploymentId',
- lookup_url_kwarg='app_deployment_id')
+ view_name="django_airavata_api:application-deployment-queues",
+ lookup_field="appDeploymentId",
+ lookup_url_kwarg="app_deployment_id",
+ )
userHasWriteAccess = serializers.SerializerMethodField()
- moduleLoadCmds = OrderedListField(
- order_by='commandOrder',
- child=CommandObjectSerializer(),
- allow_null=True)
- preJobCommands = OrderedListField(
- order_by='commandOrder',
- child=CommandObjectSerializer(),
- allow_null=True)
- postJobCommands = OrderedListField(
- order_by='commandOrder',
- child=CommandObjectSerializer(),
- allow_null=True)
- libPrependPaths = OrderedListField(
- order_by='envPathOrder',
- child=SetEnvPathsSerializer(),
- allow_null=True)
- libAppendPaths = OrderedListField(
- order_by='envPathOrder',
- child=SetEnvPathsSerializer(),
- allow_null=True)
- setEnvironment = OrderedListField(
- order_by='envPathOrder',
- child=SetEnvPathsSerializer(),
- allow_null=True)
+ moduleLoadCmds = OrderedListField(order_by="commandOrder", child=CommandObjectSerializer(), allow_null=True)
+ preJobCommands = OrderedListField(order_by="commandOrder", child=CommandObjectSerializer(), allow_null=True)
+ postJobCommands = OrderedListField(order_by="commandOrder", child=CommandObjectSerializer(), allow_null=True)
+ libPrependPaths = OrderedListField(order_by="envPathOrder", child=SetEnvPathsSerializer(), allow_null=True)
+ libAppendPaths = OrderedListField(order_by="envPathOrder", child=SetEnvPathsSerializer(), allow_null=True)
+ setEnvironment = OrderedListField(order_by="envPathOrder", child=SetEnvPathsSerializer(), allow_null=True)
def get_userHasWriteAccess(self, appDeployment):
- request = self.context['request']
+ request = self.context["request"]
return request.airavata_client.sharing.user_has_access(
- appDeployment.appDeploymentId,
- ResourcePermissionType.WRITE)
+ appDeployment.appDeploymentId, ResourcePermissionType.WRITE
+ )
-class ComputeResourceDescriptionSerializer(
- proto_utils.create_serializer_class(ComputeResourceDescription)):
+class ComputeResourceDescriptionSerializer(proto_utils.create_serializer_class(ComputeResourceDescription)):
pass
@@ -496,58 +463,45 @@ class BatchQueueSerializer(proto_utils.create_serializer_class(BatchQueue)):
pass
-class ExperimentStatusSerializer(
- proto_utils.create_serializer_class(ExperimentStatus)):
+class ExperimentStatusSerializer(proto_utils.create_serializer_class(ExperimentStatus)):
timeOfStateChange = UTCPosixTimestampDateTimeField()
-class ProcessStatusSerializer(
- proto_utils.create_serializer_class(ProcessStatus)):
+class ProcessStatusSerializer(proto_utils.create_serializer_class(ProcessStatus)):
timeOfStateChange = UTCPosixTimestampDateTimeField()
-class ExperimentSerializer(
- proto_utils.create_serializer_class(ExperimentModel)):
+class ExperimentSerializer(proto_utils.create_serializer_class(ExperimentModel)):
class Meta:
- required = ('projectId', 'experimentType', 'experimentName')
- read_only = ('userName', 'gatewayId')
+ required = ("projectId", "experimentType", "experimentName")
+ read_only = ("userName", "gatewayId")
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:experiment-detail',
- lookup_field='experimentId',
- lookup_url_kwarg='experiment_id')
+ view_name="django_airavata_api:experiment-detail", lookup_field="experimentId", lookup_url_kwarg="experiment_id"
+ )
full_experiment = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:full-experiment-detail',
- lookup_field='experimentId',
- lookup_url_kwarg='experiment_id')
+ view_name="django_airavata_api:full-experiment-detail",
+ lookup_field="experimentId",
+ lookup_url_kwarg="experiment_id",
+ )
project = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:project-detail',
- lookup_field='projectId',
- lookup_url_kwarg='project_id')
+ view_name="django_airavata_api:project-detail", lookup_field="projectId", lookup_url_kwarg="project_id"
+ )
jobs = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:experiment-jobs',
- lookup_field='experimentId',
- lookup_url_kwarg='experiment_id')
+ view_name="django_airavata_api:experiment-jobs", lookup_field="experimentId", lookup_url_kwarg="experiment_id"
+ )
shared_entity = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:shared-entity-detail',
- lookup_field='experimentId',
- lookup_url_kwarg='entity_id')
- experimentInputs = OrderedListField(
- order_by='inputOrder',
- child=InputDataObjectTypeSerializer(),
- allow_null=True)
- experimentOutputs = serializers.ListField(
- child=OutputDataObjectTypeSerializer(),
- allow_null=True)
+ view_name="django_airavata_api:shared-entity-detail", lookup_field="experimentId", lookup_url_kwarg="entity_id"
+ )
+ experimentInputs = OrderedListField(order_by="inputOrder", child=InputDataObjectTypeSerializer(), allow_null=True)
+ experimentOutputs = serializers.ListField(child=OutputDataObjectTypeSerializer(), allow_null=True)
creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
experimentStatus = ExperimentStatusSerializer(many=True, allow_null=True)
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, experiment):
- request = self.context['request']
- return request.airavata_client.sharing.user_has_access(
- experiment.experimentId,
- ResourcePermissionType.WRITE)
+ request = self.context["request"]
+ return request.airavata_client.sharing.user_has_access(experiment.experimentId, ResourcePermissionType.WRITE)
def to_representation(self, experiment):
result = super().to_representation(experiment)
@@ -555,40 +509,41 @@ class ExperimentSerializer(
return result
def _add_intermediate_output_information(self, experiment, representation):
- request = self.context['request']
+ request = self.context["request"]
# If experiment is EXECUTING, add intermediateOutput information to
# experiment outputs
- if (experiment.experimentStatus and
- experiment.experimentStatus[-1].state == ExperimentState.EXECUTING):
+ if experiment.experimentStatus and experiment.experimentStatus[-1].state == ExperimentState.EXECUTING:
for output in representation["experimentOutputs"]:
output["intermediateOutput"] = {"processStatus": None}
try:
- can_fetch = experiment_util.intermediate_output.can_fetch_intermediate_output(request, experiment, output["name"])
+ can_fetch = experiment_util.intermediate_output.can_fetch_intermediate_output(
+ request, experiment, output["name"]
+ )
output["intermediateOutput"]["canFetch"] = can_fetch
process_status = experiment_util.intermediate_output.get_intermediate_output_process_status(
- request, experiment, output["name"])
+ request, experiment, output["name"]
+ )
if process_status:
- serializer = ProcessStatusSerializer(
- process_status, context={'request': request})
+ serializer = ProcessStatusSerializer(process_status, context={"request": request})
output["intermediateOutput"]["processStatus"] = serializer.data
data_products = experiment_util.intermediate_output.get_intermediate_output_data_products(
- request, experiment=experiment, output_name=output["name"])
+ request, experiment=experiment, output_name=output["name"]
+ )
data_product_serializer = DataProductSerializer(
- data_products, context={'request': request}, many=True)
+ data_products, context={"request": request}, many=True
+ )
output["intermediateOutput"]["dataProducts"] = data_product_serializer.data
except Exception:
log.debug("Failed to get intermediate output status", exc_info=True)
-class DataReplicaLocationSerializer(
- proto_utils.create_serializer_class(DataReplicaLocationModel)):
+class DataReplicaLocationSerializer(proto_utils.create_serializer_class(DataReplicaLocationModel)):
creationTime = UTCPosixTimestampDateTimeField()
lastModifiedTime = UTCPosixTimestampDateTimeField()
-class DataProductSerializer(
- proto_utils.create_serializer_class(DataProductModel)):
+class DataProductSerializer(proto_utils.create_serializer_class(DataProductModel)):
creationTime = UTCPosixTimestampDateTimeField()
modifiedTime = UTCPosixTimestampDateTimeField()
lastModifiedTime = UTCPosixTimestampDateTimeField()
@@ -600,7 +555,7 @@ class DataProductSerializer(
def get_downloadURL(self, data_product):
"""Getter for downloadURL field. Returns None if file is not available."""
- request = self.context['request']
+ request = self.context["request"]
if user_storage.exists(request, data_product):
return user_storage.get_lazy_download_url(request, data_product)
else:
@@ -608,20 +563,20 @@ class DataProductSerializer(
def get_isInputFileUpload(self, data_product):
"""Return True if this is an uploaded input file."""
- request = self.context['request']
+ request = self.context["request"]
return user_storage.is_input_file(request, data_product)
def get_filesize(self, data_product):
- request = self.context['request']
+ request = self.context["request"]
# For backwards compatibility with older user_storage, can be eventually removed
- if hasattr(user_storage, 'get_data_product_metadata') and user_storage.exists(request, data_product):
+ if hasattr(user_storage, "get_data_product_metadata") and user_storage.exists(request, data_product):
metadata = user_storage.get_data_product_metadata(request, data_product)
- return metadata['size']
+ return metadata["size"]
else:
return 0
def get_userHasWriteAccess(self, data_product: DataProductModel):
- request = self.context['request']
+ request = self.context["request"]
if user_storage.exists(request, data_product):
file_metadata = user_storage.get_data_product_metadata(request, data_product=data_product)
# In remote API mode, "userHasWriteAccess" is returned so we just pass it through here
@@ -642,9 +597,17 @@ class DataProductSerializer(
class FullExperiment:
"""Experiment with referenced data models."""
- def __init__(self, experimentModel, project=None, outputDataProducts=None,
- inputDataProducts=None, applicationModule=None,
- computeResource=None, jobDetails=None, outputViews=None):
+ def __init__(
+ self,
+ experimentModel,
+ project=None,
+ outputDataProducts=None,
+ inputDataProducts=None,
+ applicationModule=None,
+ computeResource=None,
+ jobDetails=None,
+ outputViews=None,
+ ):
self.experiment = experimentModel
self.experimentId = experimentModel.experimentId
self.project = project
@@ -662,9 +625,10 @@ class JobSerializer(proto_utils.create_serializer_class(JobModel)):
class FullExperimentSerializer(serializers.Serializer):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:full-experiment-detail',
- lookup_field='experimentId',
- lookup_url_kwarg='experiment_id')
+ view_name="django_airavata_api:full-experiment-detail",
+ lookup_field="experimentId",
+ lookup_url_kwarg="experiment_id",
+ )
experiment = ExperimentSerializer()
experimentId = serializers.CharField(read_only=True)
outputDataProducts = DataProductSerializer(many=True, read_only=True)
@@ -682,50 +646,42 @@ class FullExperimentSerializer(serializers.Serializer):
raise Exception("Not implemented")
-class BaseExperimentSummarySerializer(
- proto_utils.create_serializer_class(ExperimentSummaryModel)):
+class BaseExperimentSummarySerializer(proto_utils.create_serializer_class(ExperimentSummaryModel)):
creationTime = UTCPosixTimestampDateTimeField()
statusUpdateTime = UTCPosixTimestampDateTimeField()
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:experiment-detail',
- lookup_field='experimentId',
- lookup_url_kwarg='experiment_id')
+ view_name="django_airavata_api:experiment-detail", lookup_field="experimentId", lookup_url_kwarg="experiment_id"
+ )
project = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:project-detail',
- lookup_field='projectId',
- lookup_url_kwarg='project_id')
+ view_name="django_airavata_api:project-detail", lookup_field="projectId", lookup_url_kwarg="project_id"
+ )
class ExperimentSummarySerializer(BaseExperimentSummarySerializer):
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, experiment):
- request = self.context['request']
- return request.airavata_client.sharing.user_has_access(
- experiment.experimentId,
- ResourcePermissionType.WRITE)
+ request = self.context["request"]
+ return request.airavata_client.sharing.user_has_access(experiment.experimentId, ResourcePermissionType.WRITE)
-class UserProfileSerializer(
- proto_utils.create_serializer_class(UserProfile)):
+class UserProfileSerializer(proto_utils.create_serializer_class(UserProfile)):
creationTime = UTCPosixTimestampDateTimeField()
lastAccessTime = UTCPosixTimestampDateTimeField()
-class ComputeResourceReservationSerializer(
- proto_utils.create_serializer_class(ComputeResourceReservation)):
+class ComputeResourceReservationSerializer(proto_utils.create_serializer_class(ComputeResourceReservation)):
startTime = UTCPosixTimestampDateTimeField(allow_null=True)
endTime = UTCPosixTimestampDateTimeField(allow_null=True)
-class GroupComputeResourcePreferenceSerializer(
- proto_utils.create_serializer_class(GroupComputeResourcePreference)):
+class GroupComputeResourcePreferenceSerializer(proto_utils.create_serializer_class(GroupComputeResourcePreference)):
reservations = serializers.SerializerMethodField()
# Check if the object (e.g. SLURM type) has the 'reservations' attribute
def get_reservations(self, obj):
- if hasattr(obj, 'reservations'):
- reservations_data = getattr(obj, 'reservations')
+ if hasattr(obj, "reservations"):
+ reservations_data = obj.reservations
if reservations_data is not None:
return ComputeResourceReservationSerializer(reservations_data, many=True, context=self.context).data
@@ -735,7 +691,7 @@ class GroupComputeResourcePreferenceSerializer(
def _convert_nested_list_fields_to_thrift(slurm_pref):
from collections import OrderedDict
- if hasattr(slurm_pref, 'reservations') and slurm_pref.reservations:
+ if hasattr(slurm_pref, "reservations") and slurm_pref.reservations:
if isinstance(slurm_pref.reservations, list):
converted_reservations = []
for res in slurm_pref.reservations:
@@ -745,7 +701,7 @@ class GroupComputeResourcePreferenceSerializer(
converted_reservations.append(res)
slurm_pref.reservations = converted_reservations
- if hasattr(slurm_pref, 'groupSSHAccountProvisionerConfigs') and slurm_pref.groupSSHAccountProvisionerConfigs:
+ if hasattr(slurm_pref, "groupSSHAccountProvisionerConfigs") and slurm_pref.groupSSHAccountProvisionerConfigs:
if isinstance(slurm_pref.groupSSHAccountProvisionerConfigs, list):
converted_configs = []
for cfg in slurm_pref.groupSSHAccountProvisionerConfigs:
@@ -759,7 +715,7 @@ class GroupComputeResourcePreferenceSerializer(
def _convert_specific_preferences_dict_to_thrift(pref_instance, resource_type):
from collections import OrderedDict
- if not hasattr(pref_instance, 'specificPreferences'):
+ if not hasattr(pref_instance, "specificPreferences"):
return
if isinstance(pref_instance.specificPreferences, (dict, OrderedDict)):
@@ -771,8 +727,8 @@ class GroupComputeResourcePreferenceSerializer(
pref_instance.specificPreferences = union_type_class()
if resource_type == ResourceType.SLURM:
- if 'slurm' in specific_prefs_dict:
- slurm_data = specific_prefs_dict['slurm']
+ if "slurm" in specific_prefs_dict:
+ slurm_data = specific_prefs_dict["slurm"]
else:
slurm_data = specific_prefs_dict
@@ -780,8 +736,8 @@ class GroupComputeResourcePreferenceSerializer(
try:
from collections import OrderedDict
- if 'reservations' in slurm_data and slurm_data['reservations']:
- reservations_list = slurm_data['reservations']
+ if "reservations" in slurm_data and slurm_data["reservations"]:
+ reservations_list = slurm_data["reservations"]
if isinstance(reservations_list, list):
converted_reservations = []
for res in reservations_list:
@@ -789,10 +745,13 @@ class GroupComputeResourcePreferenceSerializer(
converted_reservations.append(ComputeResourceReservation(**res))
else:
converted_reservations.append(res)
- slurm_data['reservations'] = converted_reservations
+ slurm_data["reservations"] = converted_reservations
- if 'groupSSHAccountProvisionerConfigs' in slurm_data and slurm_data['groupSSHAccountProvisionerConfigs']:
- configs_list = slurm_data['groupSSHAccountProvisionerConfigs']
+ if (
+ "groupSSHAccountProvisionerConfigs" in slurm_data
+ and slurm_data["groupSSHAccountProvisionerConfigs"]
+ ):
+ configs_list = slurm_data["groupSSHAccountProvisionerConfigs"]
if isinstance(configs_list, list):
converted_configs = []
for cfg in configs_list:
@@ -800,30 +759,36 @@ class GroupComputeResourcePreferenceSerializer(
converted_configs.append(GroupAccountSSHProvisionerConfig(**cfg))
else:
converted_configs.append(cfg)
- slurm_data['groupSSHAccountProvisionerConfigs'] = converted_configs
+ slurm_data["groupSSHAccountProvisionerConfigs"] = converted_configs
slurm_pref = SlurmComputeResourcePreference(**slurm_data)
pref_instance.specificPreferences.slurm = slurm_pref
GroupComputeResourcePreferenceSerializer._convert_nested_list_fields_to_thrift(slurm_pref)
log.info(
"GCPreference: Converted specificPreferences dict to SLURM Thrift union type, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
except Exception as e:
log.error(
"GCPreference: Failed to create SlurmComputeResourcePreference from dict: %s, computeResourceId=%s",
str(e),
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
exc_info=True,
)
else:
log.info(
"GCPreference: specificPreferences dict is empty, created empty union type, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
elif resource_type == ResourceType.AWS:
- if 'aws' in specific_prefs_dict:
- aws_data = specific_prefs_dict['aws']
+ if "aws" in specific_prefs_dict:
+ aws_data = specific_prefs_dict["aws"]
else:
aws_data = specific_prefs_dict
@@ -833,24 +798,30 @@ class GroupComputeResourcePreferenceSerializer(
pref_instance.specificPreferences.aws = aws_pref
log.info(
"GCPreference: Converted specificPreferences dict to AWS Thrift union type, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
except Exception as e:
log.error(
"GCPreference: Failed to create AwsComputeResourcePreference from dict: %s, computeResourceId=%s",
str(e),
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
exc_info=True,
)
else:
log.info(
"GCPreference: specificPreferences dict is empty, created empty union type, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
else:
log.error(
"GCPreference: Could not get union type class to convert specificPreferences dict, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId if hasattr(pref_instance, "computeResourceId") else "unknown",
)
union_type_created = False
try:
@@ -860,7 +831,9 @@ class GroupComputeResourcePreferenceSerializer(
union_type_created = True
log.info(
"GCPreference: Created empty union type from test instance, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
except Exception as e:
log.warning(
@@ -869,7 +842,7 @@ class GroupComputeResourcePreferenceSerializer(
)
if not union_type_created:
- if hasattr(pref_instance, 'resourceType') and pref_instance.resourceType:
+ if hasattr(pref_instance, "resourceType") and pref_instance.resourceType:
try:
temp = GroupComputeResourcePreference(resourceType=pref_instance.resourceType)
if temp.specificPreferences is not None:
@@ -877,23 +850,27 @@ class GroupComputeResourcePreferenceSerializer(
union_type_created = True
log.info(
"GCPreference: Created empty union type using pref_instance.resourceType, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
)
except Exception as e2:
log.error(
"GCPreference: All attempts to create union type failed: %s, computeResourceId=%s",
str(e2),
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId
+ if hasattr(pref_instance, "computeResourceId")
+ else "unknown",
exc_info=True,
)
if not union_type_created:
log.error(
"GCPreference: Could not create union type at all! specificPreferences will remain as dict, computeResourceId=%s",
- pref_instance.computeResourceId if hasattr(pref_instance, 'computeResourceId') else 'unknown',
+ pref_instance.computeResourceId if hasattr(pref_instance, "computeResourceId") else "unknown",
)
else:
- if hasattr(pref_instance.specificPreferences, 'slurm') and pref_instance.specificPreferences.slurm:
+ if hasattr(pref_instance.specificPreferences, "slurm") and pref_instance.specificPreferences.slurm:
GroupComputeResourcePreferenceSerializer._convert_nested_list_fields_to_thrift(
pref_instance.specificPreferences.slurm
)
@@ -904,22 +881,22 @@ class GroupComputeResourcePreferenceSerializer(
"""
ret = super().to_representation(instance)
- if hasattr(instance, 'specificPreferences') and instance.specificPreferences:
- if hasattr(instance.specificPreferences, 'slurm') and instance.specificPreferences.slurm:
+ if hasattr(instance, "specificPreferences") and instance.specificPreferences:
+ if hasattr(instance.specificPreferences, "slurm") and instance.specificPreferences.slurm:
slurm_pref = instance.specificPreferences.slurm
- if hasattr(slurm_pref, 'allocationProjectNumber'):
- ret['allocationProjectNumber'] = slurm_pref.allocationProjectNumber
- if 'specificPreferences' in ret and isinstance(ret['specificPreferences'], dict):
- if 'slurm' not in ret['specificPreferences']:
- ret['specificPreferences'] = {'slurm': ret['specificPreferences']}
- elif hasattr(instance.specificPreferences, 'aws') and instance.specificPreferences.aws:
+ if hasattr(slurm_pref, "allocationProjectNumber"):
+ ret["allocationProjectNumber"] = slurm_pref.allocationProjectNumber
+ if "specificPreferences" in ret and isinstance(ret["specificPreferences"], dict):
+ if "slurm" not in ret["specificPreferences"]:
+ ret["specificPreferences"] = {"slurm": ret["specificPreferences"]}
+ elif hasattr(instance.specificPreferences, "aws") and instance.specificPreferences.aws:
aws_pref = instance.specificPreferences.aws
aws_fields = {
- 'region': getattr(aws_pref, 'region', None),
- 'preferredAmiId': getattr(aws_pref, 'preferredAmiId', None),
- 'preferredInstanceType': getattr(aws_pref, 'preferredInstanceType', None),
+ "region": getattr(aws_pref, "region", None),
+ "preferredAmiId": getattr(aws_pref, "preferredAmiId", None),
+ "preferredInstanceType": getattr(aws_pref, "preferredInstanceType", None),
}
- ret['specificPreferences'] = aws_fields
+ ret["specificPreferences"] = aws_fields
return ret
@@ -929,20 +906,24 @@ class GroupComputeResourcePreferenceSerializer(
"""
if isinstance(validated_data, GroupComputeResourcePreference):
resource_type = None
- if not hasattr(validated_data, 'resourceType') or validated_data.resourceType is None:
+ if not hasattr(validated_data, "resourceType") or validated_data.resourceType is None:
from collections import OrderedDict
- if hasattr(validated_data, 'specificPreferences') and validated_data.specificPreferences:
+
+ if hasattr(validated_data, "specificPreferences") and validated_data.specificPreferences:
if isinstance(validated_data.specificPreferences, (dict, OrderedDict)):
specific_prefs_dict = validated_data.specificPreferences
- if 'slurm' in specific_prefs_dict or 'allocationProjectNumber' in specific_prefs_dict:
+ if "slurm" in specific_prefs_dict or "allocationProjectNumber" in specific_prefs_dict:
resource_type = ResourceType.SLURM
- elif 'aws' in specific_prefs_dict or 'region' in specific_prefs_dict:
+ elif "aws" in specific_prefs_dict or "region" in specific_prefs_dict:
resource_type = ResourceType.AWS
else:
resource_type = ResourceType.SLURM
- elif hasattr(validated_data.specificPreferences, 'slurm') and validated_data.specificPreferences.slurm:
+ elif (
+ hasattr(validated_data.specificPreferences, "slurm")
+ and validated_data.specificPreferences.slurm
+ ):
resource_type = ResourceType.SLURM
- elif hasattr(validated_data.specificPreferences, 'aws') and validated_data.specificPreferences.aws:
+ elif hasattr(validated_data.specificPreferences, "aws") and validated_data.specificPreferences.aws:
resource_type = ResourceType.AWS
else:
resource_type = ResourceType.SLURM
@@ -961,13 +942,22 @@ class GroupComputeResourcePreferenceSerializer(
data = copy.deepcopy(validated_data)
- resource_type = data.get('resourceType')
+ resource_type = data.get("resourceType")
if resource_type is None:
- if 'allocationProjectNumber' in data or ('specificPreferences' in data and isinstance(data.get('specificPreferences'), dict) and 'slurm' in data.get('specificPreferences', {})):
+ if "allocationProjectNumber" in data or (
+ "specificPreferences" in data
+ and isinstance(data.get("specificPreferences"), dict)
+ and "slurm" in data.get("specificPreferences", {})
+ ):
resource_type = ResourceType.SLURM
- elif 'specificPreferences' in data and isinstance(data.get('specificPreferences'), dict) and 'aws' in data.get('specificPreferences', {}):
- resource_type = ResourceType.AWS
- elif 'region' in data or 'preferredAmiId' in data or 'preferredInstanceType' in data:
+ elif (
+ "specificPreferences" in data
+ and isinstance(data.get("specificPreferences"), dict)
+ and "aws" in data.get("specificPreferences", {})
+ or "region" in data
+ or "preferredAmiId" in data
+ or "preferredInstanceType" in data
+ ):
resource_type = ResourceType.AWS
else:
resource_type = ResourceType.SLURM
@@ -983,18 +973,24 @@ class GroupComputeResourcePreferenceSerializer(
except (ValueError, AttributeError):
resource_type = ResourceType.SLURM
- data['resourceType'] = resource_type
+ data["resourceType"] = resource_type
- specific_prefs = data.pop('specificPreferences', None)
+ specific_prefs = data.pop("specificPreferences", None)
slurm_data = {}
aws_data = {}
- slurm_fields = ['allocationProjectNumber', 'preferredBatchQueue', 'qualityOfService',
- 'usageReportingGatewayId', 'sshAccountProvisioner',
- 'groupSSHAccountProvisionerConfigs', 'sshAccountProvisionerAdditionalInfo',
- 'reservations']
- aws_fields = ['region', 'preferredAmiId', 'preferredInstanceType']
+ slurm_fields = [
+ "allocationProjectNumber",
+ "preferredBatchQueue",
+ "qualityOfService",
+ "usageReportingGatewayId",
+ "sshAccountProvisioner",
+ "groupSSHAccountProvisionerConfigs",
+ "sshAccountProvisionerAdditionalInfo",
+ "reservations",
+ ]
+ aws_fields = ["region", "preferredAmiId", "preferredInstanceType"]
for field in slurm_fields:
if field in data:
@@ -1023,8 +1019,8 @@ class GroupComputeResourcePreferenceSerializer(
if resource_type == ResourceType.SLURM and slurm_data:
from collections import OrderedDict
- if 'reservations' in slurm_data and slurm_data['reservations']:
- reservations_list = slurm_data['reservations']
+ if "reservations" in slurm_data and slurm_data["reservations"]:
+ reservations_list = slurm_data["reservations"]
if isinstance(reservations_list, list):
converted_reservations = []
for res in reservations_list:
@@ -1032,10 +1028,13 @@ class GroupComputeResourcePreferenceSerializer(
converted_reservations.append(ComputeResourceReservation(**res))
else:
converted_reservations.append(res)
- slurm_data['reservations'] = converted_reservations
+ slurm_data["reservations"] = converted_reservations
- if 'groupSSHAccountProvisionerConfigs' in slurm_data and slurm_data['groupSSHAccountProvisionerConfigs']:
- configs_list = slurm_data['groupSSHAccountProvisionerConfigs']
+ if (
+ "groupSSHAccountProvisionerConfigs" in slurm_data
+ and slurm_data["groupSSHAccountProvisionerConfigs"]
+ ):
+ configs_list = slurm_data["groupSSHAccountProvisionerConfigs"]
if isinstance(configs_list, list):
converted_configs = []
for cfg in configs_list:
@@ -1043,7 +1042,7 @@ class GroupComputeResourcePreferenceSerializer(
converted_configs.append(GroupAccountSSHProvisionerConfig(**cfg))
else:
converted_configs.append(cfg)
- slurm_data['groupSSHAccountProvisionerConfigs'] = converted_configs
+ slurm_data["groupSSHAccountProvisionerConfigs"] = converted_configs
slurm_pref = SlurmComputeResourcePreference(**slurm_data)
if union_type_class:
@@ -1056,9 +1055,7 @@ class GroupComputeResourcePreferenceSerializer(
instance.specificPreferences = type(test_instance.specificPreferences)()
instance.specificPreferences.slurm = slurm_pref
else:
- log.warning(
- "GCPreference create: Could not create union type, instance may be invalid"
- )
+ log.warning("GCPreference create: Could not create union type, instance may be invalid")
except Exception as e:
log.error(
"GCPreference create: Failed to set specificPreferences.slurm: %s",
@@ -1083,13 +1080,13 @@ class GroupComputeResourcePreferenceSerializer(
exc_info=True,
)
elif isinstance(specific_prefs, dict):
- if 'slurm' in specific_prefs:
- slurm_dict = specific_prefs['slurm'].copy() if isinstance(specific_prefs['slurm'], dict) else {}
+ if "slurm" in specific_prefs:
+ slurm_dict = specific_prefs["slurm"].copy() if isinstance(specific_prefs["slurm"], dict) else {}
slurm_dict.update(slurm_data)
from collections import OrderedDict
- if 'reservations' in slurm_dict and slurm_dict['reservations']:
- reservations_list = slurm_dict['reservations']
+ if "reservations" in slurm_dict and slurm_dict["reservations"]:
+ reservations_list = slurm_dict["reservations"]
if isinstance(reservations_list, list):
converted_reservations = []
for res in reservations_list:
@@ -1097,10 +1094,13 @@ class GroupComputeResourcePreferenceSerializer(
converted_reservations.append(ComputeResourceReservation(**res))
else:
converted_reservations.append(res)
- slurm_dict['reservations'] = converted_reservations
+ slurm_dict["reservations"] = converted_reservations
- if 'groupSSHAccountProvisionerConfigs' in slurm_dict and slurm_dict['groupSSHAccountProvisionerConfigs']:
- configs_list = slurm_dict['groupSSHAccountProvisionerConfigs']
+ if (
+ "groupSSHAccountProvisionerConfigs" in slurm_dict
+ and slurm_dict["groupSSHAccountProvisionerConfigs"]
+ ):
+ configs_list = slurm_dict["groupSSHAccountProvisionerConfigs"]
if isinstance(configs_list, list):
converted_configs = []
for cfg in configs_list:
@@ -1108,22 +1108,22 @@ class GroupComputeResourcePreferenceSerializer(
converted_configs.append(GroupAccountSSHProvisionerConfig(**cfg))
else:
converted_configs.append(cfg)
- slurm_dict['groupSSHAccountProvisionerConfigs'] = converted_configs
+ slurm_dict["groupSSHAccountProvisionerConfigs"] = converted_configs
slurm_pref = SlurmComputeResourcePreference(**slurm_dict)
if union_type_class:
instance.specificPreferences = union_type_class()
instance.specificPreferences.slurm = slurm_pref
- elif 'aws' in specific_prefs:
- aws_pref = AwsComputeResourcePreference(**specific_prefs['aws'])
+ elif "aws" in specific_prefs:
+ aws_pref = AwsComputeResourcePreference(**specific_prefs["aws"])
if union_type_class:
instance.specificPreferences = union_type_class()
instance.specificPreferences.aws = aws_pref
elif slurm_data:
from collections import OrderedDict
- if 'reservations' in slurm_data and slurm_data['reservations']:
- reservations_list = slurm_data['reservations']
+ if "reservations" in slurm_data and slurm_data["reservations"]:
+ reservations_list = slurm_data["reservations"]
if isinstance(reservations_list, list):
converted_reservations = []
for res in reservations_list:
@@ -1131,10 +1131,13 @@ class GroupComputeResourcePreferenceSerializer(
converted_reservations.append(ComputeResourceReservation(**res))
else:
converted_reservations.append(res)
- slurm_data['reservations'] = converted_reservations
+ slurm_data["reservations"] = converted_reservations
- if 'groupSSHAccountProvisionerConfigs' in slurm_data and slurm_data['groupSSHAccountProvisionerConfigs']:
- configs_list = slurm_data['groupSSHAccountProvisionerConfigs']
+ if (
+ "groupSSHAccountProvisionerConfigs" in slurm_data
+ and slurm_data["groupSSHAccountProvisionerConfigs"]
+ ):
+ configs_list = slurm_data["groupSSHAccountProvisionerConfigs"]
if isinstance(configs_list, list):
converted_configs = []
for cfg in configs_list:
@@ -1142,26 +1145,30 @@ class GroupComputeResourcePreferenceSerializer(
converted_configs.append(GroupAccountSSHProvisionerConfig(**cfg))
else:
converted_configs.append(cfg)
- slurm_data['groupSSHAccountProvisionerConfigs'] = converted_configs
+ slurm_data["groupSSHAccountProvisionerConfigs"] = converted_configs
slurm_pref = SlurmComputeResourcePreference(**slurm_data)
if union_type_class:
instance.specificPreferences = union_type_class()
instance.specificPreferences.slurm = slurm_pref
- if not hasattr(instance, 'resourceType') or instance.resourceType is None:
- if hasattr(instance, 'specificPreferences') and instance.specificPreferences:
+ if not hasattr(instance, "resourceType") or instance.resourceType is None:
+ if hasattr(instance, "specificPreferences") and instance.specificPreferences:
from collections import OrderedDict
+
if isinstance(instance.specificPreferences, (dict, OrderedDict)):
- if 'slurm' in instance.specificPreferences or 'allocationProjectNumber' in instance.specificPreferences:
+ if (
+ "slurm" in instance.specificPreferences
+ or "allocationProjectNumber" in instance.specificPreferences
+ ):
instance.resourceType = ResourceType.SLURM
- elif 'aws' in instance.specificPreferences or 'region' in instance.specificPreferences:
+ elif "aws" in instance.specificPreferences or "region" in instance.specificPreferences:
instance.resourceType = ResourceType.AWS
else:
instance.resourceType = ResourceType.SLURM
- elif hasattr(instance.specificPreferences, 'slurm') and instance.specificPreferences.slurm:
+ elif hasattr(instance.specificPreferences, "slurm") and instance.specificPreferences.slurm:
instance.resourceType = ResourceType.SLURM
- elif hasattr(instance.specificPreferences, 'aws') and instance.specificPreferences.aws:
+ elif hasattr(instance.specificPreferences, "aws") and instance.specificPreferences.aws:
instance.resourceType = ResourceType.AWS
else:
instance.resourceType = ResourceType.SLURM
@@ -1169,52 +1176,49 @@ class GroupComputeResourcePreferenceSerializer(
instance.resourceType = ResourceType.SLURM
log.warning(
"GCPreference create: Had to set resourceType=%s at end of create(), computeResourceId=%s",
- instance.resourceType.name if hasattr(instance.resourceType, 'name') else instance.resourceType,
- instance.computeResourceId if hasattr(instance, 'computeResourceId') else 'unknown',
+ instance.resourceType.name if hasattr(instance.resourceType, "name") else instance.resourceType,
+ instance.computeResourceId if hasattr(instance, "computeResourceId") else "unknown",
)
- if hasattr(instance, 'resourceType') and instance.resourceType:
+ if hasattr(instance, "resourceType") and instance.resourceType:
if instance.specificPreferences is None:
instance.specificPreferences = EnvironmentSpecificPreferences()
log.debug(
"GCPreference create: Initialized empty specificPreferences union type, computeResourceId=%s",
- instance.computeResourceId if hasattr(instance, 'computeResourceId') else 'unknown',
+ instance.computeResourceId if hasattr(instance, "computeResourceId") else "unknown",
)
self._convert_specific_preferences_dict_to_thrift(instance, instance.resourceType)
return instance
-class GroupResourceProfileSerializer(
- proto_utils.create_serializer_class(GroupResourceProfile)):
+class GroupResourceProfileSerializer(proto_utils.create_serializer_class(GroupResourceProfile)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:group-resource-profile-detail',
- lookup_field='groupResourceProfileId',
- lookup_url_kwarg='group_resource_profile_id')
+ view_name="django_airavata_api:group-resource-profile-detail",
+ lookup_field="groupResourceProfileId",
+ lookup_url_kwarg="group_resource_profile_id",
+ )
creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
updatedTime = UTCPosixTimestampDateTimeField(allow_null=True)
userHasWriteAccess = serializers.SerializerMethodField()
computePreferences = GroupComputeResourcePreferenceSerializer(many=True)
class Meta:
- required = ('groupResourceProfileName',)
+ required = ("groupResourceProfileName",)
def create(self, validated_data):
"""
Override create() to preserve Thrift instances in computePreferences.
"""
- compute_prefs = validated_data.get('computePreferences')
+ compute_prefs = validated_data.get("computePreferences")
if compute_prefs:
- all_thrift_instances = all(
- isinstance(item, GroupComputeResourcePreference)
- for item in compute_prefs
- )
+ all_thrift_instances = all(isinstance(item, GroupComputeResourcePreference) for item in compute_prefs)
if all_thrift_instances:
validated_data_copy = copy.deepcopy(validated_data)
- validated_data_copy['computePreferences'] = []
+ validated_data_copy["computePreferences"] = []
params = self.process_nested_fields(validated_data_copy)
- params['computePreferences'] = [copy.deepcopy(pref) for pref in compute_prefs]
+ params["computePreferences"] = [copy.deepcopy(pref) for pref in compute_prefs]
thrift_spec = GroupResourceProfile.thrift_spec
for field_spec in thrift_spec:
@@ -1229,8 +1233,8 @@ class GroupResourceProfileSerializer(
params = self.process_nested_fields(validated_data)
- if 'computePreferences' in params and params['computePreferences']:
- compute_prefs = params['computePreferences']
+ if "computePreferences" in params and params["computePreferences"]:
+ compute_prefs = params["computePreferences"]
processed_compute_prefs = []
for pref in compute_prefs:
if isinstance(pref, GroupComputeResourcePreference):
@@ -1240,23 +1244,27 @@ class GroupResourceProfileSerializer(
try:
log.debug(
"GCPreference create: Converting dict to Thrift instance, computeResourceId=%s",
- pref.get('computeResourceId', 'unknown'),
+ pref.get("computeResourceId", "unknown"),
)
thrift_pref = serializer.create(pref)
if isinstance(thrift_pref, GroupComputeResourcePreference):
log.debug(
"GCPreference create: Successfully created Thrift instance, computeResourceId=%s resourceType=%s",
- thrift_pref.computeResourceId if hasattr(thrift_pref, 'computeResourceId') else 'unknown',
- getattr(thrift_pref, 'resourceType', None),
+ thrift_pref.computeResourceId
+ if hasattr(thrift_pref, "computeResourceId")
+ else "unknown",
+ getattr(thrift_pref, "resourceType", None),
)
processed_compute_prefs.append(thrift_pref)
else:
log.warning(
"GCPreference create: serializer.create() returned non-Thrift instance: %s, type=%s",
- pref.get('computeResourceId', 'unknown'),
+ pref.get("computeResourceId", "unknown"),
type(thrift_pref).__name__,
)
- raise ValueError(f"serializer.create() returned {type(thrift_pref).__name__}, expected GroupComputeResourcePreference")
+ raise ValueError(
+ f"serializer.create() returned {type(thrift_pref).__name__}, expected GroupComputeResourcePreference"
+ )
except Exception as e:
log.warning(
"GCPreference create: Failed to convert dict to Thrift instance using serializer.create(): %s, trying direct construction",
@@ -1264,13 +1272,13 @@ class GroupResourceProfileSerializer(
exc_info=True,
)
pref_copy = copy.deepcopy(pref)
- if 'resourceType' not in pref_copy or pref_copy.get('resourceType') is None:
- if 'allocationProjectNumber' in pref_copy:
- pref_copy['resourceType'] = ResourceType.SLURM
- elif 'region' in pref_copy or 'preferredAmiId' in pref_copy:
- pref_copy['resourceType'] = ResourceType.AWS
+ if "resourceType" not in pref_copy or pref_copy.get("resourceType") is None:
+ if "allocationProjectNumber" in pref_copy:
+ pref_copy["resourceType"] = ResourceType.SLURM
+ elif "region" in pref_copy or "preferredAmiId" in pref_copy:
+ pref_copy["resourceType"] = ResourceType.AWS
else:
- pref_copy['resourceType'] = ResourceType.SLURM # Default
+ pref_copy["resourceType"] = ResourceType.SLURM # Default
try:
processed_compute_prefs.append(GroupComputeResourcePreference(**pref_copy))
except Exception as e2:
@@ -1282,7 +1290,7 @@ class GroupResourceProfileSerializer(
processed_compute_prefs.append(pref)
else:
processed_compute_prefs.append(pref)
- params['computePreferences'] = processed_compute_prefs
+ params["computePreferences"] = processed_compute_prefs
thrift_spec = GroupResourceProfile.thrift_spec
for field_spec in thrift_spec:
@@ -1296,25 +1304,26 @@ class GroupResourceProfileSerializer(
return GroupResourceProfile(**params)
def process_nested_fields(self, validated_data):
- compute_prefs = validated_data.get('computePreferences')
+ compute_prefs = validated_data.get("computePreferences")
if compute_prefs is None or compute_prefs == []:
validated_data_copy = copy.deepcopy(validated_data)
- validated_data_copy.pop('computePreferences', None)
+ validated_data_copy.pop("computePreferences", None)
params = self._process_nested_fields_base(validated_data_copy)
- params['computePreferences'] = compute_prefs if compute_prefs is not None else []
+ params["computePreferences"] = compute_prefs if compute_prefs is not None else []
return params
if compute_prefs and all(isinstance(item, GroupComputeResourcePreference) for item in compute_prefs):
validated_data_copy = copy.deepcopy(validated_data)
- validated_data_copy.pop('computePreferences', None)
+ validated_data_copy.pop("computePreferences", None)
params = self._process_nested_fields_base(validated_data_copy)
- params['computePreferences'] = compute_prefs
+ params["computePreferences"] = compute_prefs
return params
return self._process_nested_fields_base(validated_data)
def _process_nested_fields_base(self, validated_data):
from rest_framework.serializers import ListField, ListSerializer, Serializer
+
if not isinstance(validated_data, dict):
return validated_data
@@ -1322,30 +1331,31 @@ class GroupResourceProfileSerializer(
fields = self.fields
for field_name, serializer in fields.items():
- if (isinstance(serializer, ListField) or isinstance(serializer, ListSerializer)):
- if (params.get(field_name, None) is not None or not serializer.allow_null):
+ if isinstance(serializer, ListField) or isinstance(serializer, ListSerializer):
+ if params.get(field_name, None) is not None or not serializer.allow_null:
if isinstance(serializer.child, Serializer):
items = params[field_name]
if items and all(not isinstance(item, dict) for item in items):
continue
- if field_name == 'experimentInputs' and 'type' in serializer.child.fields:
+ if (
+ field_name == "experimentInputs"
+ and "type" in serializer.child.fields
+ or field_name == "experimentOutputs"
+ and "type" in serializer.child.fields
+ ):
for item in params[field_name]:
- if isinstance(item, dict) and 'type' in item and isinstance(item['type'], int):
- item['type'] = DataType(item['type'])
- elif field_name == 'experimentOutputs' and 'type' in serializer.child.fields:
+ if isinstance(item, dict) and "type" in item and isinstance(item["type"], int):
+ item["type"] = DataType(item["type"])
+ elif field_name == "experimentStatus" and "state" in serializer.child.fields:
for item in params[field_name]:
- if isinstance(item, dict) and 'type' in item and isinstance(item['type'], int):
- item['type'] = DataType(item['type'])
- elif field_name == 'experimentStatus' and 'state' in serializer.child.fields:
- for item in params[field_name]:
- if isinstance(item, dict) and 'state' in item and isinstance(item['state'], int):
- item['state'] = ExperimentState(item['state'])
+ if isinstance(item, dict) and "state" in item and isinstance(item["state"], int):
+ item["state"] = ExperimentState(item["state"])
processed_items = []
for item in params[field_name]:
if isinstance(item, dict):
- if hasattr(serializer.child, 'create'):
+ if hasattr(serializer.child, "create"):
try:
processed_items.append(serializer.child.create(item))
except NotImplementedError:
@@ -1361,7 +1371,7 @@ class GroupResourceProfileSerializer(
if field_name in params and params[field_name] is not None:
if not isinstance(params[field_name], dict):
continue
- if hasattr(serializer, 'create'):
+ if hasattr(serializer, "create"):
try:
params[field_name] = serializer.create(params[field_name])
except NotImplementedError:
@@ -1371,35 +1381,39 @@ class GroupResourceProfileSerializer(
def update(self, instance, validated_data):
# Merge existing computePreferences with incoming data to preserve fields that aren't being updated
- if 'computePreferences' in validated_data and instance.computePreferences:
+ if "computePreferences" in validated_data and instance.computePreferences:
existing_prefs_by_id = {
pref.computeResourceId: pref
for pref in instance.computePreferences
- if hasattr(pref, 'computeResourceId')
+ if hasattr(pref, "computeResourceId")
}
- for incoming_pref in validated_data['computePreferences']:
+ for incoming_pref in validated_data["computePreferences"]:
if isinstance(incoming_pref, dict):
- compute_resource_id = incoming_pref.get('computeResourceId')
+ compute_resource_id = incoming_pref.get("computeResourceId")
if compute_resource_id and compute_resource_id in existing_prefs_by_id:
existing_pref = existing_prefs_by_id[compute_resource_id]
- if 'specificPreferences' in incoming_pref and isinstance(incoming_pref['specificPreferences'], dict):
- if 'slurm' in incoming_pref['specificPreferences']:
- incoming_slurm = incoming_pref['specificPreferences']['slurm']
+ if "specificPreferences" in incoming_pref and isinstance(
+ incoming_pref["specificPreferences"], dict
+ ):
+ if "slurm" in incoming_pref["specificPreferences"]:
+ incoming_slurm = incoming_pref["specificPreferences"]["slurm"]
if isinstance(incoming_slurm, dict):
existing_slurm = None
- if (hasattr(existing_pref, 'specificPreferences') and
- existing_pref.specificPreferences and
- hasattr(existing_pref.specificPreferences, 'slurm') and
- existing_pref.specificPreferences.slurm):
+ if (
+ hasattr(existing_pref, "specificPreferences")
+ and existing_pref.specificPreferences
+ and hasattr(existing_pref.specificPreferences, "slurm")
+ and existing_pref.specificPreferences.slurm
+ ):
existing_slurm = existing_pref.specificPreferences.slurm
simple_string_fields = [
- 'preferredBatchQueue',
- 'qualityOfService',
- 'usageReportingGatewayId',
- 'sshAccountProvisioner',
- 'sshAccountProvisionerAdditionalInfo',
+ "preferredBatchQueue",
+ "qualityOfService",
+ "usageReportingGatewayId",
+ "sshAccountProvisioner",
+ "sshAccountProvisionerAdditionalInfo",
]
for field in simple_string_fields:
if incoming_slurm.get(field) is None and existing_slurm:
@@ -1414,29 +1428,43 @@ class GroupResourceProfileSerializer(
)
list_fields = [
- 'groupSSHAccountProvisionerConfigs',
- 'reservations',
+ "groupSSHAccountProvisionerConfigs",
+ "reservations",
]
for field in list_fields:
if incoming_slurm.get(field) is None and existing_slurm:
existing_value = getattr(existing_slurm, field, None)
- if existing_value is not None and isinstance(existing_value, list) and len(existing_value) > 0:
+ if (
+ existing_value is not None
+ and isinstance(existing_value, list)
+ and len(existing_value) > 0
+ ):
converted_list = []
for item in existing_value:
- if hasattr(item, '__dict__'):
- if field == 'reservations':
+ if hasattr(item, "__dict__"):
+ if field == "reservations":
try:
serializer = ComputeResourceReservationSerializer()
- converted_list.append(serializer.to_representation(item))
+ converted_list.append(
+ serializer.to_representation(item)
+ )
except Exception as e:
log.warning(
"GCPreference update: Could not serialize reservation item: %s",
str(e),
)
- item_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')}
+ item_dict = {
+ k: v
+ for k, v in item.__dict__.items()
+ if not k.startswith("_")
+ }
converted_list.append(item_dict)
else:
- item_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')}
+ item_dict = {
+ k: v
+ for k, v in item.__dict__.items()
+ if not k.startswith("_")
+ }
converted_list.append(item_dict)
else:
converted_list.append(item)
@@ -1448,43 +1476,46 @@ class GroupResourceProfileSerializer(
compute_resource_id,
)
- if 'computeResourcePolicies' in validated_data and instance.computeResourcePolicies:
+ if "computeResourcePolicies" in validated_data and instance.computeResourcePolicies:
existing_policies_by_resource_id = {
pol.computeResourceId: pol
for pol in instance.computeResourcePolicies
- if hasattr(pol, 'computeResourceId') and hasattr(pol, 'resourcePolicyId')
+ if hasattr(pol, "computeResourceId") and hasattr(pol, "resourcePolicyId")
}
- for incoming_policy in validated_data['computeResourcePolicies']:
+ for incoming_policy in validated_data["computeResourcePolicies"]:
if isinstance(incoming_policy, dict):
- compute_resource_id = incoming_policy.get('computeResourceId')
+ compute_resource_id = incoming_policy.get("computeResourceId")
if compute_resource_id and compute_resource_id in existing_policies_by_resource_id:
existing_policy = existing_policies_by_resource_id[compute_resource_id]
- if 'resourcePolicyId' not in incoming_policy or incoming_policy.get('resourcePolicyId') is None:
- incoming_policy['resourcePolicyId'] = existing_policy.resourcePolicyId
+ if "resourcePolicyId" not in incoming_policy or incoming_policy.get("resourcePolicyId") is None:
+ incoming_policy["resourcePolicyId"] = existing_policy.resourcePolicyId
log.debug(
"GCPreference update: Preserved existing resourcePolicyId=%s for computeResourceId=%s",
existing_policy.resourcePolicyId,
compute_resource_id,
)
- if 'batchQueueResourcePolicies' in validated_data and instance.batchQueueResourcePolicies:
+ if "batchQueueResourcePolicies" in validated_data and instance.batchQueueResourcePolicies:
existing_bq_policies_by_key = {}
for pol in instance.batchQueueResourcePolicies:
- if hasattr(pol, 'computeResourceId') and hasattr(pol, 'queuename') and hasattr(pol, 'resourcePolicyId'):
+ if hasattr(pol, "computeResourceId") and hasattr(pol, "queuename") and hasattr(pol, "resourcePolicyId"):
key = (pol.computeResourceId, pol.queuename)
existing_bq_policies_by_key[key] = pol
- for incoming_bq_policy in validated_data['batchQueueResourcePolicies']:
+ for incoming_bq_policy in validated_data["batchQueueResourcePolicies"]:
if isinstance(incoming_bq_policy, dict):
- compute_resource_id = incoming_bq_policy.get('computeResourceId')
- queuename = incoming_bq_policy.get('queuename')
+ compute_resource_id = incoming_bq_policy.get("computeResourceId")
+ queuename = incoming_bq_policy.get("queuename")
if compute_resource_id and queuename:
key = (compute_resource_id, queuename)
if key in existing_bq_policies_by_key:
existing_bq_policy = existing_bq_policies_by_key[key]
- if 'resourcePolicyId' not in incoming_bq_policy or incoming_bq_policy.get('resourcePolicyId') is None:
- incoming_bq_policy['resourcePolicyId'] = existing_bq_policy.resourcePolicyId
+ if (
+ "resourcePolicyId" not in incoming_bq_policy
+ or incoming_bq_policy.get("resourcePolicyId") is None
+ ):
+ incoming_bq_policy["resourcePolicyId"] = existing_bq_policy.resourcePolicyId
log.debug(
"GCPreference update: Preserved existing resourcePolicyId=%s for batchQueueResourcePolicy computeResourceId=%s queuename=%s",
existing_bq_policy.resourcePolicyId,
@@ -1503,65 +1534,62 @@ class GroupResourceProfileSerializer(
if isinstance(pref, GroupComputeResourcePreference):
pref_id = pref.computeResourceId
elif isinstance(pref, dict):
- pref_id = pref.get('computeResourceId')
+ pref_id = pref.get("computeResourceId")
else:
continue
if pref_id == compute_resource_preference.computeResourceId:
existing_compute_resource_preference = pref
break
if not existing_compute_resource_preference:
- result._removed_compute_resource_preferences.append(
- compute_resource_preference)
+ result._removed_compute_resource_preferences.append(compute_resource_preference)
# Find all compute resource policies that were removed
for compute_resource_policy in instance.computeResourcePolicies:
existing_compute_resource_policy = None
for pol in result.computeResourcePolicies:
- if hasattr(pol, 'resourcePolicyId'):
+ if hasattr(pol, "resourcePolicyId"):
pol_id = pol.resourcePolicyId
elif isinstance(pol, dict):
- pol_id = pol.get('resourcePolicyId')
+ pol_id = pol.get("resourcePolicyId")
else:
continue
if pol_id == compute_resource_policy.resourcePolicyId:
existing_compute_resource_policy = pol
break
if not existing_compute_resource_policy:
- result._removed_compute_resource_policies.append(
- compute_resource_policy)
+ result._removed_compute_resource_policies.append(compute_resource_policy)
# Find all batch queue resource policies that were removed
for batch_queue_resource_policy in instance.batchQueueResourcePolicies:
existing_batch_queue_resource_policy_for_update = None
for bq in result.batchQueueResourcePolicies:
- if hasattr(bq, 'resourcePolicyId'):
+ if hasattr(bq, "resourcePolicyId"):
bq_id = bq.resourcePolicyId
elif isinstance(bq, dict):
- bq_id = bq.get('resourcePolicyId')
+ bq_id = bq.get("resourcePolicyId")
else:
continue
if bq_id == batch_queue_resource_policy.resourcePolicyId:
existing_batch_queue_resource_policy_for_update = bq
break
if not existing_batch_queue_resource_policy_for_update:
- result._removed_batch_queue_resource_policies.append(
- batch_queue_resource_policy)
+ result._removed_batch_queue_resource_policies.append(batch_queue_resource_policy)
return result
def get_userHasWriteAccess(self, groupResourceProfile):
- request = self.context['request']
+ request = self.context["request"]
write_access = request.airavata_client.sharing.user_has_access(
- groupResourceProfile.groupResourceProfileId,
- ResourcePermissionType.WRITE)
+ groupResourceProfile.groupResourceProfileId, ResourcePermissionType.WRITE
+ )
if not write_access:
return False
# Check that user has READ access to all tokens in this
# GroupResourceProfile
- tokens = set([groupResourceProfile.defaultCredentialStoreToken] +
- [cp.resourceSpecificCredentialStoreToken
- for cp in groupResourceProfile.computePreferences])
+ tokens = set(
+ [groupResourceProfile.defaultCredentialStoreToken]
+ + [cp.resourceSpecificCredentialStoreToken for cp in groupResourceProfile.computePreferences]
+ )
def check_token(token):
- return token is None or request.airavata_client.sharing.user_has_access(
- token, ResourcePermissionType.READ)
+ return token is None or request.airavata_client.sharing.user_has_access(token, ResourcePermissionType.READ)
return all(map(check_token, tokens))
@@ -1591,12 +1619,11 @@ class SharedEntitySerializer(serializers.Serializer):
# Compute lists of ids to grant/revoke READ/WRITE/MANAGE_SHARING
# permission
existing_user_permissions = {
- user['user'].airavataInternalUserId: user['permissionType']
- for user in instance['userPermissions']}
+ user["user"].airavataInternalUserId: user["permissionType"] for user in instance["userPermissions"]
+ }
new_user_permissions = {
- user['user']['airavataInternalUserId']:
- user['permissionType']
- for user in validated_data['userPermissions']}
+ user["user"]["airavataInternalUserId"]: user["permissionType"] for user in validated_data["userPermissions"]
+ }
(
user_grant_read_permission,
@@ -1604,16 +1631,15 @@ class SharedEntitySerializer(serializers.Serializer):
user_grant_manage_sharing_permission,
user_revoke_read_permission,
user_revoke_write_permission,
- user_revoke_manage_sharing_permission) = self._compute_all_revokes_and_grants(
- existing_user_permissions,
- new_user_permissions)
+ user_revoke_manage_sharing_permission,
+ ) = self._compute_all_revokes_and_grants(existing_user_permissions, new_user_permissions)
existing_group_permissions = {
- group['group'].id: group['permissionType']
- for group in instance['groupPermissions']}
+ group["group"].id: group["permissionType"] for group in instance["groupPermissions"]
+ }
new_group_permissions = {
- group['group']['id']: group['permissionType']
- for group in validated_data['groupPermissions']}
+ group["group"]["id"]: group["permissionType"] for group in validated_data["groupPermissions"]
+ }
(
group_grant_read_permission,
@@ -1621,35 +1647,32 @@ class SharedEntitySerializer(serializers.Serializer):
group_grant_manage_sharing_permission,
group_revoke_read_permission,
group_revoke_write_permission,
- group_revoke_manage_sharing_permission) = self._compute_all_revokes_and_grants(
- existing_group_permissions,
- new_group_permissions)
-
- instance['_user_grant_read_permission'] = user_grant_read_permission
- instance['_user_grant_write_permission'] = user_grant_write_permission
- instance['_user_grant_manage_sharing_permission'] = user_grant_manage_sharing_permission
- instance['_user_revoke_read_permission'] = user_revoke_read_permission
- instance['_user_revoke_write_permission'] = user_revoke_write_permission
- instance['_user_revoke_manage_sharing_permission'] = user_revoke_manage_sharing_permission
- instance['_group_grant_read_permission'] = group_grant_read_permission
- instance['_group_grant_write_permission'] = group_grant_write_permission
- instance['_group_grant_manage_sharing_permission'] = group_grant_manage_sharing_permission
- instance['_group_revoke_read_permission'] = group_revoke_read_permission
- instance['_group_revoke_write_permission'] = group_revoke_write_permission
- instance['_group_revoke_manage_sharing_permission'] = group_revoke_manage_sharing_permission
- instance['userPermissions'] = [
- {'user': UserProfile(**data['user']),
- 'permissionType': data['permissionType']}
- for data in validated_data.get(
- 'userPermissions', instance['userPermissions'])]
- instance['groupPermissions'] = [
- {'group': GroupModel(**data['group']),
- 'permissionType': data['permissionType']}
- for data in validated_data.get('groupPermissions', instance['groupPermissions'])]
+ group_revoke_manage_sharing_permission,
+ ) = self._compute_all_revokes_and_grants(existing_group_permissions, new_group_permissions)
+
+ instance["_user_grant_read_permission"] = user_grant_read_permission
+ instance["_user_grant_write_permission"] = user_grant_write_permission
+ instance["_user_grant_manage_sharing_permission"] = user_grant_manage_sharing_permission
+ instance["_user_revoke_read_permission"] = user_revoke_read_permission
+ instance["_user_revoke_write_permission"] = user_revoke_write_permission
+ instance["_user_revoke_manage_sharing_permission"] = user_revoke_manage_sharing_permission
+ instance["_group_grant_read_permission"] = group_grant_read_permission
+ instance["_group_grant_write_permission"] = group_grant_write_permission
+ instance["_group_grant_manage_sharing_permission"] = group_grant_manage_sharing_permission
+ instance["_group_revoke_read_permission"] = group_revoke_read_permission
+ instance["_group_revoke_write_permission"] = group_revoke_write_permission
+ instance["_group_revoke_manage_sharing_permission"] = group_revoke_manage_sharing_permission
+ instance["userPermissions"] = [
+ {"user": UserProfile(**data["user"]), "permissionType": data["permissionType"]}
+ for data in validated_data.get("userPermissions", instance["userPermissions"])
+ ]
+ instance["groupPermissions"] = [
+ {"group": GroupModel(**data["group"]), "permissionType": data["permissionType"]}
+ for data in validated_data.get("groupPermissions", instance["groupPermissions"])
+ ]
return instance
- def _compute_all_revokes_and_grants(self, existing_permissions,
- new_permissions):
+ def _compute_all_revokes_and_grants(self, existing_permissions, new_permissions):
grant_read_permission = []
grant_write_permission = []
grant_manage_sharing_permission = []
@@ -1659,10 +1682,7 @@ class SharedEntitySerializer(serializers.Serializer):
# Union the two sets of user/group ids
all_ids = existing_permissions.keys() | new_permissions.keys()
for id in all_ids:
- revokes, grants = self._compute_revokes_and_grants(
- existing_permissions.get(id),
- new_permissions.get(id)
- )
+ revokes, grants = self._compute_revokes_and_grants(existing_permissions.get(id), new_permissions.get(id))
if ResourcePermissionType.READ in revokes:
revoke_read_permission.append(id)
if ResourcePermissionType.WRITE in revokes:
@@ -1681,17 +1701,15 @@ class SharedEntitySerializer(serializers.Serializer):
grant_manage_sharing_permission,
revoke_read_permission,
revoke_write_permission,
- revoke_manage_sharing_permission)
+ revoke_manage_sharing_permission,
+ )
- def _compute_revokes_and_grants(self, current_permission=None,
- new_permission=None):
+ def _compute_revokes_and_grants(self, current_permission=None, new_permission=None):
read_permissions = set((ResourcePermissionType.READ,))
- write_permissions = set((ResourcePermissionType.READ,
- ResourcePermissionType.WRITE))
+ write_permissions = set((ResourcePermissionType.READ, ResourcePermissionType.WRITE))
manage_share_permissions = set(
- (ResourcePermissionType.READ,
- ResourcePermissionType.WRITE,
- ResourcePermissionType.MANAGE_SHARING))
+ (ResourcePermissionType.READ, ResourcePermissionType.WRITE, ResourcePermissionType.MANAGE_SHARING)
+ )
current_permissions_set = set()
new_permissions_set = set()
if current_permission == ResourcePermissionType.READ:
@@ -1708,82 +1726,76 @@ class SharedEntitySerializer(serializers.Serializer):
new_permissions_set = manage_share_permissions
# return tuple: permissions to revoke and permissions to grant
- return (current_permissions_set - new_permissions_set,
- new_permissions_set - current_permissions_set)
+ return (current_permissions_set - new_permissions_set, new_permissions_set - current_permissions_set)
def get_isOwner(self, shared_entity):
- request = self.context['request']
- return shared_entity['owner'].userId == request.user.username
+ request = self.context["request"]
+ return shared_entity["owner"].userId == request.user.username
def get_hasSharingPermission(self, shared_entity):
- request = self.context['request']
+ request = self.context["request"]
return request.airavata_client.sharing.user_has_access(
- shared_entity['entityId'],
- ResourcePermissionType.MANAGE_SHARING)
+ shared_entity["entityId"], ResourcePermissionType.MANAGE_SHARING
+ )
-class CredentialSummarySerializer(
- proto_utils.create_serializer_class(CredentialSummary)):
+class CredentialSummarySerializer(proto_utils.create_serializer_class(CredentialSummary)):
type = proto_utils.ThriftEnumField(SummaryType)
persistedTime = UTCPosixTimestampDateTimeField()
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, credential_summary):
- request = self.context['request']
- return request.airavata_client.sharing.user_has_access(
- credential_summary.token,
- ResourcePermissionType.WRITE)
+ request = self.context["request"]
+ return request.airavata_client.sharing.user_has_access(credential_summary.token, ResourcePermissionType.WRITE)
-class StoragePreferenceSerializer(
- proto_utils.create_serializer_class(StoragePreference)):
+class StoragePreferenceSerializer(proto_utils.create_serializer_class(StoragePreference)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:storage-preference-detail',
- lookup_field='storageResourceId',
- lookup_url_kwarg='storage_resource_id')
+ view_name="django_airavata_api:storage-preference-detail",
+ lookup_field="storageResourceId",
+ lookup_url_kwarg="storage_resource_id",
+ )
def to_representation(self, instance):
ret = super().to_representation(instance)
# Convert empty string to null
- if ret['resourceSpecificCredentialStoreToken'] == '':
- ret['resourceSpecificCredentialStoreToken'] = None
+ if ret["resourceSpecificCredentialStoreToken"] == "":
+ ret["resourceSpecificCredentialStoreToken"] = None
return ret
-class GatewayResourceProfileSerializer(
- proto_utils.create_serializer_class(GatewayResourceProfile)):
+class GatewayResourceProfileSerializer(proto_utils.create_serializer_class(GatewayResourceProfile)):
storagePreferences = StoragePreferenceSerializer(many=True)
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, gatewayResourceProfile):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
-class StorageResourceSerializer(
- proto_utils.create_serializer_class(StorageResourceDescription)):
+class StorageResourceSerializer(proto_utils.create_serializer_class(StorageResourceDescription)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:storage-resource-detail',
- lookup_field='storageResourceId',
- lookup_url_kwarg='storage_resource_id')
+ view_name="django_airavata_api:storage-resource-detail",
+ lookup_field="storageResourceId",
+ lookup_url_kwarg="storage_resource_id",
+ )
creationTime = UTCPosixTimestampDateTimeField()
updateTime = UTCPosixTimestampDateTimeField()
class ParserSerializer(proto_utils.create_serializer_class(Parser)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:parser-detail',
- lookup_field='id',
- lookup_url_kwarg='parser_id')
+ view_name="django_airavata_api:parser-detail", lookup_field="id", lookup_url_kwarg="parser_id"
+ )
class UserHasWriteAccessToPathSerializer(serializers.Serializer):
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, instance):
- request = self.context['request']
+ request = self.context["request"]
# Special handling when using remote API to access user data storage
- if hasattr(settings, 'GATEWAY_DATA_STORE_REMOTE_API'):
+ if hasattr(settings, "GATEWAY_DATA_STORE_REMOTE_API"):
if "userHasWriteAccess" in instance:
return instance["userHasWriteAccess"]
elif instance.get("isDir", False):
@@ -1812,30 +1824,29 @@ class UserHasWriteAccessToPathSerializer(serializers.Serializer):
class UserStorageFileSerializer(UserHasWriteAccessToPathSerializer):
name = serializers.CharField()
downloadURL = serializers.SerializerMethodField()
- dataProductURI = serializers.CharField(source='data-product-uri')
- createdTime = serializers.DateTimeField(source='created_time')
- modifiedTime = serializers.DateTimeField(source='modified_time')
- mimeType = serializers.CharField(source='mime_type')
+ dataProductURI = serializers.CharField(source="data-product-uri")
+ createdTime = serializers.DateTimeField(source="created_time")
+ modifiedTime = serializers.DateTimeField(source="modified_time")
+ mimeType = serializers.CharField(source="mime_type")
size = serializers.IntegerField()
hidden = serializers.BooleanField()
def get_downloadURL(self, file):
"""Getter for downloadURL field."""
- request = self.context['request']
- return user_storage.get_lazy_download_url(request, data_product_uri=file['data-product-uri'])
+ request = self.context["request"]
+ return user_storage.get_lazy_download_url(request, data_product_uri=file["data-product-uri"])
class UserStorageDirectorySerializer(UserHasWriteAccessToPathSerializer):
name = serializers.CharField()
path = serializers.CharField()
- createdTime = serializers.DateTimeField(source='created_time')
- modifiedTime = serializers.DateTimeField(source='modified_time')
+ createdTime = serializers.DateTimeField(source="created_time")
+ modifiedTime = serializers.DateTimeField(source="modified_time")
size = serializers.IntegerField()
hidden = serializers.BooleanField()
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:user-storage-items',
- lookup_field='path',
- lookup_url_kwarg='path')
+ view_name="django_airavata_api:user-storage-items", lookup_field="path", lookup_url_kwarg="path"
+ )
isSharedDir = serializers.SerializerMethodField()
def get_isSharedDir(self, directory):
@@ -1861,19 +1872,20 @@ ExperimentStorageFileSerializer = UserStorageFileSerializer
class ExperimentStorageDirectorySerializer(serializers.Serializer):
name = serializers.CharField()
path = serializers.CharField()
- createdTime = serializers.DateTimeField(source='created_time')
- modifiedTime = serializers.DateTimeField(source='modified_time')
+ createdTime = serializers.DateTimeField(source="created_time")
+ modifiedTime = serializers.DateTimeField(source="modified_time")
size = serializers.IntegerField()
url = serializers.SerializerMethodField()
def get_url(self, dir):
- request = self.context['request']
+ request = self.context["request"]
return request.build_absolute_uri(
- reverse("django_airavata_api:experiment-storage-items", kwargs={
- "experiment_id": dir['experiment_id'],
- "path": dir['path']
- }))
+ reverse(
+ "django_airavata_api:experiment-storage-items",
+ kwargs={"experiment_id": dir["experiment_id"], "path": dir["path"]},
+ )
+ )
class ExperimentStoragePathSerializer(serializers.Serializer):
@@ -1887,16 +1899,15 @@ class ExperimentStoragePathSerializer(serializers.Serializer):
class ApplicationPreferencesSerializer(serializers.ModelSerializer):
class Meta:
model = models.ApplicationPreferences
- exclude = ('id', 'username', 'workspace_preferences')
+ exclude = ("id", "username", "workspace_preferences")
class WorkspacePreferencesSerializer(serializers.ModelSerializer):
- application_preferences = ApplicationPreferencesSerializer(
- source="applicationpreferences_set", many=True)
+ application_preferences = ApplicationPreferencesSerializer(source="applicationpreferences_set", many=True)
class Meta:
model = models.WorkspacePreferences
- exclude = ('username',)
+ exclude = ("username",)
class IAMUserProfile(serializers.Serializer):
@@ -1912,38 +1923,35 @@ class IAMUserProfile(serializers.Serializer):
creationTime = UTCPosixTimestampDateTimeField()
groups = GroupSerializer(many=True)
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:iam-user-profile-detail',
- lookup_field='userId',
- lookup_url_kwarg='user_id')
+ view_name="django_airavata_api:iam-user-profile-detail", lookup_field="userId", lookup_url_kwarg="user_id"
+ )
userHasWriteAccess = serializers.SerializerMethodField()
newUsername = serializers.CharField(write_only=True, required=False)
externalIDPUserInfo = serializers.SerializerMethodField()
userProfileInvalidFields = serializers.SerializerMethodField()
def update(self, instance, validated_data):
- existing_group_ids = [group.id for group in instance['groups']]
- new_group_ids = [group['id'] for group in validated_data['groups']]
- instance['_added_group_ids'] = list(
- set(new_group_ids) - set(existing_group_ids))
- instance['_removed_group_ids'] = list(
- set(existing_group_ids) - set(new_group_ids))
+ existing_group_ids = [group.id for group in instance["groups"]]
+ new_group_ids = [group["id"] for group in validated_data["groups"]]
+ instance["_added_group_ids"] = list(set(new_group_ids) - set(existing_group_ids))
+ instance["_removed_group_ids"] = list(set(existing_group_ids) - set(new_group_ids))
return instance
def get_userHasWriteAccess(self, userProfile):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
def get_externalIDPUserInfo(self, userProfile):
result = {}
try:
- if get_user_model().objects.filter(username=userProfile['userId']).exists():
- django_user = get_user_model().objects.get(username=userProfile['userId'])
+ if get_user_model().objects.filter(username=userProfile["userId"]).exists():
+ django_user = get_user_model().objects.get(username=userProfile["userId"])
claims = django_user.user_profile.idp_userinfo.all()
if claims.exists():
- result['idp_alias'] = claims.first().idp_alias
- result['userinfo'] = {}
+ result["idp_alias"] = claims.first().idp_alias
+ result["userinfo"] = {}
for claim in claims:
- result['userinfo'][claim.claim] = claim.value
+ result["userinfo"][claim.claim] = claim.value
except Exception as e:
log.warning(f"Failed to load idp_userinfo for {userProfile['userId']}", exc_info=e)
return result
@@ -1951,9 +1959,9 @@ class IAMUserProfile(serializers.Serializer):
def get_userProfileInvalidFields(self, userProfile):
try:
User = get_user_model()
- if User.objects.filter(username=userProfile['userId']).exists():
- django_user = User.objects.get(username=userProfile['userId'])
- if hasattr(django_user, 'user_profile'):
+ if User.objects.filter(username=userProfile["userId"]).exists():
+ django_user = User.objects.get(username=userProfile["userId"])
+ if hasattr(django_user, "user_profile"):
return django_user.user_profile.invalid_fields
else:
# For backwards compatibility, return True if no user_profile
@@ -1970,9 +1978,10 @@ class AckNotificationSerializer(serializers.ModelSerializer):
class NotificationSerializer(proto_utils.create_serializer_class(Notification)):
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:manage-notifications-detail',
- lookup_field='notificationId',
- lookup_url_kwarg='notification_id')
+ view_name="django_airavata_api:manage-notifications-detail",
+ lookup_field="notificationId",
+ lookup_url_kwarg="notification_id",
+ )
priority = proto_utils.ThriftEnumField(NotificationPriority)
creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
publishedTime = UTCPosixTimestampDateTimeField()
@@ -1981,7 +1990,7 @@ class NotificationSerializer(proto_utils.create_serializer_class(Notification)):
showInDashboard = serializers.BooleanField(default=False)
def get_userHasWriteAccess(self, userProfile):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
def validate(self, attrs):
@@ -1991,9 +2000,11 @@ class NotificationSerializer(proto_utils.create_serializer_class(Notification)):
def to_representation(self, notification):
notification_extension_list = models.NotificationExtension.objects.filter(
- notification_id=notification.notificationId)
- setattr(notification, "showInDashboard",
- False if len(notification_extension_list) == 0 else notification_extension_list[0].showInDashboard)
+ notification_id=notification.notificationId
+ )
+ notification.showInDashboard = (
+ False if len(notification_extension_list) == 0 else notification_extension_list[0].showInDashboard
+ )
return super().to_representation(notification)
@@ -2002,18 +2013,14 @@ class NotificationSerializer(proto_utils.create_serializer_class(Notification)):
existing_entries = models.NotificationExtension.objects.filter(notification_id=notification.notificationId)
if len(existing_entries) > 0:
- existing_entries.update(
- showInDashboard=request.data["showInDashboard"]
- )
+ existing_entries.update(showInDashboard=request.data["showInDashboard"])
else:
models.NotificationExtension.objects.create(
- notification_id=notification.notificationId,
- showInDashboard=request.data["showInDashboard"]
+ notification_id=notification.notificationId, showInDashboard=request.data["showInDashboard"]
)
-class ExperimentStatisticsSerializer(
- proto_utils.create_serializer_class(ExperimentStatistics)):
+class ExperimentStatisticsSerializer(proto_utils.create_serializer_class(ExperimentStatistics)):
allExperiments = BaseExperimentSummarySerializer(many=True)
completedExperiments = BaseExperimentSummarySerializer(many=True)
failedExperiments = BaseExperimentSummarySerializer(many=True)
@@ -2032,13 +2039,14 @@ class UnverifiedEmailUserProfile(serializers.Serializer):
emailVerified = serializers.BooleanField()
creationTime = UTCPosixTimestampDateTimeField()
url = FullyEncodedHyperlinkedIdentityField(
- view_name='django_airavata_api:unverified-email-user-profile-detail',
- lookup_field='userId',
- lookup_url_kwarg='user_id')
+ view_name="django_airavata_api:unverified-email-user-profile-detail",
+ lookup_field="userId",
+ lookup_url_kwarg="user_id",
+ )
userHasWriteAccess = serializers.SerializerMethodField()
def get_userHasWriteAccess(self, userProfile):
- request = self.context['request']
+ request = self.context["request"]
return request.is_gateway_admin
diff --git a/airavata-django-portal/django_airavata/apps/api/signals.py b/airavata-django-portal/django_airavata/apps/api/signals.py
index ceab29b86..8b25c161d 100644
--- a/airavata-django-portal/django_airavata/apps/api/signals.py
+++ b/airavata-django-portal/django_airavata/apps/api/signals.py
@@ -22,8 +22,8 @@ def create_user_storage_dir(sender, request, user, **kwargs):
path = ""
if not user_storage.dir_exists(request, path):
user_storage.create_user_dir(request, path)
- log.info("Created home directory for user {}".format(user.username))
+ log.info(f"Created home directory for user {user.username}")
- if hasattr(settings, 'GATEWAY_DATA_SHARED_DIRECTORIES'):
+ if hasattr(settings, "GATEWAY_DATA_SHARED_DIRECTORIES"):
for name, entry in settings.GATEWAY_DATA_SHARED_DIRECTORIES.items():
- user_storage.create_symlink(request, entry['path'], name)
+ user_storage.create_symlink(request, entry["path"], name)
diff --git a/airavata-django-portal/django_airavata/apps/api/tests/test_views.py b/airavata-django-portal/django_airavata/apps/api/tests/test_views.py
index e309185a7..94c904a06 100644
--- a/airavata-django-portal/django_airavata/apps/api/tests/test_views.py
+++ b/airavata-django-portal/django_airavata/apps/api/tests/test_views.py
@@ -1,56 +1,54 @@
from unittest.mock import MagicMock, call, patch
-from django_airavata.proto_compat import GatewayGroups, GroupModel, UserProfile
from django.contrib.auth.models import User
from django.test import TestCase, override_settings
from django.urls import reverse
+
# from rest_framework import status
from rest_framework.test import APIRequestFactory, force_authenticate
from django_airavata.apps.api import signals, views
+from django_airavata.proto_compat import GatewayGroups, GroupModel, UserProfile
GATEWAY_ID = "test-gateway"
-PORTAL_ADMINS = [('Admin Name', 'admin@example.com')]
+PORTAL_ADMINS = [("Admin Name", "admin@example.com")]
-@override_settings(
- GATEWAY_ID=GATEWAY_ID,
- PORTAL_ADMINS=PORTAL_ADMINS
-)
+@override_settings(GATEWAY_ID=GATEWAY_ID, PORTAL_ADMINS=PORTAL_ADMINS)
class GroupViewSetTests(TestCase):
-
def setUp(self):
- self.user = User.objects.create_user('testuser')
+ self.user = User.objects.create_user("testuser")
self.factory = APIRequestFactory()
def test_create_group_sends_user_added_to_group_signal(self):
- url = reverse('django_airavata_api:group-list')
+ url = reverse("django_airavata_api:group-list")
data = {
"id": None,
"name": "test",
"description": None,
"members": [
- f"{self.user.username}@{GATEWAY_ID}", # owner
- f"testuser1@{GATEWAY_ID}"],
- "admins": []
+ f"{self.user.username}@{GATEWAY_ID}", # owner
+ f"testuser1@{GATEWAY_ID}",
+ ],
+ "admins": [],
}
request = self.factory.post(url, data)
force_authenticate(request, self.user)
# Mock api clients
- group_manager_mock = MagicMock(name='group_manager')
- user_profile_mock = MagicMock(name='user_profile')
+ group_manager_mock = MagicMock(name="group_manager")
+ user_profile_mock = MagicMock(name="user_profile")
request.profile_service = {
- 'group_manager': group_manager_mock,
- 'user_profile': user_profile_mock,
+ "group_manager": group_manager_mock,
+ "user_profile": user_profile_mock,
}
request.airavata_client = MagicMock(name="airavata_client")
request.airavata_client.getGatewayGroups.return_value = GatewayGroups(
gatewayId=GATEWAY_ID,
adminsGroupId="adminsGroupId",
readOnlyAdminsGroupId="readOnlyAdminsGroupId",
- defaultGatewayUsersGroupId="defaultGatewayUsersGroupId"
+ defaultGatewayUsersGroupId="defaultGatewayUsersGroupId",
)
request.authz_token = "dummy"
request.session = {}
@@ -60,66 +58,67 @@ class GroupViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
user_profile_mock.getUserProfileById.return_value = user_profile
# Mock signal handler to verify 'user_added_to_group' signal is sent
user_added_to_group_handler = MagicMock()
- signals.user_added_to_group.connect(
- user_added_to_group_handler,
- sender=views.GroupViewSet)
- group_create = views.GroupViewSet.as_view({'post': 'create'})
+ signals.user_added_to_group.connect(user_added_to_group_handler, sender=views.GroupViewSet)
+ group_create = views.GroupViewSet.as_view({"post": "create"})
response = group_create(request)
- self.assertEquals(201, response.status_code)
- self.assertEquals("abc123", response.data['id'])
+ self.assertEqual(201, response.status_code)
+ self.assertEqual("abc123", response.data["id"])
user_added_to_group_handler.assert_called_once()
args, kwargs = user_added_to_group_handler.call_args
- self.assertEquals("abc123", kwargs["groups"][0].id)
+ self.assertEqual("abc123", kwargs["groups"][0].id)
self.assertIs(user_profile, kwargs["user"])
def test_update_group_sends_user_added_to_group_signal(self):
- url = reverse('django_airavata_api:group-detail',
- kwargs={'group_id': 'abc123'})
+ url = reverse("django_airavata_api:group-detail", kwargs={"group_id": "abc123"})
data = {
"id": "abc123",
"name": "test",
"description": None,
"members": [
- f"{self.user.username}@{GATEWAY_ID}", # owner
- f"testuser1@{GATEWAY_ID}", # existing member
- f"testuser3@{GATEWAY_ID}"], # new member
- "admins": []
+ f"{self.user.username}@{GATEWAY_ID}", # owner
+ f"testuser1@{GATEWAY_ID}", # existing member
+ f"testuser3@{GATEWAY_ID}",
+ ], # new member
+ "admins": [],
}
request = self.factory.put(url, data)
force_authenticate(request, self.user)
# Mock api clients
- group_manager_mock = MagicMock(name='group_manager')
- user_profile_mock = MagicMock(name='user_profile')
+ group_manager_mock = MagicMock(name="group_manager")
+ user_profile_mock = MagicMock(name="user_profile")
request.profile_service = {
- 'group_manager': group_manager_mock,
- 'user_profile': user_profile_mock,
+ "group_manager": group_manager_mock,
+ "user_profile": user_profile_mock,
}
request.airavata_client = MagicMock(name="airavata_client")
request.airavata_client.getGatewayGroups.return_value = GatewayGroups(
gatewayId=GATEWAY_ID,
adminsGroupId="adminsGroupId",
readOnlyAdminsGroupId="readOnlyAdminsGroupId",
- defaultGatewayUsersGroupId="defaultGatewayUsersGroupId"
+ defaultGatewayUsersGroupId="defaultGatewayUsersGroupId",
)
request.authz_token = "dummy"
request.session = {}
# mock getGroup
- group = GroupModel(id="abc123", name="My Group",
- ownerId=f"{self.user.username}@{GATEWAY_ID}",
- members=[
- f"{self.user.username}@{GATEWAY_ID}", # owner
- f"testuser1@{GATEWAY_ID}", # existing member
- f"testuser2@{GATEWAY_ID}", # new member
- ],
- admins=[])
+ group = GroupModel(
+ id="abc123",
+ name="My Group",
+ ownerId=f"{self.user.username}@{GATEWAY_ID}",
+ members=[
+ f"{self.user.username}@{GATEWAY_ID}", # owner
+ f"testuser1@{GATEWAY_ID}", # existing member
+ f"testuser2@{GATEWAY_ID}", # new member
+ ],
+ admins=[],
+ )
group_manager_mock.getGroup.return_value = group
# Only user added is testuser3, so getUserProfileById will be called
@@ -129,19 +128,17 @@ class GroupViewSetTests(TestCase):
userId="testuser3",
firstName="Test",
lastName="User3",
- emails=["testuser3@example.com"]
+ emails=["testuser3@example.com"],
)
user_profile_mock.getUserProfileById.return_value = user_profile
# Mock signal handler to verify 'user_added_to_group' signal is sent
user_added_to_group_handler = MagicMock()
- signals.user_added_to_group.connect(
- user_added_to_group_handler,
- sender=views.GroupViewSet)
- group_update = views.GroupViewSet.as_view({'put': 'update'})
+ signals.user_added_to_group.connect(user_added_to_group_handler, sender=views.GroupViewSet)
+ group_update = views.GroupViewSet.as_view({"put": "update"})
response = group_update(request, group_id="abc123")
- self.assertEquals(200, response.status_code)
- self.assertEquals("abc123", response.data['id'])
+ self.assertEqual(200, response.status_code)
+ self.assertEqual("abc123", response.data["id"])
# verify addUsersToGroup
group_manager_mock.addUsersToGroup.assert_called_once()
@@ -158,28 +155,21 @@ class GroupViewSetTests(TestCase):
user_added_to_group_handler.assert_called_once()
args, kwargs = user_added_to_group_handler.call_args
- self.assertEquals("abc123", kwargs["groups"][0].id)
+ self.assertEqual("abc123", kwargs["groups"][0].id)
self.assertIs(user_profile, kwargs["user"])
-@override_settings(
- GATEWAY_ID=GATEWAY_ID,
- PORTAL_ADMINS=PORTAL_ADMINS
-)
+@override_settings(GATEWAY_ID=GATEWAY_ID, PORTAL_ADMINS=PORTAL_ADMINS)
class IAMUserViewSetTests(TestCase):
-
def setUp(self):
- self.user = User.objects.create_user('testuser')
+ self.user = User.objects.create_user("testuser")
self.factory = APIRequestFactory()
@patch("django_airavata.apps.api.views.iam_admin_client")
- def test_update_that_adds_user_to_group_sends_user_added_to_group_signal(
- self, iam_admin_client):
+ def test_update_that_adds_user_to_group_sends_user_added_to_group_signal(self, iam_admin_client):
username = "testuser1"
- url = reverse(
- 'django_airavata_api:iam-user-profile-detail',
- kwargs={'user_id': username})
+ url = reverse("django_airavata_api:iam-user-profile-detail", kwargs={"user_id": username})
data = {
"airavataInternalUserId": f"{username}@{GATEWAY_ID}",
"userId": username,
@@ -190,10 +180,7 @@ class IAMUserViewSetTests(TestCase):
"airavataUserProfileExists": True,
"enabled": True,
"emailVerified": True,
- "groups": [
- {"id": "group1", "name": "Group 1"},
- {"id": "group2", "name": "Group 2"}
- ]
+ "groups": [{"id": "group1", "name": "Group 1"}, {"id": "group2", "name": "Group 2"}],
}
request = self.factory.put(url, data)
force_authenticate(request, self.user)
@@ -205,14 +192,14 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
iam_admin_client.get_user.return_value = iam_user_profile
- group_manager_mock = MagicMock(name='group_manager')
- user_profile_mock = MagicMock(name='user_profile')
+ group_manager_mock = MagicMock(name="group_manager")
+ user_profile_mock = MagicMock(name="user_profile")
request.profile_service = {
- 'group_manager': group_manager_mock,
- 'user_profile': user_profile_mock,
+ "group_manager": group_manager_mock,
+ "user_profile": user_profile_mock,
}
request.authz_token = "dummy"
user_profile_mock.doesUserExist.return_value = True
@@ -221,41 +208,34 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
user_profile_mock.getUserProfileById.return_value = user_profile
- group_manager_mock.getAllGroupsUserBelongs.return_value = [
- GroupModel(id="group1")]
- group = GroupModel(
- id="group2", name="Group 2"
- )
+ group_manager_mock.getAllGroupsUserBelongs.return_value = [GroupModel(id="group1")]
+ group = GroupModel(id="group2", name="Group 2")
group_manager_mock.getGroup.return_value = group
request.airavata_client = MagicMock(name="airavata_client")
request.airavata_client.getGatewayGroups.return_value = GatewayGroups(
gatewayId=GATEWAY_ID,
adminsGroupId="adminsGroupId",
readOnlyAdminsGroupId="readOnlyAdminsGroupId",
- defaultGatewayUsersGroupId="defaultGatewayUsersGroupId"
+ defaultGatewayUsersGroupId="defaultGatewayUsersGroupId",
)
request.session = {}
# Mock signal handler to verify 'user_added_to_group' signal is sent
- user_added_to_group_handler = MagicMock(
- name="user_added_to_group_handler")
- signals.user_added_to_group.connect(
- user_added_to_group_handler,
- sender=views.IAMUserViewSet)
- iam_user_update = views.IAMUserViewSet.as_view({'put': 'update'})
+ user_added_to_group_handler = MagicMock(name="user_added_to_group_handler")
+ signals.user_added_to_group.connect(user_added_to_group_handler, sender=views.IAMUserViewSet)
+ iam_user_update = views.IAMUserViewSet.as_view({"put": "update"})
response = iam_user_update(request, user_id=username)
- self.assertEquals(200, response.status_code)
+ self.assertEqual(200, response.status_code)
user_profile_mock.doesUserExist.assert_called_once()
group_manager_mock.getAllGroupsUserBelongs.assert_called_once()
user_profile_mock.getUserProfileById.assert_called_once()
args, kwargs = user_profile_mock.getUserProfileById.call_args
- self.assertSequenceEqual(
- args, [request.authz_token, "testuser1", GATEWAY_ID])
+ self.assertSequenceEqual(args, [request.authz_token, "testuser1", GATEWAY_ID])
group_manager_mock.getGroup.assert_called_once()
args, kwargs = group_manager_mock.getGroup.call_args
@@ -263,9 +243,7 @@ class IAMUserViewSetTests(TestCase):
group_manager_mock.addUsersToGroup.assert_called_once()
args, kwargs = group_manager_mock.addUsersToGroup.call_args
- self.assertSequenceEqual(
- args, [request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group2"]
- )
+ self.assertSequenceEqual(args, [request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group2"])
user_added_to_group_handler.assert_called_once()
args, kwargs = user_added_to_group_handler.call_args
@@ -274,13 +252,10 @@ class IAMUserViewSetTests(TestCase):
self.assertEqual(kwargs["groups"][0], group)
@patch("django_airavata.apps.api.views.iam_admin_client")
- def test_update_that_adds_user_to_multiple_groups(
- self, iam_admin_client):
+ def test_update_that_adds_user_to_multiple_groups(self, iam_admin_client):
username = "testuser1"
- url = reverse(
- 'django_airavata_api:iam-user-profile-detail',
- kwargs={'user_id': username})
+ url = reverse("django_airavata_api:iam-user-profile-detail", kwargs={"user_id": username})
data = {
"airavataInternalUserId": f"{username}@{GATEWAY_ID}",
"userId": username,
@@ -295,7 +270,7 @@ class IAMUserViewSetTests(TestCase):
{"id": "group1", "name": "Group 1"},
{"id": "group2", "name": "Group 2"},
{"id": "group3", "name": "Group 3"},
- ]
+ ],
}
request = self.factory.put(url, data)
force_authenticate(request, self.user)
@@ -307,14 +282,14 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
iam_admin_client.get_user.return_value = iam_user_profile
- group_manager_mock = MagicMock(name='group_manager')
- user_profile_mock = MagicMock(name='user_profile')
+ group_manager_mock = MagicMock(name="group_manager")
+ user_profile_mock = MagicMock(name="user_profile")
request.profile_service = {
- 'group_manager': group_manager_mock,
- 'user_profile': user_profile_mock,
+ "group_manager": group_manager_mock,
+ "user_profile": user_profile_mock,
}
request.authz_token = "dummy"
user_profile_mock.doesUserExist.return_value = True
@@ -323,11 +298,10 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
user_profile_mock.getUserProfileById.return_value = user_profile
- group_manager_mock.getAllGroupsUserBelongs.return_value = [
- GroupModel(id="group1")]
+ group_manager_mock.getAllGroupsUserBelongs.return_value = [GroupModel(id="group1")]
def side_effect(authz_token, group_id):
if group_id == "group2":
@@ -343,37 +317,35 @@ class IAMUserViewSetTests(TestCase):
gatewayId=GATEWAY_ID,
adminsGroupId="adminsGroupId",
readOnlyAdminsGroupId="readOnlyAdminsGroupId",
- defaultGatewayUsersGroupId="defaultGatewayUsersGroupId"
+ defaultGatewayUsersGroupId="defaultGatewayUsersGroupId",
)
request.session = {}
# Mock signal handler to verify 'user_added_to_group' signal is sent
- user_added_to_group_handler = MagicMock(
- name="user_added_to_group_handler")
- signals.user_added_to_group.connect(
- user_added_to_group_handler,
- sender=views.IAMUserViewSet)
- iam_user_update = views.IAMUserViewSet.as_view({'put': 'update'})
+ user_added_to_group_handler = MagicMock(name="user_added_to_group_handler")
+ signals.user_added_to_group.connect(user_added_to_group_handler, sender=views.IAMUserViewSet)
+ iam_user_update = views.IAMUserViewSet.as_view({"put": "update"})
response = iam_user_update(request, user_id=username)
- self.assertEquals(200, response.status_code)
+ self.assertEqual(200, response.status_code)
user_profile_mock.doesUserExist.assert_called_once()
group_manager_mock.getAllGroupsUserBelongs.assert_called_once()
user_profile_mock.getUserProfileById.assert_called_once()
args, kwargs = user_profile_mock.getUserProfileById.call_args
- self.assertSequenceEqual(
- args, [request.authz_token, "testuser1", GATEWAY_ID])
+ self.assertSequenceEqual(args, [request.authz_token, "testuser1", GATEWAY_ID])
- group_manager_mock.getGroup.assert_has_calls([
- call(request.authz_token, "group2"),
- call(request.authz_token, "group3")
- ], any_order=True)
+ group_manager_mock.getGroup.assert_has_calls(
+ [call(request.authz_token, "group2"), call(request.authz_token, "group3")], any_order=True
+ )
- group_manager_mock.addUsersToGroup.assert_has_calls([
- call(request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group2"),
- call(request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group3"),
- ], any_order=True)
+ group_manager_mock.addUsersToGroup.assert_has_calls(
+ [
+ call(request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group2"),
+ call(request.authz_token, [f"testuser1@{GATEWAY_ID}"], "group3"),
+ ],
+ any_order=True,
+ )
# user_added_to_group signal should only be called once, with both
# groups passed to it
@@ -381,17 +353,13 @@ class IAMUserViewSetTests(TestCase):
args, kwargs = user_added_to_group_handler.call_args
self.assertEqual(kwargs["sender"], views.IAMUserViewSet)
self.assertEqual(kwargs["user"], user_profile)
- self.assertSetEqual({"group2", "group3"},
- {g.id for g in kwargs["groups"]})
+ self.assertSetEqual({"group2", "group3"}, {g.id for g in kwargs["groups"]})
@patch("django_airavata.apps.api.views.iam_admin_client")
- def test_update_that_does_not_add_user_to_groups(
- self, iam_admin_client):
+ def test_update_that_does_not_add_user_to_groups(self, iam_admin_client):
username = "testuser1"
- url = reverse(
- 'django_airavata_api:iam-user-profile-detail',
- kwargs={'user_id': username})
+ url = reverse("django_airavata_api:iam-user-profile-detail", kwargs={"user_id": username})
data = {
"airavataInternalUserId": f"{username}@{GATEWAY_ID}",
"userId": username,
@@ -404,7 +372,7 @@ class IAMUserViewSetTests(TestCase):
"emailVerified": True,
"groups": [
{"id": "group1", "name": "Group 1"},
- ]
+ ],
}
request = self.factory.put(url, data)
force_authenticate(request, self.user)
@@ -416,14 +384,14 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
iam_admin_client.get_user.return_value = iam_user_profile
- group_manager_mock = MagicMock(name='group_manager')
- user_profile_mock = MagicMock(name='user_profile')
+ group_manager_mock = MagicMock(name="group_manager")
+ user_profile_mock = MagicMock(name="user_profile")
request.profile_service = {
- 'group_manager': group_manager_mock,
- 'user_profile': user_profile_mock,
+ "group_manager": group_manager_mock,
+ "user_profile": user_profile_mock,
}
request.authz_token = "dummy"
user_profile_mock.doesUserExist.return_value = True
@@ -432,30 +400,26 @@ class IAMUserViewSetTests(TestCase):
userId="testuser1",
firstName="Test",
lastName="User1",
- emails=["testuser1@example.com"]
+ emails=["testuser1@example.com"],
)
user_profile_mock.getUserProfileById.return_value = user_profile
- group_manager_mock.getAllGroupsUserBelongs.return_value = [
- GroupModel(id="group1")]
+ group_manager_mock.getAllGroupsUserBelongs.return_value = [GroupModel(id="group1")]
request.airavata_client = MagicMock(name="airavata_client")
request.airavata_client.getGatewayGroups.return_value = GatewayGroups(
gatewayId=GATEWAY_ID,
adminsGroupId="adminsGroupId",
readOnlyAdminsGroupId="readOnlyAdminsGroupId",
- defaultGatewayUsersGroupId="defaultGatewayUsersGroupId"
+ defaultGatewayUsersGroupId="defaultGatewayUsersGroupId",
)
request.session = {}
# Mock signal handler to verify 'user_added_to_group' signal is sent
- user_added_to_group_handler = MagicMock(
- name="user_added_to_group_handler")
- signals.user_added_to_group.connect(
- user_added_to_group_handler,
- sender=views.IAMUserViewSet)
- iam_user_update = views.IAMUserViewSet.as_view({'put': 'update'})
+ user_added_to_group_handler = MagicMock(name="user_added_to_group_handler")
+ signals.user_added_to_group.connect(user_added_to_group_handler, sender=views.IAMUserViewSet)
+ iam_user_update = views.IAMUserViewSet.as_view({"put": "update"})
response = iam_user_update(request, user_id=username)
- self.assertEquals(200, response.status_code)
+ self.assertEqual(200, response.status_code)
user_profile_mock.doesUserExist.assert_called_once()
group_manager_mock.getAllGroupsUserBelongs.assert_called_once()
@@ -468,24 +432,20 @@ class IAMUserViewSetTests(TestCase):
user_added_to_group_handler.assert_not_called()
-@override_settings(
- GATEWAY_ID=GATEWAY_ID,
- PORTAL_ADMINS=PORTAL_ADMINS
-)
+@override_settings(GATEWAY_ID=GATEWAY_ID, PORTAL_ADMINS=PORTAL_ADMINS)
class ExceptionHandlingTest(TestCase):
-
def setUp(self):
- self.user = User.objects.create_user('testuser')
+ self.user = User.objects.create_user("testuser")
self.factory = APIRequestFactory()
def test_unauthenticated_request(self):
- url = reverse('django_airavata_api:group-list')
+ url = reverse("django_airavata_api:group-list")
data = {}
request = self.factory.post(url, data)
# Deliberately not authenticating user for request
- group_create = views.GroupViewSet.as_view({'post': 'create'})
+ group_create = views.GroupViewSet.as_view({"post": "create"})
response = group_create(request)
- self.assertEquals(403, response.status_code)
- self.assertIn('is_authenticated', response.data)
- self.assertFalse(response.data['is_authenticated'])
+ self.assertEqual(403, response.status_code)
+ self.assertIn("is_authenticated", response.data)
+ self.assertFalse(response.data["is_authenticated"])
diff --git a/airavata-django-portal/django_airavata/apps/api/tus.py b/airavata-django-portal/django_airavata/apps/api/tus.py
index 5f1d6a31b..672a1ee61 100644
--- a/airavata-django-portal/django_airavata/apps/api/tus.py
+++ b/airavata-django-portal/django_airavata/apps/api/tus.py
@@ -19,23 +19,21 @@ def save_tus_upload(upload_url, save_function):
# file UUID is last path component in URL. For example:
# http://localhost:1080/files/2c44415fdb6259a22f425145b87d0840
upload_uuid = urlparse(upload_url).path.split("/")[-1]
- upload_bin_path = os.path.join(settings.TUS_DATA_DIR,
- f"{upload_uuid}.bin")
+ upload_bin_path = os.path.join(settings.TUS_DATA_DIR, f"{upload_uuid}.bin")
logger.debug(f"upload_bin_path={upload_bin_path}")
- upload_info_path = os.path.join(settings.TUS_DATA_DIR,
- f"{upload_uuid}.info")
+ upload_info_path = os.path.join(settings.TUS_DATA_DIR, f"{upload_uuid}.info")
if os.path.getsize(upload_bin_path) > settings.FILE_UPLOAD_MAX_FILE_SIZE:
- error_message = (f"File size of {upload_bin_path} is greater than "
- f"the max of {settings.FILE_UPLOAD_MAX_FILE_SIZE} "
- f"bytes")
+ error_message = (
+ f"File size of {upload_bin_path} is greater than the max of {settings.FILE_UPLOAD_MAX_FILE_SIZE} bytes"
+ )
logger.error(error_message)
os.remove(upload_bin_path)
os.remove(upload_info_path)
raise Exception(error_message)
with open(upload_info_path) as upload_info_file:
upload_info = json.load(upload_info_file)
- filename = upload_info['MetaData']['filename']
- filetype = upload_info['MetaData']['filetype']
+ filename = upload_info["MetaData"]["filename"]
+ filetype = upload_info["MetaData"]["filetype"]
result = save_function(upload_bin_path, filename, filetype)
os.remove(upload_bin_path)
os.remove(upload_info_path)
diff --git a/airavata-django-portal/django_airavata/apps/api/urls.py b/airavata-django-portal/django_airavata/apps/api/urls.py
index 474ebca1c..76478ab20 100644
--- a/airavata-django-portal/django_airavata/apps/api/urls.py
+++ b/airavata-django-portal/django_airavata/apps/api/urls.py
@@ -9,111 +9,76 @@ from . import views
logger = logging.getLogger(__name__)
router = routers.DefaultRouter()
-router.register(r'projects', views.ProjectViewSet, basename='project')
-router.register(r'experiments', views.ExperimentViewSet,
- basename='experiment')
-router.register(r'full-experiments', views.FullExperimentViewSet,
- basename='full-experiment')
-router.register(r'experiment-search', views.ExperimentSearchViewSet,
- basename='experiment-search')
-router.register(r'groups', views.GroupViewSet, basename='group')
-router.register(r'application-interfaces', views.ApplicationInterfaceViewSet,
- basename='application-interface')
-router.register(r'applications', views.ApplicationModuleViewSet,
- basename='application')
-router.register(r'application-deployments', views.ApplicationDeploymentViewSet,
- basename='application-deployment')
-router.register(r'user-profiles', views.UserProfileViewSet,
- basename='user-profile')
-router.register(r'group-resource-profiles', views.GroupResourceProfileViewSet,
- basename='group-resource-profile')
-router.register(r'shared-entities', views.SharedEntityViewSet,
- basename='shared-entity')
-router.register(r'compute-resources', views.ComputeResourceViewSet,
- basename='compute-resource')
-router.register(r'storage-resources', views.StorageResourceViewSet,
- basename='storage-resource')
-router.register(r'credential-summaries', views.CredentialSummaryViewSet,
- basename='credential-summary')
-router.register(r'storage-preferences',
- views.StoragePreferenceViewSet,
- basename='storage-preference')
-router.register(r'parsers', views.ParserViewSet, basename='parser')
-router.register(r'manage-notifications', views.ManageNotificationViewSet,
- basename='manage-notifications')
-router.register(r'iam-user-profiles', views.IAMUserViewSet,
- basename='iam-user-profile')
-router.register(r'unverified-email-users', views.UnverifiedEmailUserViewSet,
- basename='unverified-email-user-profile')
-router.register(r'queue-settings-calculators', views.QueueSettingsCalculatorViewSet,
- basename='queue-settings-calculator')
+router.register(r"projects", views.ProjectViewSet, basename="project")
+router.register(r"experiments", views.ExperimentViewSet, basename="experiment")
+router.register(r"full-experiments", views.FullExperimentViewSet, basename="full-experiment")
+router.register(r"experiment-search", views.ExperimentSearchViewSet, basename="experiment-search")
+router.register(r"groups", views.GroupViewSet, basename="group")
+router.register(r"application-interfaces", views.ApplicationInterfaceViewSet, basename="application-interface")
+router.register(r"applications", views.ApplicationModuleViewSet, basename="application")
+router.register(r"application-deployments", views.ApplicationDeploymentViewSet, basename="application-deployment")
+router.register(r"user-profiles", views.UserProfileViewSet, basename="user-profile")
+router.register(r"group-resource-profiles", views.GroupResourceProfileViewSet, basename="group-resource-profile")
+router.register(r"shared-entities", views.SharedEntityViewSet, basename="shared-entity")
+router.register(r"compute-resources", views.ComputeResourceViewSet, basename="compute-resource")
+router.register(r"storage-resources", views.StorageResourceViewSet, basename="storage-resource")
+router.register(r"credential-summaries", views.CredentialSummaryViewSet, basename="credential-summary")
+router.register(r"storage-preferences", views.StoragePreferenceViewSet, basename="storage-preference")
+router.register(r"parsers", views.ParserViewSet, basename="parser")
+router.register(r"manage-notifications", views.ManageNotificationViewSet, basename="manage-notifications")
+router.register(r"iam-user-profiles", views.IAMUserViewSet, basename="iam-user-profile")
+router.register(r"unverified-email-users", views.UnverifiedEmailUserViewSet, basename="unverified-email-user-profile")
+router.register(
+ r"queue-settings-calculators", views.QueueSettingsCalculatorViewSet, basename="queue-settings-calculator"
+)
-app_name = 'django_airavata_api'
+app_name = "django_airavata_api"
urlpatterns = [
- re_path(r'^upload$', views.upload_input_file, name='upload_input_file'),
- re_path(r'^tus-upload-finish$', views.tus_upload_finish,
- name='tus_upload_finish'),
- re_path(r'^download', views.download_file, name='download_file'),
- re_path(r'^delete-file$', views.delete_file, name='delete_file'),
- re_path(r'^data-products', views.DataProductView.as_view(),
- name='data-products-detail'),
- re_path(r'^job/submission/local', views.LocalJobSubmissionView.as_view(),
- name="local_job_submission"),
- re_path(r'^job/submission/cloud', views.CloudJobSubmissionView.as_view(),
- name="cloud_job_submission"),
- re_path(r'^job/submission/globus', views.GlobusJobSubmissionView.as_view(),
- name="globus_job_submission"),
- re_path(r'^job/submission/ssh', views.SshJobSubmissionView.as_view(),
- name="ssh_job_submission"),
- re_path(r'^job/submission/unicore', views.UnicoreJobSubmissionView.as_view(),
- name="unicore_job_submission"),
- re_path(r'^data/movement/gridftp', views.GridFtpDataMovementView.as_view(),
- name="grid_ftp_data_movement"),
- re_path(r'^data/movement/local', views.LocalDataMovementView.as_view(),
- name="local_ftp_data_movement"),
- re_path(r'^data/movement/unicore', views.UnicoreDataMovementView.as_view(),
- name="unicore_ftp_data_movement"),
- re_path(r'^data/movement/scp', views.ScpDataMovementView.as_view(),
- name="scp_ftp_data_movement"),
- re_path(r'^gateway-resource-profile',
- views.CurrentGatewayResourceProfile.as_view(),
- name="current_gateway_resource_profile"),
- re_path(r'^workspace-preferences',
- views.WorkspacePreferencesView.as_view(),
- name="workspace-preferences"),
- re_path(r'^user-storage/~/(?P<path>.*)$',
- views.UserStoragePathView.as_view(),
- name="user-storage-items"),
- re_path(r'^experiment-storage/(?P<experiment_id>[^/]+)/(?P<path>.*)$',
- views.ExperimentStoragePathView.as_view(),
- name="experiment-storage-items"),
- re_path(r'^experiment-statistics',
- views.ExperimentStatisticsView.as_view(),
- name="experiment-statistics"),
- re_path(r'ack-notifications/<slug:id>/',
- views.AckNotificationViewSet.as_view(), name="ack-notifications"),
- re_path(r'ack-notifications/', views.AckNotificationViewSet.as_view(),
- name="ack-notifications"),
- re_path(r'^log', views.LogRecordConsumer.as_view(), name='log'),
- re_path(r'^settings', views.SettingsAPIView.as_view(), name='settings'),
- re_path(r'^api-status-check/',
- views.APIServerStatusCheckView.as_view(),
- name='api-status-check'),
- re_path(r'^notebook-output',
- views.notebook_output_view, name="notebook-output"),
- re_path(r'^html-output',
- views.html_output_view, name="html-output"),
- re_path(r'^image-output',
- views.image_output_view, name="image-output"),
- re_path(r'^link-output',
- views.link_output_view, name="link-output"),
- re_path(r'^experiment-archives/(?P<experiment_id>[^/]+)/',
- views.ExperimentArchiveView.as_view(),
- name="experiment-archives"),
+ re_path(r"^upload$", views.upload_input_file, name="upload_input_file"),
+ re_path(r"^tus-upload-finish$", views.tus_upload_finish, name="tus_upload_finish"),
+ re_path(r"^download", views.download_file, name="download_file"),
+ re_path(r"^delete-file$", views.delete_file, name="delete_file"),
+ re_path(r"^data-products", views.DataProductView.as_view(), name="data-products-detail"),
+ re_path(r"^job/submission/local", views.LocalJobSubmissionView.as_view(), name="local_job_submission"),
+ re_path(r"^job/submission/cloud", views.CloudJobSubmissionView.as_view(), name="cloud_job_submission"),
+ re_path(r"^job/submission/globus", views.GlobusJobSubmissionView.as_view(), name="globus_job_submission"),
+ re_path(r"^job/submission/ssh", views.SshJobSubmissionView.as_view(), name="ssh_job_submission"),
+ re_path(r"^job/submission/unicore", views.UnicoreJobSubmissionView.as_view(), name="unicore_job_submission"),
+ re_path(r"^data/movement/gridftp", views.GridFtpDataMovementView.as_view(), name="grid_ftp_data_movement"),
+ re_path(r"^data/movement/local", views.LocalDataMovementView.as_view(), name="local_ftp_data_movement"),
+ re_path(r"^data/movement/unicore", views.UnicoreDataMovementView.as_view(), name="unicore_ftp_data_movement"),
+ re_path(r"^data/movement/scp", views.ScpDataMovementView.as_view(), name="scp_ftp_data_movement"),
+ re_path(
+ r"^gateway-resource-profile",
+ views.CurrentGatewayResourceProfile.as_view(),
+ name="current_gateway_resource_profile",
+ ),
+ re_path(r"^workspace-preferences", views.WorkspacePreferencesView.as_view(), name="workspace-preferences"),
+ re_path(r"^user-storage/~/(?P<path>.*)$", views.UserStoragePathView.as_view(), name="user-storage-items"),
+ re_path(
+ r"^experiment-storage/(?P<experiment_id>[^/]+)/(?P<path>.*)$",
+ views.ExperimentStoragePathView.as_view(),
+ name="experiment-storage-items",
+ ),
+ re_path(r"^experiment-statistics", views.ExperimentStatisticsView.as_view(), name="experiment-statistics"),
+ re_path(r"ack-notifications/<slug:id>/", views.AckNotificationViewSet.as_view(), name="ack-notifications"),
+ re_path(r"ack-notifications/", views.AckNotificationViewSet.as_view(), name="ack-notifications"),
+ re_path(r"^log", views.LogRecordConsumer.as_view(), name="log"),
+ re_path(r"^settings", views.SettingsAPIView.as_view(), name="settings"),
+ re_path(r"^api-status-check/", views.APIServerStatusCheckView.as_view(), name="api-status-check"),
+ re_path(r"^notebook-output", views.notebook_output_view, name="notebook-output"),
+ re_path(r"^html-output", views.html_output_view, name="html-output"),
+ re_path(r"^image-output", views.image_output_view, name="image-output"),
+ re_path(r"^link-output", views.link_output_view, name="link-output"),
+ re_path(
+ r"^experiment-archives/(?P<experiment_id>[^/]+)/",
+ views.ExperimentArchiveView.as_view(),
+ name="experiment-archives",
+ ),
]
urlpatterns = router.urls + format_suffix_patterns(urlpatterns)
if logger.isEnabledFor(logging.DEBUG):
for router_url in router.urls:
- logger.debug("router url: {}".format(router_url))
+ logger.debug(f"router url: {router_url}")
diff --git a/airavata-django-portal/django_airavata/apps/api/view_utils.py b/airavata-django-portal/django_airavata/apps/api/view_utils.py
index 30a87820c..46dc72efa 100644
--- a/airavata-django-portal/django_airavata/apps/api/view_utils.py
+++ b/airavata-django-portal/django_airavata/apps/api/view_utils.py
@@ -22,7 +22,7 @@ class GenericAPIBackedViewSet(GenericViewSet):
# Make lookup_value_regex to any set of non-forward-slash characters. Many
# Airavata ids contains period ('.') which the default lookup_value_regex
# in DRF doesn't allow.
- lookup_value_regex = '[^/]+'
+ lookup_value_regex = "[^/]+"
def get_list(self):
"""
@@ -67,12 +67,10 @@ class GenericAPIBackedViewSet(GenericViewSet):
def authz_token(self):
# Deprecated: SDK facade handles auth internally.
# Kept for backward compatibility with code that references self.authz_token.
- return getattr(self.request, 'authz_token', None)
+ return getattr(self.request, "authz_token", None)
-class ReadOnlyAPIBackedViewSet(mixins.RetrieveModelMixin,
- mixins.ListModelMixin,
- GenericAPIBackedViewSet):
+class ReadOnlyAPIBackedViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericAPIBackedViewSet):
"""
A viewset that provides default `retrieve()` and `list()` actions.
@@ -80,15 +78,18 @@ class ReadOnlyAPIBackedViewSet(mixins.RetrieveModelMixin,
* get_list(self)
* get_instance(self, lookup_value)
"""
+
pass
-class APIBackedViewSet(mixins.CreateModelMixin,
- mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.DestroyModelMixin,
- mixins.ListModelMixin,
- GenericAPIBackedViewSet):
+class APIBackedViewSet(
+ mixins.CreateModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ mixins.ListModelMixin,
+ GenericAPIBackedViewSet,
+):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
@@ -100,10 +101,11 @@ class APIBackedViewSet(mixins.CreateModelMixin,
* perform_update(self, serializer)
* perform_destroy(self, instance)
"""
+
pass
-class APIResultIterator(object):
+class APIResultIterator:
"""
Iterable container over API results which allow limit/offset style slicing.
"""
@@ -137,11 +139,11 @@ class APIResultPagination(pagination.LimitOffsetPagination):
have a known count, so it isn't always possible to know how many pages there
are.
"""
+
default_limit = 10
def paginate_queryset(self, queryset, request, view=None):
- assert isinstance(
- queryset, APIResultIterator), "queryset is not an APIResultIterator: {}".format(queryset)
+ assert isinstance(queryset, APIResultIterator), f"queryset is not an APIResultIterator: {queryset}"
self.query_params = queryset.query_params.copy()
self.limit = self.get_limit(request)
if self.limit is None:
@@ -153,27 +155,30 @@ class APIResultPagination(pagination.LimitOffsetPagination):
# When a paged view is called from another view (for example, to get the
# initial data to display), this pagination class needs to know the name
# of the view being paginated.
- if view and hasattr(view, 'pagination_viewname'):
+ if view and hasattr(view, "pagination_viewname"):
self.viewname = view.pagination_viewname
- return list(queryset[self.offset:self.offset + self.limit])
+ return list(queryset[self.offset : self.offset + self.limit])
def get_limit(self, request):
# If limit <= 0 then don't paginate
- if self.limit_query_param in request.query_params and int(
- request.query_params[self.limit_query_param]) <= 0:
+ if self.limit_query_param in request.query_params and int(request.query_params[self.limit_query_param]) <= 0:
return None
return super().get_limit(request)
def get_paginated_response(self, data):
has_next_link = len(data) >= self.limit
- return Response(OrderedDict([
- ('next', self.get_next_link() if has_next_link else None),
- ('previous', self.get_previous_link()),
- ('results', data),
- ('limit', self.limit),
- ('offset', self.offset)
- ]))
+ return Response(
+ OrderedDict(
+ [
+ ("next", self.get_next_link() if has_next_link else None),
+ ("previous", self.get_previous_link()),
+ ("results", data),
+ ("limit", self.limit),
+ ("offset", self.offset),
+ ]
+ )
+ )
def get_next_link(self):
url = self.get_base_url()
@@ -196,7 +201,7 @@ class APIResultPagination(pagination.LimitOffsetPagination):
return replace_query_param(url, self.offset_query_param, offset)
def get_base_url(self):
- if hasattr(self, 'viewname'):
+ if hasattr(self, "viewname"):
base_url = self.request.build_absolute_uri(reverse(self.viewname))
if len(self.query_params) > 0:
base_url += f"?{self.query_params.urlencode()}"
@@ -208,11 +213,9 @@ class APIResultPagination(pagination.LimitOffsetPagination):
def convert_utc_iso8601_to_date(iso8601_utc_string):
# This is meant to convert a JavaScript `new Date().toJSON()` into a
# datetime instance
- timestamp = datetime.strptime(
- iso8601_utc_string, "%Y-%m-%dT%H:%M:%S.%fZ")
+ timestamp = datetime.strptime(iso8601_utc_string, "%Y-%m-%dT%H:%M:%S.%fZ")
timestamp = timestamp.replace(tzinfo=pytz.UTC)
- logger.debug("convert_utc_iso8601_to_date({})={}".format(
- iso8601_utc_string, timestamp))
+ logger.debug(f"convert_utc_iso8601_to_date({iso8601_utc_string})={timestamp}")
return timestamp
@@ -222,8 +225,7 @@ class IsInAdminsGroupPermission(permissions.BasePermission):
def has_permission(self, request, view):
# Read Only Admins can make GET requests only
if request.method in permissions.SAFE_METHODS:
- return (request.is_gateway_admin or
- request.is_read_only_gateway_admin)
+ return request.is_gateway_admin or request.is_read_only_gateway_admin
else:
return request.is_gateway_admin
@@ -234,12 +236,12 @@ class ReadOnly(permissions.BasePermission):
def is_shared_dir(path):
- shared_dirs: dict = getattr(settings, 'GATEWAY_DATA_SHARED_DIRECTORIES', {})
+ shared_dirs: dict = getattr(settings, "GATEWAY_DATA_SHARED_DIRECTORIES", {})
return any(map(lambda n: Path(n) == Path(path), shared_dirs.keys()))
def is_shared_path(path):
- shared_dirs: dict = getattr(settings, 'GATEWAY_DATA_SHARED_DIRECTORIES', {})
+ shared_dirs: dict = getattr(settings, "GATEWAY_DATA_SHARED_DIRECTORIES", {})
# FIXME: path returned when creating a new directory in user storage is an
# absolute path. Assume that when an absolute path is given that it was for
# a newly created directory and so it is not a shared path
@@ -264,7 +266,7 @@ class BaseSharedDirPermission(permissions.BasePermission):
shared_dir = is_shared_dir(path)
if shared_path:
# No user can delete a shared directory
- if shared_dir and request.method == 'DELETE':
+ if shared_dir and request.method == "DELETE":
return False
# Only admins can create/update/delete files/directories in a shared directory
return request.is_gateway_admin
@@ -274,16 +276,16 @@ class BaseSharedDirPermission(permissions.BasePermission):
class DataProductSharedDirPermission(BaseSharedDirPermission):
def get_path(self, request, view) -> str:
- data_product_uri = request.query_params.get('data-product-uri', request.query_params.get('product-uri', ''))
+ data_product_uri = request.query_params.get("data-product-uri", request.query_params.get("product-uri", ""))
file_metadata = user_storage.get_data_product_metadata(request, data_product_uri=data_product_uri)
return file_metadata["path"]
def has_permission(self, request, view):
# Special handling for remote API, just get the userHasWriteAccess attribute and use that
- if hasattr(settings, 'GATEWAY_DATA_STORE_REMOTE_API'):
+ if hasattr(settings, "GATEWAY_DATA_STORE_REMOTE_API"):
if request.method in permissions.SAFE_METHODS:
return True
- data_product_uri = request.query_params.get('data-product-uri', request.query_params.get('product-uri', ''))
+ data_product_uri = request.query_params.get("data-product-uri", request.query_params.get("product-uri", ""))
file_metadata = user_storage.get_data_product_metadata(request, data_product_uri=data_product_uri)
return file_metadata["userHasWriteAccess"]
else:
@@ -291,7 +293,6 @@ class DataProductSharedDirPermission(BaseSharedDirPermission):
class UserStorageSharedDirPermission(BaseSharedDirPermission):
-
def get_path(self, request, view):
# 'path' can be a url path parameter, query parameter or in the request body (data)
- return request.query_params.get('path', request.data.get('path', view.kwargs.get('path')))
+ return request.query_params.get("path", request.data.get("path", view.kwargs.get("path")))
diff --git a/airavata-django-portal/django_airavata/apps/api/views.py b/airavata-django-portal/django_airavata/apps/api/views.py
index 3f2ea46fe..68850fda8 100644
--- a/airavata-django-portal/django_airavata/apps/api/views.py
+++ b/airavata-django-portal/django_airavata/apps/api/views.py
@@ -5,34 +5,7 @@ import os
import warnings
from datetime import datetime, timedelta
-from django_airavata.proto_compat import (
- BatchQueueResourcePolicy,
- CloudJobSubmission,
- ComputeResourcePolicy,
- ComputeResourceReservation,
- DataType,
- ExperimentModel,
- ExperimentSearchFields,
- GlobusJobSubmission,
- GridFTPDataMovement,
- GroupAccountSSHProvisionerConfig,
- GroupComputeResourcePreference,
- LOCALDataMovement,
- LOCALSubmission,
- ResourcePermissionType,
- ResourceType,
- SCPDataMovement,
- SSHJobSubmission,
- Status,
- SummaryType,
- UnicoreDataMovement,
- UnicoreJobSubmission,
-)
-from airavata_django_portal_sdk import (
- experiment_util,
- user_storage
-)
-from . import queue_settings as queue_settings_calculators
+from airavata_django_portal_sdk import experiment_util, user_storage
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
@@ -56,32 +29,47 @@ from django_airavata.apps.api.view_utils import (
DataProductSharedDirPermission,
GenericAPIBackedViewSet,
IsInAdminsGroupPermission,
- UserStorageSharedDirPermission
+ UserStorageSharedDirPermission,
)
from django_airavata.apps.auth import iam_admin_client
from django_airavata.apps.auth.models import EmailVerification
-
-from . import (
- exceptions,
- helpers,
- models,
- output_views,
- serializers,
- signals,
- tus,
- view_utils
+from django_airavata.proto_compat import (
+ BatchQueueResourcePolicy,
+ CloudJobSubmission,
+ ComputeResourcePolicy,
+ ComputeResourceReservation,
+ DataType,
+ ExperimentModel,
+ ExperimentSearchFields,
+ GlobusJobSubmission,
+ GridFTPDataMovement,
+ GroupAccountSSHProvisionerConfig,
+ GroupComputeResourcePreference,
+ LOCALDataMovement,
+ LOCALSubmission,
+ ResourcePermissionType,
+ ResourceType,
+ SCPDataMovement,
+ SSHJobSubmission,
+ Status,
+ SummaryType,
+ UnicoreDataMovement,
+ UnicoreJobSubmission,
)
-READ_PERMISSION_TYPE = '{}:READ'
+from . import exceptions, helpers, models, output_views, serializers, signals, tus, view_utils
+from . import queue_settings as queue_settings_calculators
+
+READ_PERMISSION_TYPE = "{}:READ"
log = logging.getLogger(__name__)
class GroupViewSet(APIBackedViewSet):
serializer_class = serializers.GroupSerializer
- lookup_field = 'group_id'
+ lookup_field = "group_id"
pagination_class = APIResultPagination
- pagination_viewname = 'django_airavata_api:group-list'
+ pagination_viewname = "django_airavata_api:group-list"
def get_list(self):
view = self
@@ -124,20 +112,17 @@ class GroupViewSet(APIBackedViewSet):
def _send_users_added_to_group(self, internal_user_ids, group):
for internal_user_id in internal_user_ids:
user_id, gateway_id = internal_user_id.rsplit("@", maxsplit=1)
- user_profile = self.request.airavata_client.iam.get_user_profile_by_id(
- user_id, gateway_id)
+ user_profile = self.request.airavata_client.iam.get_user_profile_by_id(user_id, gateway_id)
signals.user_added_to_group.send(
- sender=self.__class__,
- user=user_profile,
- groups=[group],
- request=self.request)
+ sender=self.__class__, user=user_profile, groups=[group], request=self.request
+ )
class ProjectViewSet(APIBackedViewSet):
serializer_class = serializers.ProjectSerializer
- lookup_field = 'project_id'
+ lookup_field = "project_id"
pagination_class = APIResultPagination
- pagination_viewname = 'django_airavata_api:project-list'
+ pagination_viewname = "django_airavata_api:project-list"
def get_list(self):
view = self
@@ -145,7 +130,8 @@ class ProjectViewSet(APIBackedViewSet):
class ProjectResultIterator(APIResultIterator):
def get_results(self, limit=-1, offset=0):
return view.request.airavata_client.research.get_user_projects(
- view.gateway_id, view.username, limit, offset)
+ view.gateway_id, view.username, limit, offset
+ )
return ProjectResultIterator()
@@ -153,34 +139,26 @@ class ProjectViewSet(APIBackedViewSet):
return self.request.airavata_client.research.get_project(lookup_value)
def perform_create(self, serializer):
- project = serializer.save(
- owner=self.username,
- gatewayId=self.gateway_id)
- project_id = self.request.airavata_client.research.create_project(
- self.gateway_id, project)
+ project = serializer.save(owner=self.username, gatewayId=self.gateway_id)
+ project_id = self.request.airavata_client.research.create_project(self.gateway_id, project)
project.projectID = project_id
self._update_most_recent_project(project_id)
def perform_update(self, serializer):
project = serializer.save()
- self.request.airavata_client.research.update_project(
- project.projectID, project)
+ self.request.airavata_client.research.update_project(project.projectID, project)
self._update_most_recent_project(project.projectID)
@action(detail=False)
def list_all(self, request):
- projects = self.request.airavata_client.research.get_user_projects(
- self.gateway_id, self.username, -1, 0)
- serializer = serializers.ProjectSerializer(
- projects, many=True, context={'request': request})
+ projects = self.request.airavata_client.research.get_user_projects(self.gateway_id, self.username, -1, 0)
+ serializer = serializers.ProjectSerializer(projects, many=True, context={"request": request})
return Response(serializer.data)
@action(detail=True)
def experiments(self, request, project_id=None):
- experiments = request.airavata_client.research.get_experiments_in_project(
- project_id, -1, 0)
- serializer = serializers.ExperimentSerializer(
- experiments, many=True, context={'request': request})
+ experiments = request.airavata_client.research.get_experiments_in_project(project_id, -1, 0)
+ serializer = serializers.ExperimentSerializer(experiments, many=True, context={"request": request})
return Response(serializer.data)
def _update_most_recent_project(self, project_id):
@@ -189,95 +167,83 @@ class ProjectViewSet(APIBackedViewSet):
prefs.save()
-class ExperimentViewSet(mixins.CreateModelMixin,
- mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- GenericAPIBackedViewSet):
+class ExperimentViewSet(
+ mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericAPIBackedViewSet
+):
serializer_class = serializers.ExperimentSerializer
- lookup_field = 'experiment_id'
+ lookup_field = "experiment_id"
def get_instance(self, lookup_value):
return self.request.airavata_client.research.get_experiment(lookup_value)
def perform_create(self, serializer):
- experiment = serializer.save(
- gatewayId=self.gateway_id,
- userName=self.username)
- experiment_id = self.request.airavata_client.research.create_experiment(
- self.gateway_id, experiment)
+ experiment = serializer.save(gatewayId=self.gateway_id, userName=self.username)
+ experiment_id = self.request.airavata_client.research.create_experiment(self.gateway_id, experiment)
self._update_workspace_preferences(
project_id=experiment.projectId,
group_resource_profile_id=experiment.userConfigurationData.groupResourceProfileId,
- compute_resource_id=experiment.userConfigurationData.computationalResourceScheduling.resourceHostId)
+ compute_resource_id=experiment.userConfigurationData.computationalResourceScheduling.resourceHostId,
+ )
experiment.experimentId = experiment_id
def perform_update(self, serializer):
- experiment = serializer.save(
- gatewayId=self.gateway_id,
- userName=self.username)
- self.request.airavata_client.research.update_experiment(
- experiment.experimentId, experiment)
+ experiment = serializer.save(gatewayId=self.gateway_id, userName=self.username)
+ self.request.airavata_client.research.update_experiment(experiment.experimentId, experiment)
self._update_workspace_preferences(
project_id=experiment.projectId,
group_resource_profile_id=experiment.userConfigurationData.groupResourceProfileId,
- compute_resource_id=experiment.userConfigurationData.computationalResourceScheduling.resourceHostId)
+ compute_resource_id=experiment.userConfigurationData.computationalResourceScheduling.resourceHostId,
+ )
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def launch(self, request, experiment_id=None):
try:
- experiment = request.airavata_client.research.get_experiment(
- experiment_id)
- if (experiment.enableEmailNotification):
+ experiment = request.airavata_client.research.get_experiment(experiment_id)
+ if experiment.enableEmailNotification:
experiment.emailAddresses = [request.user.email]
- request.airavata_client.research.update_experiment(
- experiment_id, experiment)
+ request.airavata_client.research.update_experiment(experiment_id, experiment)
experiment_util.launch(request, experiment_id)
- return Response({'success': True})
+ return Response({"success": True})
except Exception as e:
- log.exception(f"Failed to launch experiment {experiment_id}", extra={'request': request})
- return Response({'success': False, 'errorMessage': str(e)})
+ log.exception(f"Failed to launch experiment {experiment_id}", extra={"request": request})
+ return Response({"success": False, "errorMessage": str(e)})
- @action(methods=['get'], detail=True)
+ @action(methods=["get"], detail=True)
def jobs(self, request, experiment_id=None):
jobs = request.airavata_client.research.get_job_details(experiment_id)
- serializer = serializers.JobSerializer(
- jobs, many=True, context={'request': request})
+ serializer = serializers.JobSerializer(jobs, many=True, context={"request": request})
return Response(serializer.data)
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def clone(self, request, experiment_id=None):
cloned_experiment_id = experiment_util.clone(request, experiment_id)
- cloned_experiment = request.airavata_client.research.get_experiment(
- cloned_experiment_id)
- serializer = self.serializer_class(
- cloned_experiment, context={'request': request})
+ cloned_experiment = request.airavata_client.research.get_experiment(cloned_experiment_id)
+ serializer = self.serializer_class(cloned_experiment, context={"request": request})
return Response(serializer.data)
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def cancel(self, request, experiment_id=None):
try:
- request.airavata_client.research.terminate_experiment(
- experiment_id, self.gateway_id)
- return Response({'success': True})
+ request.airavata_client.research.terminate_experiment(experiment_id, self.gateway_id)
+ return Response({"success": True})
except Exception as e:
- log.exception("Cancel action has thrown the following error", extra={'request': request})
+ log.exception("Cancel action has thrown the following error", extra={"request": request})
raise e
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def fetch_intermediate_outputs(self, request, experiment_id=None):
if "outputNames" not in request.data:
return Response(status=status.HTTP_400_BAD_REQUEST)
try:
experiment_util.intermediate_output.fetch_intermediate_output(
- request, experiment_id, *request.data["outputNames"])
- return Response({'success': True})
+ request, experiment_id, *request.data["outputNames"]
+ )
+ return Response({"success": True})
except Exception as e:
- log.exception("fetchIntermediateOutputs failed with the following error", extra={'request': request})
+ log.exception("fetchIntermediateOutputs failed with the following error", extra={"request": request})
raise e
- def _update_workspace_preferences(self, project_id,
- group_resource_profile_id,
- compute_resource_id):
+ def _update_workspace_preferences(self, project_id, group_resource_profile_id, compute_resource_id):
prefs = helpers.WorkspacePreferencesHelper().get(self.request)
prefs.most_recent_project_id = project_id
prefs.most_recent_group_resource_profile_id = group_resource_profile_id
@@ -288,7 +254,7 @@ class ExperimentViewSet(mixins.CreateModelMixin,
class ExperimentSearchViewSet(mixins.ListModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.ExperimentSummarySerializer
pagination_class = APIResultPagination
- pagination_viewname = 'django_airavata_api:experiment-search-list'
+ pagination_viewname = "django_airavata_api:experiment-search-list"
def get_list(self):
view = self
@@ -303,8 +269,8 @@ class ExperimentSearchViewSet(mixins.ListModelMixin, GenericAPIBackedViewSet):
class ExperimentSearchResultIterator(APIResultIterator):
def get_results(self, limit=-1, offset=0):
return view.request.airavata_client.research.search_experiments(
- view.gateway_id, view.username, filters,
- limit, offset)
+ view.gateway_id, view.username, filters, limit, offset
+ )
# Preserve query parameters when moving to next and previous links
return ExperimentSearchResultIterator(query_params=self.request.query_params.copy())
@@ -313,66 +279,62 @@ class ExperimentSearchViewSet(mixins.ListModelMixin, GenericAPIBackedViewSet):
raise NotImplementedError()
-class FullExperimentViewSet(mixins.RetrieveModelMixin,
- GenericAPIBackedViewSet):
+class FullExperimentViewSet(mixins.RetrieveModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.FullExperimentSerializer
- lookup_field = 'experiment_id'
+ lookup_field = "experiment_id"
def get_instance(self, lookup_value):
"""Get FullExperiment instance with resolved references."""
# TODO: move loading experiment and references to airavata_sdk?
- experimentModel = self.request.airavata_client.research.get_experiment(
- lookup_value)
+ experimentModel = self.request.airavata_client.research.get_experiment(lookup_value)
outputDataProducts = [
self.request.airavata_client.research.get_data_product(output.value)
for output in experimentModel.experimentOutputs
- if (output.value and
- output.value.startswith('airavata-dp') and
- output.type in (DataType.URI,
- DataType.STDOUT,
- DataType.STDERR))]
+ if (
+ output.value
+ and output.value.startswith("airavata-dp")
+ and output.type in (DataType.URI, DataType.STDOUT, DataType.STDERR)
+ )
+ ]
outputDataProducts += [
self.request.airavata_client.research.get_data_product(dp)
for output in experimentModel.experimentOutputs
- if (output.value and
- output.type == DataType.URI_COLLECTION)
- for dp in output.value.split(',')
- if output.value.startswith('airavata-dp')]
+ if (output.value and output.type == DataType.URI_COLLECTION)
+ for dp in output.value.split(",")
+ if output.value.startswith("airavata-dp")
+ ]
appInterfaceId = experimentModel.executionId
try:
- applicationInterface = self.request.airavata_client.research \
- .get_application_interface(appInterfaceId)
+ applicationInterface = self.request.airavata_client.research.get_application_interface(appInterfaceId)
except Exception as e:
log.warning(f"Failed to load app interface: {e}")
applicationInterface = None
- exp_output_views = output_views.get_output_views(
- self.request, experimentModel, applicationInterface)
+ exp_output_views = output_views.get_output_views(self.request, experimentModel, applicationInterface)
inputDataProducts = [
self.request.airavata_client.research.get_data_product(inp.value)
for inp in experimentModel.experimentInputs
- if (inp.value and
- inp.value.startswith('airavata-dp') and
- inp.type in (DataType.URI,
- DataType.STDOUT,
- DataType.STDERR))]
+ if (
+ inp.value
+ and inp.value.startswith("airavata-dp")
+ and inp.type in (DataType.URI, DataType.STDOUT, DataType.STDERR)
+ )
+ ]
inputDataProducts += [
self.request.airavata_client.research.get_data_product(dp)
for inp in experimentModel.experimentInputs
- if (inp.value and
- inp.type == DataType.URI_COLLECTION)
- for dp in inp.value.split(',')
- if inp.value.startswith('airavata-dp')]
+ if (inp.value and inp.type == DataType.URI_COLLECTION)
+ for dp in inp.value.split(",")
+ if inp.value.startswith("airavata-dp")
+ ]
applicationModule = None
try:
if applicationInterface is not None:
appModuleId = applicationInterface.applicationModules[0]
- applicationModule = self.request.airavata_client.research \
- .get_application_module(appModuleId)
+ applicationModule = self.request.airavata_client.research.get_application_module(appModuleId)
else:
- log.warning(
- "Cannot load application model since app interface failed to load")
+ log.warning("Cannot load application model since app interface failed to load")
except Exception:
- log.exception("Failed to load app interface/module", extra={'request': self.request})
+ log.exception("Failed to load app interface/module", extra={"request": self.request})
compute_resource_id = None
user_conf = experimentModel.userConfigurationData
@@ -380,23 +342,20 @@ class FullExperimentViewSet(mixins.RetrieveModelMixin,
comp_res_sched = user_conf.computationalResourceScheduling
compute_resource_id = comp_res_sched.resourceHostId
try:
- compute_resource = self.request.airavata_client.compute.get_compute_resource(
- compute_resource_id) \
- if compute_resource_id else None
+ compute_resource = (
+ self.request.airavata_client.compute.get_compute_resource(compute_resource_id)
+ if compute_resource_id
+ else None
+ )
except Exception:
- log.exception("Failed to load compute resource for {}".format(
- compute_resource_id), extra={'request': self.request})
+ log.exception(f"Failed to load compute resource for {compute_resource_id}", extra={"request": self.request})
compute_resource = None
- if self.request.airavata_client.sharing.user_has_access(
- experimentModel.projectId,
- ResourcePermissionType.READ):
- project = self.request.airavata_client.research.get_project(
- experimentModel.projectId)
+ if self.request.airavata_client.sharing.user_has_access(experimentModel.projectId, ResourcePermissionType.READ):
+ project = self.request.airavata_client.research.get_project(experimentModel.projectId)
else:
# User may not have access to project, only experiment
project = None
- job_details = self.request.airavata_client.research.get_job_details(
- lookup_value)
+ job_details = self.request.airavata_client.research.get_job_details(lookup_value)
full_experiment = serializers.FullExperiment(
experimentModel,
project=project,
@@ -405,41 +364,36 @@ class FullExperimentViewSet(mixins.RetrieveModelMixin,
applicationModule=applicationModule,
computeResource=compute_resource,
jobDetails=job_details,
- outputViews=exp_output_views)
+ outputViews=exp_output_views,
+ )
return full_experiment
class ApplicationModuleViewSet(APIBackedViewSet):
serializer_class = serializers.ApplicationModuleSerializer
- lookup_field = 'app_module_id'
+ lookup_field = "app_module_id"
def get_list(self):
- return self.request.airavata_client.research.get_accessible_app_modules(
- self.gateway_id)
+ return self.request.airavata_client.research.get_accessible_app_modules(self.gateway_id)
def get_instance(self, lookup_value):
- return self.request.airavata_client.research.get_application_module(
- lookup_value)
+ return self.request.airavata_client.research.get_application_module(lookup_value)
def perform_create(self, serializer):
app_module = serializer.save()
- app_module_id = self.request.airavata_client.research.register_application_module(
- self.gateway_id, app_module)
+ app_module_id = self.request.airavata_client.research.register_application_module(self.gateway_id, app_module)
app_module.appModuleId = app_module_id
def perform_update(self, serializer):
app_module = serializer.save()
- self.request.airavata_client.research.update_application_module(
- app_module.appModuleId, app_module)
+ self.request.airavata_client.research.update_application_module(app_module.appModuleId, app_module)
def perform_destroy(self, instance):
- self.request.airavata_client.research.delete_application_module(
- instance.appModuleId)
+ self.request.airavata_client.research.delete_application_module(instance.appModuleId)
@action(detail=True)
def application_interface(self, request, app_module_id):
- all_app_interfaces = request.airavata_client.research.get_all_application_interfaces(
- self.gateway_id)
+ all_app_interfaces = request.airavata_client.research.get_all_application_interfaces(self.gateway_id)
app_interfaces = []
for app_interface in all_app_interfaces:
if not app_interface.applicationModules:
@@ -448,91 +402,77 @@ class ApplicationModuleViewSet(APIBackedViewSet):
app_interfaces.append(app_interface)
if len(app_interfaces) == 1:
serializer = serializers.ApplicationInterfaceDescriptionSerializer(
- app_interfaces[0], context={'request': request})
+ app_interfaces[0], context={"request": request}
+ )
return Response(serializer.data)
elif len(app_interfaces) > 1:
log.error(
- "More than one application interface found for module {}: {}"
- .format(app_module_id, app_interfaces), extra={'request': request})
- raise Exception(
- 'More than one application interface found for module {}'
- .format(app_module_id)
+ f"More than one application interface found for module {app_module_id}: {app_interfaces}",
+ extra={"request": request},
)
+ raise Exception(f"More than one application interface found for module {app_module_id}")
else:
- raise Http404("No application interface found for module id {}"
- .format(app_module_id))
+ raise Http404(f"No application interface found for module id {app_module_id}")
@action(detail=True)
def application_deployments(self, request, app_module_id):
- all_deployments = self.request.airavata_client.research.get_all_application_deployments(
- self.gateway_id)
- app_deployments = [
- dep for dep in all_deployments if dep.appModuleId == app_module_id]
+ all_deployments = self.request.airavata_client.research.get_all_application_deployments(self.gateway_id)
+ app_deployments = [dep for dep in all_deployments if dep.appModuleId == app_module_id]
serializer = serializers.ApplicationDeploymentDescriptionSerializer(
- app_deployments, many=True, context={'request': request})
+ app_deployments, many=True, context={"request": request}
+ )
return Response(serializer.data)
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def favorite(self, request, app_module_id):
helper = helpers.WorkspacePreferencesHelper()
workspace_preferences = helper.get(request)
try:
- application_preferences = (
- workspace_preferences.applicationpreferences_set.get(
- application_id=app_module_id))
+ application_preferences = workspace_preferences.applicationpreferences_set.get(application_id=app_module_id)
application_preferences.favorite = True
application_preferences.save()
except ObjectDoesNotExist:
workspace_preferences.applicationpreferences_set.create(
- username=request.user.username,
- application_id=app_module_id,
- favorite=True)
+ username=request.user.username, application_id=app_module_id, favorite=True
+ )
return HttpResponse(status=204)
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def unfavorite(self, request, app_module_id):
helper = helpers.WorkspacePreferencesHelper()
workspace_preferences = helper.get(request)
try:
- application_preferences = (
- workspace_preferences.applicationpreferences_set.get(
- application_id=app_module_id))
+ application_preferences = workspace_preferences.applicationpreferences_set.get(application_id=app_module_id)
application_preferences.favorite = False
application_preferences.save()
except ObjectDoesNotExist:
workspace_preferences.applicationpreferences_set.create(
- username=request.user.username,
- application_id=app_module_id,
- favorite=False)
+ username=request.user.username, application_id=app_module_id, favorite=False
+ )
return HttpResponse(status=204)
@action(detail=False)
def list_all(self, request, format=None):
- all_modules = self.request.airavata_client.research.get_all_app_modules(
- self.gateway_id)
- serializer = self.serializer_class(
- all_modules, many=True, context={'request': request})
+ all_modules = self.request.airavata_client.research.get_all_app_modules(self.gateway_id)
+ serializer = self.serializer_class(all_modules, many=True, context={"request": request})
return Response(serializer.data)
class ApplicationInterfaceViewSet(APIBackedViewSet):
serializer_class = serializers.ApplicationInterfaceDescriptionSerializer
- lookup_field = 'app_interface_id'
+ lookup_field = "app_interface_id"
def get_list(self):
- return self.request.airavata_client.research.get_all_application_interfaces(
- self.gateway_id)
+ return self.request.airavata_client.research.get_all_application_interfaces(self.gateway_id)
def get_instance(self, lookup_value):
try:
- return self.request.airavata_client.research.get_application_interface(
- lookup_value)
+ return self.request.airavata_client.research.get_application_interface(lookup_value)
except Exception:
# If it failed to load, check to see if it exists at all
- all_interfaces = self.request.airavata_client.research.get_all_application_interfaces(
- self.gateway_id)
+ all_interfaces = self.request.airavata_client.research.get_all_application_interfaces(self.gateway_id)
interface_ids = map(lambda i: i.applicationInterfaceId, all_interfaces)
if lookup_value not in interface_ids:
raise Http404("Application interface does not exist")
@@ -542,21 +482,21 @@ class ApplicationInterfaceViewSet(APIBackedViewSet):
def perform_create(self, serializer):
application_interface = serializer.save()
self._update_input_metadata(application_interface)
- log.debug("application_interface: {}".format(application_interface))
+ log.debug(f"application_interface: {application_interface}")
app_interface_id = self.request.airavata_client.research.register_application_interface(
- self.gateway_id, application_interface)
+ self.gateway_id, application_interface
+ )
application_interface.applicationInterfaceId = app_interface_id
def perform_update(self, serializer):
application_interface = serializer.save()
self._update_input_metadata(application_interface)
self.request.airavata_client.research.update_application_interface(
- application_interface.applicationInterfaceId,
- application_interface)
+ application_interface.applicationInterfaceId, application_interface
+ )
def perform_destroy(self, instance):
- self.request.airavata_client.research.delete_application_interface(
- instance.applicationInterfaceId)
+ self.request.airavata_client.research.delete_application_interface(instance.applicationInterfaceId)
def _update_input_metadata(self, app_interface):
for app_input in app_interface.applicationInputs:
@@ -564,9 +504,11 @@ class ApplicationInterfaceViewSet(APIBackedViewSet):
metadata = json.loads(app_input.metaData)
# Automatically add {showOptions: {isRequired: true/false}} to
# toggle isRequired on hidden/shown inputs
- if ("editor" in metadata and
- "dependencies" in metadata["editor"] and
- "show" in metadata["editor"]["dependencies"]):
+ if (
+ "editor" in metadata
+ and "dependencies" in metadata["editor"]
+ and "show" in metadata["editor"]["dependencies"]
+ ):
if "showOptions" not in metadata["editor"]["dependencies"]:
metadata["editor"]["dependencies"]["showOptions"] = {}
o = metadata["editor"]["dependencies"]["showOptions"]
@@ -576,55 +518,53 @@ class ApplicationInterfaceViewSet(APIBackedViewSet):
@action(detail=True)
def compute_resources(self, request, app_interface_id):
compute_resources = request.airavata_client.research.get_available_app_interface_compute_resources(
- app_interface_id)
+ app_interface_id
+ )
return Response(compute_resources)
class ApplicationDeploymentViewSet(APIBackedViewSet):
serializer_class = serializers.ApplicationDeploymentDescriptionSerializer
- lookup_field = 'app_deployment_id'
+ lookup_field = "app_deployment_id"
def get_list(self):
- app_module_id = self.request.query_params.get('appModuleId', None)
- group_resource_profile_id = self.request.query_params.get(
- 'groupResourceProfileId', None)
- if (app_module_id and not group_resource_profile_id)\
- or (not app_module_id and group_resource_profile_id):
- raise ParseError("Query params appModuleId and "
- "groupResourceProfileId are required together.")
+ app_module_id = self.request.query_params.get("appModuleId", None)
+ group_resource_profile_id = self.request.query_params.get("groupResourceProfileId", None)
+ if (app_module_id and not group_resource_profile_id) or (not app_module_id and group_resource_profile_id):
+ raise ParseError("Query params appModuleId and groupResourceProfileId are required together.")
if app_module_id and group_resource_profile_id:
return self.request.airavata_client.research.get_application_deployments_for_app_module_and_group_resource_profile(
- app_module_id, group_resource_profile_id)
+ app_module_id, group_resource_profile_id
+ )
else:
return self.request.airavata_client.research.get_accessible_application_deployments(
- self.gateway_id, ResourcePermissionType.READ)
+ self.gateway_id, ResourcePermissionType.READ
+ )
def get_instance(self, lookup_value):
- return self.request.airavata_client.research.get_application_deployment(
- lookup_value)
+ return self.request.airavata_client.research.get_application_deployment(lookup_value)
def perform_create(self, serializer):
application_deployment = serializer.save()
app_deployment_id = self.request.airavata_client.research.register_application_deployment(
- self.gateway_id, application_deployment)
+ self.gateway_id, application_deployment
+ )
application_deployment.appDeploymentId = app_deployment_id
def perform_update(self, serializer):
application_deployment = serializer.save()
self.request.airavata_client.research.update_application_deployment(
- application_deployment.appDeploymentId, application_deployment)
+ application_deployment.appDeploymentId, application_deployment
+ )
def perform_destroy(self, instance):
- self.request.airavata_client.research.delete_application_deployment(
- instance.appDeploymentId)
+ self.request.airavata_client.research.delete_application_deployment(instance.appDeploymentId)
@action(detail=True)
def queues(self, request, app_deployment_id):
"""Return queues for this deployment with defaults overridden by deployment defaults if they exist"""
- app_deployment = self.request.airavata_client.research.get_application_deployment(
- app_deployment_id)
- compute_resource = request.airavata_client.compute.get_compute_resource(
- app_deployment.computeHostId)
+ app_deployment = self.request.airavata_client.research.get_application_deployment(app_deployment_id)
+ compute_resource = request.airavata_client.compute.get_compute_resource(app_deployment.computeHostId)
# Override defaults with app deployment default queue, if defined
batch_queues = []
for batch_queue in compute_resource.batchQueues:
@@ -637,46 +577,43 @@ class ApplicationDeploymentViewSet(APIBackedViewSet):
else:
batch_queue.isDefaultQueue = False
batch_queues.append(batch_queue)
- serializer = serializers.BatchQueueSerializer(
- batch_queues, many=True, context={'request': request})
+ serializer = serializers.BatchQueueSerializer(batch_queues, many=True, context={"request": request})
return Response(serializer.data)
-class ComputeResourceViewSet(mixins.RetrieveModelMixin,
- GenericAPIBackedViewSet):
+class ComputeResourceViewSet(mixins.RetrieveModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.ComputeResourceDescriptionSerializer
- lookup_field = 'compute_resource_id'
+ lookup_field = "compute_resource_id"
def get_instance(self, lookup_value, format=None):
- return self.request.airavata_client.compute.get_compute_resource(
- lookup_value)
+ return self.request.airavata_client.compute.get_compute_resource(lookup_value)
@action(detail=False)
def all_names(self, request, format=None):
"""Return a map of compute resource names keyed by resource id."""
- return Response(
- request.airavata_client.compute.get_all_compute_resource_names())
+ return Response(request.airavata_client.compute.get_all_compute_resource_names())
@action(detail=False)
def all_names_list(self, request, format=None):
"""Return a list of compute resource names keyed by resource id."""
all_names = request.airavata_client.compute.get_all_compute_resource_names()
- return Response([
- {
- 'host_id': host_id,
- 'host': host,
- 'url': request.build_absolute_uri(
- reverse('django_airavata_api:compute-resource-detail',
- args=[host_id]))
- } for host_id, host in all_names.items()
- ])
+ return Response(
+ [
+ {
+ "host_id": host_id,
+ "host": host,
+ "url": request.build_absolute_uri(
+ reverse("django_airavata_api:compute-resource-detail", args=[host_id])
+ ),
+ }
+ for host_id, host in all_names.items()
+ ]
+ )
@action(detail=True)
def queues(self, request, compute_resource_id, format=None):
- details = request.airavata_client.compute.get_compute_resource(
- compute_resource_id)
- serializer = self.serializer_class(instance=details,
- context={'request': request})
+ details = request.airavata_client.compute.get_compute_resource(compute_resource_id)
+ serializer = self.serializer_class(instance=details, context={"request": request})
data = serializer.data
return Response([queue["queueName"] for queue in data["batchQueues"]])
@@ -686,13 +623,10 @@ class LocalJobSubmissionView(APIView):
def get(self, request, format=None):
job_submission_id = request.query_params["id"]
- local_job_submission = request.airavata_client.compute.get_local_job_submission(
- job_submission_id)
+ local_job_submission = request.airavata_client.compute.get_local_job_submission(job_submission_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- LOCALSubmission,
- instance=local_job_submission).data)
+
+ return Response(proto_utils.create_serializer(LOCALSubmission, instance=local_job_submission).data)
class CloudJobSubmissionView(APIView):
@@ -700,13 +634,10 @@ class CloudJobSubmissionView(APIView):
def get(self, request, format=None):
job_submission_id = request.query_params["id"]
- job_submission = request.airavata_client.compute.get_cloud_job_submission(
- job_submission_id)
+ job_submission = request.airavata_client.compute.get_cloud_job_submission(job_submission_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- CloudJobSubmission,
- instance=job_submission).data)
+
+ return Response(proto_utils.create_serializer(CloudJobSubmission, instance=job_submission).data)
class GlobusJobSubmissionView(APIView):
@@ -714,13 +645,10 @@ class GlobusJobSubmissionView(APIView):
def get(self, request, format=None):
job_submission_id = request.query_params["id"]
- job_submission = request.airavata_client.compute.get_globus_job_submission(
- job_submission_id)
+ job_submission = request.airavata_client.compute.get_globus_job_submission(job_submission_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- GlobusJobSubmission,
- instance=job_submission).data)
+
+ return Response(proto_utils.create_serializer(GlobusJobSubmission, instance=job_submission).data)
class SshJobSubmissionView(APIView):
@@ -728,13 +656,10 @@ class SshJobSubmissionView(APIView):
def get(self, request, format=None):
job_submission_id = request.query_params["id"]
- job_submission = request.airavata_client.compute.get_ssh_job_submission(
- job_submission_id)
+ job_submission = request.airavata_client.compute.get_ssh_job_submission(job_submission_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- SSHJobSubmission,
- instance=job_submission).data)
+
+ return Response(proto_utils.create_serializer(SSHJobSubmission, instance=job_submission).data)
class UnicoreJobSubmissionView(APIView):
@@ -742,13 +667,10 @@ class UnicoreJobSubmissionView(APIView):
def get(self, request, format=None):
job_submission_id = request.query_params["id"]
- job_submission = request.airavata_client.compute.get_unicore_job_submission(
- job_submission_id)
+ job_submission = request.airavata_client.compute.get_unicore_job_submission(job_submission_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- UnicoreJobSubmission,
- instance=job_submission).data)
+
+ return Response(proto_utils.create_serializer(UnicoreJobSubmission, instance=job_submission).data)
class GridFtpDataMovementView(APIView):
@@ -756,13 +678,10 @@ class GridFtpDataMovementView(APIView):
def get(self, request, format=None):
data_movement_id = request.query_params["id"]
- data_movement = request.airavata_client.compute.get_grid_ftp_data_movement(
- data_movement_id)
+ data_movement = request.airavata_client.compute.get_grid_ftp_data_movement(data_movement_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- GridFTPDataMovement,
- instance=data_movement).data)
+
+ return Response(proto_utils.create_serializer(GridFTPDataMovement, instance=data_movement).data)
class ScpDataMovementView(APIView):
@@ -770,13 +689,10 @@ class ScpDataMovementView(APIView):
def get(self, request, format=None):
data_movement_id = request.query_params["id"]
- data_movement = request.airavata_client.compute.get_scp_data_movement(
- data_movement_id)
+ data_movement = request.airavata_client.compute.get_scp_data_movement(data_movement_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- SCPDataMovement,
- instance=data_movement).data)
+
+ return Response(proto_utils.create_serializer(SCPDataMovement, instance=data_movement).data)
class UnicoreDataMovementView(APIView):
@@ -784,13 +700,10 @@ class UnicoreDataMovementView(APIView):
def get(self, request, format=None):
data_movement_id = request.query_params["id"]
- data_movement = request.airavata_client.compute.get_unicore_data_movement(
- data_movement_id)
+ data_movement = request.airavata_client.compute.get_unicore_data_movement(data_movement_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- UnicoreDataMovement,
- instance=data_movement).data)
+
+ return Response(proto_utils.create_serializer(UnicoreDataMovement, instance=data_movement).data)
class LocalDataMovementView(APIView):
@@ -798,73 +711,60 @@ class LocalDataMovementView(APIView):
def get(self, request, format=None):
data_movement_id = request.query_params["id"]
- data_movement = request.airavata_client.compute.get_local_data_movement(
- data_movement_id)
+ data_movement = request.airavata_client.compute.get_local_data_movement(data_movement_id)
from . import proto_utils
- return Response(
- proto_utils.create_serializer(
- LOCALDataMovement,
- instance=data_movement).data)
+ return Response(proto_utils.create_serializer(LOCALDataMovement, instance=data_movement).data)
-class DataProductView(APIView):
+class DataProductView(APIView):
serializer_class = serializers.DataProductSerializer
permission_classes = [IsAuthenticated, DataProductSharedDirPermission]
def get(self, request, format=None):
- data_product_uri = request.query_params['product-uri']
- data_product = request.airavata_client.research.get_data_product(
- data_product_uri)
- serializer = self.serializer_class(
- data_product, context={'request': request})
+ data_product_uri = request.query_params["product-uri"]
+ data_product = request.airavata_client.research.get_data_product(data_product_uri)
+ serializer = self.serializer_class(data_product, context={"request": request})
return Response(serializer.data)
def put(self, request, format=None):
- data_product_uri = request.query_params['product-uri']
- data_product = request.airavata_client.research.get_data_product(
- data_product_uri)
+ data_product_uri = request.query_params["product-uri"]
+ data_product = request.airavata_client.research.get_data_product(data_product_uri)
if request.data and "fileContentText" in request.data:
user_storage.update_data_product_content(
- request=request,
- data_product=data_product,
- fileContentText=request.data["fileContentText"])
+ request=request, data_product=data_product, fileContentText=request.data["fileContentText"]
+ )
return self.get(request=request, format=format)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
-@api_view(http_method_names=['POST'])
+@api_view(http_method_names=["POST"])
def upload_input_file(request):
try:
- input_file = request.FILES['file']
- data_product = user_storage.save_input_file(
- request, input_file, content_type=input_file.content_type)
- serializer = serializers.DataProductSerializer(
- data_product, context={'request': request})
- return JsonResponse({'uploaded': True,
- 'data-product': serializer.data})
+ input_file = request.FILES["file"]
+ data_product = user_storage.save_input_file(request, input_file, content_type=input_file.content_type)
+ serializer = serializers.DataProductSerializer(data_product, context={"request": request})
+ return JsonResponse({"uploaded": True, "data-product": serializer.data})
except Exception as e:
- log.error("Failed to upload file", exc_info=True, extra={'request': request})
- resp = JsonResponse({'uploaded': False, 'error': str(e)})
+ log.error("Failed to upload file", exc_info=True, extra={"request": request})
+ resp = JsonResponse({"uploaded": False, "error": str(e)})
resp.status_code = 500
return resp
-@api_view(http_method_names=['POST'])
+@api_view(http_method_names=["POST"])
def tus_upload_finish(request):
- uploadURL = request.POST['uploadURL']
+ uploadURL = request.POST["uploadURL"]
def save_upload(file_path, file_name, file_type):
- with open(file_path, 'rb') as uploaded_file:
- return user_storage.save_input_file(request, uploaded_file,
- name=file_name, content_type=file_type)
+ with open(file_path, "rb") as uploaded_file:
+ return user_storage.save_input_file(request, uploaded_file, name=file_name, content_type=file_type)
+
try:
data_product = tus.save_tus_upload(uploadURL, save_upload)
- serializer = serializers.DataProductSerializer(
- data_product, context={'request': request})
- return JsonResponse({'uploaded': True,
- 'data-product': serializer.data})
+ serializer = serializers.DataProductSerializer(data_product, context={"request": request})
+ return JsonResponse({"uploaded": True, "data-product": serializer.data})
except Exception as e:
return exceptions.generic_json_exception_response(e, status=400)
@@ -875,26 +775,23 @@ def download_file(request):
# TODO: remove this deprecated view
warnings.warn("download_file view has moved to SDK", DeprecationWarning)
# redirect to /sdk/download
- data_product_uri = request.GET.get('data-product-uri', '')
+ data_product_uri = request.GET.get("data-product-uri", "")
return redirect(user_storage.get_download_url(request, data_product_uri=data_product_uri))
-@api_view(http_method_names=['DELETE'])
+@api_view(http_method_names=["DELETE"])
@permission_classes([IsAuthenticated, DataProductSharedDirPermission])
def delete_file(request):
# TODO check that user has write access to this file using sharing API
- data_product_uri = request.GET.get('data-product-uri', '')
+ data_product_uri = request.GET.get("data-product-uri", "")
data_product = None
try:
- data_product = request.airavata_client.research.get_data_product(
- data_product_uri)
+ data_product = request.airavata_client.research.get_data_product(data_product_uri)
except Exception as e:
- log.warning("Failed to load DataProduct for {}"
- .format(data_product_uri), exc_info=True)
+ log.warning(f"Failed to load DataProduct for {data_product_uri}", exc_info=True)
raise Http404("data product does not exist") from e
try:
- if (data_product.gatewayId != settings.GATEWAY_ID or
- data_product.ownerName != request.user.username):
+ if data_product.gatewayId != settings.GATEWAY_ID or data_product.ownerName != request.user.username:
raise PermissionDenied()
user_storage.delete(request, data_product)
return HttpResponse(status=204)
@@ -902,80 +799,77 @@ def delete_file(request):
raise Http404(str(e)) from e
-class UserProfileViewSet(mixins.RetrieveModelMixin,
- mixins.ListModelMixin,
- GenericAPIBackedViewSet):
+class UserProfileViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.UserProfileSerializer
def get_list(self):
- return self.request.airavata_client.iam.get_all_user_profiles_in_gateway(
- self.gateway_id, 0, -1)
+ return self.request.airavata_client.iam.get_all_user_profiles_in_gateway(self.gateway_id, 0, -1)
def get_instance(self, lookup_value):
- return self.request.airavata_client.iam.get_user_profile_by_id(
- self.request.user.username, self.gateway_id)
+ return self.request.airavata_client.iam.get_user_profile_by_id(self.request.user.username, self.gateway_id)
class GroupResourceProfileViewSet(APIBackedViewSet):
serializer_class = serializers.GroupResourceProfileSerializer
- lookup_field = 'group_resource_profile_id'
+ lookup_field = "group_resource_profile_id"
def get_list(self):
- return self.request.airavata_client.compute.get_group_resource_list(
- self.gateway_id)
+ return self.request.airavata_client.compute.get_group_resource_list(self.gateway_id)
def get_instance(self, lookup_value):
- return self.request.airavata_client.compute.get_group_resource_profile(
- lookup_value)
+ return self.request.airavata_client.compute.get_group_resource_profile(lookup_value)
def perform_create(self, serializer):
group_resource_profile = serializer.save()
group_resource_profile.gatewayId = self.gateway_id
group_resource_profile_id = self.request.airavata_client.compute.create_group_resource_profile(
- group_resource_profile=group_resource_profile)
+ group_resource_profile=group_resource_profile
+ )
group_resource_profile.groupResourceProfileId = group_resource_profile_id
# Update the creationTime field on the group resource profile
new_group_resource_profile = self.request.airavata_client.compute.get_group_resource_profile(
- group_resource_profile_id)
+ group_resource_profile_id
+ )
group_resource_profile.creationTime = new_group_resource_profile.creationTime
def perform_update(self, serializer):
original_instance = serializer.instance
grp = serializer.save()
- for removed_compute_resource_preference \
- in grp._removed_compute_resource_preferences:
+ for removed_compute_resource_preference in grp._removed_compute_resource_preferences:
self.request.airavata_client.compute.remove_group_compute_prefs(
removed_compute_resource_preference.computeResourceId,
- removed_compute_resource_preference.groupResourceProfileId)
- for removed_compute_resource_policy \
- in grp._removed_compute_resource_policies:
+ removed_compute_resource_preference.groupResourceProfileId,
+ )
+ for removed_compute_resource_policy in grp._removed_compute_resource_policies:
self.request.airavata_client.compute.remove_group_compute_resource_policy(
- removed_compute_resource_policy.resourcePolicyId)
- for removed_batch_queue_resource_policy \
- in grp._removed_batch_queue_resource_policies:
+ removed_compute_resource_policy.resourcePolicyId
+ )
+ for removed_batch_queue_resource_policy in grp._removed_batch_queue_resource_policies:
self.request.airavata_client.compute.remove_group_batch_queue_resource_policy(
- removed_batch_queue_resource_policy.resourcePolicyId)
- if hasattr(grp, 'computePreferences') and grp.computePreferences:
+ removed_batch_queue_resource_policy.resourcePolicyId
+ )
+ if hasattr(grp, "computePreferences") and grp.computePreferences:
from collections import OrderedDict
+
from django_airavata.apps.api.serializers import GroupComputeResourcePreferenceSerializer
for pref in grp.computePreferences:
if isinstance(pref, GroupComputeResourcePreference):
- if not hasattr(pref, 'resourceType') or pref.resourceType is None:
+ if not hasattr(pref, "resourceType") or pref.resourceType is None:
resource_type = None
- if hasattr(pref, 'specificPreferences') and pref.specificPreferences:
+ if hasattr(pref, "specificPreferences") and pref.specificPreferences:
if isinstance(pref.specificPreferences, (dict, OrderedDict)):
specific_prefs_dict = pref.specificPreferences
- if 'slurm' in specific_prefs_dict or 'allocationProjectNumber' in specific_prefs_dict:
+ if "slurm" in specific_prefs_dict or "allocationProjectNumber" in specific_prefs_dict:
resource_type = ResourceType.SLURM
- elif 'aws' in specific_prefs_dict or 'region' in specific_prefs_dict:
+ elif "aws" in specific_prefs_dict or "region" in specific_prefs_dict:
resource_type = ResourceType.AWS
else:
resource_type = ResourceType.SLURM
- elif hasattr(pref.specificPreferences, 'slurm') and pref.specificPreferences.slurm:
+ elif hasattr(pref.specificPreferences, "slurm") and pref.specificPreferences.slurm:
resource_type = ResourceType.SLURM
- elif hasattr(pref.specificPreferences, 'aws') and pref.specificPreferences.aws:
+ elif hasattr(pref.specificPreferences, "aws") and pref.specificPreferences.aws:
resource_type = ResourceType.AWS
else:
resource_type = ResourceType.SLURM
@@ -983,24 +877,25 @@ class GroupResourceProfileViewSet(APIBackedViewSet):
resource_type = ResourceType.SLURM
pref.resourceType = resource_type
- resource_type = pref.resourceType if hasattr(pref, 'resourceType') and pref.resourceType else None
+ resource_type = pref.resourceType if hasattr(pref, "resourceType") and pref.resourceType else None
if resource_type:
- if hasattr(pref, 'specificPreferences') and isinstance(pref.specificPreferences, (dict, OrderedDict)):
- GroupComputeResourcePreferenceSerializer._convert_specific_preferences_dict_to_thrift(
- pref, resource_type
- )
- elif hasattr(pref, 'specificPreferences') and pref.specificPreferences:
+ if (
+ hasattr(pref, "specificPreferences")
+ and isinstance(pref.specificPreferences, (dict, OrderedDict))
+ or hasattr(pref, "specificPreferences")
+ and pref.specificPreferences
+ ):
GroupComputeResourcePreferenceSerializer._convert_specific_preferences_dict_to_thrift(
pref, resource_type
)
from collections import OrderedDict
- if hasattr(grp, 'computeResourcePolicies') and grp.computeResourcePolicies:
+ if hasattr(grp, "computeResourcePolicies") and grp.computeResourcePolicies:
existing_policies_by_resource_id = {}
- if original_instance and hasattr(original_instance, 'computeResourcePolicies'):
+ if original_instance and hasattr(original_instance, "computeResourcePolicies"):
for existing_policy in original_instance.computeResourcePolicies:
- if hasattr(existing_policy, 'computeResourceId') and hasattr(existing_policy, 'resourcePolicyId'):
+ if hasattr(existing_policy, "computeResourceId") and hasattr(existing_policy, "resourcePolicyId"):
existing_policies_by_resource_id[existing_policy.computeResourceId] = existing_policy
indices_to_remove = []
@@ -1010,19 +905,26 @@ class GroupResourceProfileViewSet(APIBackedViewSet):
if isinstance(policy, OrderedDict):
policy = dict(policy)
- compute_resource_id = policy.get('computeResourceId')
- current_resource_policy_id = policy.get('resourcePolicyId')
+ compute_resource_id = policy.get("computeResourceId")
+ current_resource_policy_id = policy.get("resourcePolicyId")
if not current_resource_policy_id:
if compute_resource_id and compute_resource_id in existing_policies_by_resource_id:
existing_policy = existing_policies_by_resource_id[compute_resource_id]
- policy['resourcePolicyId'] = existing_policy.resourcePolicyId
- elif original_instance and hasattr(original_instance, 'computeResourcePolicies') and idx < len(original_instance.computeResourcePolicies):
+ policy["resourcePolicyId"] = existing_policy.resourcePolicyId
+ elif (
+ original_instance
+ and hasattr(original_instance, "computeResourcePolicies")
+ and idx < len(original_instance.computeResourcePolicies)
+ ):
existing_policy_by_idx = original_instance.computeResourcePolicies[idx]
- if hasattr(existing_policy_by_idx, 'resourcePolicyId') and existing_policy_by_idx.resourcePolicyId:
- policy['resourcePolicyId'] = existing_policy_by_idx.resourcePolicyId
+ if (
+ hasattr(existing_policy_by_idx, "resourcePolicyId")
+ and existing_policy_by_idx.resourcePolicyId
+ ):
+ policy["resourcePolicyId"] = existing_policy_by_idx.resourcePolicyId
- if not policy.get('resourcePolicyId'):
+ if not policy.get("resourcePolicyId"):
indices_to_remove.append(idx)
continue
@@ -1040,27 +942,29 @@ class GroupResourceProfileViewSet(APIBackedViewSet):
for idx in reversed(indices_to_remove):
grp.computeResourcePolicies.pop(idx)
- if hasattr(grp, 'batchQueueResourcePolicies') and grp.batchQueueResourcePolicies:
+ if hasattr(grp, "batchQueueResourcePolicies") and grp.batchQueueResourcePolicies:
existing_bq_policies_by_key = {}
- if original_instance and hasattr(original_instance, 'batchQueueResourcePolicies'):
+ if original_instance and hasattr(original_instance, "batchQueueResourcePolicies"):
for existing_bq_policy in original_instance.batchQueueResourcePolicies:
- if (hasattr(existing_bq_policy, 'computeResourceId') and
- hasattr(existing_bq_policy, 'queuename') and
- hasattr(existing_bq_policy, 'resourcePolicyId')):
+ if (
+ hasattr(existing_bq_policy, "computeResourceId")
+ and hasattr(existing_bq_policy, "queuename")
+ and hasattr(existing_bq_policy, "resourcePolicyId")
+ ):
key = (existing_bq_policy.computeResourceId, existing_bq_policy.queuename)
existing_bq_policies_by_key[key] = existing_bq_policy
for idx, policy in enumerate(grp.batchQueueResourcePolicies):
if isinstance(policy, (dict, OrderedDict)):
try:
- compute_resource_id = policy.get('computeResourceId')
- queuename = policy.get('queuename')
+ compute_resource_id = policy.get("computeResourceId")
+ queuename = policy.get("queuename")
if compute_resource_id and queuename:
key = (compute_resource_id, queuename)
if key in existing_bq_policies_by_key:
existing_bq_policy = existing_bq_policies_by_key[key]
- if 'resourcePolicyId' not in policy or policy.get('resourcePolicyId') is None:
- policy['resourcePolicyId'] = existing_bq_policy.resourcePolicyId
+ if "resourcePolicyId" not in policy or policy.get("resourcePolicyId") is None:
+ policy["resourcePolicyId"] = existing_bq_policy.resourcePolicyId
grp.batchQueueResourcePolicies[idx] = BatchQueueResourcePolicy(**policy)
except Exception as e:
log.error(
@@ -1070,10 +974,11 @@ class GroupResourceProfileViewSet(APIBackedViewSet):
exc_info=True,
)
- if hasattr(grp, 'computePreferences') and grp.computePreferences:
+ if hasattr(grp, "computePreferences") and grp.computePreferences:
for idx, pref in enumerate(grp.computePreferences):
if isinstance(pref, (dict, OrderedDict)):
from django_airavata.apps.api.serializers import GroupComputeResourcePreferenceSerializer
+
serializer = GroupComputeResourcePreferenceSerializer()
try:
pref = serializer.create(pref)
@@ -1086,32 +991,41 @@ class GroupResourceProfileViewSet(APIBackedViewSet):
)
if isinstance(pref, GroupComputeResourcePreference):
- if hasattr(pref, 'specificPreferences') and pref.specificPreferences:
- if hasattr(pref.specificPreferences, 'slurm') and pref.specificPreferences.slurm:
+ if hasattr(pref, "specificPreferences") and pref.specificPreferences:
+ if hasattr(pref.specificPreferences, "slurm") and pref.specificPreferences.slurm:
GroupComputeResourcePreferenceSerializer._convert_nested_list_fields_to_thrift(
pref.specificPreferences.slurm
)
- if hasattr(pref.specificPreferences.slurm, 'reservations') and pref.specificPreferences.slurm.reservations:
+ if (
+ hasattr(pref.specificPreferences.slurm, "reservations")
+ and pref.specificPreferences.slurm.reservations
+ ):
for res_idx, res in enumerate(pref.specificPreferences.slurm.reservations):
if isinstance(res, (dict, OrderedDict)):
- pref.specificPreferences.slurm.reservations[res_idx] = ComputeResourceReservation(**res)
- if hasattr(pref.specificPreferences.slurm, 'groupSSHAccountProvisionerConfigs') and pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs:
- for cfg_idx, cfg in enumerate(pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs):
+ pref.specificPreferences.slurm.reservations[res_idx] = (
+ ComputeResourceReservation(**res)
+ )
+ if (
+ hasattr(pref.specificPreferences.slurm, "groupSSHAccountProvisionerConfigs")
+ and pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs
+ ):
+ for cfg_idx, cfg in enumerate(
+ pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs
+ ):
if isinstance(cfg, (dict, OrderedDict)):
- pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs[cfg_idx] = GroupAccountSSHProvisionerConfig(**cfg)
+ pref.specificPreferences.slurm.groupSSHAccountProvisionerConfigs[cfg_idx] = (
+ GroupAccountSSHProvisionerConfig(**cfg)
+ )
self.request.airavata_client.compute.update_group_resource_profile(grp)
def perform_destroy(self, instance):
- self.request.airavata_client.compute.remove_group_resource_profile(
- instance.groupResourceProfileId)
+ self.request.airavata_client.compute.remove_group_resource_profile(instance.groupResourceProfileId)
-class SharedEntityViewSet(mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- GenericAPIBackedViewSet):
+class SharedEntityViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.SharedEntitySerializer
- lookup_field = 'entity_id'
+ lookup_field = "entity_id"
def get_instance(self, lookup_value):
users = {}
@@ -1119,14 +1033,10 @@ class SharedEntityViewSet(mixins.RetrieveModelMixin,
# ones that can be edited
# Load accessible users in order of permission precedence: users that
# have WRITE permission should also have READ
- users.update(self._load_directly_accessible_users(
- lookup_value, ResourcePermissionType.READ))
- users.update(self._load_directly_accessible_users(
- lookup_value, ResourcePermissionType.WRITE))
- users.update(self._load_directly_accessible_users(
- lookup_value, ResourcePermissionType.MANAGE_SHARING))
- owner_ids = self._load_directly_accessible_users(
- lookup_value, ResourcePermissionType.OWNER)
+ users.update(self._load_directly_accessible_users(lookup_value, ResourcePermissionType.READ))
+ users.update(self._load_directly_accessible_users(lookup_value, ResourcePermissionType.WRITE))
+ users.update(self._load_directly_accessible_users(lookup_value, ResourcePermissionType.MANAGE_SHARING))
+ owner_ids = self._load_directly_accessible_users(lookup_value, ResourcePermissionType.OWNER)
# Assume that there is one and only one DIRECT owner (there may be one
# or more INDIRECT cascading owners, which would the owners of the
# ancestor entities, but getAllDirectlyAccessibleUsers does not return
@@ -1136,47 +1046,39 @@ class SharedEntityViewSet(mixins.RetrieveModelMixin,
del users[owner_id]
user_list = []
for user_id in users:
- user_list.append({'user': self._load_user_profile(user_id),
- 'permissionType': users[user_id]})
+ user_list.append({"user": self._load_user_profile(user_id), "permissionType": users[user_id]})
groups = {}
- groups.update(self._load_directly_accessible_groups(
- lookup_value, ResourcePermissionType.READ))
- groups.update(self._load_directly_accessible_groups(
- lookup_value, ResourcePermissionType.WRITE))
- groups.update(self._load_directly_accessible_groups(
- lookup_value, ResourcePermissionType.MANAGE_SHARING))
+ groups.update(self._load_directly_accessible_groups(lookup_value, ResourcePermissionType.READ))
+ groups.update(self._load_directly_accessible_groups(lookup_value, ResourcePermissionType.WRITE))
+ groups.update(self._load_directly_accessible_groups(lookup_value, ResourcePermissionType.MANAGE_SHARING))
group_list = []
for group_id in groups:
- group_list.append({'group': self._load_group(group_id),
- 'permissionType': groups[group_id]})
- return {'entityId': lookup_value,
- 'userPermissions': user_list,
- 'groupPermissions': group_list,
- 'owner': self._load_user_profile(owner_id)}
+ group_list.append({"group": self._load_group(group_id), "permissionType": groups[group_id]})
+ return {
+ "entityId": lookup_value,
+ "userPermissions": user_list,
+ "groupPermissions": group_list,
+ "owner": self._load_user_profile(owner_id),
+ }
def _load_accessible_users(self, entity_id, permission_type):
- users = self.request.airavata_client.sharing.get_all_accessible_users(
- entity_id, permission_type)
+ users = self.request.airavata_client.sharing.get_all_accessible_users(entity_id, permission_type)
return {user_id: permission_type for user_id in users}
def _load_directly_accessible_users(self, entity_id, permission_type):
- users = self.request.airavata_client.sharing.get_all_directly_accessible_users(
- entity_id, permission_type)
+ users = self.request.airavata_client.sharing.get_all_directly_accessible_users(entity_id, permission_type)
return {user_id: permission_type for user_id in users}
def _load_user_profile(self, user_id):
- username = user_id[0:user_id.rindex('@')]
- return self.request.airavata_client.iam.get_user_profile_by_id(
- username, settings.GATEWAY_ID)
+ username = user_id[0 : user_id.rindex("@")]
+ return self.request.airavata_client.iam.get_user_profile_by_id(username, settings.GATEWAY_ID)
def _load_accessible_groups(self, entity_id, permission_type):
- groups = self.request.airavata_client.sharing.get_all_accessible_groups(
- entity_id, permission_type)
+ groups = self.request.airavata_client.sharing.get_all_accessible_groups(entity_id, permission_type)
return {group_id: permission_type for group_id in groups}
def _load_directly_accessible_groups(self, entity_id, permission_type):
- groups = self.request.airavata_client.sharing.get_all_directly_accessible_groups(
- entity_id, permission_type)
+ groups = self.request.airavata_client.sharing.get_all_directly_accessible_groups(entity_id, permission_type)
return {group_id: permission_type for group_id in groups}
def _load_group(self, group_id):
@@ -1184,77 +1086,81 @@ class SharedEntityViewSet(mixins.RetrieveModelMixin,
def perform_update(self, serializer):
shared_entity = serializer.save()
- entity_id = shared_entity['entityId']
- if len(shared_entity['_user_grant_read_permission']) > 0:
- self._share_with_users(
- entity_id, ResourcePermissionType.READ,
- shared_entity['_user_grant_read_permission'])
- if len(shared_entity['_user_grant_write_permission']) > 0:
+ entity_id = shared_entity["entityId"]
+ if len(shared_entity["_user_grant_read_permission"]) > 0:
+ self._share_with_users(entity_id, ResourcePermissionType.READ, shared_entity["_user_grant_read_permission"])
+ if len(shared_entity["_user_grant_write_permission"]) > 0:
self._share_with_users(
- entity_id, ResourcePermissionType.WRITE,
- shared_entity['_user_grant_write_permission'])
- if len(shared_entity['_user_grant_manage_sharing_permission']) > 0:
+ entity_id, ResourcePermissionType.WRITE, shared_entity["_user_grant_write_permission"]
+ )
+ if len(shared_entity["_user_grant_manage_sharing_permission"]) > 0:
self._share_with_users(
- entity_id, ResourcePermissionType.MANAGE_SHARING,
- shared_entity['_user_grant_manage_sharing_permission'])
- if len(shared_entity['_user_revoke_read_permission']) > 0:
+ entity_id, ResourcePermissionType.MANAGE_SHARING, shared_entity["_user_grant_manage_sharing_permission"]
+ )
+ if len(shared_entity["_user_revoke_read_permission"]) > 0:
self._revoke_from_users(
- entity_id, ResourcePermissionType.READ,
- shared_entity['_user_revoke_read_permission'])
- if len(shared_entity['_user_revoke_write_permission']) > 0:
+ entity_id, ResourcePermissionType.READ, shared_entity["_user_revoke_read_permission"]
+ )
+ if len(shared_entity["_user_revoke_write_permission"]) > 0:
self._revoke_from_users(
- entity_id, ResourcePermissionType.WRITE,
- shared_entity['_user_revoke_write_permission'])
- if len(shared_entity['_user_revoke_manage_sharing_permission']) > 0:
+ entity_id, ResourcePermissionType.WRITE, shared_entity["_user_revoke_write_permission"]
+ )
+ if len(shared_entity["_user_revoke_manage_sharing_permission"]) > 0:
self._revoke_from_users(
- entity_id, ResourcePermissionType.MANAGE_SHARING,
- shared_entity['_user_revoke_manage_sharing_permission'])
- if len(shared_entity['_group_grant_read_permission']) > 0:
+ entity_id,
+ ResourcePermissionType.MANAGE_SHARING,
+ shared_entity["_user_revoke_manage_sharing_permission"],
+ )
+ if len(shared_entity["_group_grant_read_permission"]) > 0:
self._share_with_groups(
- entity_id, ResourcePermissionType.READ,
- shared_entity['_group_grant_read_permission'])
- if len(shared_entity['_group_grant_write_permission']) > 0:
+ entity_id, ResourcePermissionType.READ, shared_entity["_group_grant_read_permission"]
+ )
+ if len(shared_entity["_group_grant_write_permission"]) > 0:
self._share_with_groups(
- entity_id, ResourcePermissionType.WRITE,
- shared_entity['_group_grant_write_permission'])
- if len(shared_entity['_group_grant_manage_sharing_permission']) > 0:
+ entity_id, ResourcePermissionType.WRITE, shared_entity["_group_grant_write_permission"]
+ )
+ if len(shared_entity["_group_grant_manage_sharing_permission"]) > 0:
self._share_with_groups(
- entity_id, ResourcePermissionType.MANAGE_SHARING,
- shared_entity['_group_grant_manage_sharing_permission'])
- if len(shared_entity['_group_revoke_read_permission']) > 0:
+ entity_id,
+ ResourcePermissionType.MANAGE_SHARING,
+ shared_entity["_group_grant_manage_sharing_permission"],
+ )
+ if len(shared_entity["_group_revoke_read_permission"]) > 0:
self._revoke_from_groups(
- entity_id, ResourcePermissionType.READ,
- shared_entity['_group_revoke_read_permission'])
- if len(shared_entity['_group_revoke_write_permission']) > 0:
+ entity_id, ResourcePermissionType.READ, shared_entity["_group_revoke_read_permission"]
+ )
+ if len(shared_entity["_group_revoke_write_permission"]) > 0:
self._revoke_from_groups(
- entity_id, ResourcePermissionType.WRITE,
- shared_entity['_group_revoke_write_permission'])
- if len(shared_entity['_group_revoke_manage_sharing_permission']) > 0:
+ entity_id, ResourcePermissionType.WRITE, shared_entity["_group_revoke_write_permission"]
+ )
+ if len(shared_entity["_group_revoke_manage_sharing_permission"]) > 0:
self._revoke_from_groups(
- entity_id, ResourcePermissionType.MANAGE_SHARING,
- shared_entity['_group_revoke_manage_sharing_permission'])
+ entity_id,
+ ResourcePermissionType.MANAGE_SHARING,
+ shared_entity["_group_revoke_manage_sharing_permission"],
+ )
def _share_with_users(self, entity_id, permission_type, user_ids):
self.request.airavata_client.sharing.share_resource_with_users(
- entity_id,
- {user_id: permission_type for user_id in user_ids})
+ entity_id, {user_id: permission_type for user_id in user_ids}
+ )
def _revoke_from_users(self, entity_id, permission_type, user_ids):
self.request.airavata_client.sharing.revoke_sharing_of_resource_from_users(
- entity_id,
- {user_id: permission_type for user_id in user_ids})
+ entity_id, {user_id: permission_type for user_id in user_ids}
+ )
def _share_with_groups(self, entity_id, permission_type, group_ids):
self.request.airavata_client.sharing.share_resource_with_groups(
- entity_id,
- {group_id: permission_type for group_id in group_ids})
+ entity_id, {group_id: permission_type for group_id in group_ids}
+ )
def _revoke_from_groups(self, entity_id, permission_type, group_ids):
self.request.airavata_client.sharing.revoke_sharing_of_resource_from_groups(
- entity_id,
- {group_id: permission_type for group_id in group_ids})
+ entity_id, {group_id: permission_type for group_id in group_ids}
+ )
- @action(methods=['put'], detail=True)
+ @action(methods=["put"], detail=True)
def merge(self, request, entity_id=None):
# Validate updated sharing settings
updated = self.get_serializer(data=request.data)
@@ -1263,34 +1169,27 @@ class SharedEntityViewSet(mixins.RetrieveModelMixin,
existing_instance = self.get_object()
existing = self.get_serializer(instance=existing_instance)
merged_data = existing.data
- merged_data['userPermissions'] = existing.data['userPermissions'] + \
- updated.initial_data['userPermissions']
- merged_data['groupPermissions'] = existing.data['groupPermissions'] + \
- updated.initial_data['groupPermissions']
+ merged_data["userPermissions"] = existing.data["userPermissions"] + updated.initial_data["userPermissions"]
+ merged_data["groupPermissions"] = existing.data["groupPermissions"] + updated.initial_data["groupPermissions"]
# Create a merged_serializer from the existing sharing settings and the
# merged settings. This will calculate all permissions that need to be
# granted and revoked to go from the exisitng settings to the merged
# settings.
- merged_serializer = self.get_serializer(
- existing_instance, data=merged_data)
+ merged_serializer = self.get_serializer(existing_instance, data=merged_data)
merged_serializer.is_valid(raise_exception=True)
self.perform_update(merged_serializer)
return Response(merged_serializer.data)
- @action(methods=['get'], detail=True)
+ @action(methods=["get"], detail=True)
def all(self, request, entity_id=None):
"""Load direct plus indirectly (inherited) shared permissions."""
users = {}
# Load accessible users in order of permission precedence: users that
# have WRITE permission should also have READ
- users.update(self._load_accessible_users(
- entity_id, ResourcePermissionType.READ))
- users.update(self._load_accessible_users(
- entity_id, ResourcePermissionType.WRITE))
- users.update(self._load_accessible_users(
- entity_id, ResourcePermissionType.MANAGE_SHARING))
- owner_ids = self._load_accessible_users(
- entity_id, ResourcePermissionType.OWNER)
+ users.update(self._load_accessible_users(entity_id, ResourcePermissionType.READ))
+ users.update(self._load_accessible_users(entity_id, ResourcePermissionType.WRITE))
+ users.update(self._load_accessible_users(entity_id, ResourcePermissionType.MANAGE_SHARING))
+ owner_ids = self._load_accessible_users(entity_id, ResourcePermissionType.OWNER)
# Assume that there is one and only one DIRECT owner (there may be one
# or more INDIRECT cascading owners, which would the owners of the
# ancestor entities, but getAllAccessibleUsers does not return
@@ -1300,25 +1199,21 @@ class SharedEntityViewSet(mixins.RetrieveModelMixin,
del users[owner_id]
user_list = []
for user_id in users:
- user_list.append({'user': self._load_user_profile(user_id),
- 'permissionType': users[user_id]})
+ user_list.append({"user": self._load_user_profile(user_id), "permissionType": users[user_id]})
groups = {}
- groups.update(self._load_accessible_groups(
- entity_id, ResourcePermissionType.READ))
- groups.update(self._load_accessible_groups(
- entity_id, ResourcePermissionType.WRITE))
- groups.update(self._load_accessible_groups(
- entity_id, ResourcePermissionType.MANAGE_SHARING))
+ groups.update(self._load_accessible_groups(entity_id, ResourcePermissionType.READ))
+ groups.update(self._load_accessible_groups(entity_id, ResourcePermissionType.WRITE))
+ groups.update(self._load_accessible_groups(entity_id, ResourcePermissionType.MANAGE_SHARING))
group_list = []
for group_id in groups:
- group_list.append({'group': self._load_group(group_id),
- 'permissionType': groups[group_id]})
- shared_entity = {'entityId': entity_id,
- 'userPermissions': user_list,
- 'groupPermissions': group_list,
- 'owner': self._load_user_profile(owner_id)}
- serializer = self.serializer_class(
- shared_entity, context={'request': request})
+ group_list.append({"group": self._load_group(group_id), "permissionType": groups[group_id]})
+ shared_entity = {
+ "entityId": entity_id,
+ "userPermissions": user_list,
+ "groupPermissions": group_list,
+ "owner": self._load_user_profile(owner_id),
+ }
+ serializer = self.serializer_class(shared_entity, context={"request": request})
return Response(serializer.data)
@@ -1326,102 +1221,87 @@ class CredentialSummaryViewSet(APIBackedViewSet):
serializer_class = serializers.CredentialSummarySerializer
def get_list(self):
- ssh_creds = self.request.airavata_client.credential.get_all_credential_summaries(
- SummaryType.SSH)
- pwd_creds = self.request.airavata_client.credential.get_all_credential_summaries(
- SummaryType.PASSWD)
+ ssh_creds = self.request.airavata_client.credential.get_all_credential_summaries(SummaryType.SSH)
+ pwd_creds = self.request.airavata_client.credential.get_all_credential_summaries(SummaryType.PASSWD)
return ssh_creds + pwd_creds
def get_instance(self, lookup_value):
- return self.request.airavata_client.credential.get_credential_summary(
- lookup_value)
+ return self.request.airavata_client.credential.get_credential_summary(lookup_value)
@action(detail=False)
def ssh(self, request):
- summaries = self.request.airavata_client.credential.get_all_credential_summaries(
- SummaryType.SSH)
+ summaries = self.request.airavata_client.credential.get_all_credential_summaries(SummaryType.SSH)
serializer = self.get_serializer(summaries, many=True)
return Response(serializer.data)
@action(detail=False)
def password(self, request):
- summaries = self.request.airavata_client.credential.get_all_credential_summaries(
- SummaryType.PASSWD)
+ summaries = self.request.airavata_client.credential.get_all_credential_summaries(SummaryType.PASSWD)
serializer = self.get_serializer(summaries, many=True)
return Response(serializer.data)
- @action(methods=['post'], detail=False)
+ @action(methods=["post"], detail=False)
def create_ssh(self, request):
- if 'description' not in request.data:
+ if "description" not in request.data:
raise ParseError("'description' is required in request")
- description = request.data.get('description')
- token_id = self.request.airavata_client.credential.generate_and_register_ssh_keys(
- description)
- credential_summary = self.request.airavata_client.credential.get_credential_summary(
- token_id)
+ description = request.data.get("description")
+ token_id = self.request.airavata_client.credential.generate_and_register_ssh_keys(description)
+ credential_summary = self.request.airavata_client.credential.get_credential_summary(token_id)
serializer = self.get_serializer(credential_summary)
return Response(serializer.data)
- @action(methods=['post'], detail=False)
+ @action(methods=["post"], detail=False)
def create_password(self, request):
- if ('username' not in request.data or
- 'password' not in request.data or
- 'description' not in request.data):
- raise ParseError("'username', 'password' and 'description' "
- "are all required in request")
- username = request.data.get('username')
- password = request.data.get('password')
- description = request.data.get('description')
- token_id = self.request.airavata_client.credential.register_pwd_credential(
- username, password, description)
- credential_summary = self.request.airavata_client.credential.get_credential_summary(
- token_id)
+ if "username" not in request.data or "password" not in request.data or "description" not in request.data:
+ raise ParseError("'username', 'password' and 'description' are all required in request")
+ username = request.data.get("username")
+ password = request.data.get("password")
+ description = request.data.get("description")
+ token_id = self.request.airavata_client.credential.register_pwd_credential(username, password, description)
+ credential_summary = self.request.airavata_client.credential.get_credential_summary(token_id)
serializer = self.get_serializer(credential_summary)
return Response(serializer.data)
def perform_destroy(self, instance):
if instance.type == SummaryType.SSH:
- self.request.airavata_client.credential.delete_ssh_pub_key(
- instance.token)
+ self.request.airavata_client.credential.delete_ssh_pub_key(instance.token)
elif instance.type == SummaryType.PASSWD:
- self.request.airavata_client.credential.delete_pwd_credential(
- instance.token)
+ self.request.airavata_client.credential.delete_pwd_credential(instance.token)
class CurrentGatewayResourceProfile(APIView):
-
def get(self, request, format=None):
- gateway_resource_profile = \
- request.airavata_client.compute.get_gateway_resource_profile(
- settings.GATEWAY_ID)
+ gateway_resource_profile = request.airavata_client.compute.get_gateway_resource_profile(settings.GATEWAY_ID)
serializer = serializers.GatewayResourceProfileSerializer(
- gateway_resource_profile, context={'request': request})
+ gateway_resource_profile, context={"request": request}
+ )
return Response(serializer.data)
def put(self, request, format=None):
- serializer = serializers.GatewayResourceProfileSerializer(
- data=request.data, context={'request': request})
+ serializer = serializers.GatewayResourceProfileSerializer(data=request.data, context={"request": request})
if serializer.is_valid():
gateway_resource_profile = serializer.save()
request.airavata_client.compute.update_gateway_resource_profile(
- settings.GATEWAY_ID,
- gateway_resource_profile)
+ settings.GATEWAY_ID, gateway_resource_profile
+ )
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ExperimentArchiveView(APIView):
-
def get(self, request, experiment_id=None, format=None):
- experiment: ExperimentModel = request.airavata_client.research.get_experiment(
- experiment_id)
- result = dict(archived=False, archive_name=None, created_date=None,
- max_age=settings.GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS)
+ experiment: ExperimentModel = request.airavata_client.research.get_experiment(experiment_id)
+ result = dict(
+ archived=False,
+ archive_name=None,
+ created_date=None,
+ max_age=settings.GATEWAY_USER_DATA_ARCHIVE_MAX_AGE_DAYS,
+ )
try:
archive_entry = UserDataArchiveEntry.objects.get(
- entry_path=experiment.userConfigurationData.experimentDataDir,
- user_data_archive__rolled_back=False)
+ entry_path=experiment.userConfigurationData.experimentDataDir, user_data_archive__rolled_back=False
+ )
result["archived"] = True
result["archive_name"] = archive_entry.user_data_archive.archive_name
result["created_date"] = archive_entry.user_data_archive.created_date
@@ -1430,68 +1310,62 @@ class ExperimentArchiveView(APIView):
return Response(result, status=status.HTTP_200_OK)
-class StorageResourceViewSet(mixins.RetrieveModelMixin,
- GenericAPIBackedViewSet):
+class StorageResourceViewSet(mixins.RetrieveModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.StorageResourceSerializer
- lookup_field = 'storage_resource_id'
+ lookup_field = "storage_resource_id"
def get_instance(self, lookup_value, format=None):
- return self.request.airavata_client.storage.get_storage_resource(
- lookup_value)
+ return self.request.airavata_client.storage.get_storage_resource(lookup_value)
@action(detail=False)
def all_names(self, request, format=None):
"""Return a map of compute resource names keyed by resource id."""
- return Response(
- request.airavata_client.storage.get_all_storage_resource_names())
+ return Response(request.airavata_client.storage.get_all_storage_resource_names())
class StoragePreferenceViewSet(APIBackedViewSet):
serializer_class = serializers.StoragePreferenceSerializer
- lookup_field = 'storage_resource_id'
+ lookup_field = "storage_resource_id"
def get_list(self):
- return self.request.airavata_client.compute.get_all_gateway_storage_preferences(
- settings.GATEWAY_ID)
+ return self.request.airavata_client.compute.get_all_gateway_storage_preferences(settings.GATEWAY_ID)
def get_instance(self, lookup_value):
- return self.request.airavata_client.compute.get_gateway_storage_preference(
- settings.GATEWAY_ID, lookup_value)
+ return self.request.airavata_client.compute.get_gateway_storage_preference(settings.GATEWAY_ID, lookup_value)
def perform_create(self, serializer):
storage_preference = serializer.save()
self.request.airavata_client.compute.add_gateway_storage_preference(
- settings.GATEWAY_ID,
- storage_preference.storageResourceId,
- storage_preference)
+ settings.GATEWAY_ID, storage_preference.storageResourceId, storage_preference
+ )
def perform_update(self, serializer):
storage_preference = serializer.save()
self.request.airavata_client.compute.update_gateway_storage_preference(
- settings.GATEWAY_ID,
- storage_preference.storageResourceId,
- storage_preference)
+ settings.GATEWAY_ID, storage_preference.storageResourceId, storage_preference
+ )
def perform_destroy(self, instance):
self.request.airavata_client.compute.delete_gateway_storage_preference(
- settings.GATEWAY_ID, instance.storageResourceId)
+ settings.GATEWAY_ID, instance.storageResourceId
+ )
-class ParserViewSet(mixins.CreateModelMixin,
- mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.ListModelMixin,
- GenericAPIBackedViewSet):
+class ParserViewSet(
+ mixins.CreateModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.ListModelMixin,
+ GenericAPIBackedViewSet,
+):
serializer_class = serializers.ParserSerializer
- lookup_field = 'parser_id'
+ lookup_field = "parser_id"
def get_list(self):
- return self.request.airavata_client.research.list_all_parsers(
- settings.GATEWAY_ID)
+ return self.request.airavata_client.research.list_all_parsers(settings.GATEWAY_ID)
def get_instance(self, lookup_value):
- return self.request.airavata_client.research.get_parser(
- lookup_value, settings.GATEWAY_ID)
+ return self.request.airavata_client.research.get_parser(lookup_value, settings.GATEWAY_ID)
def perform_create(self, serializer):
parser = serializer.save()
@@ -1508,13 +1382,13 @@ class UserStoragePathView(APIView):
def get(self, request, path="/", format=None):
# AIRAVATA-3460 Allow passing path as a query parameter instead
- path = request.query_params.get('path', path)
- experiment_id = request.query_params.get('experiment-id')
+ path = request.query_params.get("path", path)
+ experiment_id = request.query_params.get("experiment-id")
return self._create_response(request, path, experiment_id=experiment_id)
def post(self, request, path="/", format=None):
- path = request.data.get('path', path)
- experiment_id = request.data.get('experiment-id')
+ path = request.data.get("path", path)
+ experiment_id = request.data.get("experiment-id")
if not user_storage.dir_exists(request, path, experiment_id=experiment_id):
_, resource_path = user_storage.create_user_dir(request, path, experiment_id=experiment_id)
# create_user_dir may create the directory with a different name
@@ -1524,45 +1398,50 @@ class UserStoragePathView(APIView):
data_product = None
# Handle direct upload
- if 'file' in request.FILES:
- user_file = request.FILES['file']
+ if "file" in request.FILES:
+ user_file = request.FILES["file"]
data_product = user_storage.save(
- request, path, user_file, content_type=user_file.content_type,
- experiment_id=experiment_id)
+ request, path, user_file, content_type=user_file.content_type, experiment_id=experiment_id
+ )
# Handle a tus upload
- elif 'uploadURL' in request.POST:
- uploadURL = request.POST['uploadURL']
+ elif "uploadURL" in request.POST:
+ uploadURL = request.POST["uploadURL"]
def save_file(file_path, file_name, file_type):
- with open(file_path, 'rb') as uploaded_file:
- return user_storage.save(request, path, uploaded_file,
- name=file_name, content_type=file_type,
- experiment_id=experiment_id)
+ with open(file_path, "rb") as uploaded_file:
+ return user_storage.save(
+ request,
+ path,
+ uploaded_file,
+ name=file_name,
+ content_type=file_type,
+ experiment_id=experiment_id,
+ )
+
data_product = tus.save_tus_upload(uploadURL, save_file)
return self._create_response(request, path, uploaded=data_product, experiment_id=experiment_id)
# Accept wither to replace file or to replace file content text.
def put(self, request, path="/", format=None):
- path = request.POST.get('path', path)
+ path = request.POST.get("path", path)
# Replace the file if the request has a file upload.
- if 'file' in request.FILES:
+ if "file" in request.FILES:
self.delete(request=request, path=path, format=format)
dir_path, file_name = os.path.split(path)
self.post(request=request, path=dir_path, format=format, file_name=file_name)
# Replace only the file content if the request body has the `fileContentText`
elif request.data and "fileContentText" in request.data:
user_storage.update_file_content(
- request=request,
- path=path,
- fileContentText=request.data["fileContentText"])
+ request=request, path=path, fileContentText=request.data["fileContentText"]
+ )
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
return self._create_response(request=request, path=path)
def delete(self, request, path="/", format=None):
- path = request.data.get('path', path)
- experiment_id = request.data.get('experiment-id')
+ path = request.data.get("path", path)
+ experiment_id = request.data.get("experiment-id")
if user_storage.dir_exists(request, path, experiment_id=experiment_id):
user_storage.delete_dir(request, path, experiment_id=experiment_id)
else:
@@ -1573,30 +1452,20 @@ class UserStoragePathView(APIView):
def _create_response(self, request, path, uploaded=None, experiment_id=None):
if user_storage.dir_exists(request, path, experiment_id=experiment_id):
directories, files = user_storage.listdir(request, path, experiment_id=experiment_id)
- data = {
- 'isDir': True,
- 'directories': directories,
- 'files': files
- }
+ data = {"isDir": True, "directories": directories, "files": files}
if uploaded is not None:
- data['uploaded'] = uploaded
- data['parts'] = self._split_path(path)
- data['path'] = path
- serializer = self.serializer_class(
- data, context={'request': request})
+ data["uploaded"] = uploaded
+ data["parts"] = self._split_path(path)
+ data["path"] = path
+ serializer = self.serializer_class(data, context={"request": request})
return Response(serializer.data)
else:
file = user_storage.get_file_metadata(request, path, experiment_id=experiment_id)
- data = {
- 'isDir': False,
- 'directories': [],
- 'files': [file]
- }
+ data = {"isDir": False, "directories": [], "files": [file]}
if uploaded is not None:
- data['uploaded'] = uploaded
- data['parts'] = self._split_path(path)
- serializer = self.serializer_class(
- data, context={'request': request})
+ data["uploaded"] = uploaded
+ data["parts"] = self._split_path(path)
+ serializer = self.serializer_class(data, context={"request": request})
return Response(serializer.data)
def _split_path(self, path):
@@ -1610,7 +1479,6 @@ class UserStoragePathView(APIView):
class ExperimentStoragePathView(APIView):
-
serializer_class = serializers.ExperimentStoragePathSerializer
def get(self, request, experiment_id=None, path="", format=None):
@@ -1621,16 +1489,12 @@ class ExperimentStoragePathView(APIView):
directories, files = user_storage.list_experiment_dir(request, experiment_id, path)
def add_expid(d):
- d['experiment_id'] = experiment_id
+ d["experiment_id"] = experiment_id
return d
- data = {
- 'isDir': True,
- 'directories': map(add_expid, directories),
- 'files': map(add_expid, files)
- }
- data['parts'] = self._split_path(path)
- serializer = self.serializer_class(
- data, context={'request': request})
+
+ data = {"isDir": True, "directories": map(add_expid, directories), "files": map(add_expid, files)}
+ data["parts"] = self._split_path(path)
+ serializer = self.serializer_class(data, context={"request": request})
return Response(serializer.data)
else:
raise Http404(f"Path '{path}' does not exist for {experiment_id}")
@@ -1651,31 +1515,26 @@ class WorkspacePreferencesView(APIView):
def get(self, request, format=None):
helper = helpers.WorkspacePreferencesHelper()
workspace_preferences = helper.get(request)
- serializer = self.serializer_class(
- workspace_preferences, context={'request': request})
+ serializer = self.serializer_class(workspace_preferences, context={"request": request})
return Response(serializer.data)
class ManageNotificationViewSet(APIBackedViewSet):
serializer_class = serializers.NotificationSerializer
- lookup_field = 'notification_id'
+ lookup_field = "notification_id"
def get_instance(self, lookup_value):
- return self.request.airavata_client.research.get_notification(
- settings.GATEWAY_ID, lookup_value)
+ return self.request.airavata_client.research.get_notification(settings.GATEWAY_ID, lookup_value)
def get_list(self):
- return self.request.airavata_client.research.get_all_notifications(
- self.gateway_id)
+ return self.request.airavata_client.research.get_all_notifications(self.gateway_id)
def perform_destroy(self, instance):
- self.request.airavata_client.research.delete_notification(
- settings.GATEWAY_ID, instance.notificationId)
+ self.request.airavata_client.research.delete_notification(settings.GATEWAY_ID, instance.notificationId)
def perform_create(self, serializer):
notification = serializer.save(gatewayId=self.gateway_id)
- notificationId = self.request.airavata_client.research.create_notification(
- notification)
+ notificationId = self.request.airavata_client.research.create_notification(notification)
notification.notificationId = notificationId
serializer.update_notification_extension(self.request, notification)
@@ -1688,87 +1547,85 @@ class ManageNotificationViewSet(APIBackedViewSet):
class AckNotificationViewSet(APIView):
-
def get(self, request, format=None):
- if 'id' in request.GET:
- notification_id = request.GET['id']
+ if "id" in request.GET:
+ notification_id = request.GET["id"]
try:
notification = models.User_Notifications.objects.get(
- notification_id=notification_id,
- username=request.user.username)
+ notification_id=notification_id, username=request.user.username
+ )
notification.is_read = True
notification.save()
except ObjectDoesNotExist:
models.User_Notifications.objects.create(
- username=request.user.username,
- notification_id=notification.notificationId)
+ username=request.user.username, notification_id=notification.notificationId
+ )
return HttpResponse(status=204)
-class IAMUserViewSet(mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.ListModelMixin,
- mixins.DestroyModelMixin,
- GenericAPIBackedViewSet):
+class IAMUserViewSet(
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.ListModelMixin,
+ mixins.DestroyModelMixin,
+ GenericAPIBackedViewSet,
+):
serializer_class = serializers.IAMUserProfile
pagination_class = APIResultPagination
- permission_classes = (IsAuthenticated, IsInAdminsGroupPermission,)
- lookup_field = 'user_id'
+ permission_classes = (
+ IsAuthenticated,
+ IsInAdminsGroupPermission,
+ )
+ lookup_field = "user_id"
def get_list(self):
- search = self.request.GET.get('search', None)
+ search = self.request.GET.get("search", None)
convert_user_profile = self._convert_user_profile
class IAMUsersResultIterator(APIResultIterator):
def get_results(self, limit=-1, offset=0):
- return map(convert_user_profile,
- iam_admin_client.get_users(offset, limit, search))
+ return map(convert_user_profile, iam_admin_client.get_users(offset, limit, search))
+
return IAMUsersResultIterator(query_params=self.request.query_params.copy())
def get_instance(self, lookup_value):
- return self._convert_user_profile(
- iam_admin_client.get_user(lookup_value))
+ return self._convert_user_profile(iam_admin_client.get_user(lookup_value))
def perform_update(self, serializer):
managed_user_profile = serializer.save()
sharing_client = self.request.airavata_client.sharing
iam_client = self.request.airavata_client.iam
- user_id = managed_user_profile['airavataInternalUserId']
+ user_id = managed_user_profile["airavataInternalUserId"]
added_groups = []
- for group_id in managed_user_profile['_added_group_ids']:
+ for group_id in managed_user_profile["_added_group_ids"]:
group = sharing_client.get_group(group_id)
sharing_client.add_users_to_group([user_id], group_id)
added_groups.append(group)
if len(added_groups) > 0:
- user_profile = iam_client.get_user_profile_by_id(
- managed_user_profile['userId'],
- settings.GATEWAY_ID)
+ user_profile = iam_client.get_user_profile_by_id(managed_user_profile["userId"], settings.GATEWAY_ID)
signals.user_added_to_group.send(
- sender=self.__class__,
- user=user_profile,
- groups=added_groups,
- request=self.request)
- for group_id in managed_user_profile['_removed_group_ids']:
+ sender=self.__class__, user=user_profile, groups=added_groups, request=self.request
+ )
+ for group_id in managed_user_profile["_removed_group_ids"]:
sharing_client.remove_users_from_group([user_id], group_id)
def perform_destroy(self, instance):
- iam_admin_client.delete_user(instance['userId'])
+ iam_admin_client.delete_user(instance["userId"])
- @action(methods=['post'], detail=True)
+ @action(methods=["post"], detail=True)
def enable(self, request, user_id=None):
iam_admin_client.enable_user(user_id)
instance = self.get_instance(user_id)
- serializer = self.serializer_class(instance=instance,
- context={'request': request})
+ serializer = self.serializer_class(instance=instance, context={"request": request})
return Response(serializer.data)
- @action(methods=['put'], detail=False)
+ @action(methods=["put"], detail=False)
def update_username(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
- old_username = serializer.validated_data['userId']
- new_username = serializer.validated_data['newUsername']
+ old_username = serializer.validated_data["userId"]
+ new_username = serializer.validated_data["newUsername"]
iam_admin_client.update_username(old_username, new_username)
# set username_initialized to True so it is treated as valid.
django_user = get_user_model().objects.get(username=old_username)
@@ -1780,32 +1637,28 @@ class IAMUserViewSet(mixins.RetrieveModelMixin,
django_user.username = new_username
django_user.save()
instance = self.get_instance(new_username)
- serializer = self.serializer_class(instance=instance,
- context={'request': request})
+ serializer = self.serializer_class(instance=instance, context={"request": request})
return Response(serializer.data)
def _convert_user_profile(self, user_profile):
iam_client = self.request.airavata_client.iam
sharing_client = self.request.airavata_client.sharing
- airavata_user_profile_exists = iam_client.does_user_exist(
- user_profile.userId, self.gateway_id)
+ airavata_user_profile_exists = iam_client.does_user_exist(user_profile.userId, self.gateway_id)
groups = []
if airavata_user_profile_exists:
- groups = sharing_client.get_all_groups_user_belongs(
- user_profile.airavataInternalUserId)
+ groups = sharing_client.get_all_groups_user_belongs(user_profile.airavataInternalUserId)
return {
- 'airavataInternalUserId': user_profile.airavataInternalUserId,
- 'userId': user_profile.userId,
- 'gatewayId': user_profile.gatewayId,
- 'email': user_profile.emails[0],
- 'firstName': user_profile.firstName,
- 'lastName': user_profile.lastName,
- 'enabled': user_profile.State == Status.ACTIVE,
- 'emailVerified': (user_profile.State == Status.CONFIRMED or
- user_profile.State == Status.ACTIVE),
- 'airavataUserProfileExists': airavata_user_profile_exists,
- 'creationTime': user_profile.creationTime,
- 'groups': groups
+ "airavataInternalUserId": user_profile.airavataInternalUserId,
+ "userId": user_profile.userId,
+ "gatewayId": user_profile.gatewayId,
+ "email": user_profile.emails[0],
+ "firstName": user_profile.firstName,
+ "lastName": user_profile.lastName,
+ "enabled": user_profile.State == Status.ACTIVE,
+ "emailVerified": (user_profile.State == Status.CONFIRMED or user_profile.State == Status.ACTIVE),
+ "airavataUserProfileExists": airavata_user_profile_exists,
+ "creationTime": user_profile.creationTime,
+ "groups": groups,
}
@@ -1814,29 +1667,26 @@ class ExperimentStatisticsView(APIView):
serializer_class = serializers.ExperimentStatisticsSerializer
def get(self, request, format=None):
- if 'fromTime' in request.GET:
- from_time = view_utils.convert_utc_iso8601_to_date(
- request.GET['fromTime']).timestamp() * 1000
+ if "fromTime" in request.GET:
+ from_time = view_utils.convert_utc_iso8601_to_date(request.GET["fromTime"]).timestamp() * 1000
else:
- from_time = (datetime.utcnow() -
- timedelta(days=7)).timestamp() * 1000
+ from_time = (datetime.utcnow() - timedelta(days=7)).timestamp() * 1000
from_time = int(from_time)
- if 'toTime' in request.GET:
- to_time = view_utils.convert_utc_iso8601_to_date(
- request.GET['toTime']).timestamp() * 1000
+ if "toTime" in request.GET:
+ to_time = view_utils.convert_utc_iso8601_to_date(request.GET["toTime"]).timestamp() * 1000
else:
to_time = datetime.utcnow().timestamp() * 1000
to_time = int(to_time)
- username = request.GET.get('userName', None)
- application_name = request.GET.get('applicationName', None)
- resource_hostname = request.GET.get('resourceHostName', None)
- limit = int(request.GET.get('limit', '50'))
- offset = int(request.GET.get('offset', '0'))
+ username = request.GET.get("userName", None)
+ application_name = request.GET.get("applicationName", None)
+ resource_hostname = request.GET.get("resourceHostName", None)
+ limit = int(request.GET.get("limit", "50"))
+ offset = int(request.GET.get("offset", "0"))
statistics = request.airavata_client.research.get_experiment_statistics(
- settings.GATEWAY_ID, from_time, to_time,
- username, application_name, resource_hostname, limit, offset)
- serializer = self.serializer_class(statistics, context={'request': request})
+ settings.GATEWAY_ID, from_time, to_time, username, application_name, resource_hostname, limit, offset
+ )
+ serializer = self.serializer_class(statistics, context={"request": request})
paginator = pagination.LimitOffsetPagination()
paginator.count = statistics.allExperimentCount
@@ -1845,18 +1695,19 @@ class ExperimentStatisticsView(APIView):
paginator.request = request
response = paginator.get_paginated_response(serializer.data)
# Also add limit and offset to the response
- response.data['limit'] = limit
- response.data['offset'] = offset
+ response.data["limit"] = limit
+ response.data["offset"] = offset
return response
-class UnverifiedEmailUserViewSet(mixins.ListModelMixin,
- mixins.RetrieveModelMixin,
- GenericAPIBackedViewSet):
+class UnverifiedEmailUserViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericAPIBackedViewSet):
serializer_class = serializers.UnverifiedEmailUserProfile
pagination_class = APIResultPagination
- permission_classes = (IsAuthenticated, IsInAdminsGroupPermission,)
- lookup_field = 'user_id'
+ permission_classes = (
+ IsAuthenticated,
+ IsInAdminsGroupPermission,
+ )
+ lookup_field = "user_id"
def get_list(self):
get_users = self._get_unverified_email_user_profiles
@@ -1864,53 +1715,51 @@ class UnverifiedEmailUserViewSet(mixins.ListModelMixin,
class UnverifiedEmailUsersResultIterator(APIResultIterator):
def get_results(self, limit=-1, offset=0):
return get_users(limit, offset)
+
return UnverifiedEmailUsersResultIterator()
def get_instance(self, lookup_value):
- users = self._get_unverified_email_user_profiles(
- limit=1, username=lookup_value)
+ users = self._get_unverified_email_user_profiles(limit=1, username=lookup_value)
if len(users) == 0:
- raise Http404("No unverified email record found for user {}"
- .format(lookup_value))
+ raise Http404(f"No unverified email record found for user {lookup_value}")
else:
return users[0]
- def _get_unverified_email_user_profiles(
- self, limit=-1, offset=0, username=None):
- unverified_emails = EmailVerification.objects.filter(
- verified=False).order_by('username').values('username').distinct()
+ def _get_unverified_email_user_profiles(self, limit=-1, offset=0, username=None):
+ unverified_emails = (
+ EmailVerification.objects.filter(verified=False).order_by("username").values("username").distinct()
+ )
if username is not None:
unverified_emails = unverified_emails.filter(username=username)
if limit > 0:
- unverified_emails = unverified_emails[offset:offset + limit]
+ unverified_emails = unverified_emails[offset : offset + limit]
results = []
for unverified_email in unverified_emails:
- unverified_username = unverified_email['username']
+ unverified_username = unverified_email["username"]
if iam_admin_client.is_user_exist(unverified_username):
user_profile = iam_admin_client.get_user(unverified_username)
- if (user_profile.State == Status.CONFIRMED or
- user_profile.State == Status.ACTIVE):
+ if user_profile.State == Status.CONFIRMED or user_profile.State == Status.ACTIVE:
# TODO: test this
- EmailVerification.objects.filter(
- username=unverified_username).update(
- verified=True)
+ EmailVerification.objects.filter(username=unverified_username).update(verified=True)
continue
- results.append({
- 'userId': user_profile.userId,
- 'gatewayId': user_profile.gatewayId,
- 'email': user_profile.emails[0],
- 'firstName': user_profile.firstName,
- 'lastName': user_profile.lastName,
- 'enabled': user_profile.State == Status.ACTIVE,
- 'emailVerified': (user_profile.State == Status.CONFIRMED or
- user_profile.State == Status.ACTIVE),
- 'creationTime': user_profile.creationTime,
- })
+ results.append(
+ {
+ "userId": user_profile.userId,
+ "gatewayId": user_profile.gatewayId,
+ "email": user_profile.emails[0],
+ "firstName": user_profile.firstName,
+ "lastName": user_profile.lastName,
+ "enabled": user_profile.State == Status.ACTIVE,
+ "emailVerified": (
+ user_profile.State == Status.CONFIRMED or user_profile.State == Status.ACTIVE
+ ),
+ "creationTime": user_profile.creationTime,
+ }
+ )
else:
# Delete the EmailVerification records since that user no
# longer exists in the IAM service
- EmailVerification.objects.filter(
- username=unverified_username).delete()
+ EmailVerification.objects.filter(username=unverified_username).delete()
return results
@@ -1921,15 +1770,16 @@ class LogRecordConsumer(APIView):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
log_record = serializer.validated_data
- log_level = getattr(logging, log_record['level'], None)
+ log_level = getattr(logging, log_record["level"], None)
if log_level is not None:
- stacktrace = "".join(
- map(lambda a: "\n " + a, log_record['stacktrace']))
- log.log(log_level,
- "Frontend error: {}: {}\nstacktrace: {}".format(
- log_record['message'],
- json.dumps(log_record['details'], indent=4),
- stacktrace), extra={'request': request})
+ stacktrace = "".join(map(lambda a: "\n " + a, log_record["stacktrace"]))
+ log.log(
+ log_level,
+ "Frontend error: {}: {}\nstacktrace: {}".format(
+ log_record["message"], json.dumps(log_record["details"], indent=4), stacktrace
+ ),
+ extra={"request": request},
+ )
return Response(serializer.data)
@@ -1938,45 +1788,37 @@ class SettingsAPIView(APIView):
def get(self, request, format=None):
data = {
- 'fileUploadMaxFileSize': settings.FILE_UPLOAD_MAX_FILE_SIZE,
- 'tusEndpoint': settings.TUS_ENDPOINT,
- 'pgaUrl': settings.PGA_URL
+ "fileUploadMaxFileSize": settings.FILE_UPLOAD_MAX_FILE_SIZE,
+ "tusEndpoint": settings.TUS_ENDPOINT,
+ "pgaUrl": settings.PGA_URL,
}
- serializer = self.serializer_class(
- data, context={'request': request})
+ serializer = self.serializer_class(data, context={"request": request})
return Response(serializer.data)
class APIServerStatusCheckView(APIView):
-
def get(self, request, format=None):
try:
request.airavata_client.research.get_user_projects(
- settings.GATEWAY_ID,
- request.user.username,
- 1, # limit
- 0) # offset
- data = {
- "apiServerUp": True
- }
+ settings.GATEWAY_ID,
+ request.user.username,
+ 1, # limit
+ 0,
+ ) # offset
+ data = {"apiServerUp": True}
except Exception as e:
- log.debug("API server status check failed: {}".format(str(e)))
- data = {
- "apiServerUp": False
- }
+ log.debug(f"API server status check failed: {str(e)}")
+ data = {"apiServerUp": False}
return Response(data)
@api_view()
def notebook_output_view(request):
- provider_id = request.GET['provider-id']
- experiment_id = request.GET['experiment-id']
- experiment_output_name = request.GET['experiment-output-name']
- data = output_views.generate_data(request,
- provider_id,
- experiment_output_name,
- experiment_id)
- return HttpResponse(data['output'])
+ provider_id = request.GET["provider-id"]
+ experiment_id = request.GET["experiment-id"]
+ experiment_output_name = request.GET["experiment-output-name"]
+ data = output_views.generate_data(request, provider_id, experiment_output_name, experiment_id)
+ return HttpResponse(data["output"])
@api_view()
@@ -1990,7 +1832,7 @@ def image_output_view(request):
data = _generate_output_view_data(request)
# data should contain 'image' as a file-like object or raw bytes with the
# file data and 'mime-type' with the images mimetype
- data['image'] = base64.b64encode(data['image']).decode('utf-8')
+ data["image"] = base64.b64encode(data["image"]).decode("utf-8")
return JsonResponse(data)
@@ -2002,16 +1844,13 @@ def link_output_view(request):
def _generate_output_view_data(request):
params = request.GET.copy()
- provider_id = params.pop('provider-id')[0]
- experiment_id = params.pop('experiment-id')[0]
- experiment_output_name = params.pop('experiment-output-name')[0]
- test_mode = ('test-mode' in params and params.pop('test-mode')[0] == "true")
- return output_views.generate_data(request,
- provider_id,
- experiment_output_name,
- experiment_id,
- test_mode=test_mode,
- **params.dict())
+ provider_id = params.pop("provider-id")[0]
+ experiment_id = params.pop("experiment-id")[0]
+ experiment_output_name = params.pop("experiment-output-name")[0]
+ test_mode = "test-mode" in params and params.pop("test-mode")[0] == "true"
+ return output_views.generate_data(
+ request, provider_id, experiment_output_name, experiment_id, test_mode=test_mode, **params.dict()
+ )
class QueueSettingsCalculatorViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericAPIBackedViewSet):
@@ -2027,7 +1866,7 @@ class QueueSettingsCalculatorViewSet(mixins.ListModelMixin, mixins.RetrieveModel
return None
return calc[0]
- @action(methods=['post'], detail=True, serializer_class=serializers.ExperimentSerializer)
+ @action(methods=["post"], detail=True, serializer_class=serializers.ExperimentSerializer)
def calculate(self, request, pk=None):
serializer = self.get_serializer(data=request.data)
diff --git a/airavata-django-portal/django_airavata/apps/auth/apps.py b/airavata-django-portal/django_airavata/apps/auth/apps.py
index cca02f9f2..eb7b7e84d 100644
--- a/airavata-django-portal/django_airavata/apps/auth/apps.py
+++ b/airavata-django-portal/django_airavata/apps/auth/apps.py
@@ -2,8 +2,8 @@ from django.apps import AppConfig
class AuthConfig(AppConfig):
- name = 'django_airavata.apps.auth'
- label = 'django_airavata_auth'
+ name = "django_airavata.apps.auth"
+ label = "django_airavata_auth"
def ready(self):
from . import signals # noqa
diff --git a/airavata-django-portal/django_airavata/apps/auth/backends.py b/airavata-django-portal/django_airavata/apps/auth/backends.py
index bd8292a05..e9b0fc207 100644
--- a/airavata-django-portal/django_airavata/apps/auth/backends.py
+++ b/airavata-django-portal/django_airavata/apps/auth/backends.py
@@ -1,4 +1,5 @@
"""Django Airavata Auth Backends: KeycloakBackend."""
+
import logging
import os
import time
@@ -17,7 +18,7 @@ from . import models, utils
logger = logging.getLogger(__name__)
-class KeycloakBackend(object):
+class KeycloakBackend:
"""Django authentication backend for Keycloak."""
# mask all local variables from error emails since they contain the user's
@@ -25,25 +26,19 @@ class KeycloakBackend(object):
# variables that are sensitive, but this decorator doesn't apply explicitly
# listed variable masking to library function calls
@sensitive_variables()
- def authenticate(self,
- request=None,
- username=None,
- password=None,
- refresh_token=None,
- idp_alias=None):
+ def authenticate(self, request=None, username=None, password=None, refresh_token=None, idp_alias=None):
try:
user = None
access_token = None
if username and password:
- token, userinfo = self._get_token_and_userinfo_password_flow(
- username, password)
+ token, userinfo = self._get_token_and_userinfo_password_flow(username, password)
if token is None: # login failed
return None
self._process_token(request, token)
user = self._process_userinfo(request, userinfo)
- access_token = token['access_token']
- elif 'HTTP_AUTHORIZATION' in request.META:
- bearer, token = request.META.get('HTTP_AUTHORIZATION').split()
+ access_token = token["access_token"]
+ elif "HTTP_AUTHORIZATION" in request.META:
+ bearer, token = request.META.get("HTTP_AUTHORIZATION").split()
if bearer != "Bearer":
raise Exception("Unexpected Authorization header")
# implicitly validate token by using it to get userinfo
@@ -53,38 +48,33 @@ class KeycloakBackend(object):
# user is already logged in and can use refresh token
elif request.user.is_authenticated and not utils.is_refresh_token_expired(request):
logger.debug("Refreshing token...")
- token, userinfo = \
- self._get_token_and_userinfo_from_refresh_token(request)
+ token, userinfo = self._get_token_and_userinfo_from_refresh_token(request)
if token is None: # refresh failed
return None
self._process_token(request, token)
# user is already logged in
user = request.user
- access_token = token['access_token']
+ access_token = token["access_token"]
elif refresh_token:
logger.debug("Refreshing supplied token...")
- token, userinfo = \
- self._get_token_and_userinfo_from_refresh_token(
- request, refresh_token=refresh_token)
+ token, userinfo = self._get_token_and_userinfo_from_refresh_token(request, refresh_token=refresh_token)
if token is None: # refresh failed
return None
self._process_token(request, token)
user = self._process_userinfo(request, userinfo)
- access_token = token['access_token']
+ access_token = token["access_token"]
else:
- token, userinfo = self._get_token_and_userinfo_redirect_flow(
- request)
+ token, userinfo = self._get_token_and_userinfo_redirect_flow(request)
self._process_token(request, token)
user = self._process_userinfo(request, userinfo)
if idp_alias is not None:
self._store_idp_userinfo(user, token, idp_alias)
self._check_username_initialization(request, user)
- access_token = token['access_token']
+ access_token = token["access_token"]
# authz_token_middleware has already run, so must manually add
# the `request.authz_token` attribute
if user is not None:
- request.authz_token = get_authz_token(
- request, user=user, access_token=access_token)
+ request.authz_token = get_authz_token(request, user=user, access_token=access_token)
return user
except Exception as e:
logger.warning("login failed", exc_info=e)
@@ -103,24 +93,25 @@ class KeycloakBackend(object):
token_url = settings.KEYCLOAK_TOKEN_URL
userinfo_url = settings.KEYCLOAK_USERINFO_URL
verify_ssl = settings.KEYCLOAK_VERIFY_SSL
- scope = ['openid', 'profile', 'email']
+ scope = ["openid", "profile", "email"]
oauth2_session = OAuth2Session(client=LegacyApplicationClient(client_id=client_id), scope=scope)
verify = verify_ssl
- if verify_ssl and hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ if verify_ssl and hasattr(settings, "KEYCLOAK_CA_CERTFILE"):
verify = settings.KEYCLOAK_CA_CERTFILE
- token = oauth2_session.fetch_token(token_url=token_url,
- username=username,
- password=password,
- client_id=client_id,
- client_secret=client_secret,
- verify=verify,
- scope=scope)
+ token = oauth2_session.fetch_token(
+ token_url=token_url,
+ username=username,
+ password=password,
+ client_id=client_id,
+ client_secret=client_secret,
+ verify=verify,
+ scope=scope,
+ )
userinfo = oauth2_session.get(userinfo_url).json()
return token, userinfo
except InvalidGrantError as e:
# password wasn't valid, just log as a warning
- logger.warning(f"Failed to log in user {username} with "
- f"password: {e}")
+ logger.warning(f"Failed to log in user {username} with password: {e}")
return None, None
def _get_token_and_userinfo_redirect_flow(self, request):
@@ -130,72 +121,63 @@ class KeycloakBackend(object):
token_url = settings.KEYCLOAK_TOKEN_URL
userinfo_url = settings.KEYCLOAK_USERINFO_URL
verify_ssl = settings.KEYCLOAK_VERIFY_SSL
- state = request.session['OAUTH2_STATE']
- redirect_uri = request.session['OAUTH2_REDIRECT_URI']
- logger.debug("state={}".format(state))
- oauth2_session = OAuth2Session(client_id,
- scope='openid profile email',
- redirect_uri=redirect_uri,
- state=state)
+ state = request.session["OAUTH2_STATE"]
+ redirect_uri = request.session["OAUTH2_REDIRECT_URI"]
+ logger.debug(f"state={state}")
+ oauth2_session = OAuth2Session(client_id, scope="openid profile email", redirect_uri=redirect_uri, state=state)
verify = verify_ssl
- if verify_ssl and hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ if verify_ssl and hasattr(settings, "KEYCLOAK_CA_CERTFILE"):
verify = settings.KEYCLOAK_CA_CERTFILE
- if not request.is_secure() and settings.DEBUG and not os.environ.get('OAUTHLIB_INSECURE_TRANSPORT'):
+ if not request.is_secure() and settings.DEBUG and not os.environ.get("OAUTHLIB_INSECURE_TRANSPORT"):
# For local development (DEBUG=True), allow insecure OAuth redirect flow
# if OAUTHLIB_INSECURE_TRANSPORT isn't already set
- os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = "1"
- logger.info("Adding env var OAUTHLIB_INSECURE_TRANSPORT=1 to allow "
- "OAuth redirect flow even though request is not secure")
+ os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
+ logger.info(
+ "Adding env var OAUTHLIB_INSECURE_TRANSPORT=1 to allow "
+ "OAuth redirect flow even though request is not secure"
+ )
token = oauth2_session.fetch_token(
- token_url, client_secret=client_secret,
- authorization_response=authorization_code_url, verify=verify)
+ token_url, client_secret=client_secret, authorization_response=authorization_code_url, verify=verify
+ )
userinfo = oauth2_session.get(userinfo_url).json()
return token, userinfo
- def _get_token_and_userinfo_from_refresh_token(self,
- request,
- refresh_token=None):
+ def _get_token_and_userinfo_from_refresh_token(self, request, refresh_token=None):
client_id = settings.KEYCLOAK_CLIENT_ID
client_secret = settings.KEYCLOAK_CLIENT_SECRET
token_url = settings.KEYCLOAK_TOKEN_URL
userinfo_url = settings.KEYCLOAK_USERINFO_URL
verify_ssl = settings.KEYCLOAK_VERIFY_SSL
- oauth2_session = OAuth2Session(client_id, scope='openid profile email')
+ oauth2_session = OAuth2Session(client_id, scope="openid profile email")
verify = verify_ssl
- if verify_ssl and hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ if verify_ssl and hasattr(settings, "KEYCLOAK_CA_CERTFILE"):
verify = settings.KEYCLOAK_CA_CERTFILE
- refresh_token_ = (refresh_token
- if refresh_token is not None
- else request.session['REFRESH_TOKEN'])
+ refresh_token_ = refresh_token if refresh_token is not None else request.session["REFRESH_TOKEN"]
# refresh_token doesn't take client_secret kwarg, so create auth
# explicitly
auth = requests.auth.HTTPBasicAuth(client_id, client_secret)
try:
- token = oauth2_session.refresh_token(token_url=token_url,
- refresh_token=refresh_token_,
- auth=auth,
- verify=verify)
+ token = oauth2_session.refresh_token(
+ token_url=token_url, refresh_token=refresh_token_, auth=auth, verify=verify
+ )
userinfo = oauth2_session.get(userinfo_url).json()
return token, userinfo
except InvalidGrantError as e:
# probably session was terminated by admin or by user logging out in another client
- logger.warning(f"Failed to refresh token for user {request.user.username} "
- f": {e}")
+ logger.warning(f"Failed to refresh token for user {request.user.username} : {e}")
return None, None
def _get_userinfo_from_token(self, request, token):
client_id = settings.KEYCLOAK_CLIENT_ID
userinfo_url = settings.KEYCLOAK_USERINFO_URL
verify_ssl = settings.KEYCLOAK_VERIFY_SSL
- oauth2_session = OAuth2Session(
- client_id, token={'access_token': token})
+ oauth2_session = OAuth2Session(client_id, token={"access_token": token})
verify = verify_ssl
- if verify_ssl and hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ if verify_ssl and hasattr(settings, "KEYCLOAK_CA_CERTFILE"):
verify = settings.KEYCLOAK_CA_CERTFILE
- userinfo = oauth2_session.get(
- userinfo_url, verify=verify).json()
- if 'error' in userinfo:
- msg = userinfo.get('error_description')
+ userinfo = oauth2_session.get(userinfo_url, verify=verify).json()
+ if "error" in userinfo:
+ msg = userinfo.get("error_description")
if msg is None:
msg = f"Error fetching userinfo: {userinfo['error']}"
raise Exception(msg)
@@ -203,29 +185,29 @@ class KeycloakBackend(object):
def _process_token(self, request, token):
# TODO validate the JWS signature
- logger.debug("token: {}".format(token))
+ logger.debug(f"token: {token}")
now = time.time()
# Put access_token into session to be used for authenticating with API
# server
sess = request.session
- sess['ACCESS_TOKEN'] = token['access_token']
- sess['ACCESS_TOKEN_EXPIRES_AT'] = now + token['expires_in']
- sess['REFRESH_TOKEN'] = token['refresh_token']
- sess['REFRESH_TOKEN_EXPIRES_AT'] = now + token['refresh_expires_in']
+ sess["ACCESS_TOKEN"] = token["access_token"]
+ sess["ACCESS_TOKEN_EXPIRES_AT"] = now + token["expires_in"]
+ sess["REFRESH_TOKEN"] = token["refresh_token"]
+ sess["REFRESH_TOKEN_EXPIRES_AT"] = now + token["refresh_expires_in"]
def _process_userinfo(self, request, userinfo):
- logger.debug("userinfo: {}".format(userinfo))
- sub = userinfo['sub']
- username = userinfo['preferred_username']
- email = userinfo.get('email', '')
- first_name = userinfo.get('given_name', None)
- last_name = userinfo.get('family_name', None)
+ logger.debug(f"userinfo: {userinfo}")
+ sub = userinfo["sub"]
+ username = userinfo["preferred_username"]
+ email = userinfo.get("email", "")
+ first_name = userinfo.get("given_name", None)
+ last_name = userinfo.get("family_name", None)
user = self._get_or_create_user(sub, username)
user_profile = user.user_profile
# Save the user info claims
- for (claim, value) in userinfo.items():
+ for claim, value in userinfo.items():
if user_profile.userinfo_set.filter(claim=claim).exists():
userinfo_claim = user_profile.userinfo_set.get(claim=claim)
userinfo_claim.value = value
@@ -246,8 +228,7 @@ class KeycloakBackend(object):
def _get_or_create_user(self, sub, username):
try:
- user_profile = models.UserProfile.objects.get(
- userinfo__claim='sub', userinfo__value=sub)
+ user_profile = models.UserProfile.objects.get(userinfo__claim="sub", userinfo__value=sub)
return user_profile.user
except models.UserProfile.DoesNotExist:
try:
@@ -255,17 +236,17 @@ class KeycloakBackend(object):
user = User.objects.get(username=username)
# Make sure there is a user_profile with the sub claim, which
# will be used to do the lookup next time
- if not hasattr(user, 'user_profile'):
+ if not hasattr(user, "user_profile"):
user_profile = models.UserProfile(user=user)
user_profile.save()
- user_profile.userinfo_set.create(
- claim='sub', value=sub)
+ user_profile.userinfo_set.create(claim="sub", value=sub)
else:
- userinfo = user.user_profile.userinfo_set.get(claim='sub')
+ userinfo = user.user_profile.userinfo_set.get(claim="sub")
logger.warning(
f"User {username} exists but sub claims don't match: "
f"old={userinfo.value}, new={sub}. Updating to new "
- "sub claim.")
+ "sub claim."
+ )
userinfo.value = sub
userinfo.save()
return user
@@ -274,39 +255,41 @@ class KeycloakBackend(object):
user.save()
user_profile = models.UserProfile(user=user)
user_profile.save()
- user_profile.userinfo_set.create(claim='sub', value=sub)
+ user_profile.userinfo_set.create(claim="sub", value=sub)
return user
def _store_idp_userinfo(self, user, token, idp_alias):
try:
idp_token_url = None
userinfo_url = None
- for auth_option in settings.AUTHENTICATION_OPTIONS['external']:
- if auth_option['idp_alias'] == idp_alias:
- idp_token_url = auth_option.get('idp_token_url')
- userinfo_url = auth_option.get('userinfo_url')
+ for auth_option in settings.AUTHENTICATION_OPTIONS["external"]:
+ if auth_option["idp_alias"] == idp_alias:
+ idp_token_url = auth_option.get("idp_token_url")
+ userinfo_url = auth_option.get("userinfo_url")
break
if idp_token_url is None or userinfo_url is None:
- logger.debug(f"idp_token_url and/or userinfo_url not set for {idp_alias} "
- "in AUTHENTICATION_OPTIONS, skipping retrieval of external IDP userinfo")
+ logger.debug(
+ f"idp_token_url and/or userinfo_url not set for {idp_alias} "
+ "in AUTHENTICATION_OPTIONS, skipping retrieval of external IDP userinfo"
+ )
return
- access_token = token['access_token']
+ access_token = token["access_token"]
logger.debug(f"access_token={access_token} for idp_alias={idp_alias}")
# fetch the idp's token
- headers = {'Authorization': f'Bearer {access_token}'}
+ headers = {"Authorization": f"Bearer {access_token}"}
# For the following to work, in Keycloak the IDP should have 'Store
# Tokens' and 'Stored Tokens Readable' enabled and the user needs
# the broker/read-token role
r = requests.get(idp_token_url, headers=headers)
idp_token = r.json()
- idp_headers = {'Authorization': f"Bearer {idp_token['access_token']}"}
+ idp_headers = {"Authorization": f"Bearer {idp_token['access_token']}"}
r = requests.get(userinfo_url, headers=idp_headers)
userinfo = r.json()
logger.debug(f"userinfo={userinfo}")
# Save the idp user info claims
user_profile = user.user_profile
- for (claim, value) in userinfo.items():
+ for claim, value in userinfo.items():
if user_profile.idp_userinfo.filter(idp_alias=idp_alias, claim=claim).exists():
userinfo_claim = user_profile.idp_userinfo.get(idp_alias=idp_alias, claim=claim)
userinfo_claim.value = value
@@ -322,10 +305,13 @@ class KeycloakBackend(object):
# sub). If the latter, we'll want to alert the admins so that they can
# assign a proper username for the user.
user_profile = user.user_profile
- if (not user_profile.username_initialized and
- user_profile.userinfo_set.filter(claim='email').exists() and
- user_profile.userinfo_set.filter(claim='preferred_username').exists() and
- user_profile.userinfo_set.get(claim='email').value == user_profile.userinfo_set.get(claim='preferred_username').value):
+ if (
+ not user_profile.username_initialized
+ and user_profile.userinfo_set.filter(claim="email").exists()
+ and user_profile.userinfo_set.filter(claim="preferred_username").exists()
+ and user_profile.userinfo_set.get(claim="email").value
+ == user_profile.userinfo_set.get(claim="preferred_username").value
+ ):
user_profile.username_initialized = True
user_profile.save()
@@ -334,6 +320,10 @@ class KeycloakBackend(object):
if not user_profile.username_initialized and not user_profile.is_username_valid:
try:
utils.send_admin_alert_about_uninitialized_username(
- request, user.username, user.email, user.first_name, user.last_name)
+ request, user.username, user.email, user.first_name, user.last_name
+ )
except Exception:
- logger.exception(f"Failed to send alert about username being uninitialized: {user.username}", extra={'request': request})
+ logger.exception(
+ f"Failed to send alert about username being uninitialized: {user.username}",
+ extra={"request": request},
+ )
diff --git a/airavata-django-portal/django_airavata/apps/auth/forms.py b/airavata-django-portal/django_airavata/apps/auth/forms.py
index edd551aad..4c4487cd3 100644
--- a/airavata-django-portal/django_airavata/apps/auth/forms.py
+++ b/airavata-django-portal/django_airavata/apps/auth/forms.py
@@ -8,99 +8,77 @@ from . import iam_admin_client
logger = logging.getLogger(__name__)
USERNAME_VALIDATOR = validators.RegexValidator(
- regex=r"^[a-z0-9_-]+$",
- message="Username can only contain lowercase letters, numbers, "
- "underscores and hyphens."
+ regex=r"^[a-z0-9_-]+$", message="Username can only contain lowercase letters, numbers, underscores and hyphens."
)
PASSWORD_VALIDATOR = validators.RegexValidator(
regex=r"^.*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@!$#*&]).*$",
message="Password needs to contain at least (a) One lower case letter (b) "
- "One Upper case letter and (c) One number (d) One of the following"
- " special characters - !@#$&*"
+ "One Upper case letter and (c) One number (d) One of the following"
+ " special characters - !@#$&*",
)
class CreateAccountForm(forms.Form):
error_css_class = "is-invalid"
username = forms.CharField(
- label='Username',
- widget=forms.TextInput(attrs={'class': 'form-control',
- 'placeholder': 'Username'}),
+ label="Username",
+ widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Username"}),
min_length=6,
validators=[USERNAME_VALIDATOR],
- help_text=USERNAME_VALIDATOR.message)
+ help_text=USERNAME_VALIDATOR.message,
+ )
password = forms.CharField(
- label='Password',
- widget=forms.PasswordInput(attrs={'class': 'form-control',
- 'placeholder': 'Password'}),
+ label="Password",
+ widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "Password"}),
min_length=8,
max_length=48,
validators=[PASSWORD_VALIDATOR],
- help_text=PASSWORD_VALIDATOR.message)
+ help_text=PASSWORD_VALIDATOR.message,
+ )
password_again = forms.CharField(
- label='Password (again)',
- widget=forms.PasswordInput(attrs={'class': 'form-control',
- 'placeholder': 'Password (again)'}))
+ label="Password (again)",
+ widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "Password (again)"}),
+ )
email = forms.EmailField(
- label='E-mail',
- widget=forms.EmailInput(attrs={'class': 'form-control',
- 'placeholder': 'email@example.com'}))
+ label="E-mail", widget=forms.EmailInput(attrs={"class": "form-control", "placeholder": "email@example.com"})
+ )
email_again = forms.EmailField(
- label='E-mail (again)',
- widget=forms.EmailInput(
- attrs={
- 'class': 'form-control',
- 'placeholder': 'email@example.com (again)'}))
+ label="E-mail (again)",
+ widget=forms.EmailInput(attrs={"class": "form-control", "placeholder": "email@example.com (again)"}),
+ )
first_name = forms.CharField(
- label='First Name',
- widget=forms.TextInput(attrs={'class': 'form-control',
- 'placeholder': 'First Name'}))
+ label="First Name", widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "First Name"})
+ )
last_name = forms.CharField(
- label='Last Name',
- widget=forms.TextInput(attrs={'class': 'form-control',
- 'placeholder': 'Last Name'}))
+ label="Last Name", widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Last Name"})
+ )
next = forms.CharField(widget=forms.HiddenInput(), required=False)
def clean(self):
cleaned_data = super().clean()
- password = cleaned_data.get('password')
- password_again = cleaned_data.get('password_again')
+ password = cleaned_data.get("password")
+ password_again = cleaned_data.get("password_again")
if password and password_again and password != password_again:
- self.add_error(
- 'password',
- forms.ValidationError("Passwords do not match"))
- self.add_error(
- 'password_again',
- forms.ValidationError("Passwords do not match"))
+ self.add_error("password", forms.ValidationError("Passwords do not match"))
+ self.add_error("password_again", forms.ValidationError("Passwords do not match"))
- email = cleaned_data.get('email')
- email_again = cleaned_data.get('email_again')
+ email = cleaned_data.get("email")
+ email_again = cleaned_data.get("email_again")
if email and email_again and email != email_again:
- self.add_error(
- 'email',
- forms.ValidationError("E-mail addresses do not match")
- )
- self.add_error(
- 'email_again',
- forms.ValidationError("E-mail addresses do not match")
- )
+ self.add_error("email", forms.ValidationError("E-mail addresses do not match"))
+ self.add_error("email_again", forms.ValidationError("E-mail addresses do not match"))
- username = cleaned_data.get('username')
+ username = cleaned_data.get("username")
try:
- if username and not iam_admin_client.is_username_available(
- username):
- self.add_error(
- 'username',
- forms.ValidationError("That username is not available")
- )
+ if username and not iam_admin_client.is_username_available(username):
+ self.add_error("username", forms.ValidationError("That username is not available"))
except Exception as e:
logger.exception("Failed to check if username is available")
self.add_error(
- 'username',
- forms.ValidationError("Error occurred while checking if "
- "username is available: " + str(e)))
+ "username", forms.ValidationError("Error occurred while checking if username is available: " + str(e))
+ )
return cleaned_data
@@ -108,51 +86,47 @@ class CreateAccountForm(forms.Form):
class ResendEmailVerificationLinkForm(forms.Form):
error_css_class = "is-invalid"
username = forms.CharField(
- label='Username',
- widget=forms.TextInput(attrs={'class': 'form-control',
- 'placeholder': 'Username'}),
+ label="Username",
+ widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Username"}),
min_length=6,
- validators=[USERNAME_VALIDATOR])
+ validators=[USERNAME_VALIDATOR],
+ )
class ForgotPasswordForm(forms.Form):
error_css_class = "is-invalid"
username = forms.CharField(
- label='Username',
- widget=forms.TextInput(attrs={'class': 'form-control',
- 'placeholder': 'Username'}),
+ label="Username",
+ widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Username"}),
min_length=6,
validators=[USERNAME_VALIDATOR],
- help_text=USERNAME_VALIDATOR.message)
+ help_text=USERNAME_VALIDATOR.message,
+ )
class ResetPasswordForm(forms.Form):
error_css_class = "is-invalid"
password = forms.CharField(
- label='Password',
- widget=forms.PasswordInput(attrs={'class': 'form-control',
- 'placeholder': 'Password'}),
+ label="Password",
+ widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "Password"}),
min_length=8,
max_length=48,
validators=[PASSWORD_VALIDATOR],
- help_text=PASSWORD_VALIDATOR.message)
+ help_text=PASSWORD_VALIDATOR.message,
+ )
password_again = forms.CharField(
- label='Password (again)',
- widget=forms.PasswordInput(attrs={'class': 'form-control',
- 'placeholder': 'Password (again)'}))
+ label="Password (again)",
+ widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "Password (again)"}),
+ )
def clean(self):
cleaned_data = super().clean()
- password = cleaned_data.get('password')
- password_again = cleaned_data.get('password_again')
+ password = cleaned_data.get("password")
+ password_again = cleaned_data.get("password_again")
if password and password_again and password != password_again:
- self.add_error(
- 'password',
- forms.ValidationError("Passwords do not match"))
- self.add_error(
- 'password_again',
- forms.ValidationError("Passwords do not match"))
+ self.add_error("password", forms.ValidationError("Passwords do not match"))
+ self.add_error("password_again", forms.ValidationError("Passwords do not match"))
return cleaned_data
diff --git a/airavata-django-portal/django_airavata/apps/auth/iam_admin_client.py b/airavata-django-portal/django_airavata/apps/auth/iam_admin_client.py
index fb36cf10d..fb218ddff 100644
--- a/airavata-django-portal/django_airavata/apps/auth/iam_admin_client.py
+++ b/airavata-django-portal/django_airavata/apps/auth/iam_admin_client.py
@@ -22,13 +22,7 @@ def is_username_available(username):
def register_user(username, email_address, first_name, last_name, password):
authz_token = utils.get_service_account_authz_token()
- return iamadmin_client_pool.registerUser(
- authz_token,
- username,
- email_address,
- first_name,
- last_name,
- password)
+ return iamadmin_client_pool.registerUser(authz_token, username, email_address, first_name, last_name, password)
def is_user_enabled(username):
@@ -63,8 +57,7 @@ def get_users(offset, limit, search=None):
def reset_user_password(username, new_password):
authz_token = utils.get_service_account_authz_token()
- return iamadmin_client_pool.resetUserPassword(
- authz_token, username, new_password)
+ return iamadmin_client_pool.resetUserPassword(authz_token, username, new_password)
def update_username(username, new_username):
@@ -73,44 +66,50 @@ def update_username(username, new_username):
raise Exception(f"Can't change username of {username} to {new_username} because it is not available")
# fetch user representation
authz_token = utils.get_service_account_authz_token()
- headers = {'Authorization': f'Bearer {authz_token['accessToken']}'}
+ headers = {"Authorization": f"Bearer {authz_token['accessToken']}"}
parsed = urlparse(settings.KEYCLOAK_AUTHORIZE_URL)
- r = requests.get(f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users",
- params={'username': username},
- headers=headers)
+ r = requests.get(
+ f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users",
+ params={"username": username},
+ headers=headers,
+ )
r.raise_for_status()
user_list = r.json()
user = None
# The users search finds partial matches. Loop to find the exact match.
for u in user_list:
- if u['username'] == username:
+ if u["username"] == username:
user = u
break
if user is None:
raise Exception(f"Could not find user {username}")
# update username
- user['username'] = new_username
- r = requests.put(f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users/{user['id']}",
- json=user,
- headers=headers)
+ user["username"] = new_username
+ r = requests.put(
+ f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users/{user['id']}",
+ json=user,
+ headers=headers,
+ )
r.raise_for_status()
def update_user(username, first_name=None, last_name=None, email=None):
# fetch user representation
authz_token = utils.get_service_account_authz_token()
- headers = {'Authorization': f'Bearer {authz_token['accessToken']}'}
+ headers = {"Authorization": f"Bearer {authz_token['accessToken']}"}
parsed = urlparse(settings.KEYCLOAK_AUTHORIZE_URL)
- r = requests.get(f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users",
- params={'username': username},
- headers=headers)
+ r = requests.get(
+ f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users",
+ params={"username": username},
+ headers=headers,
+ )
r.raise_for_status()
user_list = r.json()
user = None
# The users search finds partial matches. Loop to find the exact match.
for u in user_list:
- if u['username'] == username:
+ if u["username"] == username:
user = u
break
if user is None:
@@ -118,12 +117,14 @@ def update_user(username, first_name=None, last_name=None, email=None):
# update user
if first_name is not None:
- user['firstName'] = first_name
+ user["firstName"] = first_name
if last_name is not None:
- user['lastName'] = last_name
+ user["lastName"] = last_name
if email is not None:
- user['email'] = email
- r = requests.put(f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users/{user['id']}",
- json=user,
- headers=headers)
+ user["email"] = email
+ r = requests.put(
+ f"{parsed.scheme}://{parsed.netloc}/auth/admin/realms/{settings.GATEWAY_ID}/users/{user['id']}",
+ json=user,
+ headers=headers,
+ )
r.raise_for_status()
diff --git a/airavata-django-portal/django_airavata/apps/auth/middleware.py b/airavata-django-portal/django_airavata/apps/auth/middleware.py
index 6c9a1f3fd..a81c39840 100644
--- a/airavata-django-portal/django_airavata/apps/auth/middleware.py
+++ b/airavata-django-portal/django_airavata/apps/auth/middleware.py
@@ -1,4 +1,5 @@
"""Django Airavata Auth Middleware."""
+
import copy
import logging
@@ -14,6 +15,7 @@ log = logging.getLogger(__name__)
def authz_token_middleware(get_response):
"""Automatically add the 'authz_token' to the request."""
+
def middleware(request):
authz_token = None
@@ -35,11 +37,16 @@ def set_admin_group_attributes(request, gateway_groups=None):
"""Set is_gateway_admin and is_read_only_gateway_admin request attrs."""
if gateway_groups is None:
gateway_groups = request.airavata_client.iam.get_gateway_groups()
- admins_group_id = gateway_groups.get('adminsGroupId') if isinstance(gateway_groups, dict) else gateway_groups.admins_group_id
- read_only_admins_group_id = gateway_groups.get('readOnlyAdminsGroupId') if isinstance(gateway_groups, dict) else gateway_groups.read_only_admins_group_id
+ admins_group_id = (
+ gateway_groups.get("adminsGroupId") if isinstance(gateway_groups, dict) else gateway_groups.admins_group_id
+ )
+ read_only_admins_group_id = (
+ gateway_groups.get("readOnlyAdminsGroupId")
+ if isinstance(gateway_groups, dict)
+ else gateway_groups.read_only_admins_group_id
+ )
airavata_internal_user_id = request.user.username + "@" + settings.GATEWAY_ID
- group_memberships = request.airavata_client.sharing.get_all_groups_user_belongs(
- airavata_internal_user_id)
+ group_memberships = request.airavata_client.sharing.get_all_groups_user_belongs(airavata_internal_user_id)
group_ids = [group.id for group in group_memberships]
request.is_gateway_admin = admins_group_id in group_ids
request.is_read_only_gateway_admin = read_only_admins_group_id in group_ids
@@ -47,63 +54,72 @@ def set_admin_group_attributes(request, gateway_groups=None):
def gateway_groups_middleware(get_response):
"""Add 'is_gateway_admin' and 'is_read_only_gateway_admin' to request."""
+
def middleware(request):
request.is_gateway_admin = False
request.is_read_only_gateway_admin = False
- if (not request.user.is_authenticated or
- not request.authz_token or
- (hasattr(request.user, "user_profile") and
- not request.user.user_profile.is_complete)):
+ if (
+ not request.user.is_authenticated
+ or not request.authz_token
+ or (hasattr(request.user, "user_profile") and not request.user.user_profile.is_complete)
+ ):
return get_response(request)
try:
# Load the GatewayGroups and check if user is in the Admins and/or
# Read Only Admins groups
- if not request.session.get('GATEWAY_GROUPS'):
+ if not request.session.get("GATEWAY_GROUPS"):
gateway_groups = request.airavata_client.iam.get_gateway_groups()
- gateway_groups_dict = copy.deepcopy(gateway_groups.__dict__) if hasattr(gateway_groups, '__dict__') else dict(gateway_groups)
- request.session['GATEWAY_GROUPS'] = gateway_groups_dict
+ gateway_groups_dict = (
+ copy.deepcopy(gateway_groups.__dict__)
+ if hasattr(gateway_groups, "__dict__")
+ else dict(gateway_groups)
+ )
+ request.session["GATEWAY_GROUPS"] = gateway_groups_dict
set_admin_group_attributes(request, gateway_groups=request.session.get("GATEWAY_GROUPS"))
# Gateway Admins are made 'superuser' in Django so they can edit
# pages in the CMS
- if request.is_gateway_admin and (
- not request.user.is_superuser or
- not request.user.is_staff):
+ if request.is_gateway_admin and (not request.user.is_superuser or not request.user.is_staff):
request.user.is_superuser = True
request.user.is_staff = True
request.user.save()
except Exception as e:
- log.warning("Failed to set is_gateway_admin, "
- "is_read_only_gateway_admin for user", exc_info=e)
+ log.warning("Failed to set is_gateway_admin, is_read_only_gateway_admin for user", exc_info=e)
return get_response(request)
+
return middleware
def user_profile_completeness_check(get_response):
"""Check if user profile is complete and if not, redirect to user profile editor."""
+
def middleware(request):
if not request.user.is_authenticated:
return get_response(request)
allowed_paths = [
- reverse('django_airavata_auth:user_profile'),
- reverse('django_airavata_auth:logout'),
+ reverse("django_airavata_auth:user_profile"),
+ reverse("django_airavata_auth:logout"),
]
- incomplete_user_profile = (hasattr(request.user, "user_profile") and
- not request.user.user_profile.is_complete)
+ incomplete_user_profile = hasattr(request.user, "user_profile") and not request.user.user_profile.is_complete
# Exclude admin's from the ext user profile check since they will be
# creating/editing the ext user profile fields
- invalid_ext_user_profile = (not getattr(request, "is_gateway_admin", False) and
- hasattr(request.user, "user_profile") and
- not request.user.user_profile.is_ext_user_profile_valid)
- if ((incomplete_user_profile or invalid_ext_user_profile) and
- request.path not in allowed_paths and
- 'text/html' in request.META['HTTP_ACCEPT']):
- return redirect('django_airavata_auth:user_profile')
+ invalid_ext_user_profile = (
+ not getattr(request, "is_gateway_admin", False)
+ and hasattr(request.user, "user_profile")
+ and not request.user.user_profile.is_ext_user_profile_valid
+ )
+ if (
+ (incomplete_user_profile or invalid_ext_user_profile)
+ and request.path not in allowed_paths
+ and "text/html" in request.META["HTTP_ACCEPT"]
+ ):
+ return redirect("django_airavata_auth:user_profile")
else:
return get_response(request)
+
return middleware
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0001_initial.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0001_initial.py
index 8745b6f94..fb17e8ed8 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0001_initial.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0001_initial.py
@@ -1,27 +1,24 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2018-10-25 15:32
-from __future__ import unicode_literals
-from django.db import migrations, models
import uuid
+from django.db import migrations, models
-class Migration(migrations.Migration):
+class Migration(migrations.Migration):
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='EmailVerification',
+ name="EmailVerification",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('username', models.CharField(max_length=64)),
- ('verification_code', models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('verified', models.BooleanField(default=False)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("username", models.CharField(max_length=64)),
+ ("verification_code", models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("verified", models.BooleanField(default=False)),
],
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0002_emailtemplate.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0002_emailtemplate.py
index b9006b364..3678b8baf 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0002_emailtemplate.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0002_emailtemplate.py
@@ -1,25 +1,29 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2018-10-29 18:23
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0001_initial'),
+ ("django_airavata_auth", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='EmailTemplate',
+ name="EmailTemplate",
fields=[
- ('template_type', models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template')], primary_key=True, serialize=False)),
- ('subject', models.CharField(max_length=255)),
- ('body', models.TextField()),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
+ (
+ "template_type",
+ models.IntegerField(
+ choices=[(1, "Verify Email Template"), (2, "New User Email Template")],
+ primary_key=True,
+ serialize=False,
+ ),
+ ),
+ ("subject", models.CharField(max_length=255)),
+ ("body", models.TextField()),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
],
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0003_default_email_templates.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0003_default_email_templates.py
index c21caccae..03a9b28b0 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0003_default_email_templates.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0003_default_email_templates.py
@@ -1,13 +1,8 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2018-10-29 18:33
-from __future__ import unicode_literals
from django.db import migrations
-from django_airavata.apps.auth.models import (
- NEW_USER_EMAIL_TEMPLATE,
- VERIFY_EMAIL_TEMPLATE
-)
+from django_airavata.apps.auth.models import NEW_USER_EMAIL_TEMPLATE, VERIFY_EMAIL_TEMPLATE
def default_templates(apps, schema_editor):
@@ -15,8 +10,7 @@ def default_templates(apps, schema_editor):
EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
verify_email_template = EmailTemplate(
template_type=VERIFY_EMAIL_TEMPLATE,
- subject="{{first_name}} {{last_name}} ({{username}}), "
- "Please Verify Your Email Account in {{portal_title}}",
+ subject="{{first_name}} {{last_name}} ({{username}}), Please Verify Your Email Account in {{portal_title}}",
body="""
<p>
Dear {{first_name}} {{last_name}},
@@ -30,7 +24,8 @@ def default_templates(apps, schema_editor):
<p><a href="{{url}}">{{url}}</a></p>
<p>If you didn't create this account, just ignore this message.</p>
- """.strip())
+ """.strip(),
+ )
verify_email_template.save()
new_user_email_template = EmailTemplate(
template_type=NEW_USER_EMAIL_TEMPLATE,
@@ -41,17 +36,14 @@ def default_templates(apps, schema_editor):
<p>Username: {{username}}</p>
<p>Name: {{first_name}} {{last_name}}</p>
<p>Email: {{email}}</p>
- """.strip()
+ """.strip(),
)
new_user_email_template.save()
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0002_emailtemplate'),
+ ("django_airavata_auth", "0002_emailtemplate"),
]
- operations = [
- migrations.RunPython(default_templates)
- ]
+ operations = [migrations.RunPython(default_templates)]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0004_password_reset_request.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0004_password_reset_request.py
index e8fed01ea..d641d7b67 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0004_password_reset_request.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0004_password_reset_request.py
@@ -1,6 +1,4 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-05-07 15:49
-from __future__ import unicode_literals
import uuid
@@ -14,8 +12,7 @@ def default_templates(apps, schema_editor):
EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
verify_email_template = EmailTemplate(
template_type=PASSWORD_RESET_EMAIL_TEMPLATE,
- subject="{{first_name}} {{last_name}} ({{username}}), "
- "Reset your password in {{portal_title}}",
+ subject="{{first_name}} {{last_name}} ({{username}}), Reset your password in {{portal_title}}",
body="""
<p>
Dear {{first_name}} {{last_name}},
@@ -29,36 +26,43 @@ def default_templates(apps, schema_editor):
<p><a href="{{url}}">{{url}}</a></p>
<p>If you didn't request to reset your password, just ignore this message.</p>
- """.strip())
+ """.strip(),
+ )
verify_email_template.save()
def delete_default_templates(apps, schema_editor):
EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
- EmailTemplate.objects.filter(
- template_type=PASSWORD_RESET_EMAIL_TEMPLATE).delete()
+ EmailTemplate.objects.filter(template_type=PASSWORD_RESET_EMAIL_TEMPLATE).delete()
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0003_default_email_templates'),
+ ("django_airavata_auth", "0003_default_email_templates"),
]
operations = [
migrations.CreateModel(
- name='PasswordResetRequest',
+ name="PasswordResetRequest",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('username', models.CharField(max_length=64)),
- ('reset_code', models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
- ('created_date', models.DateTimeField(auto_now_add=True)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("username", models.CharField(max_length=64)),
+ ("reset_code", models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
],
),
migrations.AlterField(
- model_name='emailtemplate',
- name='template_type',
- field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template')], primary_key=True, serialize=False),
+ model_name="emailtemplate",
+ name="template_type",
+ field=models.IntegerField(
+ choices=[
+ (1, "Verify Email Template"),
+ (2, "New User Email Template"),
+ (3, "Password Reset Email Template"),
+ ],
+ primary_key=True,
+ serialize=False,
+ ),
),
- migrations.RunPython(default_templates, reverse_code=delete_default_templates)
+ migrations.RunPython(default_templates, reverse_code=delete_default_templates),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0005_auto_20191211_2011.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0005_auto_20191211_2011.py
index eeb4b990b..d765e0f35 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0005_auto_20191211_2011.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0005_auto_20191211_2011.py
@@ -1,6 +1,4 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-12-11 20:11
-from __future__ import unicode_literals
from django.db import migrations, models
@@ -39,28 +37,35 @@ def default_templates(apps, schema_editor):
<p>
Please let us know if you have any questions. Thanks.
</p>
- """.strip())
+ """.strip(),
+ )
user_added_to_group_template.save()
def delete_default_templates(apps, schema_editor):
EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
- EmailTemplate.objects.filter(
- template_type=USER_ADDED_TO_GROUP_TEMPLATE).delete()
+ EmailTemplate.objects.filter(template_type=USER_ADDED_TO_GROUP_TEMPLATE).delete()
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0004_password_reset_request'),
+ ("django_airavata_auth", "0004_password_reset_request"),
]
operations = [
migrations.AlterField(
- model_name='emailtemplate',
- name='template_type',
- field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template'), (4, 'User Added to Group Template')], primary_key=True, serialize=False),
+ model_name="emailtemplate",
+ name="template_type",
+ field=models.IntegerField(
+ choices=[
+ (1, "Verify Email Template"),
+ (2, "New User Email Template"),
+ (3, "Password Reset Email Template"),
+ (4, "User Added to Group Template"),
+ ],
+ primary_key=True,
+ serialize=False,
+ ),
),
- migrations.RunPython(default_templates,
- reverse_code=delete_default_templates)
+ migrations.RunPython(default_templates, reverse_code=delete_default_templates),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0006_emailverification_next.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0006_emailverification_next.py
index b68cd5c06..8c0adbbf0 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0006_emailverification_next.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0006_emailverification_next.py
@@ -1,20 +1,17 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.28 on 2020-02-26 21:13
-from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0005_auto_20191211_2011'),
+ ("django_airavata_auth", "0005_auto_20191211_2011"),
]
operations = [
migrations.AddField(
- model_name='emailverification',
- name='next',
+ model_name="emailverification",
+ name="next",
field=models.CharField(blank=True, max_length=255),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0007_auto_20200917_1610.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0007_auto_20200917_1610.py
index 4938ebf1c..c3d403f2b 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0007_auto_20200917_1610.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0007_auto_20200917_1610.py
@@ -1,43 +1,47 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-09-17 16:10
-from __future__ import unicode_literals
+import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
-import django.db.models.deletion
class Migration(migrations.Migration):
-
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('django_airavata_auth', '0006_emailverification_next'),
+ ("django_airavata_auth", "0006_emailverification_next"),
]
operations = [
migrations.CreateModel(
- name='UserInfo',
+ name="UserInfo",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('claim', models.CharField(max_length=64)),
- ('value', models.CharField(max_length=255)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("claim", models.CharField(max_length=64)),
+ ("value", models.CharField(max_length=255)),
],
),
migrations.CreateModel(
- name='UserProfile',
+ name="UserProfile",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('username_locked', models.BooleanField(default=False)),
- ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_profile', to=settings.AUTH_USER_MODEL)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("username_locked", models.BooleanField(default=False)),
+ (
+ "user",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="user_profile",
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
],
),
migrations.AddField(
- model_name='userinfo',
- name='user_profile',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='django_airavata_auth.UserProfile'),
+ model_name="userinfo",
+ name="user_profile",
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="django_airavata_auth.UserProfile"),
),
migrations.AlterUniqueTogether(
- name='userinfo',
- unique_together=set([('user_profile', 'claim')]),
+ name="userinfo",
+ unique_together=set([("user_profile", "claim")]),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0008_auto_20210422_1838.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0008_auto_20210422_1838.py
index 9a327b067..ce40a2f65 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0008_auto_20210422_1838.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0008_auto_20210422_1838.py
@@ -13,8 +13,7 @@ def default_templates(apps, schema_editor):
EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
verify_email_template = EmailTemplate(
template_type=VERIFY_EMAIL_CHANGE_TEMPLATE,
- subject="{{first_name}} {{last_name}} ({{username}}), "
- "Please Verify Your New Email Address in {{portal_title}}",
+ subject="{{first_name}} {{last_name}} ({{username}}), Please Verify Your New Email Address in {{portal_title}}",
body="""
<p>
Dear {{first_name}} {{last_name}},
@@ -27,32 +26,42 @@ def default_templates(apps, schema_editor):
</p>
<p><a href="{{url}}">{{url}}</a></p>
- """.strip())
+ """.strip(),
+ )
verify_email_template.save()
class Migration(migrations.Migration):
-
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('django_airavata_auth', '0007_auto_20200917_1610'),
+ ("django_airavata_auth", "0007_auto_20200917_1610"),
]
operations = [
migrations.AlterField(
- model_name='emailtemplate',
- name='template_type',
- field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template'), (4, 'User Added to Group Template'), (5, 'Verify Email Change Template')], primary_key=True, serialize=False),
+ model_name="emailtemplate",
+ name="template_type",
+ field=models.IntegerField(
+ choices=[
+ (1, "Verify Email Template"),
+ (2, "New User Email Template"),
+ (3, "Password Reset Email Template"),
+ (4, "User Added to Group Template"),
+ (5, "Verify Email Change Template"),
+ ],
+ primary_key=True,
+ serialize=False,
+ ),
),
migrations.CreateModel(
- name='PendingEmailChange',
+ name="PendingEmailChange",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('email_address', models.EmailField(max_length=254)),
- ('verification_code', models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('verified', models.BooleanField(default=False)),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("email_address", models.EmailField(max_length=254)),
+ ("verification_code", models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("verified", models.BooleanField(default=False)),
+ ("user", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.RunPython(default_templates, migrations.RunPython.noop),
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0009_alter_emailverification_next.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0009_alter_emailverification_next.py
index 0b554e949..0d3e8bac1 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0009_alter_emailverification_next.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0009_alter_emailverification_next.py
@@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0008_auto_20210422_1838'),
+ ("django_airavata_auth", "0008_auto_20210422_1838"),
]
operations = [
migrations.AlterField(
- model_name='emailverification',
- name='next',
+ model_name="emailverification",
+ name="next",
field=models.CharField(max_length=255, null=True),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0009_auto_20210625_1725.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0009_auto_20210625_1725.py
index 1d381999c..57608ef5f 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0009_auto_20210625_1725.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0009_auto_20210625_1725.py
@@ -1,41 +1,47 @@
# Generated by Django 2.2.23 on 2021-06-25 17:25
-from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0008_auto_20210422_1838'),
+ ("django_airavata_auth", "0008_auto_20210422_1838"),
]
operations = [
migrations.AddField(
- model_name='userinfo',
- name='created_date',
+ model_name="userinfo",
+ name="created_date",
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
- model_name='userinfo',
- name='updated_date',
+ model_name="userinfo",
+ name="updated_date",
field=models.DateTimeField(auto_now=True),
),
migrations.CreateModel(
- name='IDPUserInfo',
+ name="IDPUserInfo",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('idp_alias', models.CharField(max_length=64)),
- ('claim', models.CharField(max_length=64)),
- ('value', models.CharField(max_length=255)),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
- ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='idp_userinfo', to='django_airavata_auth.UserProfile')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("idp_alias", models.CharField(max_length=64)),
+ ("claim", models.CharField(max_length=64)),
+ ("value", models.CharField(max_length=255)),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
+ (
+ "user_profile",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="idp_userinfo",
+ to="django_airavata_auth.UserProfile",
+ ),
+ ),
],
options={
- 'unique_together': {('user_profile', 'claim', 'idp_alias')},
+ "unique_together": {("user_profile", "claim", "idp_alias")},
},
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0010_userprofile_username_initialized.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0010_userprofile_username_initialized.py
index 4b4745921..1f7b2b206 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0010_userprofile_username_initialized.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0010_userprofile_username_initialized.py
@@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0009_auto_20210625_1725'),
+ ("django_airavata_auth", "0009_auto_20210625_1725"),
]
operations = [
migrations.AddField(
- model_name='userprofile',
- name='username_initialized',
+ model_name="userprofile",
+ name="username_initialized",
field=models.BooleanField(default=False),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0011_remove_userprofile_username_locked.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0011_remove_userprofile_username_locked.py
index ca95605a7..a1b3adeb2 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0011_remove_userprofile_username_locked.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0011_remove_userprofile_username_locked.py
@@ -4,14 +4,13 @@ from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0010_userprofile_username_initialized'),
+ ("django_airavata_auth", "0010_userprofile_username_initialized"),
]
operations = [
migrations.RemoveField(
- model_name='userprofile',
- name='username_locked',
+ model_name="userprofile",
+ name="username_locked",
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0012_merge_20211210_2041.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0012_merge_20211210_2041.py
index 042a9a054..fb1cfc908 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0012_merge_20211210_2041.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0012_merge_20211210_2041.py
@@ -4,11 +4,9 @@ from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0009_alter_emailverification_next'),
- ('django_airavata_auth', '0011_remove_userprofile_username_locked'),
+ ("django_airavata_auth", "0009_alter_emailverification_next"),
+ ("django_airavata_auth", "0011_remove_userprofile_username_locked"),
]
- operations = [
- ]
+ operations = []
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0013_auto_20220118_1650.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0013_auto_20220118_1650.py
index fe52ef290..693b45984 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0013_auto_20220118_1650.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0013_auto_20220118_1650.py
@@ -10,11 +10,8 @@ def default_username_initialized(apps, schema_editor):
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0012_merge_20211210_2041'),
+ ("django_airavata_auth", "0012_merge_20211210_2041"),
]
- operations = [
- migrations.RunPython(default_username_initialized, migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(default_username_initialized, migrations.RunPython.noop)]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0014_auto_20220217_2255.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0014_auto_20220217_2255.py
index ff03168f9..1231df4b2 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0014_auto_20220217_2255.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0014_auto_20220217_2255.py
@@ -8,17 +8,14 @@ def reset_username_initialized_for_cilogon_usernames(apps, schema_editor):
# Update all existing user's user_profiles to have
# username_initialized=False when the username is invalid because it is a
# CILogon sub claim
- UserProfile.objects.filter(
- username_initialized=True, user__username__startswith="http://cilogon"
- ).update(username_initialized=False)
+ UserProfile.objects.filter(username_initialized=True, user__username__startswith="http://cilogon").update(
+ username_initialized=False
+ )
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0013_auto_20220118_1650'),
+ ("django_airavata_auth", "0013_auto_20220118_1650"),
]
- operations = [
- migrations.RunPython(reset_username_initialized_for_cilogon_usernames, migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(reset_username_initialized_for_cilogon_usernames, migrations.RunPython.noop)]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser.py
index 2b5601cb2..ba908c637 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser.py
@@ -1,107 +1,181 @@
# Generated by Django 3.2.11 on 2022-03-11 14:25
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0013_auto_20220118_1650'),
+ ("django_airavata_auth", "0013_auto_20220118_1650"),
]
operations = [
migrations.CreateModel(
- name='ExtendedUserProfileField',
+ name="ExtendedUserProfileField",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('name', models.CharField(max_length=64)),
- ('help_text', models.TextField(blank=True)),
- ('order', models.IntegerField()),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
- ('deleted', models.BooleanField(default=False)),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("name", models.CharField(max_length=64)),
+ ("help_text", models.TextField(blank=True)),
+ ("order", models.IntegerField()),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
+ ("deleted", models.BooleanField(default=False)),
],
),
migrations.CreateModel(
- name='ExtendedUserProfileAgreementField',
+ name="ExtendedUserProfileAgreementField",
fields=[
- ('field_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='user_agreement', serialize=False, to='django_airavata_auth.extendeduserprofilefield')),
- ('checkbox_label', models.TextField(blank=True)),
+ (
+ "field_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="user_agreement",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
+ ("checkbox_label", models.TextField(blank=True)),
],
- bases=('django_airavata_auth.extendeduserprofilefield',),
+ bases=("django_airavata_auth.extendeduserprofilefield",),
),
migrations.CreateModel(
- name='ExtendedUserProfileMultiChoiceField',
+ name="ExtendedUserProfileMultiChoiceField",
fields=[
- ('field_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='multi_choice', serialize=False, to='django_airavata_auth.extendeduserprofilefield')),
- ('other', models.BooleanField(default=False)),
+ (
+ "field_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="multi_choice",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
+ ("other", models.BooleanField(default=False)),
],
- bases=('django_airavata_auth.extendeduserprofilefield',),
+ bases=("django_airavata_auth.extendeduserprofilefield",),
),
migrations.CreateModel(
- name='ExtendedUserProfileSingleChoiceField',
+ name="ExtendedUserProfileSingleChoiceField",
fields=[
- ('field_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='single_choice', serialize=False, to='django_airavata_auth.extendeduserprofilefield')),
- ('other', models.BooleanField(default=False)),
+ (
+ "field_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="single_choice",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
+ ("other", models.BooleanField(default=False)),
],
- bases=('django_airavata_auth.extendeduserprofilefield',),
+ bases=("django_airavata_auth.extendeduserprofilefield",),
),
migrations.CreateModel(
- name='ExtendedUserProfileTextField',
+ name="ExtendedUserProfileTextField",
fields=[
- ('field_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='text', serialize=False, to='django_airavata_auth.extendeduserprofilefield')),
+ (
+ "field_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="text",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
],
- bases=('django_airavata_auth.extendeduserprofilefield',),
+ bases=("django_airavata_auth.extendeduserprofilefield",),
),
migrations.CreateModel(
- name='ExtendedUserProfileInfo',
+ name="ExtendedUserProfileInfo",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('id_value', models.BigIntegerField(null=True)),
- ('text_value', models.CharField(blank=True, max_length=255)),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
- ('ext_user_profile_field', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_airavata_auth.extendeduserprofilefield')),
- ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='extended_profile', to='django_airavata_auth.userprofile')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("id_value", models.BigIntegerField(null=True)),
+ ("text_value", models.CharField(blank=True, max_length=255)),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
+ (
+ "ext_user_profile_field",
+ models.ForeignKey(
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
+ (
+ "user_profile",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="extended_profile",
+ to="django_airavata_auth.userprofile",
+ ),
+ ),
],
),
migrations.CreateModel(
- name='ExtendedUserProfileFieldLink',
+ name="ExtendedUserProfileFieldLink",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('label', models.TextField()),
- ('url', models.URLField()),
- ('order', models.IntegerField()),
- ('display_link', models.BooleanField(default=True)),
- ('display_inline', models.BooleanField(default=False)),
- ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='links', to='django_airavata_auth.extendeduserprofilefield')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("label", models.TextField()),
+ ("url", models.URLField()),
+ ("order", models.IntegerField()),
+ ("display_link", models.BooleanField(default=True)),
+ ("display_inline", models.BooleanField(default=False)),
+ (
+ "field",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="links",
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
],
),
migrations.CreateModel(
- name='ExtendedUserProfileSingleChoiceFieldChoice',
+ name="ExtendedUserProfileSingleChoiceFieldChoice",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('display_text', models.CharField(max_length=255)),
- ('order', models.IntegerField()),
- ('deleted', models.BooleanField(default=False)),
- ('single_choice_field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='django_airavata_auth.extendeduserprofilesinglechoicefield')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("display_text", models.CharField(max_length=255)),
+ ("order", models.IntegerField()),
+ ("deleted", models.BooleanField(default=False)),
+ (
+ "single_choice_field",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="choices",
+ to="django_airavata_auth.extendeduserprofilesinglechoicefield",
+ ),
+ ),
],
options={
- 'abstract': False,
+ "abstract": False,
},
),
migrations.CreateModel(
- name='ExtendedUserProfileMultiChoiceFieldChoice',
+ name="ExtendedUserProfileMultiChoiceFieldChoice",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('display_text', models.CharField(max_length=255)),
- ('order', models.IntegerField()),
- ('deleted', models.BooleanField(default=False)),
- ('multi_choice_field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='django_airavata_auth.extendeduserprofilemultichoicefield')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("display_text", models.CharField(max_length=255)),
+ ("order", models.IntegerField()),
+ ("deleted", models.BooleanField(default=False)),
+ (
+ "multi_choice_field",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="choices",
+ to="django_airavata_auth.extendeduserprofilemultichoicefield",
+ ),
+ ),
],
options={
- 'abstract': False,
+ "abstract": False,
},
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0015_auto_20220329_1708.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0015_auto_20220329_1708.py
index 49da5c183..d82a80d4e 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0015_auto_20220329_1708.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0015_auto_20220329_1708.py
@@ -1,72 +1,132 @@
# Generated by Django 3.2.11 on 2022-03-29 17:08
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser'),
+ (
+ "django_airavata_auth",
+ "0014_extendeduserprofileagreementfield_extendeduserprofilefield_extendeduserprofilefieldlink_extendeduser",
+ ),
]
operations = [
migrations.CreateModel(
- name='ExtendedUserProfileMultiChoiceValueChoice',
+ name="ExtendedUserProfileMultiChoiceValueChoice",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('value', models.BigIntegerField()),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("value", models.BigIntegerField()),
],
),
migrations.CreateModel(
- name='ExtendedUserProfileValue',
+ name="ExtendedUserProfileValue",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('created_date', models.DateTimeField(auto_now_add=True)),
- ('updated_date', models.DateTimeField(auto_now=True)),
- ('ext_user_profile_field', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_airavata_auth.extendeduserprofilefield')),
- ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='extended_profile', to='django_airavata_auth.userprofile')),
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("created_date", models.DateTimeField(auto_now_add=True)),
+ ("updated_date", models.DateTimeField(auto_now=True)),
+ (
+ "ext_user_profile_field",
+ models.ForeignKey(
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="django_airavata_auth.extendeduserprofilefield",
+ ),
+ ),
+ (
+ "user_profile",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="extended_profile",
+ to="django_airavata_auth.userprofile",
+ ),
+ ),
],
),
migrations.CreateModel(
- name='ExtendedUserProfileAgreementValue',
+ name="ExtendedUserProfileAgreementValue",
fields=[
- ('value_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='user_agreement', serialize=False, to='django_airavata_auth.extendeduserprofilevalue')),
- ('agreement_value', models.BooleanField()),
+ (
+ "value_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="user_agreement",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilevalue",
+ ),
+ ),
+ ("agreement_value", models.BooleanField()),
],
- bases=('django_airavata_auth.extendeduserprofilevalue',),
+ bases=("django_airavata_auth.extendeduserprofilevalue",),
),
migrations.CreateModel(
- name='ExtendedUserProfileMultiChoiceValue',
+ name="ExtendedUserProfileMultiChoiceValue",
fields=[
- ('value_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='multi_choice', serialize=False, to='django_airavata_auth.extendeduserprofilevalue')),
- ('other_value', models.TextField(blank=True)),
+ (
+ "value_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="multi_choice",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilevalue",
+ ),
+ ),
+ ("other_value", models.TextField(blank=True)),
],
- bases=('django_airavata_auth.extendeduserprofilevalue',),
+ bases=("django_airavata_auth.extendeduserprofilevalue",),
),
migrations.CreateModel(
- name='ExtendedUserProfileSingleChoiceValue',
+ name="ExtendedUserProfileSingleChoiceValue",
fields=[
- ('value_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='single_choice', serialize=False, to='django_airavata_auth.extendeduserprofilevalue')),
- ('choice', models.BigIntegerField(null=True)),
- ('other_value', models.TextField(blank=True)),
+ (
+ "value_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="single_choice",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilevalue",
+ ),
+ ),
+ ("choice", models.BigIntegerField(null=True)),
+ ("other_value", models.TextField(blank=True)),
],
- bases=('django_airavata_auth.extendeduserprofilevalue',),
+ bases=("django_airavata_auth.extendeduserprofilevalue",),
),
migrations.CreateModel(
- name='ExtendedUserProfileTextValue',
+ name="ExtendedUserProfileTextValue",
fields=[
- ('value_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='text', serialize=False, to='django_airavata_auth.extendeduserprofilevalue')),
- ('text_value', models.TextField()),
+ (
+ "value_ptr",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ related_name="text",
+ serialize=False,
+ to="django_airavata_auth.extendeduserprofilevalue",
+ ),
+ ),
+ ("text_value", models.TextField()),
],
- bases=('django_airavata_auth.extendeduserprofilevalue',),
+ bases=("django_airavata_auth.extendeduserprofilevalue",),
),
migrations.DeleteModel(
- name='ExtendedUserProfileInfo',
+ name="ExtendedUserProfileInfo",
),
migrations.AddField(
- model_name='extendeduserprofilemultichoicevaluechoice',
- name='multi_choice_value',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='django_airavata_auth.extendeduserprofilemultichoicevalue'),
+ model_name="extendeduserprofilemultichoicevaluechoice",
+ name="multi_choice_value",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="choices",
+ to="django_airavata_auth.extendeduserprofilemultichoicevalue",
+ ),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0016_extendeduserprofilefield_required.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0016_extendeduserprofilefield_required.py
index 4c6dd6f19..4b31dced1 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0016_extendeduserprofilefield_required.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0016_extendeduserprofilefield_required.py
@@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0015_auto_20220329_1708'),
+ ("django_airavata_auth", "0015_auto_20220329_1708"),
]
operations = [
migrations.AddField(
- model_name='extendeduserprofilefield',
- name='required',
+ model_name="extendeduserprofilefield",
+ name="required",
field=models.BooleanField(default=True),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py
index 47ed79528..283db2dad 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py
@@ -40,16 +40,14 @@ def default_templates(apps, schema_editor):
{% endfor %}
</table>
{% endif %}
- """.strip())
+ """.strip(),
+ )
user_profile_completed_template.save()
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0016_extendeduserprofilefield_required'),
+ ("django_airavata_auth", "0016_extendeduserprofilefield_required"),
]
- operations = [
- migrations.RunPython(default_templates)
- ]
+ operations = [migrations.RunPython(default_templates)]
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831.py
index ff67fdb3c..69a2b841f 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831.py
@@ -4,11 +4,9 @@ from django.db import migrations
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0014_auto_20220217_2255'),
- ('django_airavata_auth', '0017_auto_20220616_1831'),
+ ("django_airavata_auth", "0014_auto_20220217_2255"),
+ ("django_airavata_auth", "0017_auto_20220616_1831"),
]
- operations = [
- ]
+ operations = []
diff --git a/airavata-django-portal/django_airavata/apps/auth/migrations/0019_auto_20221118_1323.py b/airavata-django-portal/django_airavata/apps/auth/migrations/0019_auto_20221118_1323.py
index e98657a03..335ab0996 100644
--- a/airavata-django-portal/django_airavata/apps/auth/migrations/0019_auto_20221118_1323.py
+++ b/airavata-django-portal/django_airavata/apps/auth/migrations/0019_auto_20221118_1323.py
@@ -1,24 +1,38 @@
# Generated by Django 3.2.15 on 2022-11-18 13:23
-from django.db import migrations, models
import django.db.models.deletion
+from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
- ('django_airavata_auth', '0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831'),
+ ("django_airavata_auth", "0018_merge_0014_auto_20220217_2255_0017_auto_20220616_1831"),
]
operations = [
migrations.AlterField(
- model_name='emailtemplate',
- name='template_type',
- field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template'), (4, 'User Added to Group Template'), (5, 'Verify Email Change Template'), (6, 'User Profile Completed Template')], primary_key=True, serialize=False),
+ model_name="emailtemplate",
+ name="template_type",
+ field=models.IntegerField(
+ choices=[
+ (1, "Verify Email Template"),
+ (2, "New User Email Template"),
+ (3, "Password Reset Email Template"),
+ (4, "User Added to Group Template"),
+ (5, "Verify Email Change Template"),
+ (6, "User Profile Completed Template"),
+ ],
+ primary_key=True,
+ serialize=False,
+ ),
),
migrations.AlterField(
- model_name='extendeduserprofilevalue',
- name='user_profile',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='extended_profile_values', to='django_airavata_auth.userprofile'),
+ model_name="extendeduserprofilevalue",
+ name="user_profile",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="extended_profile_values",
+ to="django_airavata_auth.userprofile",
+ ),
),
]
diff --git a/airavata-django-portal/django_airavata/apps/auth/models.py b/airavata-django-portal/django_airavata/apps/auth/models.py
index 6cc658ea9..4ad4ca18b 100644
--- a/airavata-django-portal/django_airavata/apps/auth/models.py
+++ b/airavata-django-portal/django_airavata/apps/auth/models.py
@@ -16,8 +16,7 @@ USER_PROFILE_COMPLETED_TEMPLATE = 6
class EmailVerification(models.Model):
username = models.CharField(max_length=64)
- verification_code = models.CharField(
- max_length=36, unique=True, default=uuid.uuid4)
+ verification_code = models.CharField(max_length=36, unique=True, default=uuid.uuid4)
created_date = models.DateTimeField(auto_now_add=True)
verified = models.BooleanField(default=False)
next = models.CharField(max_length=255, null=True)
@@ -25,15 +24,14 @@ class EmailVerification(models.Model):
class EmailTemplate(models.Model):
TEMPLATE_TYPE_CHOICES = (
- (VERIFY_EMAIL_TEMPLATE, 'Verify Email Template'),
- (NEW_USER_EMAIL_TEMPLATE, 'New User Email Template'),
- (PASSWORD_RESET_EMAIL_TEMPLATE, 'Password Reset Email Template'),
- (USER_ADDED_TO_GROUP_TEMPLATE, 'User Added to Group Template'),
- (VERIFY_EMAIL_CHANGE_TEMPLATE, 'Verify Email Change Template'),
- (USER_PROFILE_COMPLETED_TEMPLATE, 'User Profile Completed Template'),
+ (VERIFY_EMAIL_TEMPLATE, "Verify Email Template"),
+ (NEW_USER_EMAIL_TEMPLATE, "New User Email Template"),
+ (PASSWORD_RESET_EMAIL_TEMPLATE, "Password Reset Email Template"),
+ (USER_ADDED_TO_GROUP_TEMPLATE, "User Added to Group Template"),
+ (VERIFY_EMAIL_CHANGE_TEMPLATE, "Verify Email Change Template"),
+ (USER_PROFILE_COMPLETED_TEMPLATE, "User Profile Completed Template"),
)
- template_type = models.IntegerField(
- primary_key=True, choices=TEMPLATE_TYPE_CHOICES)
+ template_type = models.IntegerField(primary_key=True, choices=TEMPLATE_TYPE_CHOICES)
subject = models.CharField(max_length=255)
body = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
@@ -48,15 +46,12 @@ class EmailTemplate(models.Model):
class PasswordResetRequest(models.Model):
username = models.CharField(max_length=64)
- reset_code = models.CharField(
- max_length=36, unique=True, default=uuid.uuid4)
+ reset_code = models.CharField(max_length=36, unique=True, default=uuid.uuid4)
created_date = models.DateTimeField(auto_now_add=True)
class UserProfile(models.Model):
- user = models.OneToOneField(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE, related_name="user_profile")
+ user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="user_profile")
# This flag is only used for external IDP users. It indicates that the
# username was properly initialized when the user logged in through the
# external IDP. As for now that means that the username was set to the
@@ -102,13 +97,13 @@ class UserProfile(models.Model):
def invalid_fields(self):
result = []
if not self.is_username_valid:
- result.append('username')
+ result.append("username")
if not self.is_email_valid:
- result.append('email')
+ result.append("email")
if not self.is_first_name_valid:
- result.append('first_name')
+ result.append("first_name")
if not self.is_last_name_valid:
- result.append('last_name')
+ result.append("last_name")
return result
@property
@@ -136,7 +131,7 @@ class UserInfo(models.Model):
updated_date = models.DateTimeField(auto_now=True)
class Meta:
... 47281 lines suppressed ...