F: Propagate operation changes to OSS
This commit is contained in:
parent
3032d90f32
commit
60eba81001
|
@ -95,14 +95,15 @@ class OperationSchema:
|
||||||
self.save(update_fields=['time_update'])
|
self.save(update_fields=['time_update'])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def delete_operation(self, target: Operation, keep_constituents: bool = False):
|
def delete_operation(self, target: int, keep_constituents: bool = False):
|
||||||
''' Delete operation. '''
|
''' Delete operation. '''
|
||||||
|
operation = self.cache.operation_by_id[target]
|
||||||
if not keep_constituents:
|
if not keep_constituents:
|
||||||
schema = self.cache.get_schema(target)
|
schema = self.cache.get_schema(operation)
|
||||||
if schema is not None:
|
if schema is not None:
|
||||||
self.before_delete_cst(schema.cache.constituents, schema)
|
self.before_delete_cst(schema, schema.cache.constituents)
|
||||||
self.cache.remove_operation(target.pk)
|
self.cache.remove_operation(target)
|
||||||
target.delete()
|
operation.delete()
|
||||||
self.save(update_fields=['time_update'])
|
self.save(update_fields=['time_update'])
|
||||||
|
|
||||||
def set_input(self, target: int, schema: Optional[LibraryItem]) -> None:
|
def set_input(self, target: int, schema: Optional[LibraryItem]) -> None:
|
||||||
|
@ -115,7 +116,7 @@ class OperationSchema:
|
||||||
|
|
||||||
if old_schema is not None:
|
if old_schema is not None:
|
||||||
if has_children:
|
if has_children:
|
||||||
self.before_delete_cst(old_schema.cache.constituents, old_schema)
|
self.before_delete_cst(old_schema, old_schema.cache.constituents)
|
||||||
self.cache.remove_schema(old_schema)
|
self.cache.remove_schema(old_schema)
|
||||||
|
|
||||||
operation.result = schema
|
operation.result = schema
|
||||||
|
@ -128,7 +129,7 @@ class OperationSchema:
|
||||||
|
|
||||||
if schema is not None and has_children:
|
if schema is not None and has_children:
|
||||||
rsform = RSForm(schema)
|
rsform = RSForm(schema)
|
||||||
self.after_create_cst(list(rsform.constituents()), rsform)
|
self.after_create_cst(rsform, list(rsform.constituents()))
|
||||||
self.save(update_fields=['time_update'])
|
self.save(update_fields=['time_update'])
|
||||||
|
|
||||||
def set_arguments(self, target: int, arguments: list[Operation]) -> None:
|
def set_arguments(self, target: int, arguments: list[Operation]) -> None:
|
||||||
|
@ -179,7 +180,7 @@ class OperationSchema:
|
||||||
if len(deleted) > 0:
|
if len(deleted) > 0:
|
||||||
if schema is not None:
|
if schema is not None:
|
||||||
for sub in deleted:
|
for sub in deleted:
|
||||||
self._undo_substitution(sub, schema)
|
self._undo_substitution(schema, sub)
|
||||||
else:
|
else:
|
||||||
for sub in deleted:
|
for sub in deleted:
|
||||||
self.cache.remove_substitution(sub)
|
self.cache.remove_substitution(sub)
|
||||||
|
@ -194,7 +195,7 @@ class OperationSchema:
|
||||||
substitution=sub_item['substitution']
|
substitution=sub_item['substitution']
|
||||||
)
|
)
|
||||||
added.append(new_sub)
|
added.append(new_sub)
|
||||||
self._process_added_substitutions(added, schema)
|
self._process_added_substitutions(schema, added)
|
||||||
|
|
||||||
if len(added) > 0 or len(deleted) > 0:
|
if len(added) > 0 or len(deleted) > 0:
|
||||||
self.save(update_fields=['time_update'])
|
self.save(update_fields=['time_update'])
|
||||||
|
@ -257,7 +258,7 @@ class OperationSchema:
|
||||||
self.save(update_fields=['time_update'])
|
self.save(update_fields=['time_update'])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def after_create_cst(self, cst_list: list[Constituenta], source: RSForm) -> None:
|
def after_create_cst(self, source: RSForm, cst_list: list[Constituenta]) -> None:
|
||||||
''' Trigger cascade resolutions when new constituent is created. '''
|
''' Trigger cascade resolutions when new constituent is created. '''
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
inserted_aliases = [cst.alias for cst in cst_list]
|
inserted_aliases = [cst.alias for cst in cst_list]
|
||||||
|
@ -271,15 +272,15 @@ class OperationSchema:
|
||||||
if cst is not None:
|
if cst is not None:
|
||||||
alias_mapping[alias] = cst
|
alias_mapping[alias] = cst
|
||||||
operation = self.cache.get_operation(source.model.pk)
|
operation = self.cache.get_operation(source.model.pk)
|
||||||
self._cascade_create_cst(cst_list, operation, alias_mapping)
|
self._cascade_inherit_cst(operation.pk, source, cst_list, alias_mapping)
|
||||||
|
|
||||||
def after_change_cst_type(self, target: Constituenta, source: RSForm) -> None:
|
def after_change_cst_type(self, source: RSForm, target: Constituenta) -> None:
|
||||||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
operation = self.cache.get_operation(source.model.pk)
|
operation = self.cache.get_operation(source.model.pk)
|
||||||
self._cascade_change_cst_type(target.pk, target.cst_type, operation.pk)
|
self._cascade_change_cst_type(operation.pk, target.pk, target.cst_type)
|
||||||
|
|
||||||
def after_update_cst(self, target: Constituenta, data: dict, old_data: dict, source: RSForm) -> None:
|
def after_update_cst(self, source: RSForm, target: Constituenta, data: dict, old_data: dict) -> None:
|
||||||
''' Trigger cascade resolutions when constituenta data is changed. '''
|
''' Trigger cascade resolutions when constituenta data is changed. '''
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
operation = self.cache.get_operation(source.model.pk)
|
operation = self.cache.get_operation(source.model.pk)
|
||||||
|
@ -290,20 +291,20 @@ class OperationSchema:
|
||||||
if cst is not None:
|
if cst is not None:
|
||||||
alias_mapping[alias] = cst
|
alias_mapping[alias] = cst
|
||||||
self._cascade_update_cst(
|
self._cascade_update_cst(
|
||||||
cst_id=target.pk,
|
|
||||||
operation=operation.pk,
|
operation=operation.pk,
|
||||||
|
cst_id=target.pk,
|
||||||
data=data,
|
data=data,
|
||||||
old_data=old_data,
|
old_data=old_data,
|
||||||
mapping=alias_mapping
|
mapping=alias_mapping
|
||||||
)
|
)
|
||||||
|
|
||||||
def before_delete_cst(self, target: list[Constituenta], source: RSForm) -> None:
|
def before_delete_cst(self, source: RSForm, target: list[Constituenta]) -> None:
|
||||||
''' Trigger cascade resolutions before constituents are deleted. '''
|
''' Trigger cascade resolutions before constituents are deleted. '''
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
operation = self.cache.get_operation(source.model.pk)
|
operation = self.cache.get_operation(source.model.pk)
|
||||||
self._cascade_before_delete(target, operation.pk)
|
self._cascade_delete_inherited(operation.pk, target)
|
||||||
|
|
||||||
def before_substitute(self, substitutions: CstSubstitution, source: RSForm) -> None:
|
def before_substitute(self, source: RSForm, substitutions: CstSubstitution) -> None:
|
||||||
''' Trigger cascade resolutions before constituents are substituted. '''
|
''' Trigger cascade resolutions before constituents are substituted. '''
|
||||||
self.cache.insert_schema(source)
|
self.cache.insert_schema(source)
|
||||||
operation = self.cache.get_operation(source.model.pk)
|
operation = self.cache.get_operation(source.model.pk)
|
||||||
|
@ -311,45 +312,73 @@ class OperationSchema:
|
||||||
|
|
||||||
def before_delete_arguments(self, target: Operation, arguments: list[Operation]) -> None:
|
def before_delete_arguments(self, target: Operation, arguments: list[Operation]) -> None:
|
||||||
''' Trigger cascade resolutions before arguments are deleted. '''
|
''' Trigger cascade resolutions before arguments are deleted. '''
|
||||||
pass
|
if target.result_id is None:
|
||||||
|
return
|
||||||
|
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)
|
||||||
|
|
||||||
def after_create_arguments(self, target: Operation, arguments: list[Operation]) -> None:
|
def after_create_arguments(self, target: Operation, arguments: list[Operation]) -> None:
|
||||||
''' Trigger cascade resolutions after arguments are created. '''
|
''' Trigger cascade resolutions after arguments are created. '''
|
||||||
schema = self.cache.get_schema(target)
|
schema = self.cache.get_schema(target)
|
||||||
if schema is None:
|
if schema is None:
|
||||||
return
|
return
|
||||||
|
for argument in arguments:
|
||||||
|
parent_schema = self.cache.get_schema(argument)
|
||||||
|
if parent_schema is None:
|
||||||
|
continue
|
||||||
|
self._execute_inherit_cst(
|
||||||
|
target_operation=target.pk,
|
||||||
|
source=parent_schema,
|
||||||
|
items=list(parent_schema.constituents()),
|
||||||
|
mapping={}
|
||||||
|
)
|
||||||
|
|
||||||
def _cascade_create_cst(self, cst_list: list[Constituenta], operation: Operation, mapping: CstMapping) -> None:
|
def _cascade_inherit_cst(
|
||||||
children = self.cache.graph.outputs[operation.pk]
|
self,
|
||||||
|
target_operation: int,
|
||||||
|
source: RSForm,
|
||||||
|
items: list[Constituenta],
|
||||||
|
mapping: CstMapping
|
||||||
|
) -> None:
|
||||||
|
children = self.cache.graph.outputs[target_operation]
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
return
|
return
|
||||||
source_schema = self.cache.get_schema(operation)
|
|
||||||
assert source_schema is not None
|
|
||||||
for child_id in children:
|
for child_id in children:
|
||||||
child_operation = self.cache.operation_by_id[child_id]
|
self._execute_inherit_cst(child_id, source, items, mapping)
|
||||||
child_schema = self.cache.get_schema(child_operation)
|
|
||||||
if child_schema is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# TODO: update substitutions for diamond synthesis (if needed)
|
def _execute_inherit_cst(
|
||||||
|
self,
|
||||||
|
target_operation: int,
|
||||||
|
source: RSForm,
|
||||||
|
items: list[Constituenta],
|
||||||
|
mapping: CstMapping
|
||||||
|
) -> None:
|
||||||
|
operation = self.cache.operation_by_id[target_operation]
|
||||||
|
destination = self.cache.get_schema(operation)
|
||||||
|
if destination is None:
|
||||||
|
return
|
||||||
|
|
||||||
self.cache.ensure_loaded()
|
# TODO: update substitutions for diamond synthesis (if needed)
|
||||||
new_mapping = self._transform_mapping(mapping, child_operation, child_schema)
|
|
||||||
alias_mapping = OperationSchema._produce_alias_mapping(new_mapping)
|
|
||||||
insert_where = self._determine_insert_position(cst_list[0], child_operation, source_schema, child_schema)
|
|
||||||
new_cst_list = child_schema.insert_copy(cst_list, insert_where, alias_mapping)
|
|
||||||
for index, cst in enumerate(new_cst_list):
|
|
||||||
new_inheritance = Inheritance.objects.create(
|
|
||||||
operation=child_operation,
|
|
||||||
child=cst,
|
|
||||||
parent=cst_list[index]
|
|
||||||
)
|
|
||||||
self.cache.insert_inheritance(new_inheritance)
|
|
||||||
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
|
||||||
self._cascade_create_cst(new_cst_list, child_operation, new_mapping)
|
|
||||||
|
|
||||||
def _cascade_change_cst_type(self, cst_id: int, ctype: CstType, operation: int) -> None:
|
self.cache.ensure_loaded()
|
||||||
children = self.cache.graph.outputs[operation]
|
new_mapping = self._transform_mapping(mapping, operation, destination)
|
||||||
|
alias_mapping = OperationSchema._produce_alias_mapping(new_mapping)
|
||||||
|
insert_where = self._determine_insert_position(items[0], operation, source, destination)
|
||||||
|
new_cst_list = destination.insert_copy(items, insert_where, alias_mapping)
|
||||||
|
for index, cst in enumerate(new_cst_list):
|
||||||
|
new_inheritance = Inheritance.objects.create(
|
||||||
|
operation=operation,
|
||||||
|
child=cst,
|
||||||
|
parent=items[index]
|
||||||
|
)
|
||||||
|
self.cache.insert_inheritance(new_inheritance)
|
||||||
|
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
||||||
|
self._cascade_inherit_cst(operation.pk, destination, new_cst_list, new_mapping)
|
||||||
|
|
||||||
|
def _cascade_change_cst_type(self, operation_id: int, cst_id: int, ctype: CstType) -> None:
|
||||||
|
children = self.cache.graph.outputs[operation_id]
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
return
|
return
|
||||||
self.cache.ensure_loaded()
|
self.cache.ensure_loaded()
|
||||||
|
@ -359,13 +388,16 @@ class OperationSchema:
|
||||||
if successor_id is None:
|
if successor_id is None:
|
||||||
continue
|
continue
|
||||||
child_schema = self.cache.get_schema(child_operation)
|
child_schema = self.cache.get_schema(child_operation)
|
||||||
if child_schema is not None and child_schema.change_cst_type(successor_id, ctype):
|
if child_schema is None:
|
||||||
self._cascade_change_cst_type(successor_id, ctype, child_id)
|
continue
|
||||||
|
if child_schema.change_cst_type(successor_id, ctype):
|
||||||
|
self._cascade_change_cst_type(child_id, successor_id, ctype)
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments
|
# pylint: disable=too-many-arguments
|
||||||
def _cascade_update_cst(
|
def _cascade_update_cst(
|
||||||
self,
|
self,
|
||||||
cst_id: int, operation: int,
|
operation: int,
|
||||||
|
cst_id: int,
|
||||||
data: dict, old_data: dict,
|
data: dict, old_data: dict,
|
||||||
mapping: CstMapping
|
mapping: CstMapping
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -393,30 +425,33 @@ class OperationSchema:
|
||||||
continue
|
continue
|
||||||
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
new_mapping = {alias_mapping[alias]: cst for alias, cst in new_mapping.items()}
|
||||||
self._cascade_update_cst(
|
self._cascade_update_cst(
|
||||||
cst_id=successor_id,
|
|
||||||
operation=child_id,
|
operation=child_id,
|
||||||
|
cst_id=successor_id,
|
||||||
data=new_data,
|
data=new_data,
|
||||||
old_data=new_old_data,
|
old_data=new_old_data,
|
||||||
mapping=new_mapping
|
mapping=new_mapping
|
||||||
)
|
)
|
||||||
|
|
||||||
def _cascade_before_delete(self, target: list[Constituenta], operation: int) -> None:
|
def _cascade_delete_inherited(self, operation: int, target: list[Constituenta]) -> None:
|
||||||
children = self.cache.graph.outputs[operation]
|
children = self.cache.graph.outputs[operation]
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
return
|
return
|
||||||
self.cache.ensure_loaded()
|
self.cache.ensure_loaded()
|
||||||
for child_id in children:
|
for child_id in children:
|
||||||
child_operation = self.cache.operation_by_id[child_id]
|
self._execute_delete_inherited(child_id, target)
|
||||||
child_schema = self.cache.get_schema(child_operation)
|
|
||||||
if child_schema is None:
|
def _execute_delete_inherited(self, operation_id: int, parent_cst: list[Constituenta]) -> None:
|
||||||
continue
|
operation = self.cache.operation_by_id[operation_id]
|
||||||
self._undo_substitutions_cst(target, child_operation, child_schema)
|
schema = self.cache.get_schema(operation)
|
||||||
child_target_ids = self.cache.get_inheritors_list([cst.pk for cst in target], child_id)
|
if schema is None:
|
||||||
child_target_cst = [child_schema.cache.by_id[cst_id] for cst_id in child_target_ids]
|
return
|
||||||
self._cascade_before_delete(child_target_cst, child_id)
|
self._undo_substitutions_cst(parent_cst, operation, schema)
|
||||||
if len(child_target_cst) > 0:
|
target_ids = self.cache.get_inheritors_list([cst.pk for cst in parent_cst], operation_id)
|
||||||
self.cache.remove_cst(child_target_ids, child_id)
|
target_cst = [schema.cache.by_id[cst_id] for cst_id in target_ids]
|
||||||
child_schema.delete_cst(child_target_cst)
|
self._cascade_delete_inherited(operation_id, target_cst)
|
||||||
|
if len(target_cst) > 0:
|
||||||
|
self.cache.remove_cst(operation_id, target_ids)
|
||||||
|
schema.delete_cst(target_cst)
|
||||||
|
|
||||||
def _cascade_before_substitute(self, substitutions: CstSubstitution, operation: Operation) -> None:
|
def _cascade_before_substitute(self, substitutions: CstSubstitution, operation: Operation) -> None:
|
||||||
children = self.cache.graph.outputs[operation.pk]
|
children = self.cache.graph.outputs[operation.pk]
|
||||||
|
@ -582,12 +617,12 @@ class OperationSchema:
|
||||||
if sub.original_id in target_ids or sub.substitution_id in target_ids:
|
if sub.original_id in target_ids or sub.substitution_id in target_ids:
|
||||||
to_process.append(sub)
|
to_process.append(sub)
|
||||||
for sub in to_process:
|
for sub in to_process:
|
||||||
self._undo_substitution(sub, schema, target_ids)
|
self._undo_substitution(schema, sub, target_ids)
|
||||||
|
|
||||||
def _undo_substitution(
|
def _undo_substitution(
|
||||||
self,
|
self,
|
||||||
target: Substitution,
|
|
||||||
schema: RSForm,
|
schema: RSForm,
|
||||||
|
target: Substitution,
|
||||||
ignore_parents: Optional[list[int]] = None
|
ignore_parents: Optional[list[int]] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
if ignore_parents is None:
|
if ignore_parents is None:
|
||||||
|
@ -608,7 +643,7 @@ class OperationSchema:
|
||||||
new_original: Optional[Constituenta] = None
|
new_original: Optional[Constituenta] = None
|
||||||
if original_cst.pk not in ignore_parents:
|
if original_cst.pk not in ignore_parents:
|
||||||
full_cst = Constituenta.objects.get(pk=original_cst.pk)
|
full_cst = Constituenta.objects.get(pk=original_cst.pk)
|
||||||
self.after_create_cst([full_cst], original_schema)
|
self.after_create_cst(original_schema, [full_cst])
|
||||||
new_original_id = self.cache.get_inheritor(original_cst.pk, operation_id)
|
new_original_id = self.cache.get_inheritor(original_cst.pk, operation_id)
|
||||||
assert new_original_id is not None
|
assert new_original_id is not None
|
||||||
new_original = schema.cache.by_id[new_original_id]
|
new_original = schema.cache.by_id[new_original_id]
|
||||||
|
@ -621,7 +656,7 @@ class OperationSchema:
|
||||||
mapping = {cast(str, substitution_inheritor.alias): new_original}
|
mapping = {cast(str, substitution_inheritor.alias): new_original}
|
||||||
self._cascade_partial_mapping(mapping, dependant, operation_id, schema)
|
self._cascade_partial_mapping(mapping, dependant, operation_id, schema)
|
||||||
|
|
||||||
def _process_added_substitutions(self, added: list[Substitution], schema: Optional[RSForm]) -> None:
|
def _process_added_substitutions(self, schema: Optional[RSForm], added: list[Substitution]) -> None:
|
||||||
if len(added) == 0:
|
if len(added) == 0:
|
||||||
return
|
return
|
||||||
if schema is None:
|
if schema is None:
|
||||||
|
@ -638,7 +673,7 @@ class OperationSchema:
|
||||||
original_cst = schema.cache.by_id[original_id]
|
original_cst = schema.cache.by_id[original_id]
|
||||||
substitution_cst = schema.cache.by_id[substitution_id]
|
substitution_cst = schema.cache.by_id[substitution_id]
|
||||||
cst_mapping.append((original_cst, substitution_cst))
|
cst_mapping.append((original_cst, substitution_cst))
|
||||||
self.before_substitute(cst_mapping, schema)
|
self.before_substitute(schema, cst_mapping)
|
||||||
schema.substitute(cst_mapping)
|
schema.substitute(cst_mapping)
|
||||||
for sub in added:
|
for sub in added:
|
||||||
self.cache.insert_substitution(sub)
|
self.cache.insert_substitution(sub)
|
||||||
|
@ -745,7 +780,7 @@ class OssCache:
|
||||||
''' Insert new substitution. '''
|
''' Insert new substitution. '''
|
||||||
self.substitutions[sub.operation_id].append(sub)
|
self.substitutions[sub.operation_id].append(sub)
|
||||||
|
|
||||||
def remove_cst(self, target: list[int], operation: int) -> None:
|
def remove_cst(self, operation: int, target: list[int]) -> None:
|
||||||
''' Remove constituents from operation. '''
|
''' Remove constituents from operation. '''
|
||||||
subs_to_delete = [
|
subs_to_delete = [
|
||||||
sub for sub in self.substitutions[operation]
|
sub for sub in self.substitutions[operation]
|
||||||
|
|
|
@ -14,39 +14,39 @@ class PropagationFacade:
|
||||||
''' Change propagation API. '''
|
''' Change propagation API. '''
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def after_create_cst(new_cst: list[Constituenta], source: RSForm) -> None:
|
def after_create_cst(source: RSForm, new_cst: list[Constituenta]) -> None:
|
||||||
''' Trigger cascade resolutions when new constituent is created. '''
|
''' Trigger cascade resolutions when new constituent is created. '''
|
||||||
hosts = _get_oss_hosts(source.model)
|
hosts = _get_oss_hosts(source.model)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
OperationSchema(host).after_create_cst(new_cst, source)
|
OperationSchema(host).after_create_cst(source, new_cst)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def after_change_cst_type(target: Constituenta, source: RSForm) -> None:
|
def after_change_cst_type(source: RSForm, target: Constituenta) -> None:
|
||||||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||||
hosts = _get_oss_hosts(source.model)
|
hosts = _get_oss_hosts(source.model)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
OperationSchema(host).after_change_cst_type(target, source)
|
OperationSchema(host).after_change_cst_type(source, target)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def after_update_cst(target: Constituenta, data: dict, old_data: dict, source: RSForm) -> None:
|
def after_update_cst(source: RSForm, target: Constituenta, data: dict, old_data: dict) -> None:
|
||||||
''' Trigger cascade resolutions when constituenta data is changed. '''
|
''' Trigger cascade resolutions when constituenta data is changed. '''
|
||||||
hosts = _get_oss_hosts(source.model)
|
hosts = _get_oss_hosts(source.model)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
OperationSchema(host).after_update_cst(target, data, old_data, source)
|
OperationSchema(host).after_update_cst(source, target, data, old_data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def before_delete_cst(target: list[Constituenta], source: RSForm) -> None:
|
def before_delete_cst(source: RSForm, target: list[Constituenta]) -> None:
|
||||||
''' Trigger cascade resolutions before constituents are deleted. '''
|
''' Trigger cascade resolutions before constituents are deleted. '''
|
||||||
hosts = _get_oss_hosts(source.model)
|
hosts = _get_oss_hosts(source.model)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
OperationSchema(host).before_delete_cst(target, source)
|
OperationSchema(host).before_delete_cst(source, target)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def before_substitute(substitutions: CstSubstitution, source: RSForm) -> None:
|
def before_substitute(source: RSForm, substitutions: CstSubstitution) -> None:
|
||||||
''' Trigger cascade resolutions before constituents are substituted. '''
|
''' Trigger cascade resolutions before constituents are substituted. '''
|
||||||
hosts = _get_oss_hosts(source.model)
|
hosts = _get_oss_hosts(source.model)
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
OperationSchema(host).before_substitute(substitutions, source)
|
OperationSchema(host).before_substitute(source, substitutions)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def before_delete_schema(item: LibraryItem) -> None:
|
def before_delete_schema(item: LibraryItem) -> None:
|
||||||
|
@ -58,4 +58,4 @@ class PropagationFacade:
|
||||||
return
|
return
|
||||||
|
|
||||||
schema = RSForm(item)
|
schema = RSForm(item)
|
||||||
PropagationFacade.before_delete_cst(list(schema.constituents()), schema)
|
PropagationFacade.before_delete_cst(schema, list(schema.constituents()))
|
||||||
|
|
|
@ -260,7 +260,6 @@ class TestChangeOperations(EndpointTester):
|
||||||
'comment': 'Comment mod'
|
'comment': 'Comment mod'
|
||||||
},
|
},
|
||||||
'positions': [],
|
'positions': [],
|
||||||
'arguments': [self.operation1.pk, self.operation2.pk],
|
|
||||||
'substitutions': [
|
'substitutions': [
|
||||||
{
|
{
|
||||||
'original': self.ks1X1.pk,
|
'original': self.ks1X1.pk,
|
||||||
|
@ -284,3 +283,41 @@ class TestChangeOperations(EndpointTester):
|
||||||
self.assertEqual(self.ks5.constituents().count(), 7)
|
self.assertEqual(self.ks5.constituents().count(), 7)
|
||||||
self.assertEqual(self.ks4D2.definition_formal, r'X1 D1 X3 S1 D1')
|
self.assertEqual(self.ks4D2.definition_formal, r'X1 D1 X3 S1 D1')
|
||||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 D2 X3 S1 D1 D2 D3')
|
self.assertEqual(self.ks5D4.definition_formal, r'X1 D2 X3 S1 D1 D2 D3')
|
||||||
|
|
||||||
|
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||||
|
def test_change_arguments(self):
|
||||||
|
data = {
|
||||||
|
'target': self.operation4.pk,
|
||||||
|
'item_data': {
|
||||||
|
'alias': 'Test4 mod',
|
||||||
|
'title': 'Test title mod',
|
||||||
|
'comment': 'Comment mod'
|
||||||
|
},
|
||||||
|
'positions': [],
|
||||||
|
'arguments': [self.operation1.pk],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.executeOK(data=data, item=self.owned_id)
|
||||||
|
self.ks4D2.refresh_from_db()
|
||||||
|
self.ks5D4.refresh_from_db()
|
||||||
|
subs1_2 = self.operation4.getSubstitutions()
|
||||||
|
self.assertEqual(subs1_2.count(), 0)
|
||||||
|
subs3_4 = self.operation5.getSubstitutions()
|
||||||
|
self.assertEqual(subs3_4.count(), 1)
|
||||||
|
self.assertEqual(self.ks4.constituents().count(), 4)
|
||||||
|
self.assertEqual(self.ks5.constituents().count(), 6)
|
||||||
|
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||||
|
self.assertEqual(self.ks5D4.definition_formal, r'X1 DEL DEL DEL D1 D2 D3')
|
||||||
|
|
||||||
|
data['arguments'] = [self.operation1.pk, self.operation2.pk]
|
||||||
|
self.executeOK(data=data, item=self.owned_id)
|
||||||
|
self.ks4D2.refresh_from_db()
|
||||||
|
self.ks5D4.refresh_from_db()
|
||||||
|
subs1_2 = self.operation4.getSubstitutions()
|
||||||
|
self.assertEqual(subs1_2.count(), 0)
|
||||||
|
subs3_4 = self.operation5.getSubstitutions()
|
||||||
|
self.assertEqual(subs3_4.count(), 1)
|
||||||
|
self.assertEqual(self.ks4.constituents().count(), 7)
|
||||||
|
self.assertEqual(self.ks5.constituents().count(), 9)
|
||||||
|
self.assertEqual(self.ks4D2.definition_formal, r'X1 DEL DEL DEL D1')
|
||||||
|
self.assertEqual(self.ks5D4.definition_formal, r'X1 DEL DEL DEL D1 D2 D3')
|
||||||
|
|
|
@ -165,7 +165,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
old_schema: Optional[LibraryItem] = operation.result
|
old_schema: Optional[LibraryItem] = operation.result
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
oss.update_positions(serializer.validated_data['positions'])
|
oss.update_positions(serializer.validated_data['positions'])
|
||||||
oss.delete_operation(operation, serializer.validated_data['keep_constituents'])
|
oss.delete_operation(operation.pk, serializer.validated_data['keep_constituents'])
|
||||||
if old_schema is not None:
|
if old_schema is not None:
|
||||||
if serializer.validated_data['delete_schema']:
|
if serializer.validated_data['delete_schema']:
|
||||||
m.PropagationFacade.before_delete_schema(old_schema)
|
m.PropagationFacade.before_delete_schema(old_schema)
|
||||||
|
|
|
@ -87,7 +87,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
schema = m.RSForm(self._get_item())
|
schema = m.RSForm(self._get_item())
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
new_cst = schema.create_cst(data, insert_after)
|
new_cst = schema.create_cst(data, insert_after)
|
||||||
PropagationFacade.after_create_cst([new_cst], schema)
|
PropagationFacade.after_create_cst(schema, [new_cst])
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_201_CREATED,
|
status=c.HTTP_201_CREATED,
|
||||||
data={
|
data={
|
||||||
|
@ -118,7 +118,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
data = serializer.validated_data['item_data']
|
data = serializer.validated_data['item_data']
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
old_data = schema.update_cst(cst, data)
|
old_data = schema.update_cst(cst, data)
|
||||||
PropagationFacade.after_update_cst(cst, data, old_data, schema)
|
PropagationFacade.after_update_cst(schema, cst, data, old_data)
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
data=s.CstSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data
|
data=s.CstSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data
|
||||||
|
@ -159,7 +159,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
new_cst = schema.produce_structure(cst, cst_parse)
|
new_cst = schema.produce_structure(cst, cst_parse)
|
||||||
PropagationFacade.after_create_cst(new_cst, schema)
|
PropagationFacade.after_create_cst(schema, new_cst)
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
data={
|
data={
|
||||||
|
@ -197,7 +197,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
schema.save()
|
schema.save()
|
||||||
cst.refresh_from_db()
|
cst.refresh_from_db()
|
||||||
if changed_type:
|
if changed_type:
|
||||||
PropagationFacade.after_change_cst_type(cst, schema)
|
PropagationFacade.after_change_cst_type(schema, cst)
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
data={
|
data={
|
||||||
|
@ -233,7 +233,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
original = cast(m.Constituenta, substitution['original'])
|
original = cast(m.Constituenta, substitution['original'])
|
||||||
replacement = cast(m.Constituenta, substitution['substitution'])
|
replacement = cast(m.Constituenta, substitution['substitution'])
|
||||||
substitutions.append((original, replacement))
|
substitutions.append((original, replacement))
|
||||||
PropagationFacade.before_substitute(substitutions, schema)
|
PropagationFacade.before_substitute(schema, substitutions)
|
||||||
schema.substitute(substitutions)
|
schema.substitute(substitutions)
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
|
@ -263,7 +263,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
cst_list: list[m.Constituenta] = serializer.validated_data['items']
|
cst_list: list[m.Constituenta] = serializer.validated_data['items']
|
||||||
schema = m.RSForm(model)
|
schema = m.RSForm(model)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
PropagationFacade.before_delete_cst(cst_list, schema)
|
PropagationFacade.before_delete_cst(schema, cst_list)
|
||||||
schema.delete_cst(cst_list)
|
schema.delete_cst(cst_list)
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
|
@ -581,7 +581,7 @@ def inline_synthesis(request: Request) -> HttpResponse:
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
new_items = receiver.insert_copy(items)
|
new_items = receiver.insert_copy(items)
|
||||||
PropagationFacade.after_create_cst(new_items, receiver)
|
PropagationFacade.after_create_cst(receiver, new_items)
|
||||||
|
|
||||||
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
|
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
|
||||||
for substitution in serializer.validated_data['substitutions']:
|
for substitution in serializer.validated_data['substitutions']:
|
||||||
|
@ -595,7 +595,7 @@ def inline_synthesis(request: Request) -> HttpResponse:
|
||||||
replacement = new_items[index]
|
replacement = new_items[index]
|
||||||
substitutions.append((original, replacement))
|
substitutions.append((original, replacement))
|
||||||
|
|
||||||
PropagationFacade.before_substitute(substitutions, receiver)
|
PropagationFacade.before_substitute(receiver, substitutions)
|
||||||
receiver.substitute(substitutions)
|
receiver.substitute(substitutions)
|
||||||
|
|
||||||
receiver.restore_order()
|
receiver.restore_order()
|
||||||
|
|
|
@ -67,8 +67,8 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
||||||
if (cache.loading || schemas.length !== schemasIDs.length) {
|
if (cache.loading || schemas.length !== schemasIDs.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSubstitutions(prev =>
|
setSubstitutions(() =>
|
||||||
prev.filter(sub => {
|
target.substitutions.filter(sub => {
|
||||||
const original = cache.getSchemaByCst(sub.original);
|
const original = cache.getSchemaByCst(sub.original);
|
||||||
if (!original || !schemasIDs.includes(original.id)) {
|
if (!original || !schemasIDs.includes(original.id)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,7 +80,7 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}, [schemasIDs, schemas, cache.loading]);
|
}, [schemasIDs, schemas, cache.loading, target.substitutions]);
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
const data: IOperationUpdateData = {
|
const data: IOperationUpdateData = {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user