diff --git a/bindings/python/dlite-collection-python.i b/bindings/python/dlite-collection-python.i index 2a28c9e55..debfbd26c 100644 --- a/bindings/python/dlite-collection-python.i +++ b/bindings/python/dlite-collection-python.i @@ -56,19 +56,24 @@ class Collection(Instance): to it. Likewise, the len() of a collection will return the number of instances. - Use the get_relations() method (or the convenience methods - get_subjects(), get_predicates() and get_objects()) to iterate + Use the `get_relations()` method (or the convenience methods + `get_subjects()`, `get_predicates()` and `get_objects()`) to iterate over relations. The number of relations is available via the `nrelations` property. - Relations are (s, p, o, d=None)-triples with an optional fourth field + Relations are `(s, p, o, d=None)`-triples with an optional fourth field `d`, specifying the datatype of the object. The datatype may have the following values: - - None: object is an IRI. - - Starts with '@': object is a language-tagged plain literal. - The language identifier follows the '@'-sign. - - Otherwise: object is a literal with datatype `d`. + - None: object is an IRI. + - Starts with '@': object is a language-tagged plain literal. + The language identifier follows the '@'-sign. e.g. `@en` + - Otherwise: object is a literal with datatype `d`. + + Arguments: + id: URI or UUID of the new instance. The default is to create a + collection with no URI and random (version 4) UUID. + """ def __new__(cls, id=None): """Creates an empty collection.""" diff --git a/bindings/python/dlite-entity-python.i b/bindings/python/dlite-entity-python.i index d8465c6a0..eceb23c9b 100644 --- a/bindings/python/dlite-entity-python.i +++ b/bindings/python/dlite-entity-python.i @@ -86,11 +86,11 @@ class Metadata(Instance): return inst # For convenience. Easier to use than self.properties["properties"] - props = property( - fget=lambda self: {p.name: p for p in self.properties["properties"]}, - doc="A dict mapping property name to the `Property` object for the " - "described metadata.", - ) + @property + def props(self): + """A dict mapping property name to the `Property` object for the + described metadata.""" + return {p.name: p for p in self.properties["properties"]} def getprop(self, name): """Returns the metadata property object with the given name.""" @@ -248,9 +248,24 @@ def get_instance( '' if self.unit is None else self.unit, '' if self.description is None else self.description) - type = property(get_type, doc='Type name.') - dtype = property(get_dtype, doc='Type number.') - shape = property(get_shape, set_shape, doc='Array of dimension indices.') + @property + def type(self): + """Type name.""" + return self.get_type() + + @property + def dtype(self): + """Type number.""" + return self.get_dtype() + + @property + def shape(self): + """Array of dimension indices.""" + return self.get_shape() + + @shape.setter + def shape(self, value): + return self.set_shape(value) # Too be removed... def _get_dims_depr(self): @@ -376,19 +391,38 @@ def get_instance( f'"{self.uri if self.uri else self.meta.uri}"' ) - meta = property(get_meta, doc="Reference to the metadata of this instance.") - dimensions = property( - lambda self: dict((d.name, int(v)) - for d, v in zip(self.meta['dimensions'], - self.get_dimensions())), - doc='Dictionary with dimensions name-value pairs.') - properties = property(lambda self: - {p.name: self[p.name] for p in self.meta['properties']}, - doc='Dictionary with property name-value pairs.') - is_data = property(_is_data, doc='Whether this is a data instance.') - is_meta = property(_is_meta, doc='Whether this is a metadata instance.') - is_metameta = property(_is_metameta, - doc='Whether this is a meta-metadata instance.') + @property + def meta(self): + """Reference to the metadata of this instance.""" + return self.get_meta() + + @property + def dimensions(self): + """Dictionary with dimensions name-value pairs.""" + return dict( + (d.name, int(v)) + for d, v in zip(self.meta['dimensions'], self.get_dimensions()) + ) + + @property + def properties(self): + """Dictionary with property name-value pairs.""" + return {p.name: self[p.name] for p in self.meta['properties']} + + @property + def is_data(self): + """Whether this is a data instance.""" + return self._is_data() + + @property + def is_meta(self): + """Whether this is a metadata instance.""" + return self._is_meta() + + @property + def is_metameta(self): + """Whether this is a meta-metadata instance.""" + return self._is_metameta() @classmethod def from_metaid(cls, metaid, dimensions, id=None): diff --git a/bindings/python/dlite-entity.i b/bindings/python/dlite-entity.i index f1d8e731c..a01b06d51 100644 --- a/bindings/python/dlite-entity.i +++ b/bindings/python/dlite-entity.i @@ -93,10 +93,23 @@ char** dlite_swig_istore_get_uuids() %} - /* --------- * Dimension * --------- */ +%feature("docstring", "\ +A dimension represented by its name and description. +Metadata can define a set of common dimensions for its properties that +are referred to by the shape of each property. + +Arguments: + name: Dimension name. + description: Dimension description. + +Attributes: + name: Dimension name. + description: Dimension description. + +") _DLiteDimension; %rename(Dimension) _DLiteDimension; struct _DLiteDimension { char *name; @@ -123,7 +136,31 @@ struct _DLiteDimension { * Property * -------- */ %feature("docstring", "\ -Creates a new property with the provided attributes. +Represents a property. +All metadata must have one or more properties that define the instances +of the metadata. + +Arguments: + name: Property name. + type: Property type. Ex: 'int', 'blob14', 'float64', 'ref'... + ref: Optional. URL to metadata. Only needed for `type='ref'`. + shape: Optional. Specifies the dimensionality of property. If `shape` + is not given, the property is a scalar (dimensionality zero). + It should be a sequence of dimension names. + unit: Optional. The unit for properties with a unit. The unit should + be a valid unit label defined by EMMO or a custom ontology. + description: Optional: A human description of the property. + +Attributes: + name: Property name. + size: Number of bytes needed to represent a single instance of `type` + in memory. + ref: Value of the `ref` argument. + ndims: Number of dimensions of the property. A scalar has `ndims=0`. + unit: The unit of the property. + description: Property description. + dims: Deprecated alias for shape. + ") _DLiteProperty; %rename(Property) _DLiteProperty; struct _DLiteProperty { @@ -193,18 +230,20 @@ struct _DLiteProperty { * Relation * -------- */ %feature("docstring", "\ -Relations in DLite corresponds to RDF-triples, but are internally 4 fields: - - s: subject - - p: predicate - - o: object - - d: datatype - -The datatype is the datatype for literal objects. It may have three forms: - - None: object is an IRI (rdfs:Resource). - - Starts with '@': object is a language-tagged plain literal - (rdf:langString). The language identifier follows the '@'-sign. - Ex: '@en' for english. - - Otherwise: object is a literal with datatype `d`. Ex: 'xsd:int'. +A DLite relation representing an RDF triple. + +Arguments: + s: Subject IRI. + p: Predicate IRI. + o: Either an IRI for non-literal objects or the literal value for + literal objects. + d: The datatype IRI for literal objects. It may have three forms: + + - None: object is an IRI (rdfs:Resource). + - Starts with '@': object is a language-tagged plain literal + (rdf:langString). The language identifier follows the '@'-sign. + Ex: '@en' for english. + - Otherwise: object is a literal with datatype `d`. Ex: 'xsd:int'. As an internal implementation detail, relations also have an `id` field. It may change in the future, so please don't rely on it. @@ -244,24 +283,26 @@ struct _Triple { * Instance * -------- */ %feature("docstring", "\ -Returns a new instance. - -Instance(metaid=None, dims=None, id=None, url=None, storage=None, driver=None, - location=None, options=None, dimensions=None, properties=None, - description=None) - - Is called from one of the following class methods defined in dlite.py: - - - from_metaid(cls, metaid, dimensions, id=None) - - from_url(cls, url, metaid=None) - - from_storage(cls, storage, id=None, metaid=None) - - from_location(cls, driver, location, options=None, id=None) - - from_json(cls, jsoninput, id=None, metaid=None) - - from_bson(cls, bsoninput) - - from_dict(cls, d, id=None, single=None, check_storages=True) - - create_metadata(cls, uri, dimensions, properties, description) - - For details, see the documentation for the class methods. +Represents a DLite instance. + +This is the most central class in DLite. It has a complex `__init__()` +method and is intended to be instantiated with one of the following class +methods: + +- from_metaid(cls, metaid, dimensions, id=None) +- from_url(cls, url, metaid=None) +- from_storage(cls, storage, id=None, metaid=None) +- from_location(cls, driver, location, options=None, id=None) +- from_json(cls, jsoninput, id=None, metaid=None) +- from_bson(cls, bsoninput) +- from_dict(cls, d, id=None, single=None, check_storages=True) +- create_metadata(cls, uri, dimensions, properties, description) + +For details, see the documentation of the individual class methods. + +Attributes: + uuid: The UUID of the instance. + uri: The URI of the instance. ") _DLiteInstance; %apply(int *IN_ARRAY1, int DIM1) {(int *dims, int ndims)}; diff --git a/bindings/python/dlite-misc-python.i b/bindings/python/dlite-misc-python.i index 544989b0c..5de269502 100644 --- a/bindings/python/dlite-misc-python.i +++ b/bindings/python/dlite-misc-python.i @@ -32,6 +32,9 @@ class errctl(): - "": Write errors to stderr (default). - "": Write errors to stdout. + Attributes: + filename: Filename to redirect errors to. + """ def __init__(self, hide=(), show=(), filename=""): allcodes = [-i for i in range(1, _dlite._get_number_of_errors())] @@ -79,6 +82,7 @@ class errctl(): silent = errctl(filename="None") +"""Context manager for a silent code block. Same as `errctl(filename="None")`.""" # A set for keeping track of already issued deprecation warnings _deprecation_warning_record = set() diff --git a/bindings/python/dlite-python.i b/bindings/python/dlite-python.i index f0fa88e32..38870a21c 100644 --- a/bindings/python/dlite-python.i +++ b/bindings/python/dlite-python.i @@ -1477,6 +1477,7 @@ def instance_cast(inst, newtype=None): # Deprecated exceptions class DLiteSearchError(_dlite.DLiteLookupError): + """Deprecated. Has been renamed to DLiteLookupError.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) deprecation_warning( diff --git a/bindings/python/python-protocol-plugins/file.py b/bindings/python/python-protocol-plugins/file.py index d8608591b..49005d903 100644 --- a/bindings/python/python-protocol-plugins/file.py +++ b/bindings/python/python-protocol-plugins/file.py @@ -17,6 +17,7 @@ def open(self, location, options=None): Arguments: location: A URL or path to a file or directory. options: Supported options: + - `mode`: Combination of "r" (read), "w" (write) or "a" (append) Defaults to "r" if `location` exists and "w" otherwise. This default avoids accidentially overwriting an existing diff --git a/bindings/python/python-protocol-plugins/sftp.py b/bindings/python/python-protocol-plugins/sftp.py index e7a9c1ceb..9f94f9a17 100644 --- a/bindings/python/python-protocol-plugins/sftp.py +++ b/bindings/python/python-protocol-plugins/sftp.py @@ -27,6 +27,7 @@ def open(self, location, options=None): qualified as `username:password@host:port`. In the latter case the port/username/password takes precedence over `options`. options: Supported options: + - `username`: User name. - `password`: Password. - `hostname`: Host name. @@ -47,14 +48,15 @@ def open(self, location, options=None): For compresison "bzip2"; 1 to 9 are valid. Example: - - # For key-based authorisation, you may get the `key_type` and - # `key_bytes` arguments as follows: - pkey = paramiko.Ed25519Key.from_private_key_file( - "/home/john/.ssh/id_ed25519" - ) - key_type = pkey.name - key_bytes = pkey.asbytes().hex() + Here is an example of how you can use a private ssh-key + + >>> # For key-based authorisation, you may get the `key_type` + >>> # and `key_bytes` arguments as follows: + >>> pkey = paramiko.Ed25519Key.from_private_key_file( + ... "/home/john/.ssh/id_ed25519" + ... ) + >>> key_type = pkey.name + >>> key_bytes = pkey.asbytes().hex() """ options = Options(options, "port=22;compression=lzma") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 9e5667cdd..5be55188b 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -16,9 +16,10 @@ set(SPHINX_INDEX_FILE "${SPHINX_HTML_DIR}/index.html") # Doxygen intput source directory set(DOXYGEN_INPUT_DIRS ${dlite_SOURCE_DIR}/src/utils + ${dlite_SOURCE_DIR}/src/utils/compat-src ${dlite_SOURCE_DIR}/src ${dlite_SOURCE_DIR}/src/pyembed - #${dlite_BINARY_DIR}/bindings/python/dlite + ${dlite_SOURCE_DIR}/src/tests/minunit ) string(REPLACE ";" " " DOXYGEN_INPUT "${DOXYGEN_INPUT_DIRS}") @@ -32,9 +33,10 @@ set(DOXYGEN_DOXYFILE_OUT "${BINARY_BUILD_DIR}/Doxyfile") set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_XML_DIR}/index.xml) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" - "${BINARY_BUILD_DIR}/conf.py" - @ONLY) + "${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" + "${BINARY_BUILD_DIR}/conf.py" + @ONLY +) file(COPY "${CMAKE_SOURCE_DIR}/LICENSE" @@ -47,24 +49,28 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/contributors_guide" "${CMAKE_CURRENT_SOURCE_DIR}/getting_started" "${CMAKE_CURRENT_SOURCE_DIR}/user_guide" - DESTINATION - "${BINARY_BUILD_DIR}" + DESTINATION "${BINARY_BUILD_DIR}" ) configure_file( - ${DOXYGEN_DOXYFILE_IN} - ${DOXYGEN_DOXYFILE_OUT} - @ONLY) + ${DOXYGEN_DOXYFILE_IN} + ${DOXYGEN_DOXYFILE_OUT} + @ONLY +) # Doxygen command -add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} - DEPENDS ${DLITE_PUBLIC_HEADERS} - COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} - MAIN_DEPENDENCY ${DOXYFILE_OUT} - WORKING_DIRECTORY ${BINARY_BUILD_DIR} - COMMENT "Generating docs" - VERBATIM) +add_custom_command( + OUTPUT ${DOXYGEN_INDEX_FILE} + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} + MAIN_DEPENDENCY ${DOXYGEN_DOXYFILE_OUT} + DEPENDS + ${DLITE_PUBLIC_HEADERS} + dlitepy + WORKING_DIRECTORY ${BINARY_BUILD_DIR} + COMMENT "Generating docs" + VERBATIM +) # Named constom target add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) @@ -73,15 +79,16 @@ add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) add_custom_command(OUTPUT ${SPHINX_INDEX_FILE} COMMAND ${SPHINX_EXECUTABLE} - -q -b html - -c "${BINARY_BUILD_DIR}" - -d "${SPHINX_CACHE_DIR}" - ${BINARY_BUILD_DIR} - "${SPHINX_HTML_DIR}" + -q -b html + -c "${BINARY_BUILD_DIR}" + -d "${SPHINX_CACHE_DIR}" + ${BINARY_BUILD_DIR} + "${SPHINX_HTML_DIR}" DEPENDS - ${DOXYGEN_INDEX_FILE} - ${BINARY_BUILD_DIR}/respirator.py + ${DOXYGEN_INDEX_FILE} + ${BINARY_BUILD_DIR}/respirator.py MAIN_DEPENDENCY ${BINARY_BUILD_DIR}/conf.py - COMMENT "Building HTML documentation with Sphinx") + COMMENT "Building HTML documentation with Sphinx" +) add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE}) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 0a9715e4a..a3da100e1 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -815,7 +815,8 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = @dlite_SOURCE_DIR@/src/tests \ + @dlite_SOURCE_DIR@/src/utils/jsmn.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -831,7 +832,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = */tests/* \ +EXCLUDE_PATTERNS = */tests/test_* \ */old/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names @@ -843,7 +844,10 @@ EXCLUDE_PATTERNS = */tests/* \ # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = _WDIR _wdirent __attribute__ + + + # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include diff --git a/doc/_static/datamodel.png b/doc/_static/datamodel.png new file mode 100644 index 000000000..d99ac5d9b Binary files /dev/null and b/doc/_static/datamodel.png differ diff --git a/doc/_static/storage-protocol.png b/doc/_static/storage-protocol.png new file mode 100644 index 000000000..56665519e Binary files /dev/null and b/doc/_static/storage-protocol.png differ diff --git a/doc/conf.py.in b/doc/conf.py.in index 8f7ef6bc4..75559a026 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -59,7 +59,7 @@ extensions = [ "sphinx.ext.napoleon", # API ref Google and NumPy style "sphinx.ext.viewcode", "sphinxcontrib.plantuml", # PlantUml - #"sphinx_toggleprompt", # Add button for show/hide example prompts + "sphinx_toggleprompt", # Add button for show/hide example prompts "sphinx_copybutton", # Copy button for codeblocks "sphinx_design", # Create panels in a grid layout or as drop-downs and more ] @@ -186,3 +186,15 @@ def autoapi_prepare_jinja_env(jinja_env: "Environment") -> None: jinja_env.filters["remove_plugin_path"] = lambda name: ".".join( name.split(".")[1:] ) if name.split(".")[0] in dlite_share_plugins else name + + + +def skip_dlite_dlite_members(app, what, name, obj, skip, options): + """Skip class and function whos names contains 'dlite.dlite.'.""" + if "dlite.dlite." in name: + return True + return None + + +def setup(sphinx): + sphinx.connect("autoapi-skip-member", skip_dlite_dlite_members) diff --git a/doc/getting_started/about.md b/doc/getting_started/about.md index e1a5a6e6b..e0531ca51 100644 --- a/doc/getting_started/about.md +++ b/doc/getting_started/about.md @@ -18,7 +18,7 @@ By default, DLite defines four levels of metadata; instance, metadata, metadata The basic metadata schema describes itself, so no further meta levels are needed. The core idea behind these levels is if two different systems describe their data models in terms of the basic metadata schema, they can easily be made semantically interoperable, while using different metadata schemas. -![The datamodel of DLite.](../../_static/datamodel.svg) +![The datamodel of DLite.](https://raw.githubusercontent.com/SINTEF/dlite/master/doc/_static/datamodel.svg) An alternative and more flexible way to enable interoperability is to use ontologies. DLite provides a specialised _Instance_ called _Collection_. @@ -46,5 +46,5 @@ See [](features.md) for a more detailed list. - Bindings to C, Python and Fortran. [SOFT]: https://www.sintef.no/en/publications/publication/1553408/ -[user guide]: ../../user_guide/concepts.md -[MIT license]: ../../../license.md +[user guide]: https://sintef.github.io/dlite/user_guide/index.html +[MIT license]: https://sintef.github.io/dlite/license.html diff --git a/doc/getting_started/build/build.md b/doc/getting_started/build/build.md index 0660e3675..9a42d2726 100644 --- a/doc/getting_started/build/build.md +++ b/doc/getting_started/build/build.md @@ -92,7 +92,7 @@ Using [Visual Studio Code] (VS Code) it is possible to do development on the sys 1. Download and install [Visual Studio Code]. 2. Install the extension **Remote Development**. -3. [Clone DLite](#installing-from-source) +3. [Clone DLite](#build-from-source) 4. Open the DLite folder with VS Code. 5. Start VS Code, run the _Remote-Containers: Open Folder in Container..._ command from the Command Palette (F1) or quick actions Status bar item. This will build the container and restart VS Code in it. @@ -120,7 +120,6 @@ Using [Visual Studio Code] (VS Code) it is possible to do development on the sys [Python]: https://www.python.org/ [NumPy]: https://pypi.org/project/numpy/ [SWIG]: https://www.swig.org/ -[virtualenvwrapper]: https://pypi.org/project/virtualenvwrapper/ [cppcheck]: http://cppcheck.sourceforge.net/ [Doxygen]: http://www.doxygen.org/ [Sphinx]: https://www.sphinx-doc.org/ diff --git a/doc/getting_started/tutorial.md b/doc/getting_started/tutorial.md index 4495c475a..138250e53 100644 --- a/doc/getting_started/tutorial.md +++ b/doc/getting_started/tutorial.md @@ -1,7 +1,11 @@ -# Tutorial +Tutorial +======== -## Introduction -This tutorial shows the steps for creating and instantiating a Dlite entity, and populate it with data. For this, we will use an example `csv` file containing data corresponding to time measurements from a solar panel. The example file has the following format: +Introduction +------------ +This tutorial shows the steps for creating and instantiating a Dlite entity, and populate it with data. +For this, we will use an example `csv` file containing data corresponding to time measurements from a solar panel. +The example file has the following format: | time | Impp [A] | Isc [A] | MPP [W] | Vmpp [V] | Voc [V] | @@ -11,14 +15,18 @@ This tutorial shows the steps for creating and instantiating a Dlite entity, and -## Writing a DLite Entity -Let us write an Entity representing our solar panel measurement. We start by creating a `json` file called `myEntity.json`. +Writing a DLite Entity +---------------------- +Let us write an Entity representing our solar panel measurement. +We start by creating a `json` file called `myEntity.json`. ### **Step 1**: Giving it a unique identifier -Firstly, we must provide a unique identifier for our Entity. There are several ways of doing this: +First, we must provide a unique identifier for our Entity. +There are several ways of doing this: #### **1. Uniform Resource Identifier (URI)** -We can create and assign a unique Uniform Resource Identifier (URI). A URI has the form **namespace/version/nameOfEntity**, and it can be either written directly in the json file: +We can create and assign a unique Uniform Resource Identifier (URI). +A URI has the form **namespace/version/nameOfEntity**, and it can be either written directly in the json file: ```json "uri": "http://www.ontotrans.eu/0.1/solarPanelMeasurement", @@ -32,27 +40,38 @@ or we can give the **namespace**, **version**, and **name** of our Entity as sep ``` #### **2. Universally Unique Identifier (UUID)** -Alternatively, we can generate and assign a universally unique identifier (UUID). In Python, this can be achieved by the use of the `dlite.get_uuid()` function or the [dlite-getuuid](https://github.com/SINTEF/dlite/blob/master/doc/user_guide/tools.md#dlite-getuuid) tool. +Alternatively, we can generate and assign a universally unique identifier (UUID). +In Python, this can be achieved by the use of the `dlite.get_uuid()` function or the [dlite-getuuid] tool. ```python -import uuid + >>> import uuid -# Generate a random UUID -entity_uuid = uuid.uuid4() + # Generate a random UUID + >>> entity_uuid = uuid.uuid4() + + >>> with open("myEntity.json", "w") as entity_file: + ... entity_file.write('"uuid": {}'.format(entity_uuid)) -with open("myEntity.json", "w") as entity_file: - entity_file.write('"uuid": {}'.format(entity_uuid)) ``` Our json file now contains the following: + ```json -"uuid": +"uuid": "" ``` + where `` is a unique identifier for our Entity. ### **Step 2**: Providing a link to the metadata -Let us assume that we have followed option 1 and provided a URI. The next step consists in adding a **meta** field that will link the Entity to its metadata. In DLite, all Entities are instances of the *EntitySchema*. The *EntitySchema* defines the structure of the Entity. In the **meta** field of our Entity, we need to provide the URI of the EntitySchema. For a schematic overview of the DLite data structures and further detail, see [Concepts section of the DLite User Guide](https://sintef.github.io/dlite/user_guide/concepts.html). We add this information to our json file in the following manner: +Let us assume that we have followed option 1 and provided a URI. +The next step consists in adding a **meta** field that will link the Entity to its metadata. +In DLite, all Entities are instances of the *EntitySchema*. +The *EntitySchema* defines the structure of the Entity. +In the **meta** field of our Entity, we need to provide the URI of the EntitySchema. +For a schematic overview of the DLite data structures and further detail, see [Concepts section of the DLite User Guide]. +We add this information to our json file in the following manner: + ```json "uri": "http://www.ontotrans.eu/0.1/solarPanelMeasurement", "meta": "http://onto-ns.com/meta/0.3/EntitySchema", @@ -63,7 +82,8 @@ The **meta** field actually defaults to `http://onto-ns.com/meta/0.3/EntitySchem ::: ### **Step 3**: Adding a human-understandable description -Next, we want to include a human-understandable description of what the Entity represents. In our example case, such a **description** field could be +Next, we want to include a human-understandable description of what the Entity represents. +In our example case, such a **description** field could be ```json "uri": "http://www.ontotrans.eu/0.1/solarPanelMeasurement", @@ -72,7 +92,10 @@ Next, we want to include a human-understandable description of what the Entity r ``` ### **Step 4**: Defining the dimensions -We continue by defining the dimensions for our Entity. Each dimension should have a **name** and a human-understandable **description**. In our example case, we only have one dimension since all the quantities we are interested in are measured with the same frequency (i.e., we have the same number of data points for all the measured quantities). Note that even though we only have one dimension, we need to give it in a list format. +We continue by defining the dimensions for our Entity. +Each dimension should have a **name** and a human-understandable **description**. +In our example case, we only have one dimension since all the quantities we are interested in are measured with the same frequency (i.e., we have the same number of data points for all the measured quantities). +Note that even though we only have one dimension, we need to give it in a list format. We will give our dimension the generic name "N", and describe it as the number of measurements: @@ -145,9 +168,13 @@ Inserting the properties displayed in the table above, our Entity is complete an Both dimensions and properties can also be provided as arrays using a `dict` with the name as key. This may look like ```json +{ "dimensions": [ - {"name": "N", "description": "Number of measurements."} - ] + { + "name": "N", + "description": "Number of measurements." + } + ], "properties": [ { "name": "t", @@ -163,90 +190,123 @@ Both dimensions and properties can also be provided as arrays using a `dict` wit "shape": ["N"], "description": "Maximum Power" }, - ... + { + "name": "impp", + "type": "float64", + "unit": "A", + "shape": ["N"], + "description": "Maximum power point current." + }, + { + "name": "isc", + "type": "float64", + "unit": "A", + "shape": ["N"], + "description": "Short circuit current." + }, + { + "name": "vmpp", + "type": "float64", + "unit": "V", + "shape": ["N"], + "description": "Maximum power point voltage." + }, + { + "name": "voc", + "type": "float64", + "unit": "V", + "shape": ["N"], + "description": "Open circuit voltage." + } ] +} ``` + DLite supports both syntaxes. ::: -## Loading an Entity with DLite +Loading an Entity with DLite +---------------------------- We will now load our Entity in Python. There are several ways of doing this. ### 1. Using the json storage plugin: + ```python -import dlite + >>> import dlite -SolarPanelEntity = dlite.Instance.from_location('json', 'myEntity.json') + >>> SolarPanelEntity = dlite.Instance.from_location('json', 'myEntity.json') ``` ### 2. Adding the file to `storage_path` -In this method, we append the `json` file to `storage_path` and then use the [get_instance()](https://sintef.github.io/dlite/autoapi/dlite/index.html?highlight=get_instance#dlite.get_instance) function to load the Entity using its URI. In Python, this may be done by +In this method, we append the `json` file to `storage_path` and then use the [get_instance()] function to load the Entity using its URI. +In Python, this may be done by ``` python -import dlite + >>> import dlite + + # Append the entity file path to the search path for storages + >>> dlite.storage_path.append('myEntity.json') -# Append the entity file path to the search path for storages -dlite.storage_path.append('myEntity.json') + # Load Entity using its uri + >>> SolarPanelEntity = dlite.get_instance("http://www.ontotrans.eu/0.1/solarPanelMeasurement") -# Load Entity using its uri -SolarPanelEntity = dlite.get_instance("http://www.ontotrans.eu/0.1/solarPanelMeasurement") ``` **Note:** The same approach applies if a UUID is used. -## Connect loaded entity to data - -Now that we have loaded our Entity, we can instantiate it, and populate with the data from the `csv` file mentioned in the introduction. Note that you may have to provide a full file path to the `read_csv()` function, depending on where you have stored your `csv` file. +Connect loaded entity to data +----------------------------- +Now that we have loaded our Entity, we can instantiate it, and populate with the data from the `csv` file mentioned in the introduction. +Note that you may have to provide a full file path to the `read_csv()` function, depending on where you have stored your `csv` file. ```python -import pandas as pd + >>> import pandas as pd -# Read csv file using pandas, store its contents in a pandas DataFrame -solar_panel_dataframe = pd.read_csv('data.csv', sep=',', header = 0) + # Read csv file using pandas, store its contents in a pandas DataFrame + >>> solar_panel_dataframe = pd.read_csv('data.csv', sep=',', header = 0) -# Instantiate an instance of the Entity that we loaded above -inst = SolarPanelEntity({"N": len(solar_panel_dataframe)}) + # Instantiate an instance of the Entity that we loaded above + >>> inst = SolarPanelEntity({"N": len(solar_panel_dataframe)}) -# Create a dicitionary that defines the mapping between property names and column headers -mapping = { - "t":"time", - "MPP":"MPP [W]", - "voc":"Voc [V]", - "vmpp":"Vmpp [V]", - "isc" :"Isc [A]", - "impp":"Impp [A]" + # Create a dicitionary that defines the mapping between property names and column headers + >>> mapping = { + ... "t": "time", + ... "MPP": "MPP [W]", + ... "voc": "Voc [V]", + ... "vmpp": "Vmpp [V]", + ... "isc" : "Isc [A]", + ... "impp": "Impp [A]", + ... } -} - -# Loop through the dictionary keys and populate the instance with data -for key in mapping: - inst[key] = solar_panel_dataframe[mapping[key]] + # Loop through the dictionary keys and populate the instance with data + >>> for key in mapping: + ... inst[key] = solar_panel_dataframe[mapping[key]] ``` -More examples of how to use DLite are available in the [examples](https://github.com/SINTEF/dlite/tree/master/examples) directory. - +More examples of how to use DLite are available in the [examples] directory. -## Working with physical quantities +Working with physical quantities +-------------------------------- As you can read in the previous sections, a property of a dlite entity can be -defined with a **unit** (a unit of measurement). The dlite.Instance object can -set (or get) their properties from (or to) physical quanities (the product of a -numerical value and a unit of measurement). The dlite library uses the physical -quantities defined and implemented by the Python package -[pint](https://pint.readthedocs.io/en/stable/getting/overview.html). +defined with a **unit** (a unit of measurement). +The dlite.Instance object can set (or get) their properties from (or to) physical quanities (the product of a numerical value and a unit of measurement). +The dlite library uses the physical quantities defined and implemented by the Python package [pint]. -> You must install pint if you want to to work with physical quantities, -> try to run the command ```pip install pint```, see the page -> [pint installation](https://pint.readthedocs.io/en/stable/getting/index.html#installation). +```{note} +You must install pint if you want to to work with physical quantities, +try to run the command `pip install pint`, see the page [pint installation]. +``` This section illustrates how to work with physical quantities when manipulating -the dlite **instance** objects. The code example will use the following data model: +the dlite **instance** objects. +The code example will use the following data model: ```yaml uri: http://onto-ns.com/meta/0.1/BodyMassIndex @@ -276,73 +336,103 @@ properties: description: Underweight, normal, or overweight. ``` -The code below will create one BodyMassIndex instance object (variable ```person```) and assign the properties of the ```person``` using physical quantities. You can use the method ```person.set_quantity``` to set a property with a quantity or you can use the shortcut ```person.q``` like shown below: +The code below will create one BodyMassIndex instance object (variable `person`) and assign the properties of the `person` using physical quantities. +You can use the method `person.set_quantity` to set a property with a quantity or you can use the shortcut `person.q` like shown below: ```python -BodyMassIndex = dlite.get_instance("http://onto-ns.com/meta/0.1/BodyMassIndex") -# create a BodyMassIndex instance -person = BodyMassIndex() -# assign the name of the person -person.name = "John Doe" -# assign the age of the person without a physical quantity -person.age = 5 -assert person.age == 5.0 -# assign the age of the person with a physical quantity -person.set_quantity("age", 3.0, "years") -assert person.age == 3.0 -person.q.age = (1461, "days") -assert person.age == 4.0 -# assign the height and the weight -person.q.height = "1.72m" -person.q.weight = "63kg" -assert person.height == 172.0 -assert person.weight == 63.0 -# compute the BMI -person.q.bmi = person.q.weight.to("kg") / person.q.height.to("m") ** 2 -assert np.round(person.get_quantity("bmi").magnitude) == 21.0 -# the following line will give the same result as the line above -person.q.bmi = person.q.weight / person.q.height ** 2 -# the following line will raise a TypeError exception, because the property -# "category" with the type "string" cannot be converted into a quantity. -category = person.q.category -# assign the category -person.category = "normal" -if person.bmi < 18.5: - person.category = = "underweight" -elif person.bmi >= 25.0: - person.category = "overweight" + >>> BodyMassIndex = dlite.get_instance("http://onto-ns.com/meta/0.1/BodyMassIndex") + + # create a BodyMassIndex instance + >>> person = BodyMassIndex() + + # assign the name of the person + >>> person.name = "John Doe" + + # assign the age of the person without a physical quantity + >>> person.age = 5 + >>> assert person.age == 5.0 + + # assign the age of the person with a physical quantity + >>> person.set_quantity("age", 3.0, "years") + >>> assert person.age == 3.0 + >>> person.q.age = (1461, "days") + >>> assert person.age == 4.0 + + # assign the height and the weight + >>> person.q.height = "1.72m" + >>> person.q.weight = "63kg" + >>> assert person.height == 172.0 + >>> assert person.weight == 63.0 + + # compute the BMI + >>> person.q.bmi = person.q.weight.to("kg") / person.q.height.to("m") ** 2 + >>> assert np.round(person.get_quantity("bmi").magnitude) == 21.0 + + # the following line will give the same result as the line above + >>> person.q.bmi = person.q.weight / person.q.height ** 2 + + # the following line will raise a TypeError exception, because the property + # "category" with the type "string" cannot be converted into a quantity. + >>> category = person.q.category + + # assign the category + >>> person.category = "normal" + >>> if person.bmi < 18.5: + ... person.category = = "underweight" + ... elif person.bmi >= 25.0: + ... person.category = "overweight" + ``` -> If you need in your program to use a specific units registry, use the function -> [pint.set_application_registry](https://pint.readthedocs.io/en/0.10.1/tutorial.html#using-pint-in-your-projects) +```note +If you need in your program to use a specific units registry, use the function +[`pint.set_application_registry()`] +``` -The Python property ```q``` of the dlite.Instance objects as some other methods: +The Python property `q` of the dlite.Instance objects as some other methods: ```python -assert person.q.names() == ["age", "height", "weight", "bmi"] -assert person.q.units() == ["year", "cm", "kg", "kg/m^2"] -for name, quantity in persion.q.items(): - quantity.defaut_format = "~" # format the unit with a compact format - print(f"{name} = {quantity}") + >>> assert person.q.names() == ["age", "height", "weight", "bmi"] + >>> assert person.q.units() == ["year", "cm", "kg", "kg/m^2"] + >>> for name, quantity in persion.q.items(): + ... quantity.defaut_format = "~" # format the unit with a compact format + ... print(f"{name} = {quantity}") + ``` -> see [quantity formatting](https://pint.readthedocs.io/en/stable/user/formatting.html) +See [quantity formatting]. -You should not keep the Python property ```q``` as a local variable, it will result with wrong assigment if you work with several instances. +You should not keep the Python property `q` as a local variable, it will result with wrong assignment if you work with several instances. ```python -# >>> don't do that -p1 = person1.q -p2 = person2.q -# this will assign the weight to person2, and not to person1 -p1.weight = "34kg" -# <<< -# you must write this code -person1.q.weight = "34kg" -person2.q.weight = "32kg" -# for more complex formula, you can get the quantities in local variables -w1, h1 = person1.q.get("weight", "height") -w2, h2, a2 = person2.q.get("weight", "height", "age") + # Don't do this! + >>> p1 = person1.q + >>> p2 = person2.q + # this will assign the weight to person2, and not to person1 + >>> p1.weight = "34kg" + + # Instead, you should write the code like this + >>> person1.q.weight = "34kg" + >>> person2.q.weight = "32kg" + + # For more complex formulas, you can assign the quantities to local variables + >>> w1, h1 = person1.q.get("weight", "height") + >>> w2, h2, a2 = person2.q.get("weight", "height", "age") + ``` -The first line of the code above prepare the [singleton](https://www.geeksforgeeks.org/singleton-pattern-in-python-a-complete-guide/) dlite.quantity.QuantityHelper for the person1 and return the singleton. The second line do the same as the first line, so the variable ```p2``` is the singleton and is prepared to work on ```person2```. \ No newline at end of file +The first line of the code above prepare the [singleton] `dlite.quantity.QuantityHelper` for the person1 and return the singleton. +The second line do the same as the first line, so the variable `p2` is the singleton and is prepared to work on `person2`. + + + +[dlite-getuuid]: https://github.com/SINTEF/dlite/blob/master/doc/user_guide/tools.md#dlite-getuuid +[Concepts section of the DLite User Guide]: https://sintef.github.io/dlite/user_guide/concepts.html +[get_instance()]: https://sintef.github.io/dlite/autoapi/dlite/index.html?highlight=get_instance#dlite.get_instance + +[examples]: https://github.com/SINTEF/dlite/tree/master/examples +[pint]: https://pint.readthedocs.io/en/stable/getting/overview.html +[singleton]: https://www.geeksforgeeks.org/singleton-pattern-in-python-a-complete-guide/ +[quantity formatting]: https://pint.readthedocs.io/en/stable/user/formatting.html +[`pint.set_application_registry()`]: https://pint.readthedocs.io/en/0.10.1/tutorial.html#using-pint-in-your-projects +[pint installation]: https://pint.readthedocs.io/en/stable/getting/index.html#installation diff --git a/doc/user_guide/datamodels.md b/doc/user_guide/datamodels.md index 76c2c455e..84899adef 100644 --- a/doc/user_guide/datamodels.md +++ b/doc/user_guide/datamodels.md @@ -1,14 +1,14 @@ Representing a datamodel (entity) ----------------------------------- +================================= The underlying structure of DLite datamodels are described under [concepts]. Here, at set of rules on how to create a datamodel is presented. Note that several other possibilities are avilable, and this can be seen in the -examples and tests present in the repository. +examples and tests present in the repository. -We choose here to present only one method as mixing reprentation methods might +We choose here to present only one method as mixing reprentation methods might be confusing. Note, however that yaml and json representations are interchangable. A generic example with some comments for clarity can be seen below. @@ -31,8 +31,8 @@ The keywords in the datamodel have the following meaning: * `uri`: A URI that uniquely identifies the datamodel. * `description`: A human description that describes what this datamodel represents. * `dimensions`: Dimensions of the properties (referred to by the property shape). Properties can have the same dimensions, but not necessarily. Each dimension is described by: - - name of the dimension - - a human description of the dimension + - name of the dimension + - a human description of the dimension In the below example there is one dimension with name "N" and description "Number of skills." * `properties`: Sub-parts of the datamodel that describe the individual data fields. A property has a name and is further specified by the following keywords: - `description`: Human description of the property. @@ -48,7 +48,7 @@ A slightly more realistic example is the "Person" entity, where we want to descr ```yaml uri: http://onto-ns.com/meta/0.1/Person description: A person. -dimensions: +dimensions: N: Number of skills. properties: name: @@ -66,7 +66,7 @@ properties: dlite-validate -============== +-------------- The [dlite-validate tool][./tools.md#dlite_validate] can be used to check if a specific representation (in a file) is a valid DLite datamodel diff --git a/doc/user_guide/protocol_plugins.md b/doc/user_guide/protocol_plugins.md index c930a6ec6..f0eeab382 100644 --- a/doc/user_guide/protocol_plugins.md +++ b/doc/user_guide/protocol_plugins.md @@ -3,7 +3,7 @@ Protocol plugins Protocol plugins is a new feature of DLite that allow a clear separation between serialising/parsing DLite instances to/from external data representations and transferring data to/from external data resources. This is illustrated in the Figure below. -![DLite storage and protocol plugins.](../../_static/storage-protocol.svg) +![DLite storage and protocol plugins.](https://raw.githubusercontent.com/SINTEF/dlite/master/doc/_static/storage-protocol.svg) It allows to mix and match different protocol and storage plugins, thereby reducing the total number of plugins that has to be implemented. diff --git a/doc/user_guide/storage_plugins.md b/doc/user_guide/storage_plugins.md index eb422c72f..ac934a17a 100644 --- a/doc/user_guide/storage_plugins.md +++ b/doc/user_guide/storage_plugins.md @@ -4,10 +4,11 @@ Storage plugins / Drivers Content ------- 1. [Introduction](#introduction) - 2. [Working with storages in Python](#working-with-storages-in-python) - 3. [Using storages implicitely](#using-storages-implicitly) - 4. [Writing Python storage plugins](#writing-python-storage-plugins) - 5. [Working with storages from C and Fortran](#working-with-storages-from-c-and-fortran) + 2. [How to make storage plugins available](#how-to-make-storage-plugins-available) + 3. [Using storages implicitely from Python](#using-storages-implicitly-from-python) + 4. [Working with storages in Python](#working-with-storages-in-python) + 5. [Writing Python storage plugins](#writing-python-storage-plugins) + 6. [Working with storages from C and Fortran](#working-with-storages-from-c-and-fortran) Introduction @@ -30,7 +31,6 @@ Storage plugins can be written in either C or Python. How to make storage plugins available ------------------------------------- - As described below it is possible (and most often advisable) to create specific drivers (storage plugins) for your data. Additional storage plugins drivers can be made available by setting the environment variables `DLITE_STORAGE_PLUGIN_DIRS` or `DLITE_PYTHON_STORAGE_PLUGIN_DIRS` e.g.: diff --git a/src/pyembed/dlite-python-storage.h b/src/pyembed/dlite-python-storage.h index 168e66096..83b783b0b 100644 --- a/src/pyembed/dlite-python-storage.h +++ b/src/pyembed/dlite-python-storage.h @@ -67,12 +67,4 @@ void *dlite_python_storage_load(void); void dlite_python_storage_unload(void); -/** - Returns the base class for storage plugins. -*/ -#ifndef NOPYTHON -PyObject *dlite_python_storage_base(void); -#endif - - #endif /* _DLITE_PYTHON_STORAGE_H */ diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 6366940e7..ec94fe8a2 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -290,7 +290,7 @@ if(NOT (HAVE_SNPRINTF OR HAVE__SNPRINTF) OR NOT (HAVE_ASPRINTF OR HAVE__ASPRINTF) OR NOT (HAVE_VASPRINTF OR HAVE__VASPRINTF)) set(WITH_SNPRINTF 1) - configure_file(compat/config_snprintf.h.in config_snprintf.h) + configure_file(compat-src/config_snprintf.h.in config_snprintf.h) endif() @@ -329,14 +329,14 @@ set(sources uuid4.c ) if(NOT HAVE_GETOPT) - list(APPEND sources compat/getopt.c) + list(APPEND sources compat-src/getopt.c) endif() if(WITH_SNPRINTF) - list(APPEND sources compat/snprintf.c) + list(APPEND sources compat-src/snprintf.c) add_definitions(-DHAVE_CONFIG_SNPRINTF_H) endif() if(NOT HAVE_REALPATH AND UNIX) - list(APPEND sources compat/realpath.c) + list(APPEND sources compat-src/realpath.c) endif() add_definitions( @@ -417,8 +417,8 @@ install( install( FILES - compat/dirent.h - compat/getopt.h + compat-src/dirent.h + compat-src/getopt.h DESTINATION include/dlite/utils/compat ) diff --git a/src/utils/LICENSES.txt b/src/utils/LICENSES.txt index 3c45e3dcd..86d46e4ad 100644 --- a/src/utils/LICENSES.txt +++ b/src/utils/LICENSES.txt @@ -91,8 +91,8 @@ Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd . -License for compat/realpath.c ------------------------------ +License for compat-src/realpath.c +--------------------------------- Copyright (c) 2003 Constantin S. Svintsoff Redistribution and use in source and binary forms, with or without @@ -120,8 +120,8 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Lisense for compat/snprintf.c ------------------------------ +Lisense for compat-src/snprintf.c +--------------------------------- Copyright (c) 1995 Patrick Powell. This code is based on code written by Patrick Powell . diff --git a/src/utils/README.md b/src/utils/README.md index 4f496851a..bf864cd37 100644 --- a/src/utils/README.md +++ b/src/utils/README.md @@ -9,7 +9,7 @@ in the list below. Content of this library: -- compat/ -- subdir with compatibility implementations for non-POSIX systems +- compat-src/ -- subdir with compatibility implementations for non-POSIX systems - license: varies, MIT-compatible - declared in: config.h - depends on: config.h generated by cmake diff --git a/src/utils/compat/config_snprintf.h.in b/src/utils/compat-src/config_snprintf.h.in similarity index 100% rename from src/utils/compat/config_snprintf.h.in rename to src/utils/compat-src/config_snprintf.h.in diff --git a/src/utils/compat/dirent.h b/src/utils/compat-src/dirent.h similarity index 99% rename from src/utils/compat/dirent.h rename to src/utils/compat-src/dirent.h index 51c79ecfa..67e3e3f80 100644 --- a/src/utils/compat/dirent.h +++ b/src/utils/compat-src/dirent.h @@ -1231,4 +1231,4 @@ dirent_set_errno( #ifdef __cplusplus } #endif -#endif /*DIRENT_H*/ +#endif /* DIRENT_H */ diff --git a/src/utils/compat/getopt.c b/src/utils/compat-src/getopt.c similarity index 100% rename from src/utils/compat/getopt.c rename to src/utils/compat-src/getopt.c diff --git a/src/utils/compat/getopt.h b/src/utils/compat-src/getopt.h similarity index 100% rename from src/utils/compat/getopt.h rename to src/utils/compat-src/getopt.h diff --git a/src/utils/compat/realpath.c b/src/utils/compat-src/realpath.c similarity index 100% rename from src/utils/compat/realpath.c rename to src/utils/compat-src/realpath.c diff --git a/src/utils/compat/snprintf.c b/src/utils/compat-src/snprintf.c similarity index 100% rename from src/utils/compat/snprintf.c rename to src/utils/compat-src/snprintf.c diff --git a/src/utils/compat.h b/src/utils/compat.h index 1cdc4af54..509af0221 100644 --- a/src/utils/compat.h +++ b/src/utils/compat.h @@ -4,16 +4,16 @@ * * Distributed under terms of the MIT license. */ +#ifndef _COMPAT_H +#define _COMPAT_H /** @file @brief auxiliary compatibility functions - Note that the declarations for the functions found in the compat/ + Note that the declarations for the functions found in the compat-src/ subdirectory are provided in config.h.in. */ -#ifndef _COMPAT_H -#define _COMPAT_H #include #ifdef WIN32 @@ -36,7 +36,7 @@ #endif /* - * compat/setenv.c + * compat-src/setenv.c */ /** setenv() - change or add an environment variable */ @@ -56,7 +56,7 @@ char *realpath(const char *path, char *resolved); /* - * compat/snprintf.c + * compat-src/snprintf.c */ /** snprintf() - write formatted output to sized buffer */ diff --git a/src/utils/config.h.in b/src/utils/config.h.in index a7b4e65ad..b64d04949 100644 --- a/src/utils/config.h.in +++ b/src/utils/config.h.in @@ -39,7 +39,7 @@ #cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_IO_H -/* Whether symbols exists. If not, they are defined in compat.c or compat/ */ +/* Whether symbols exists. If not, they are defined in compat.c or compat-src/ */ #cmakedefine HAVE_STRDUP #cmakedefine HAVE__STRDUP #cmakedefine HAVE_STRNDUP diff --git a/src/utils/fileutils.h b/src/utils/fileutils.h index 74b9c35ce..817385cde 100644 --- a/src/utils/fileutils.h +++ b/src/utils/fileutils.h @@ -40,7 +40,7 @@ enum { # ifndef WINDOWS # define WINDOWS # endif -# include "compat/dirent.h" +# include "compat-src/dirent.h" # ifndef PATHSEP # define PATHSEP ";" # endif diff --git a/storages/python/python-storage-plugins/http.py b/storages/python/python-storage-plugins/http.py index 7e7f42c35..730cb091f 100644 --- a/storages/python/python-storage-plugins/http.py +++ b/storages/python/python-storage-plugins/http.py @@ -22,9 +22,11 @@ def open(self, location, options=None): Arguments: location: web address to access options: Supported options: + - `single`: Whether the input is assumed to be in single- - entity form. The default (`"auto"`) will try to infer - it automatically. + entity form. The default (`"auto"`) will try to infer + it automatically. + """ self.options = Options("single=auto") diff --git a/storages/python/python-storage-plugins/image.py b/storages/python/python-storage-plugins/image.py index 17b27a962..ec7052f18 100644 --- a/storages/python/python-storage-plugins/image.py +++ b/storages/python/python-storage-plugins/image.py @@ -15,6 +15,7 @@ class image(dlite.DLiteStorageBase): Arguments: location: Path to YAML file. options: Supported options: + - `plugin`: Name of scikit image io plugin to use for loading the image. By default, the different plugins are tried (starting with imageio) until a suitable candidate is found. @@ -34,6 +35,7 @@ class image(dlite.DLiteStorageBase): - `order`: Order of spline interpolation for resize. Default to zero for binary images and 1 otherwise. Should be in the range 0-5. + """ meta = "http://onto-ns.com/meta/0.1/Image" diff --git a/storages/python/python-storage-plugins/mongodb.py b/storages/python/python-storage-plugins/mongodb.py index 5bd1b283a..fbec7acc4 100644 --- a/storages/python/python-storage-plugins/mongodb.py +++ b/storages/python/python-storage-plugins/mongodb.py @@ -30,15 +30,16 @@ def open(self, uri, options=None): An ampersand (&) may be used instead of the semicolon (;). Options: + - mode: "r" for opening in read-only mode, "w" for read/write mode. - database: Name of database to use (default: "test") - collection: Name of collection to use (default: "test_coll") - options for the constructor of the pymongo.MongoClient could pass by using the dlite.Options object, for example: - opt = Options("mode=r;database=test;collection=testc") - opt.update(directConnection=False, maxPoolSize=200) - storage = dlite.Storage("mongodb", "localhost", str(opt)) + opt = Options("mode=r;database=test;collection=testc") + opt.update(directConnection=False, maxPoolSize=200) + storage = dlite.Storage("mongodb", "localhost", str(opt)) see more details of the pymongo.MongoClient options https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient: diff --git a/storages/python/python-storage-plugins/postgresql.py b/storages/python/python-storage-plugins/postgresql.py index 1053d7d87..187dd45e2 100644 --- a/storages/python/python-storage-plugins/postgresql.py +++ b/storages/python/python-storage-plugins/postgresql.py @@ -62,19 +62,21 @@ def open(self, uri, options=None): An ampersand (&) may be used instead of the semicolon (;). Typical options supported by most drivers include: + - database : Name of database to connect to (default: dlite) - user : User name. - password : Password. - mode : append | r - Valid values are: - - append Append to existing file or create new file (default) - - r Open existing file for read-only + Valid values are: + + - `a`, `append`: Append to existing file or create new file (default) + - `r`: Open existing file for read-only After the options are passed, this method may set attribute `writable` to true if it is writable and to false otherwise. If `writable` is not set, it is assumed to be true. """ - self.options = Options(options, defaults="database=dlite;mode=append") + self.options = Options(options, defaults="database=dlite;mode=a") opts = self.options opts.setdefault("password", None) self.writable = False if opts.mode == "r" else True diff --git a/storages/python/python-storage-plugins/pyrdf.py b/storages/python/python-storage-plugins/pyrdf.py index 9d395ac88..1e0cfac61 100644 --- a/storages/python/python-storage-plugins/pyrdf.py +++ b/storages/python/python-storage-plugins/pyrdf.py @@ -30,8 +30,8 @@ def open(self, location: str, options: "Optional[str]" = None) -> None: - `w`: Truncate existing file or create new file. * `format`: File format. For a complete list of valid formats, see - https://rdflib.readthedocs.io/en/stable/intro_to_parsing.html - A sample list of valid format values: "turtle", "xml", "n3", + https://rdflib.readthedocs.io/en/stable/intro_to_parsing.html. + A sample list of valid format values: "turtle", "xml", "n3", "nt", "json-ld", "nquads". * `base_uri`: Base URI that is prepended to the instance UUID or @@ -41,6 +41,7 @@ def open(self, location: str, options: "Optional[str]" = None) -> None: * `include_meta`: Whether to also serialise metadata. The default is to only include metadata if `inst` is a data object. + """ self.options = Options(options, defaults="mode=a") self.writable = "r" not in self.options.mode diff --git a/storages/python/python-storage-plugins/template.py b/storages/python/python-storage-plugins/template.py index da73fc67d..1b01c5ebb 100644 --- a/storages/python/python-storage-plugins/template.py +++ b/storages/python/python-storage-plugins/template.py @@ -13,12 +13,14 @@ def open(self, location, options=None): Arguments: location: Path to file to generate. options: Supported options: + - `template`: Path to template file. - `engine`: Template engine to use. One of: - - "format": Use format() function from the standard library. - See https://docs.python.org/3/library/string.html#formatspec - for specifications. This is the default. - - "jinja": Use jinja. See https://jinja.palletsprojects.com/ + + - "format": Use format() function from the standard library. + See https://docs.python.org/3/library/string.html#formatspec + for specifications. This is the default. + - "jinja": Use jinja. See https://jinja.palletsprojects.com/ """ self.options = Options(options, defaults="engine=format") diff --git a/tools/dlite-codegen.c b/tools/dlite-codegen.c index 3a7d7c90d..6c11818b7 100644 --- a/tools/dlite-codegen.c +++ b/tools/dlite-codegen.c @@ -8,7 +8,7 @@ #include "config.h" #include "utils/compat.h" -#include "utils/compat/getopt.h" +#include "utils/compat-src/getopt.h" #include "utils/err.h" #include "utils/fileutils.h" #include "utils/tgen.h" diff --git a/tools/dlite-env.c b/tools/dlite-env.c index f02f9e303..7f4976d37 100644 --- a/tools/dlite-env.c +++ b/tools/dlite-env.c @@ -9,7 +9,7 @@ #include "dlite.h" #include "utils/compat.h" -#include "utils/compat/getopt.h" +#include "utils/compat-src/getopt.h" #include "utils/err.h" #include "utils/execprocess.h" #include "dlite-macros.h" diff --git a/tools/dlite-getuuid.c b/tools/dlite-getuuid.c index c08004e62..dacc7173e 100644 --- a/tools/dlite-getuuid.c +++ b/tools/dlite-getuuid.c @@ -5,7 +5,7 @@ #include "config.h" -#include "utils/compat/getopt.h" +#include "utils/compat-src/getopt.h" #include "utils/err.h" #include "getuuid.h"