OpenDMA REST client for Python
Please see OpenDMA API for Python for an introduction to OpenDMA and it's Python API.
Provides an OpenDMA Adaptor consuming the OpenDMA REST API.
Installation
This project is available on PyPI. You can simply install it with pip:
pip install opendma-remote
Usage
Import this module and use the connect function to establish an OdmaSession
with a REST-ful OpenDMA service:
import opendma.remote
session = opendma.remote.connect(endpoint="http://127.0.0.1:8080/opendma/",
username="user",
password="secret")
Example
Run the tutorial REST service docker container:
docker run -p 8080:8080 ghcr.io/opendma/tutorial-xmlrepo:0.8
It will provide the tutorial xml repository. Make sure that this service is available
by opening
http://localhost:8080/opendma
in a web browser.
Troubleshooting
If the GitHub Container Registry (ghcr.io) is blocked in your environment, you can use our mirror on Docker Hub:
docker run -p 8080:8080 opendma/tutorial-xmlrepo:latest
If the local port 8080 is already in use, you can map to a different port, e.g. 8090:
docker run -p 8090:8080 ghcr.io/opendma/tutorial-xmlrepo:latest
To run in deamon mode in the background:
docker run -d --name opendma-tutorial-xmlrepo -p 8080:8080 ghcr.io/opendma/tutorial-xmlrepo:latest
The following python application will establish a connection to this service and print out the entire repository:
from typing import Optional
from opendma.api import OdmaType, OdmaQName, OdmaId, OdmaObject, OdmaClass, OdmaPropertyInfo, OdmaFolder, OdmaAssociation, OdmaDocument, OdmaContentElement, OdmaDataContentElement, OdmaContent, OdmaVersionCollection, OdmaServiceException
import opendma.remote
def printClassTree(clazz: OdmaClass, indent: int = 0) -> None:
print(f"{' ' * indent}{clazz.get_qname()}")
aspects = clazz.get_aspects()
if aspects is not None:
for aspect in aspects:
print(f"{' ' * indent} @{aspect.get_qname()}")
subclasses = clazz.get_sub_classes()
if subclasses is not None:
for subclass in subclasses:
printClassTree(subclass, indent + 1)
def printObjectInfo(obj: OdmaObject, indent: int, include_props: bool, expand_special: bool):
print(f"{' ' * indent}{obj.get_id()} {obj.get_odma_class().get_qname()}")
if not include_props:
return
properties = obj.get_odma_class().get_properties()
indent = indent + 1
for propinfo in properties:
pi: OdmaPropertyInfo = propinfo
prop = obj.get_property(pi.get_qname())
type = prop.get_type()
value = prop.get_value()
if prop.is_multi_value():
if type == OdmaType.REFERENCE:
print(f"{' ' * indent}{pi.get_qname()}=")
for pos, item in enumerate(value):
id = item.get_id()
if '/' in str(id):
printObjectInfo(item, indent+1, True, False)
else:
print(f"{' ' * (indent+3)}* Object<{id}>")
else:
print(f"{' ' * indent}{pi.get_qname()}=")
for pos, item in enumerate(value):
print(f"{' ' * (indent+3)}[{pos}] {item}")
else:
if value == None:
print(f"{' ' * indent}{pi.get_qname()}=None")
else:
if type == OdmaType.REFERENCE:
if expand_special and (isinstance(value, OdmaVersionCollection) or isinstance(value, OdmaContentElement)):
print(f"{' ' * indent}{pi.get_qname()}=")
printObjectInfo(value, indent+1, True, False)
else:
print(f"{' ' * indent}{pi.get_qname()}=Object<{value.get_id()}>")
elif type == OdmaType.CONTENT:
cnt: OdmaContent = value
stream = cnt.get_stream()
data = stream.read(25)
hex_bytes = ' '.join(f'{b:02x}' for b in data)
print(f"{' ' * indent}{pi.get_qname()}= {cnt.get_size()} bytes; first 25 bytes: {hex_bytes}")
else:
print(f"{' ' * indent}{pi.get_qname()}={value}")
def printFolderTree(folder: OdmaFolder, indent: int = 0) -> None:
print(f"{' ' * indent}{folder.get_title()}")
associations = folder.get_associations()
if associations is not None:
for association in associations:
assoc: OdmaAssociation = association
print(f"{' ' * indent} -{assoc.get_name()}")
printObjectInfo(assoc.get_containable(), indent + 2, True, True)
subfolders = folder.get_sub_folders()
if subfolders is not None:
for subfolder in subfolders:
printFolderTree(subfolder, indent + 1)
def printRepo(endpoint: str, username: Optional[str] = None, password: Optional[str] = None, includeClassTree: bool = True, includeFolderTree: bool = True) -> None:
print(f"Trying to connect...")
session = opendma.remote.connect(endpoint=endpoint, username=username, password=password, requestTraceLevel = 0)
print(f"Connected.")
print(f"Repositories: {session.get_repository_ids()}")
repoId = session.get_repository_ids()[0]
print(f"Trying to get repository {repoId}...")
repo = session.get_repository(repoId)
print(f"Got repository.")
print(f" Id: {repo.get_id()}")
print(f" Display Name: {repo.get_display_name()}")
if includeClassTree:
print(f"")
print(f"Class tree:")
rootClass = repo.get_root_class()
printClassTree(rootClass)
if includeFolderTree:
print(f"")
print(f"Folder tree:")
rootFolder = repo.get_root_folder()
if rootFolder is None:
print(f"No root folder is in this repository")
else:
printFolderTree(rootFolder)
if __name__ == "__main__":
printRepo(endpoint="http://127.0.0.1:8080/opendma/")
Metadata
Release files for opendma-remote 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| opendma_remote-0.8.0.tar.gz | 11.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opendma_remote-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.1 kB
Release files / opendma_remote-0.8.0.tar.gz
| Download URL | opendma_remote-0.8.0.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
351008a5439792d43a18c37a6b5234fb363a2f80752970d81b8b4bf6567bf0ed
|
|
BLAKE2b-256 checksum How to use checksums |
c0d26786b209084785afa22e10e5503c2c9b5ff25c9e8d1a491f74ef11736103
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / opendma_remote-0.8.0-py3-none-any.whl
| Download URL | opendma_remote-0.8.0-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a19deeb744636c6f45c605691f594569e02f6f5fee0073f84fa30e4ed008129
|
|
BLAKE2b-256 checksum How to use checksums |
6841e3b85bc9ff532d922ce88ca1089fee611944f8694b8900a741d0d9eebf2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Security for opendma-remote 0.8.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.