mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-13 12:20:36 +03:00
R: Refactoring cache models pt2
This commit is contained in:
parent
25ec175d79
commit
2bacaf34b6
|
@ -1,7 +1,7 @@
|
|||
''' Models: OSS API. '''
|
||||
# pylint: disable=duplicate-code
|
||||
|
||||
from typing import Optional, cast
|
||||
from typing import Optional
|
||||
|
||||
from cctext import extract_entities
|
||||
from rest_framework.serializers import ValidationError
|
||||
|
@ -59,18 +59,17 @@ class OperationSchemaCached:
|
|||
schema = self.cache.get_schema(operation)
|
||||
children = self.cache.graph.outputs[target]
|
||||
if schema is not None and len(children) > 0:
|
||||
ids = [cst.pk for cst in schema.cache.constituents]
|
||||
if not keep_constituents:
|
||||
self.before_delete_cst(schema, schema.cache.constituents)
|
||||
self.before_delete_cst(schema.model.pk, ids)
|
||||
else:
|
||||
items = schema.cache.constituents
|
||||
ids = [cst.pk for cst in items]
|
||||
inheritance_to_delete: list[Inheritance] = []
|
||||
for child_id in children:
|
||||
child_operation = self.cache.operation_by_id[child_id]
|
||||
child_schema = self.cache.get_schema(child_operation)
|
||||
if child_schema is None:
|
||||
continue
|
||||
self._undo_substitutions_cst(items, child_operation, child_schema)
|
||||
self._undo_substitutions_cst(ids, child_operation, child_schema)
|
||||
for item in self.cache.inheritance[child_id]:
|
||||
if item.parent_id in ids:
|
||||
inheritance_to_delete.append(item)
|
||||
|
@ -91,7 +90,7 @@ class OperationSchemaCached:
|
|||
|
||||
if old_schema is not None:
|
||||
if has_children:
|
||||
self.before_delete_cst(old_schema, old_schema.cache.constituents)
|
||||
self.before_delete_cst(old_schema.model.pk, [cst.pk for cst in old_schema.cache.constituents])
|
||||
self.cache.remove_schema(old_schema)
|
||||
|
||||
operation.setQ_result(schema)
|
||||
|
@ -238,19 +237,17 @@ class OperationSchemaCached:
|
|||
receiver.model.save(update_fields=['time_update'])
|
||||
return True
|
||||
|
||||
def relocate_down(self, source: RSFormCached, destination: RSFormCached, items: list[Constituenta]):
|
||||
def relocate_down(self, source: RSFormCached, destination: RSFormCached, items: list[int]):
|
||||
''' Move list of Constituents to destination Schema inheritor. '''
|
||||
self.cache.ensure_loaded_subs()
|
||||
self.cache.insert_schema(source)
|
||||
self.cache.insert_schema(destination)
|
||||
operation = self.cache.get_operation(destination.model.pk)
|
||||
|
||||
self._undo_substitutions_cst(items, operation, destination)
|
||||
|
||||
inheritance_to_delete = [item for item in self.cache.inheritance[operation.pk] if item.parent_id in items]
|
||||
for item in inheritance_to_delete:
|
||||
self.cache.remove_inheritance(item)
|
||||
Inheritance.objects.filter(operation_id=operation.pk, parent__in=items).delete()
|
||||
Inheritance.objects.filter(operation_id=operation.pk, parent_id__in=items).delete()
|
||||
|
||||
def relocate_up(self, source: RSFormCached, destination: RSFormCached,
|
||||
items: list[Constituenta]) -> list[Constituenta]:
|
||||
|
@ -285,6 +282,7 @@ class OperationSchemaCached:
|
|||
exclude: Optional[list[int]] = None
|
||||
) -> None:
|
||||
''' Trigger cascade resolutions when new Constituenta is created. '''
|
||||
source.cache.ensure_loaded()
|
||||
self.cache.insert_schema(source)
|
||||
inserted_aliases = [cst.alias for cst in cst_list]
|
||||
depend_aliases: set[str] = set()
|
||||
|
@ -299,12 +297,12 @@ class OperationSchemaCached:
|
|||
operation = self.cache.get_operation(source.model.pk)
|
||||
self._cascade_inherit_cst(operation.pk, source, cst_list, alias_mapping, exclude)
|
||||
|
||||
def after_change_cst_type(self, target: Constituenta) -> None:
|
||||
def after_change_cst_type(self, schemaID: int, target: int, new_type: CstType) -> None:
|
||||
''' Trigger cascade resolutions when Constituenta type is changed. '''
|
||||
operation = self.cache.get_operation(target.schema.pk)
|
||||
self._cascade_change_cst_type(operation.pk, target.pk, cast(CstType, target.cst_type))
|
||||
operation = self.cache.get_operation(schemaID)
|
||||
self._cascade_change_cst_type(operation.pk, target, new_type)
|
||||
|
||||
def after_update_cst(self, source: RSFormCached, target: Constituenta, data: dict, old_data: dict) -> None:
|
||||
def after_update_cst(self, source: RSFormCached, target: int, data: dict, old_data: dict) -> None:
|
||||
''' Trigger cascade resolutions when Constituenta data is changed. '''
|
||||
self.cache.insert_schema(source)
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
|
@ -316,16 +314,15 @@ class OperationSchemaCached:
|
|||
alias_mapping[alias] = cst
|
||||
self._cascade_update_cst(
|
||||
operation=operation.pk,
|
||||
cst_id=target.pk,
|
||||
cst_id=target,
|
||||
data=data,
|
||||
old_data=old_data,
|
||||
mapping=alias_mapping
|
||||
)
|
||||
|
||||
def before_delete_cst(self, source: RSFormCached, target: list[Constituenta]) -> None:
|
||||
def before_delete_cst(self, sourceID: int, target: list[int]) -> None:
|
||||
''' Trigger cascade resolutions before Constituents are deleted. '''
|
||||
self.cache.insert_schema(source)
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
operation = self.cache.get_operation(sourceID)
|
||||
self._cascade_delete_inherited(operation.pk, target)
|
||||
|
||||
def before_substitute(self, schemaID: int, substitutions: CstSubstitution) -> None:
|
||||
|
@ -340,7 +337,7 @@ class OperationSchemaCached:
|
|||
for argument in arguments:
|
||||
parent_schema = self.cache.get_schema(argument)
|
||||
if parent_schema is not None:
|
||||
self._execute_delete_inherited(target.pk, parent_schema.cache.constituents)
|
||||
self._execute_delete_inherited(target.pk, [cst.pk for cst in parent_schema.cache.constituents])
|
||||
|
||||
def after_create_arguments(self, target: Operation, arguments: list[Operation]) -> None:
|
||||
''' Trigger cascade resolutions after arguments are created. '''
|
||||
|
@ -443,7 +440,7 @@ class OperationSchemaCached:
|
|||
new_data = self._prepare_update_data(successor, data, old_data, alias_mapping)
|
||||
if len(new_data) == 0:
|
||||
continue
|
||||
new_old_data = child_schema.update_cst(successor, new_data)
|
||||
new_old_data = child_schema.update_cst(successor.pk, new_data)
|
||||
if len(new_old_data) == 0:
|
||||
continue
|
||||
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
||||
|
@ -455,7 +452,7 @@ class OperationSchemaCached:
|
|||
mapping=new_mapping
|
||||
)
|
||||
|
||||
def _cascade_delete_inherited(self, operation: int, target: list[Constituenta]) -> None:
|
||||
def _cascade_delete_inherited(self, operation: int, target: list[int]) -> None:
|
||||
children = self.cache.graph.outputs[operation]
|
||||
if len(children) == 0:
|
||||
return
|
||||
|
@ -463,18 +460,17 @@ class OperationSchemaCached:
|
|||
for child_id in children:
|
||||
self._execute_delete_inherited(child_id, target)
|
||||
|
||||
def _execute_delete_inherited(self, operation_id: int, parent_cst: list[Constituenta]) -> None:
|
||||
def _execute_delete_inherited(self, operation_id: int, parent_ids: list[int]) -> None:
|
||||
operation = self.cache.operation_by_id[operation_id]
|
||||
schema = self.cache.get_schema(operation)
|
||||
if schema is None:
|
||||
return
|
||||
self._undo_substitutions_cst(parent_cst, operation, schema)
|
||||
target_ids = self.cache.get_inheritors_list([cst.pk for cst in parent_cst], operation_id)
|
||||
target_cst = [schema.cache.by_id[cst_id] for cst_id in target_ids]
|
||||
self._cascade_delete_inherited(operation_id, target_cst)
|
||||
if len(target_cst) > 0:
|
||||
self._undo_substitutions_cst(parent_ids, operation, schema)
|
||||
target_ids = self.cache.get_inheritors_list(parent_ids, operation_id)
|
||||
self._cascade_delete_inherited(operation_id, target_ids)
|
||||
if len(target_ids) > 0:
|
||||
self.cache.remove_cst(operation_id, target_ids)
|
||||
schema.delete_cst(target_cst)
|
||||
schema.delete_cst(target_ids)
|
||||
|
||||
def _cascade_before_substitute(self, substitutions: CstSubstitution, operation: Operation) -> None:
|
||||
children = self.cache.graph.outputs[operation.pk]
|
||||
|
@ -635,8 +631,7 @@ class OperationSchemaCached:
|
|||
result.append((schema.cache.by_id[new_original_id], schema.cache.by_id[new_substitution_id]))
|
||||
return result
|
||||
|
||||
def _undo_substitutions_cst(self, target: list[Constituenta], operation: Operation, schema: RSFormCached) -> None:
|
||||
target_ids = [cst.pk for cst in target]
|
||||
def _undo_substitutions_cst(self, target_ids: list[int], operation: Operation, schema: RSFormCached) -> None:
|
||||
to_process = []
|
||||
for sub in self.cache.substitutions[operation.pk]:
|
||||
if sub.original_id in target_ids or sub.substitution_id in target_ids:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from typing import Optional
|
||||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.rsform.models import Constituenta, RSFormCached
|
||||
from apps.rsform.models import Constituenta, CstType, RSFormCached
|
||||
|
||||
from .OperationSchemaCached import CstSubstitution, OperationSchemaCached
|
||||
|
||||
|
@ -25,17 +25,18 @@ class PropagationFacade:
|
|||
OperationSchemaCached(host).after_create_cst(source, new_cst)
|
||||
|
||||
@staticmethod
|
||||
def after_change_cst_type(target: Constituenta, exclude: Optional[list[int]] = None) -> None:
|
||||
def after_change_cst_type(sourceID: int, target: int, new_type: CstType,
|
||||
exclude: Optional[list[int]] = None) -> None:
|
||||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||
hosts = _get_oss_hosts(target.schema.pk)
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).after_change_cst_type(target)
|
||||
OperationSchemaCached(host).after_change_cst_type(sourceID, target, new_type)
|
||||
|
||||
@staticmethod
|
||||
def after_update_cst(
|
||||
source: RSFormCached,
|
||||
target: Constituenta,
|
||||
target: int,
|
||||
data: dict,
|
||||
old_data: dict,
|
||||
exclude: Optional[list[int]] = None
|
||||
|
@ -47,13 +48,13 @@ class PropagationFacade:
|
|||
OperationSchemaCached(host).after_update_cst(source, target, data, old_data)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_cst(source: RSFormCached, target: list[Constituenta],
|
||||
def before_delete_cst(sourceID: int, target: list[int],
|
||||
exclude: Optional[list[int]] = None) -> None:
|
||||
''' Trigger cascade resolutions before constituents are deleted. '''
|
||||
hosts = _get_oss_hosts(source.model.pk)
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).before_delete_cst(source, target)
|
||||
OperationSchemaCached(host).before_delete_cst(sourceID, target)
|
||||
|
||||
@staticmethod
|
||||
def before_substitute(sourceID: int, substitutions: CstSubstitution,
|
||||
|
@ -75,5 +76,5 @@ class PropagationFacade:
|
|||
if len(hosts) == 0:
|
||||
return
|
||||
|
||||
schema = RSFormCached(item)
|
||||
PropagationFacade.before_delete_cst(schema, list(schema.constituentsQ().order_by('order')), exclude)
|
||||
ids = list(Constituenta.objects.filter(schema=item).order_by('order').values_list('pk', flat=True))
|
||||
PropagationFacade.before_delete_cst(item.pk, ids, exclude)
|
||||
|
|
|
@ -118,9 +118,11 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
serializer = s.LayoutSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
item = self._get_item()
|
||||
|
||||
with transaction.atomic():
|
||||
m.Layout.update_data(pk, serializer.validated_data['data'])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(status=c.HTTP_200_OK, data=s.OperationSchemaSerializer(item).data)
|
||||
|
||||
@extend_schema(
|
||||
|
@ -143,13 +145,13 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
children_blocks: list[m.Block] = serializer.validated_data['children_blocks']
|
||||
children_operations: list[m.Operation] = serializer.validated_data['children_operations']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
new_block = oss.create_block(**serializer.validated_data['item_data'])
|
||||
layout.append({
|
||||
'nodeID': 'b' + str(new_block.pk),
|
||||
|
@ -197,8 +199,8 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
block: m.Block = cast(m.Block, serializer.validated_data['target'])
|
||||
|
||||
with transaction.atomic():
|
||||
if 'title' in serializer.validated_data['item_data']:
|
||||
block.title = serializer.validated_data['item_data']['title']
|
||||
|
@ -211,6 +213,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
layout = serializer.validated_data['layout']
|
||||
m.Layout.update_data(pk, layout)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.OperationSchemaSerializer(item).data
|
||||
|
@ -236,12 +239,12 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
block = cast(m.Block, serializer.validated_data['target'])
|
||||
layout = serializer.validated_data['layout']
|
||||
layout = [x for x in layout if x['nodeID'] != 'b' + str(block.pk)]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
oss.delete_block(block)
|
||||
m.Layout.update_data(pk, layout)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
@ -271,8 +274,8 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
layout = serializer.validated_data['layout']
|
||||
|
||||
with transaction.atomic():
|
||||
m.Layout.update_data(pk, layout)
|
||||
for operation in serializer.validated_data['operations']:
|
||||
|
@ -308,13 +311,13 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
data = serializer.validated_data['item_data']
|
||||
data['operation_type'] = m.OperationType.INPUT
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
new_operation = oss.create_operation(**serializer.validated_data['item_data'])
|
||||
layout.append({
|
||||
'nodeID': 'o' + str(new_operation.pk),
|
||||
|
@ -356,9 +359,9 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
|
||||
with transaction.atomic():
|
||||
source = cast(m.Operation, serializer.validated_data['source_operation'])
|
||||
alias = '+' + source.alias
|
||||
|
@ -426,15 +429,15 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
data = serializer.validated_data['item_data']
|
||||
data['operation_type'] = m.OperationType.INPUT
|
||||
if not serializer.validated_data['clone_source']:
|
||||
data['result'] = serializer.validated_data['source']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
new_operation = oss.create_operation(**serializer.validated_data['item_data'])
|
||||
layout.append({
|
||||
'nodeID': 'o' + str(new_operation.pk),
|
||||
|
@ -481,11 +484,11 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
target = cast(m.Operation, serializer.validated_data['target'])
|
||||
new_operation = oss.create_reference(target)
|
||||
layout.append({
|
||||
|
@ -526,13 +529,13 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
position = serializer.validated_data['position']
|
||||
data = serializer.validated_data['item_data']
|
||||
data['operation_type'] = m.OperationType.SYNTHESIS
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
new_operation = oss.create_operation(**serializer.validated_data['item_data'])
|
||||
layout.append({
|
||||
'nodeID': 'o' + str(new_operation.pk),
|
||||
|
@ -575,10 +578,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
operation: m.Operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
oss = m.OperationSchemaCached(item)
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
if 'layout' in serializer.validated_data:
|
||||
layout = serializer.validated_data['layout']
|
||||
m.Layout.update_data(pk, layout)
|
||||
|
@ -630,13 +633,13 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchemaCached(item)
|
||||
operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
old_schema = operation.result
|
||||
layout = serializer.validated_data['layout']
|
||||
layout = [x for x in layout if x['nodeID'] != 'o' + str(operation.pk)]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss.delete_operation(operation.pk, serializer.validated_data['keep_constituents'])
|
||||
m.Layout.update_data(pk, layout)
|
||||
if old_schema is not None:
|
||||
|
@ -673,12 +676,12 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
oss = m.OperationSchemaCached(item)
|
||||
operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
layout = serializer.validated_data['layout']
|
||||
layout = [x for x in layout if x['nodeID'] != 'o' + str(operation.pk)]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
m.Layout.update_data(pk, layout)
|
||||
oss.delete_reference(operation, serializer.validated_data['keep_connections'])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
@ -708,7 +711,6 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
operation: m.Operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
if len(operation.getQ_arguments()) > 0:
|
||||
raise serializers.ValidationError({
|
||||
|
@ -718,10 +720,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
raise serializers.ValidationError({
|
||||
'target': msg.operationResultNotEmpty(operation.alias)
|
||||
})
|
||||
|
||||
oss = m.OperationSchema(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchema(item)
|
||||
m.Layout.update_data(pk, layout)
|
||||
schema = oss.create_input(operation)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
@ -769,9 +771,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
raise serializers.ValidationError({
|
||||
'input': msg.operationInputAlreadyConnected()
|
||||
})
|
||||
oss = m.OperationSchemaCached(item)
|
||||
old_schema = target_operation.result
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
if old_schema is not None:
|
||||
if old_schema.is_synced(item):
|
||||
old_schema.visible = True
|
||||
|
@ -805,7 +808,6 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
context={'oss': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
operation: m.Operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
if operation.operation_type != m.OperationType.SYNTHESIS:
|
||||
raise serializers.ValidationError({
|
||||
|
@ -815,10 +817,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
raise serializers.ValidationError({
|
||||
'target': msg.operationResultNotEmpty(operation.alias)
|
||||
})
|
||||
|
||||
oss = m.OperationSchemaCached(item)
|
||||
layout = serializer.validated_data['layout']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss.execute_operation(operation)
|
||||
m.Layout.update_data(pk, layout)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
@ -877,17 +879,17 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
''' Relocate constituents from one schema to another. '''
|
||||
serializer = s.RelocateConstituentsSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
data = serializer.validated_data
|
||||
oss = m.OperationSchemaCached(LibraryItem.objects.get(pk=data['oss']))
|
||||
source = RSFormCached(LibraryItem.objects.get(pk=data['source']))
|
||||
destination = RSFormCached(LibraryItem.objects.get(pk=data['destination']))
|
||||
ids = [cst.pk for cst in data['items']]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(LibraryItem.objects.get(pk=data['oss']))
|
||||
source = RSFormCached(LibraryItem.objects.get(pk=data['source']))
|
||||
destination = RSFormCached(LibraryItem.objects.get(pk=data['destination']))
|
||||
if data['move_down']:
|
||||
oss.relocate_down(source, destination, data['items'])
|
||||
m.PropagationFacade.before_delete_cst(source, data['items'])
|
||||
source.delete_cst(data['items'])
|
||||
oss.relocate_down(source, destination, ids)
|
||||
m.PropagationFacade.before_delete_cst(data['source'], ids)
|
||||
source.delete_cst(ids)
|
||||
else:
|
||||
new_items = oss.relocate_up(source, destination, data['items'])
|
||||
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.model.pk])
|
||||
|
|
|
@ -233,6 +233,17 @@ class RSForm:
|
|||
count_bot += 1
|
||||
Constituenta.objects.bulk_update(cst_list, ['order'])
|
||||
|
||||
def delete_cst(self, target: list[Constituenta]) -> None:
|
||||
''' Delete multiple constituents. '''
|
||||
ids = [cst.pk for cst in target]
|
||||
mapping = {cst.alias: DELETED_ALIAS for cst in target}
|
||||
Constituenta.objects.filter(pk__in=ids).delete()
|
||||
all_cst = Constituenta.objects.filter(schema=self.model).only(
|
||||
'alias', 'definition_formal', 'term_raw', 'definition_raw', 'order'
|
||||
).order_by('order')
|
||||
RSForm.apply_mapping(mapping, all_cst, change_aliases=False)
|
||||
RSForm.save_order(all_cst)
|
||||
|
||||
def reset_aliases(self) -> None:
|
||||
''' Recreate all aliases based on constituents order. '''
|
||||
bases = cast(dict[str, int], {})
|
||||
|
|
|
@ -153,12 +153,12 @@ class RSFormCached:
|
|||
return result
|
||||
|
||||
# pylint: disable=too-many-branches
|
||||
def update_cst(self, target: Constituenta, data: dict) -> dict:
|
||||
def update_cst(self, target: int, data: dict) -> dict:
|
||||
''' Update persistent attributes of a given constituenta. Return old values. '''
|
||||
self.cache.ensure_loaded_terms()
|
||||
cst = self.cache.by_id.get(target.pk)
|
||||
cst = self.cache.by_id.get(target)
|
||||
if cst is None:
|
||||
raise ValidationError(msg.constituentaNotInRSform(target.alias))
|
||||
raise ValidationError(msg.constituentaNotInRSform(str(target)))
|
||||
|
||||
old_data = {}
|
||||
term_changed = False
|
||||
|
@ -211,13 +211,14 @@ class RSFormCached:
|
|||
)
|
||||
return old_data
|
||||
|
||||
def delete_cst(self, target: Iterable[Constituenta]) -> None:
|
||||
def delete_cst(self, target: list[int]) -> None:
|
||||
''' Delete multiple constituents. '''
|
||||
mapping = {cst.alias: DELETED_ALIAS for cst in target}
|
||||
self.cache.ensure_loaded()
|
||||
self.cache.remove_multi(target)
|
||||
cst_list = [self.cache.by_id[cst_id] for cst_id in target]
|
||||
mapping = {cst.alias: DELETED_ALIAS for cst in cst_list}
|
||||
self.cache.remove_multi(cst_list)
|
||||
self.apply_mapping(mapping)
|
||||
Constituenta.objects.filter(pk__in=[cst.pk for cst in target]).delete()
|
||||
Constituenta.objects.filter(pk__in=target).delete()
|
||||
RSForm.save_order(self.cache.constituents)
|
||||
|
||||
def substitute(self, substitutions: list[tuple[Constituenta, Constituenta]]) -> None:
|
||||
|
|
|
@ -97,3 +97,23 @@ class TestRSForm(DBTester):
|
|||
x2.refresh_from_db()
|
||||
self.assertEqual(x1.order, 1)
|
||||
self.assertEqual(x2.order, 0)
|
||||
|
||||
def test_delete_cst(self):
|
||||
x1 = self.schema.insert_last('X1')
|
||||
x2 = self.schema.insert_last('X2')
|
||||
d1 = self.schema.insert_last(
|
||||
alias='D1',
|
||||
definition_formal='X1 = X2',
|
||||
definition_raw='@{X1|sing}',
|
||||
term_raw='@{X2|plur}'
|
||||
)
|
||||
|
||||
self.schema.delete_cst([x1])
|
||||
x2.refresh_from_db()
|
||||
d1.refresh_from_db()
|
||||
self.assertEqual(self.schema.constituentsQ().count(), 2)
|
||||
self.assertEqual(x2.order, 0)
|
||||
self.assertEqual(d1.order, 1)
|
||||
self.assertEqual(d1.definition_formal, 'DEL = X2')
|
||||
self.assertEqual(d1.definition_raw, '@{DEL|sing}')
|
||||
self.assertEqual(d1.term_raw, '@{X2|plur}')
|
||||
|
|
|
@ -118,7 +118,7 @@ class TestRSFormCached(DBTester):
|
|||
term_raw='@{X2|plur}'
|
||||
)
|
||||
|
||||
self.schema.delete_cst([x1])
|
||||
self.schema.delete_cst([x1.pk])
|
||||
x2.refresh_from_db()
|
||||
d1.refresh_from_db()
|
||||
self.assertEqual(self.schema.constituentsQ().count(), 2)
|
||||
|
|
|
@ -86,11 +86,13 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
insert_after = None
|
||||
else:
|
||||
insert_after = data['insert_after']
|
||||
schema = m.RSFormCached(item)
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSFormCached(item)
|
||||
new_cst = schema.create_cst(data, insert_after)
|
||||
PropagationFacade.after_create_cst(schema, [new_cst])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_201_CREATED,
|
||||
data={
|
||||
|
@ -117,11 +119,12 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
serializer = s.CstUpdateSerializer(data=request.data, partial=True, context={'schema': item})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
cst = cast(m.Constituenta, serializer.validated_data['target'])
|
||||
schema = m.RSFormCached(item)
|
||||
data = serializer.validated_data['item_data']
|
||||
|
||||
with transaction.atomic():
|
||||
old_data = schema.update_cst(cst, data)
|
||||
PropagationFacade.after_update_cst(schema, cst, data, old_data)
|
||||
schema = m.RSFormCached(item)
|
||||
old_data = schema.update_cst(cst.pk, data)
|
||||
PropagationFacade.after_update_cst(schema, cst.pk, data, old_data)
|
||||
if 'alias' in data and data['alias'] != cst.alias:
|
||||
cst.refresh_from_db()
|
||||
changed_type = 'cst_type' in data and cst.cst_type != data['cst_type']
|
||||
|
@ -131,9 +134,8 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
cst.cst_type = data['cst_type']
|
||||
cst.save()
|
||||
schema.apply_mapping(mapping=mapping, change_aliases=False)
|
||||
cst.refresh_from_db()
|
||||
if changed_type:
|
||||
PropagationFacade.after_change_cst_type(cst)
|
||||
PropagationFacade.after_change_cst_type(item.pk, cst.pk, cast(m.CstType, cst.cst_type))
|
||||
item.save(update_fields=['time_update'])
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
|
@ -202,8 +204,8 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
data={f'{cst.pk}': msg.constituentaNoStructure()}
|
||||
)
|
||||
|
||||
schema = m.RSFormCached(item)
|
||||
with transaction.atomic():
|
||||
schema = m.RSFormCached(item)
|
||||
new_cst = schema.produce_structure(cst, cst_parse)
|
||||
PropagationFacade.after_create_cst(schema, new_cst)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
@ -215,7 +217,6 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
}
|
||||
)
|
||||
|
||||
|
||||
@extend_schema(
|
||||
summary='execute substitutions',
|
||||
tags=['RSForm'],
|
||||
|
@ -236,9 +237,10 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
context={'schema': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
schema = m.RSForm(item)
|
||||
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSForm(item)
|
||||
for substitution in serializer.validated_data['substitutions']:
|
||||
original = cast(m.Constituenta, substitution['original'])
|
||||
replacement = cast(m.Constituenta, substitution['substitution'])
|
||||
|
@ -246,6 +248,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
PropagationFacade.before_substitute(item.pk, substitutions)
|
||||
schema.substitute(substitutions)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
|
@ -272,14 +275,16 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
cst_list: list[m.Constituenta] = serializer.validated_data['items']
|
||||
schema = m.RSFormCached(item)
|
||||
|
||||
with transaction.atomic():
|
||||
PropagationFacade.before_delete_cst(schema, cst_list)
|
||||
schema = m.RSForm(item)
|
||||
PropagationFacade.before_delete_cst(item.pk, [cst.pk for cst in cst_list])
|
||||
schema.delete_cst(cst_list)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(schema.model).data
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
|
@ -302,13 +307,15 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
context={'schema': item}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
schema = m.RSForm(item)
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSForm(item)
|
||||
schema.move_cst(
|
||||
target=serializer.validated_data['items'],
|
||||
destination=serializer.validated_data['move_to']
|
||||
)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
|
@ -328,10 +335,12 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
def reset_aliases(self, request: Request, pk) -> HttpResponse:
|
||||
''' Endpoint: Recreate all aliases based on order. '''
|
||||
item = self._get_item()
|
||||
schema = m.RSForm(item)
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSForm(item)
|
||||
schema.reset_aliases()
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
|
@ -351,9 +360,11 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
def restore_order(self, request: Request, pk) -> HttpResponse:
|
||||
''' Endpoint: Restore order based on types and Term graph. '''
|
||||
item = self._get_item()
|
||||
|
||||
with transaction.atomic():
|
||||
m.OrderManager(m.RSFormCached(item)).restore_order()
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
|
|
Loading…
Reference in New Issue
Block a user