forked from enviPath/enviPy
Copy Objects between Packages (#59)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#59
This commit is contained in:
128
epdb/logic.py
128
epdb/logic.py
@ -1,6 +1,6 @@
|
||||
import re
|
||||
import logging
|
||||
from typing import Union, List, Optional, Set, Dict
|
||||
from typing import Union, List, Optional, Set, Dict, Any
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import transaction
|
||||
@ -13,6 +13,132 @@ from utilities.chem import FormatConverter
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EPDBURLParser:
|
||||
|
||||
UUID_PATTERN = r'[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'
|
||||
|
||||
MODEL_PATTERNS = {
|
||||
'epdb.User': re.compile(rf'^.*/user/{UUID_PATTERN}'),
|
||||
'epdb.Group': re.compile(rf'^.*/group/{UUID_PATTERN}'),
|
||||
'epdb.Package': re.compile(rf'^.*/package/{UUID_PATTERN}'),
|
||||
'epdb.Compound': re.compile(rf'^.*/package/{UUID_PATTERN}/compound/{UUID_PATTERN}'),
|
||||
'epdb.CompoundStructure': re.compile(rf'^.*/package/{UUID_PATTERN}/compound/{UUID_PATTERN}/structure/{UUID_PATTERN}'),
|
||||
'epdb.Rule': re.compile(rf'^.*/package/{UUID_PATTERN}/(?:simple-ambit-rule|simple-rdkit-rule|parallel-rule|sequential-rule|rule)/{UUID_PATTERN}'),
|
||||
'epdb.Reaction': re.compile(rf'^.*/package/{UUID_PATTERN}/reaction/{UUID_PATTERN}$'),
|
||||
'epdb.Pathway': re.compile(rf'^.*/package/{UUID_PATTERN}/pathway/{UUID_PATTERN}'),
|
||||
'epdb.Node': re.compile(rf'^.*/package/{UUID_PATTERN}/pathway/{UUID_PATTERN}/node/{UUID_PATTERN}'),
|
||||
'epdb.Edge': re.compile(rf'^.*/package/{UUID_PATTERN}/pathway/{UUID_PATTERN}/edge/{UUID_PATTERN}'),
|
||||
'epdb.Scenario': re.compile(rf'^.*/package/{UUID_PATTERN}/scenario/{UUID_PATTERN}'),
|
||||
'epdb.EPModel': re.compile(rf'^.*/package/{UUID_PATTERN}/model/{UUID_PATTERN}'),
|
||||
'epdb.Setting': re.compile(rf'^.*/setting/{UUID_PATTERN}'),
|
||||
}
|
||||
|
||||
def __init__(self, url: str):
|
||||
self.url = url
|
||||
self._matches = {}
|
||||
self._analyze_url()
|
||||
|
||||
def _analyze_url(self):
|
||||
for model_path, pattern in self.MODEL_PATTERNS.items():
|
||||
match = pattern.findall(self.url)
|
||||
if match:
|
||||
self._matches[model_path] = match[0]
|
||||
|
||||
def _get_model_class(self, model_path: str):
|
||||
try:
|
||||
from django.apps import apps
|
||||
app_label, model_name = model_path.split('.')[-2:]
|
||||
return apps.get_model(app_label, model_name)
|
||||
except (ImportError, LookupError, ValueError):
|
||||
raise ValueError(f"Model {model_path} does not exist!")
|
||||
|
||||
def _get_object_by_url(self, model_path: str, url: str):
|
||||
model_class = self._get_model_class(model_path)
|
||||
return model_class.objects.get(url=url)
|
||||
|
||||
def is_package_url(self) -> bool:
|
||||
return bool(re.compile(rf'^.*/package/{self.UUID_PATTERN}$').findall(self.url))
|
||||
|
||||
def contains_package_url(self):
|
||||
return bool(self.MODEL_PATTERNS['epdb.Package'].findall(self.url)) and not self.is_package_url()
|
||||
|
||||
def is_user_url(self) -> bool:
|
||||
return bool(self.MODEL_PATTERNS['epdb.User'].findall(self.url))
|
||||
|
||||
def is_group_url(self) -> bool:
|
||||
return bool(self.MODEL_PATTERNS['epdb.Group'].findall(self.url))
|
||||
|
||||
def is_setting_url(self) -> bool:
|
||||
return bool(self.MODEL_PATTERNS['epdb.Setting'].findall(self.url))
|
||||
|
||||
def get_object(self) -> Optional[Any]:
|
||||
# Define priority order from most specific to least specific
|
||||
priority_order = [
|
||||
# 3rd level
|
||||
'epdb.CompoundStructure',
|
||||
'epdb.Node',
|
||||
'epdb.Edge',
|
||||
# 2nd level
|
||||
'epdb.Compound',
|
||||
'epdb.Rule',
|
||||
'epdb.Reaction',
|
||||
'epdb.Scenario',
|
||||
'epdb.EPModel',
|
||||
'epdb.Pathway',
|
||||
# 1st level
|
||||
'epdb.Package',
|
||||
'epdb.Setting',
|
||||
'epdb.Group',
|
||||
'epdb.User',
|
||||
]
|
||||
|
||||
for model_path in priority_order:
|
||||
if model_path in self._matches:
|
||||
url = self._matches[model_path]
|
||||
return self._get_object_by_url(model_path, url)
|
||||
|
||||
raise ValueError(f"No object found for URL {self.url}")
|
||||
|
||||
def get_objects(self) -> List[Any]:
|
||||
"""
|
||||
Get all Django model objects along the URL path in hierarchical order.
|
||||
Returns objects from parent to child (e.g., Package -> Compound -> Structure).
|
||||
"""
|
||||
objects = []
|
||||
|
||||
hierarchy_order = [
|
||||
# 1st level
|
||||
'epdb.Package',
|
||||
'epdb.Setting',
|
||||
'epdb.Group',
|
||||
'epdb.User',
|
||||
# 2nd level
|
||||
'epdb.Compound',
|
||||
'epdb.Rule',
|
||||
'epdb.Reaction',
|
||||
'epdb.Scenario',
|
||||
'epdb.EPModel',
|
||||
'epdb.Pathway',
|
||||
# 3rd level
|
||||
'epdb.CompoundStructure',
|
||||
'epdb.Node',
|
||||
'epdb.Edge',
|
||||
]
|
||||
|
||||
for model_path in hierarchy_order:
|
||||
if model_path in self._matches:
|
||||
url = self._matches[model_path]
|
||||
objects.append(self._get_object_by_url(model_path, url))
|
||||
|
||||
return objects
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"EPDBURLParser(url='{self.url}')"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"EPDBURLParser(url='{self.url}', matches={list(self._matches.keys())})"
|
||||
|
||||
|
||||
class UserManager(object):
|
||||
user_pattern = re.compile(r".*/user/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user