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 ...