Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom methods to the workspace adapter #499

Merged
merged 9 commits into from
Jul 3, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add support for Django 5.0.
* Add `convert_mariadb_uuid_fields` command to convert UUID fields for MariaDB 10.7+ and Django 5.0+. See the documentation of this command for more information.
* Move app settings to their own file, and set defaults for some settings.
* Add additional customization for WorkspaceAdapters. Users can override the `before_anvil_create`, `after_anvil_create`, and `after_anvil_import` methods to run custom code before or after creating or after importing a workspace.

## 0.23.0 (2024-05-31)

Expand Down
2 changes: 1 addition & 1 deletion anvil_consortium_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.23.1.dev3"
__version__ = "0.24.0.dev0"
14 changes: 12 additions & 2 deletions anvil_consortium_manager/adapters/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ def get_extra_detail_context_data(self, workspace, request):

return {}

def before_anvil_create(self, workspace):
"""Custom actions to take after a workspace is created on AnVIL."""
pass

def after_anvil_create(self, workspace):
"""Custom actions to take after a workspace is created on AnVIL."""
pass

def after_anvil_import(self, workspace):
"""Custom actions to take after a workspace is imported from AnVIL."""
pass


class AdapterAlreadyRegisteredError(Exception):
"""Exception raised when an adapter or its type is already registered."""
Expand Down Expand Up @@ -212,8 +224,6 @@ def get_registered_names(self):
def populate_from_settings(self):
"""Populate the workspace adapter registry from settings. Called by AppConfig ready() method."""
adapter_modules = app_settings.WORKSPACE_ADAPTERS
print("adapter modules")
print(adapter_modules)
if len(self._registry):
msg = "Registry has already been populated."
raise RuntimeError(msg)
Expand Down
1 change: 0 additions & 1 deletion anvil_consortium_manager/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ def clean(self):
# Check for the same case insensitive name in the same billing project.
is_mysql = settings.DATABASES["default"]["ENGINE"] == "django.db.backends.mysql"
if not is_mysql:
print("here")
billing_project = self.cleaned_data.get("billing_project", None)
name = self.cleaned_data.get("name", None)
if (
Expand Down
41 changes: 41 additions & 0 deletions anvil_consortium_manager/tests/test_app/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,44 @@ class TestForeignKeyWorkspaceAdapter(BaseWorkspaceAdapter):
workspace_data_model = models.TestForeignKeyWorkspaceData
workspace_data_form_class = forms.TestForeignKeyWorkspaceDataForm
workspace_detail_template_name = "workspace_detail.html"


class TestWorkspaceMethodsAdapter(BaseWorkspaceAdapter):
"""Adapter superclass for testing adapter methods."""

name = "workspace adapter methods testing"
type = "methods_tester"
description = "Workspace type for testing custom adapter methods method"
list_table_class_staff_view = WorkspaceStaffTable
list_table_class_view = WorkspaceUserTable
workspace_form_class = WorkspaceForm
workspace_data_model = models.TestWorkspaceMethodsData
workspace_data_form_class = forms.TestWorkspaceMethodsForm
workspace_detail_template_name = "workspace_detail.html"


class TestBeforeWorkspaceCreateAdapter(TestWorkspaceMethodsAdapter):
"""Test adapter for workspaces with custom methods defined."""

def before_anvil_create(self, workspace):
# Append a -2 to the name of the workspace.
workspace.name = workspace.name + "-2"
workspace.save()


class TestAfterWorkspaceCreateAdapter(TestWorkspaceMethodsAdapter):
"""Test adapter for workspaces with custom methods defined."""

def after_anvil_create(self, workspace):
# Set the extra field to "FOO"
workspace.testworkspacemethodsdata.test_field = "FOO"
workspace.testworkspacemethodsdata.save()


class TestAfterWorkspaceImportAdapter(TestWorkspaceMethodsAdapter):
"""Test adapter for workspaces with custom methods defined."""

def after_anvil_import(self, workspace):
# Set the extra field.
workspace.testworkspacemethodsdata.test_field = "imported!"
workspace.testworkspacemethodsdata.save()
8 changes: 8 additions & 0 deletions anvil_consortium_manager/tests/test_app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,11 @@ class TestForeignKeyWorkspaceDataForm(forms.ModelForm):
class Meta:
model = models.TestForeignKeyWorkspaceData
fields = ("other_workspace", "workspace")


class TestWorkspaceMethodsForm(forms.ModelForm):
"""Form for a TestWorkspaceMethods object."""

class Meta:
model = models.TestWorkspaceMethodsData
fields = ("test_field", "workspace")
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Generated by Django 5.0 on 2024-07-01 22:21

import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('anvil_consortium_manager', '0019_accountuserarchive'),
('test_app', '0004_testforeignkeyworkspacedata_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='HistoricalTestWorkspaceMethodsData',
fields=[
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('test_field', models.CharField(max_length=255)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('workspace', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='anvil_consortium_manager.workspace')),
],
options={
'verbose_name': 'historical test workspace methods data',
'verbose_name_plural': 'historical test workspace methods datas',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='TestWorkspaceMethodsData',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('test_field', models.CharField(max_length=255)),
('workspace', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='anvil_consortium_manager.workspace')),
],
options={
'abstract': False,
},
),
]
6 changes: 6 additions & 0 deletions anvil_consortium_manager/tests/test_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ class TestForeignKeyWorkspaceData(BaseWorkspaceData):
"""Custom model with a second fk to Workspace."""

other_workspace = models.ForeignKey(Workspace, related_name="test_foreign_key_workspaces", on_delete=models.PROTECT)


class TestWorkspaceMethodsData(BaseWorkspaceData):
"""Custom model with additional fields."""

test_field = models.CharField(max_length=255)
Loading