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

Xml mdib #401

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open

Conversation

deichmab-draeger
Copy link
Member

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have updated the changelog accordingly.
  • I have added tests to cover my changes.

Copy link

codecov bot commented Nov 21, 2024

Codecov Report

Attention: Patch coverage is 91.12534% with 194 lines in your changes missing coverage. Please review.

Project coverage is 90.82%. Comparing base (463564c) to head (24d1c63).

Files with missing lines Patch % Lines
src/sdc11073/entity_mdib/entity_consumermdib.py 89.05% 44 Missing ⚠️
src/sdc11073/entity_mdib/entity_transactions.py 91.45% 34 Missing ⚠️
src/sdc11073/mdib/mdibbase.py 69.23% 28 Missing ⚠️
src/sdc11073/entity_mdib/entity_providermdib.py 92.36% 21 Missing ⚠️
src/sdc11073/roles/clockprovider.py 56.25% 14 Missing ⚠️
src/sdc11073/mdib/transactions.py 87.36% 12 Missing ⚠️
...rc/sdc11073/entity_mdib/entity_providermdibxtra.py 94.69% 7 Missing ⚠️
src/sdc11073/entity_mdib/entities.py 97.40% 6 Missing ⚠️
src/sdc11073/roles/alarmprovider.py 96.47% 6 Missing ⚠️
src/sdc11073/roles/audiopauseprovider.py 90.56% 5 Missing ⚠️
... and 9 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #401      +/-   ##
==========================================
- Coverage   90.84%   90.82%   -0.02%     
==========================================
  Files         116      125       +9     
  Lines       12963    14660    +1697     
==========================================
+ Hits        11776    13315    +1539     
- Misses       1187     1345     +158     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

src/sdc11073/entity_mdib/entities.py Show resolved Hide resolved
src/sdc11073/entity_mdib/entities.py Show resolved Hide resolved
f'State handle {state_handle} already exists in {self.__class__.__name__}, handle = {self.handle}')
cls = self._mdib.data_model.get_state_container_class(self.descriptor.STATE_QNAME)
state = cls(descriptor_container=self.descriptor)
state.Handle = state_handle or self.handle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handles should be unique. dont take the descriptor handle

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a context state in a SetContextState operation has Handle == DescriptorHandle, this tells the provider that it shall insert a new context state. The provider changes the Handle to something unique.
This code creates a context state that can directly be used as a new state for SetContextState.
Therefore I think the provided code is correct as it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but why does the entity need to know something about operations? shouldnt this just be a representation of data in the mdib?

source: ProviderInternalEntity | ProviderInternalMultiStateEntity,
mdib: EntityProviderMdib):
self._mdib = mdib
self.descriptor = copy.deepcopy(source.descriptor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of copy use xml_utils.copy... methods. check other occurences

Copy link
Member Author

@deichmab-draeger deichmab-draeger Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those copy methods only copy lxml nodes, not state/descriptor containers. I implemented a local copy method that creates a deep copy of the container, but without the node element.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use __copy__ or _deepcopy__ instead

src/sdc11073/entity_mdib/entity_consumermdib.py Outdated Show resolved Hide resolved
src/sdc11073/entity_mdib/entity_consumermdib.py Outdated Show resolved Hide resolved
src/sdc11073/entity_mdib/entity_consumermdib.py Outdated Show resolved Hide resolved
@leon1995 leon1995 self-requested a review December 2, 2024 15:54
@@ -168,11 +168,21 @@ suppress-none-returning = true # https://docs.astral.sh/ruff/settings/#suppress-
[tool.ruff.lint.flake8-comprehensions]
allow-dict-calls-with-keyword-arguments = true # https://docs.astral.sh/ruff/settings/#allow-dict-calls-with-keyword-arguments


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

xml_entity = self._mdib.internal_entities.get(self.handle)
if xml_entity is None:
raise ValueError('entity no longer exists in mdib')
if int(xml_entity.descriptor.get('DescriptorVersion', '0')) != self.descriptor.DescriptorVersion:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt this be < instead of !=? so you update only if there is a newer version?

source: ProviderInternalEntity | ProviderInternalMultiStateEntity,
mdib: EntityProviderMdib):
self._mdib = mdib
self.descriptor = copy.deepcopy(source.descriptor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use __copy__ or _deepcopy__ instead

f'State handle {state_handle} already exists in {self.__class__.__name__}, handle = {self.handle}')
cls = self._mdib.data_model.get_state_container_class(self.descriptor.STATE_QNAME)
state = cls(descriptor_container=self.descriptor)
state.Handle = state_handle or self.handle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but why does the entity need to know something about operations? shouldnt this just be a representation of data in the mdib?

return ProviderMultiStateEntity(self, mdib)


def _mk_copy(original: ContainerBase) -> ContainerBase:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typing should be

T = typing.TypeVar('T', bound=ContainerBase)
def _mk_copy(original: T) -> T:

if tmp_child_node.tag in add_before_q_names:
tmp_child_node.addprevious(child_node)
return
raise RuntimeError('this should not happen')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please provide a more meaningful error message

else:
self._delete_entity(entity, handles)
return handles
# Todo: update self._get_mdib_response_node
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open todo

xml_entity.states = state_nodes
elif len(state_nodes) != 1:
self.logger.error('update descriptor: Expect one state, got %d', len(state_nodes))
# Todo: what to do in this case? add entity without state?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open todo

new_internal_entity = self._mdib.entity_factory(descriptor_container, [])
if handle in self._mdib.descr_handle_version_lookup:
# This handle existed before. Use last descriptor version + 1
new_internal_entity.descriptor.DescriptorVersion = self._mdib.descr_handle_version_lookup[handle] + 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated whitespace

def __init__(self,
sdc_definitions: type[BaseDefinitions] | None = None,
log_prefix: str | None = None,
extra_functionality: type | None = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong type

@leon1995 leon1995 self-requested a review December 17, 2024 12:22
from sdc11073.loghelper import LoggerAdapter
from sdc11073.mdib.descriptorcontainers import AbstractDescriptorContainer
from sdc11073.mdib.entityprotocol import ProviderEntityGetterProtocol
from sdc11073.mdib.mdibbase import MdibVersionGroup
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import

cls = self._mdib.data_model.get_state_container_class(self.descriptor.STATE_QNAME)
state = cls(descriptor_container=self.descriptor)
state.Handle = state_handle or uuid.uuid4().hex
self.states[state.Handle] = state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

state should not be added directly, but rather when the provider accepts the state via a notification

self._mdib = mdib

def by_handle(self, handle: str) -> ConsumerEntityType | None:
"""Return entity with given handle."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be more specific about the handle you are talking about. write descriptor handle to avoid confusion. check other occurrences

self.parent_handle = parent_handle
self.source_mds = source_mds
self.node_type = node_type # name of descriptor type
self._descriptor = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of None set self._descriptor=descriptor

handle = source.descriptor.get('Handle')
self.descriptor: AbstractDescriptorContainer = cls(handle, parent_handle=source.parent_handle)
self.descriptor.update_from_node(source.descriptor)
self.descriptor.set_source_mds(source.source_mds)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source.source_mds can be None but self.descriptor.set_source_mds expects type str

old_state = self._mdib.context_states.handle.get_one(handle, allow_none=True)
if state_container is None:
# a deleted state : this cannot be communicated via notification.
# delete it internal_entity anf that is all
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo anf

@@ -129,30 +232,44 @@ def mk_context_state(self, descriptor_handle: str,
"""Create a new ContextStateContainer."""


class StateTransactionManagerProtocol(AbstractTransactionManagerProtocol):
"""Interface of a TransactionManager that modifies states (except context states)."""
class StateTransactionManagerProtocol(EntityStateTransactionManagerProtocol): # pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why pragma: no cover?

soap_client_pool.async_loop_subscr_mgr = thr
thr.start()
for _i in range(10):
if not thr.running:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of a bool you could use a threading.Event that is set if its running. Then you can use .wait to wait until its running so you dont need to do such an implementation

self._stop_worker.set()
self._worker_thread.join()

def _worker_thread_loop(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method can be reduced to

while not self._stop_worker.wait(timeout=self.WORKER_THREAD_INTERVAL):
    self._update_alert_system_state_current_alerts()

raise
sys.stderr.write(f'############### tearDown {self._testMethodName} done ##############\n')

def add_random_patient(self, count: int = 1) -> [ProviderMultiStateEntity, list]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tuple

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants