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

Improve DataObjFormatters Handling for New Tables #6324

Draft
wants to merge 1 commit into
base: production
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions specifyweb/context/app_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,42 @@ def get_app_resource(collection, user, resource_name, additional_default=False):
logger.info('looking for app resource %r for user %s in %s',
resource_name, user and user.name, collection and collection.collectionname)

# Handling for DataObjFormatters to support fallback to defaults
if resource_name == 'DataObjFormatters':
custom_formatter = None
default_formatter = None

# Try to search for the the custom formatter first
for level in DIR_LEVELS:
# First look in the database.
from_db = get_app_resource_from_db(collection, user, level, resource_name)
if from_db is not None:
custom_formatter = from_db
break

# If resource was not found, look on the filesystem.
from_fs = load_resource_at_level(collection, user, level, resource_name)
if from_fs is not None:
custom_formatter = from_fs
break

# If custom formatter not found, try to load the default formatter from the backstop level
default_formatter = load_resource_at_level(collection, user, 'Backstop', resource_name)

# If both custom and default formatters are found, merge them
if custom_formatter is not None and default_formatter is not None:
merged_formatter = merge_formatters(custom_formatter[0], default_formatter[0])
return merged_formatter, custom_formatter[1], custom_formatter[2]

# Return the custom formatter if it exists, otherwise return the default
if custom_formatter is not None:
return custom_formatter

if default_formatter is not None:
return default_formatter

return None

if not additional_default:
# Traverse the hierarchy.
for level in DIR_LEVELS:
Expand Down Expand Up @@ -202,3 +238,29 @@ def get_app_resource_dirs_for_level(collection, user, level):

# Build the queryset.
return Spappresourcedir.objects.filter(**filters)

def merge_formatters(custom_xml, default_xml):
"""Merge custom and default XML formatters.
This function takes two XML strings, one for custom formatters and one for default formatters,
and merges them by adding any formatters from the default XML that are not already present in
the custom XML. It returns the merged XML as a string.
"""

custom_root = ElementTree.fromstring(custom_xml)
default_root = ElementTree.fromstring(default_xml)

# Create a set of existing classes in the custom XML to avoid duplicates
custom_classes = set()
for format_elem in custom_root.findall('format'):
class_attr = format_elem.get('class')
if class_attr:
custom_classes.add(class_attr)

# Add formatters from default that don't exist in custom
for format_elem in default_root.findall('format'):
class_attr = format_elem.get('class')
if class_attr and class_attr not in custom_classes:
custom_root.append(format_elem)

# Convert the merged XML tree back to a string
return ElementTree.tostring(custom_root, encoding='utf-8').decode('utf-8')
Loading