Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ dmypy.json
# SAMM
core/esmf-aspect-meta-model-python/esmf_aspect_meta_model_python/samm_aspect_meta_model/samm/
/core/esmf-aspect-meta-model-python/samm-cli/
/core/esmf-aspect-meta-model-python/tests/integration/java_models/resources/
85 changes: 29 additions & 56 deletions core/esmf-aspect-meta-model-python/README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
The Aspect Model Loader as part of the Python SDK provided by the [*Eclipse Semantic Modeling Framework*](
https://projects.eclipse.org/projects/dt.esmf).

<!-- TOC -->
* [An Aspect of the Meta Model](#an-aspect-of-the-meta-model)
* [Set Up SAMM Aspect Meta Model](#set-up-samm-aspect-meta-model)
* [Install poetry](#install-poetry)
* [Install project dependencies](#install-project-dependencies)
* [Download SAMM files](#download-samm-files)
* [Download SAMM release](#download-samm-release)
* [Download SAMM branch](#download-samm-branch)
* [Input data handler usage](#input-data-handler-usage)
* [Aspect Meta Model Loader usage](#aspect-meta-model-loader-usage)
* [Samm Units](#samm-units)
* [SAMM CLI wrapper class](#samm-cli-wrapper-class)
* [Scripts](#scripts)
* [Automation Tasks](#automation-tasks)
* [tox](#tox)
* [GitHub actions](#github-actions)
* [Check New Pull Request](#check-new-pull-request)
* [Build release](#build-release)
<!-- TOC -->

# An Aspect of the Meta Model

The `esmf-aspect-model-loader` package provides the Python implementation for the SAMM Aspect Meta Model, or SAMM.
Each Meta Model element and each Characteristic class is represented by an interface with a corresponding
implementation.

## Documentation

* Check the [developer documentation](https://eclipse-esmf.github.io)
* Check the SAMM [specification](https://eclipse-esmf.github.io/samm-specification/snapshot/index.html)
* Having issues with the ESMF SDK Python Aspect Model Loader? Open a [GitHub issue](https://github.com/eclipse-esmf/esmf-sdk-py-aspect-model-loader/issues).

## Set Up SAMM Aspect Meta Model

Before getting started to use the `esmf-aspect-model-loader` library you need to apply some set up actions:
Expand Down Expand Up @@ -85,55 +71,42 @@ poetry run download-samm-branch
```
Link to all branches: [SAMM Releases](https://github.com/eclipse-esmf/esmf-semantic-aspect-meta-model/branches)

## Input data handler usage

The InputHandler is a general-purpose class designed for loading input data into an RDF graph.
It easily accommodates different input sources such as local files (.ttl) or direct data strings containing
RDF formatted data.
## SAMM Aspect Model Graph usage

SAMM Aspect Model Graph is a class that allows you to load and interact with the Semantic Data Aspect Meta Model graph.
Below is an example of how to use SAMM Aspect Model Graph in your Python code:
```python
from esmf_aspect_meta_model_python.resolver.handler import InputHandler
from esmf_aspect_meta_model_python import SAMMGraph

# Instantiating the Handler
# The InputHandler requires a path or data string upon instantiation, which defines the source of RDF data
# local file
model_path = "path/to/local/file/AspectName.ttl"
handler = InputHandler(model_path)
graph, aspect_urn = handler.get_rdf_graph()
# Define the path to your Turtle file
model_path = "absolute/path/to/turtle.ttl"

# returns a tuple containing the RDF graph and the aspect URN derived from the provided data source
```
# Create an instance of SAMMGraph
samm_graph = SAMMGraph()

```python
from esmf_aspect_meta_model_python.resolver.handler import InputHandler
# Parse the Turtle file to load the graph
samm_graph.parse(model_path)

# Alternatively, if you have RDF data in a string format, you can directly pass it as follows:
rdf_data_string = "your RDF data string here"
handler = InputHandler(rdf_data_string)
graph, aspect_urn = handler.get_rdf_graph()
# Load the aspect model from the graph
aspect = samm_graph.load_aspect_model()
```

## Aspect Meta Model Loader usage

An Aspect of the Meta Model can be loaded as follows:
The `load_model_elements` method in the SAMMGraph class creates Python objects to represent all nodes from the Aspect
model graph. It retrieves all SAMM elements from the RDF graph and converts them into structured Python objects.
```python
from esmf_aspect_meta_model_python import AspectLoader
from esmf_aspect_meta_model_python.resolver.handler import InputHandler
from esmf_aspect_meta_model_python import SAMMGraph

# Define the path to your Turtle file
model_path = "absolute/path/to/turtle.ttl"
handler = InputHandler(model_path)
graph, aspect_urn = handler.get_rdf_graph()

loader = AspectLoader()
model_elements = loader.load_aspect_model(graph, aspect_urn)
aspect = model_elements[0]
# Create an instance of SAMMGraph
samm_graph = SAMMGraph()

# or you can provide an Aspect URN
# Parse the Turtle file to load the graph
samm_graph.parse(model_path)

loader = AspectLoader()
aspect_urn = "urn:samm:org.eclipse.esmf.samm:aspect.model:0.0.1#AspectName"
model_elements = loader.load_aspect_model("absolute/path/to/turtle.ttl", aspect_urn)
aspect = model_elements[0]
# Load all model elements from the graph
model_elements = samm_graph.load_model_elements()
```

## Samm Units
Expand Down Expand Up @@ -200,7 +173,7 @@ Provided scripts:
All scripts run like a poetry command. The poetry is available from the folder where [pyproject.toml](pyproject.toml)
is located.

# Automation Tasks
# Tests running
## tox

`tox` is used for the tests automation purpose. There are two environments with different purposes and tests can
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,5 @@
DefaultTrait,
DefaultUnit,
)
from .loader.aspect_loader import AspectLoader
from .loader.samm_graph import SAMMGraph
from .resolver.handler import InputHandler
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0

from abc import ABC, abstractmethod

from esmf_aspect_meta_model_python.base.base import Base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@
from .default_either import DefaultEither
from .default_event import DefaultEvent
from .default_operation import DefaultOperation
from .default_property import DefaultProperty
from .default_property import DefaultBlankProperty, DefaultProperty, DefaultPropertyWithExtends
from .default_quantity_kind import DefaultQuantityKind
from .default_unit import DefaultUnit
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class DefaultCollection(DefaultCharacteristic, Collection):
def __init__(
self,
meta_model_base_attributes: MetaModelBaseAttributes,
data_type: DataType,
data_type: Optional[DataType],
element_characteristic: Optional[Characteristic],
):
super().__init__(meta_model_base_attributes, data_type)
Expand All @@ -35,7 +35,7 @@ def __init__(

def _set_parent_element_on_child_element(self) -> None:
"""Set a parent element on child elements."""
if self._element_characteristic is not None:
if self._element_characteristic:
self._element_characteristic.append_parent_element(self)

@property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0
from typing import Optional

from esmf_aspect_meta_model_python.base.characteristics.characteristic import Characteristic
from esmf_aspect_meta_model_python.base.data_types.complex_type import ComplexType
Expand All @@ -21,8 +22,12 @@ class DefaultCharacteristic(BaseImpl, Characteristic):

SCALAR_ATTR_NAMES = BaseImpl.SCALAR_ATTR_NAMES + ["data_type"]

def __init__(self, meta_model_base_attributes: MetaModelBaseAttributes, data_type: DataType):
def __init__(self, meta_model_base_attributes: MetaModelBaseAttributes, data_type: Optional[DataType]):
if data_type is None:
raise ValueError("Attribute 'data_type' is required for Characteristic class.")

super().__init__(meta_model_base_attributes)

self._data_type = data_type

if isinstance(self._data_type, ComplexType):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ def __init__(
@property
def extending_elements(self) -> List[ComplexType]:
"""Extending elements."""
return [DefaultComplexType._instances[element_subject] for element_subject in self.__extending_elements]
extending_elements = []
for element_subject in self.__extending_elements:
element = DefaultComplexType._instances.get(element_subject)
if element:
extending_elements.append(element)

return extending_elements
Loading