Skip to content
Snippets Groups Projects
Verified Commit 23ade264 authored by Daniel Hornung's avatar Daniel Hornung
Browse files

WIP: Rename caosdb -> linkahead

parent f2988c64
No related branches found
No related tags found
1 merge request!111MAINT: LinkAhead rename
Pipeline #40917 failed
Showing
with 81 additions and 81 deletions
......@@ -28,7 +28,7 @@
SPHINXOPTS ?= -a
SPHINXBUILD ?= sphinx-build
SPHINXAPIDOC ?= sphinx-apidoc
PY_BASEDIR = ../caosdb
PY_BASEDIR = ../linkahead
SOURCEDIR = .
BUILDDIR = ../../build/doc
......
Administration
==============
The Python script ``caosdb_admin.py`` should be used for administrative tasks.
Call ``caosdb_admin.py --help`` to see how to use it.
The Python script ``linkahead_admin.py`` should be used for administrative tasks.
Call ``linkahead_admin.py --help`` to see how to use it.
The most common task is to create a new user (in the LinkAhead realm) and set a
password for the user (note that a user typically needs to be activated):
.. code:: console
$ caosdb_admin.py create_user anna
$ caosdb_admin.py set_user_password anna
$ caosdb_admin.py add_user_roles anna administration
$ caosdb_admin.py activate_user anna
$ linkahead_admin.py create_user anna
$ linkahead_admin.py set_user_password anna
$ linkahead_admin.py add_user_roles anna administration
$ linkahead_admin.py activate_user anna
......@@ -24,7 +24,7 @@ import sphinx_rtd_theme # noqa: E402
# -- Project information -----------------------------------------------------
project = 'pycaosdb'
project = 'pylinkahead'
copyright = '2023, IndiScale GmbH'
author = 'Daniel Hornung'
......@@ -115,7 +115,7 @@ html_static_path = ['_static']
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'caosdb-pylibdoc'
htmlhelp_basename = 'linkahead-pylibdoc'
# -- Options for LaTeX output ------------------------------------------------
......@@ -142,7 +142,7 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'caosdb-pylib.tex', 'caosdb-pylib Documentation',
(master_doc, 'linkahead-pylib.tex', 'linkahead-pylib Documentation',
'IndiScale GmbH', 'manual'),
]
......@@ -152,7 +152,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pycaosdb', 'pycaosdb documentation',
(master_doc, 'pylinkahead', 'pylinkahead documentation',
[author], 1)
]
......@@ -163,8 +163,8 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'pycaosdb', 'pycaosdb documentation',
author, 'pycaosdb', 'One line description of project.',
(master_doc, 'pylinkahead', 'pylinkahead documentation',
author, 'pylinkahead', 'One line description of project.',
'Miscellaneous'),
]
......@@ -202,9 +202,9 @@ epub_exclude_files = ['search.html']
# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#confval-intersphinx_mapping
intersphinx_mapping = {
"python": ("https://docs.python.org/", None),
"caosdb-mysqlbackend": ("https://docs.indiscale.com/caosdb-mysqlbackend/",
"linkahead-mysqlbackend": ("https://docs.linkahead.org/linkahead-mysqlbackend/",
None),
"caosdb-server": ("https://docs.indiscale.com/caosdb-server/", None),
"linkahead-server": ("https://docs.linkahead.org/linkahead-server/", None),
}
......
# Configuration of PyLinkAhead #
The behavior of PyLinkAhead is defined via a configuration that is provided using configuration files.
PyLinkAhead tries to read from the inifile specified in the environment variable `PYCAOSDBINI` or
alternatively in `~/.pycaosdb.ini` upon import. After that, the ini file `pycaosdb.ini` in the
PyLinkAhead tries to read from the inifile specified in the environment variable `PYLINKAHEADINI` or
alternatively in `~/.pylinkahead.ini` upon import. After that, the ini file `pylinkahead.ini` in the
current working directory will be read additionally, if it exists.
Here, we will look at the most common configuration options. For a full and comprehensive
description please check out the [example pycaosdb.ini file](https://gitlab.com/caosdb/caosdb-pylib/-/blob/main/examples/pycaosdb.ini). You can download this file and use
description please check out the [example pylinkahead.ini file](https://gitlab.com/linkahead/linkahead-pylib/-/blob/main/examples/pylinkahead.ini). You can download this file and use
it as a starting point.
......@@ -66,5 +66,5 @@ the internals of the protocol.
`timeout` sets the timeout for requests to the server.
A complete list of options can be found in the
[pycaosdb.ini file](https://gitlab.com/caosdb/caosdb-pylib/-/blob/main/examples/pycaosdb.ini) in
[pylinkahead.ini file](https://gitlab.com/linkahead/linkahead-pylib/-/blob/main/examples/pylinkahead.ini) in
the examples folder of the source code.
......@@ -7,13 +7,13 @@ contribute to this development.
At several locations in this document there will be links to discussion issues.
If you want to discuss something new, you can create a new issue
[here](https://gitlab.com/caosdb/caosdb-pylib/-/issues/new).
[here](https://gitlab.com/linkahead/linkahead-pylib/-/issues/new).
## Overview
Let's get a general impression before discussing single aspects.
``` python
import caosdb as db
import linkahead as db
experiments = db.query("FIND Experiment")
# print name and date for each `Experiment`
for exp in experiments:
......@@ -29,13 +29,13 @@ new_one.name = "Needle Measurement"
new_one.insert()
```
Related discussions:
- [recursive retrieve in query](https://gitlab.com/caosdb/caosdb-pylib/-/issues/57)
- [create_record function](https://gitlab.com/caosdb/caosdb-pylib/-/issues/58)
- [data model utility](https://gitlab.com/caosdb/caosdb-pylib/-/issues/59)
- [recursive retrieve in query](https://gitlab.com/linkahead/linkahead-pylib/-/issues/57)
- [create_record function](https://gitlab.com/linkahead/linkahead-pylib/-/issues/58)
- [data model utility](https://gitlab.com/linkahead/linkahead-pylib/-/issues/59)
## Quickstart
Note that you can try out one possible implementation using the
`caosdb.high_level_api` module. It is experimental and might be removed in
`linkahead.high_level_api` module. It is experimental and might be removed in
future!
A `resolve_references` function allows to retrieve the referenced entities of
......@@ -76,7 +76,7 @@ but no Properties are inserted unexpectedly with NULL values.
- Raise Exception if attribute does not exist but is accessed?
[Discussion](https://gitlab.com/caosdb/caosdb-pylib/-/issues/60)
[Discussion](https://gitlab.com/linkahead/linkahead-pylib/-/issues/60)
We aim for a distinction between "concrete" Properties of Records/RecordTypes and "abstract" Properties as part of the definition of a data model. Concrete properties are always "contained" in a record or record type while abstract properties stand for themselves.
......@@ -129,7 +129,7 @@ GRPC json serialization?
I can resolve later and end up with the same result:
`recs =db.query("FIND Experiment", depth=2)` equals `recs = db.query("FIND Experiment"); recs = resolve_references(recs, depth=2)`
[Discussion](https://gitlab.com/caosdb/caosdb-pylib/-/issues/57)
[Discussion](https://gitlab.com/linkahead/linkahead-pylib/-/issues/57)
#### Alternative
......@@ -155,11 +155,11 @@ Especially the following functions operate by default NOT in-place:
- insert
- retrieve
- resolve_references
[Discussion](https://gitlab.com/caosdb/caosdb-pylib/-/issues/61)
[Discussion](https://gitlab.com/linkahead/linkahead-pylib/-/issues/61)
## Extended Example
``` python
import caosdb as db
import linkahead as db
dm = db.get_data_model()
......
......@@ -26,27 +26,27 @@ The curator role
~~~~~~~~~~~~~~~~
First, a ``curator`` role is created with a meaningful description. We'll use
``caosdb_admin.py`` for this which leads to the following command:
``linkahead_admin.py`` for this which leads to the following command:
.. code:: console
$ caosdb_admin.py create_role "curator" "A user who is permitted to create new Records, Properties, and RecordTypes but who is not allowed to change the core data model."
$ linkahead_admin.py create_role "curator" "A user who is permitted to create new Records, Properties, and RecordTypes but who is not allowed to change the core data model."
To actually see how this role's permissions change, we also need a user with
this role. Assume you already have created and activated (see
:doc:`Administration <../administration>`) a ``test_curator`` user, then
``caosdb_admin.py`` is used again to assign it the correct role:
``linkahead_admin.py`` is used again to assign it the correct role:
.. code:: console
$ caosdb_admin.py add_user_roles test_curator curator
$ linkahead_admin.py add_user_roles test_curator curator
.. note::
The ``test_curator`` user shouldn't have administration privileges, otherwise
the below changes won't have any effect.
The core data model and caosdb-advanced-user-tools
The core data model and linkahead-advanced-user-tools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In principle, the following script works with any data model defined in a json
......@@ -62,7 +62,7 @@ Clone the schemata into the same directory containing the below script via
$ git clone https://github.com/leibniz-zmt/zmt-metadata-schema.git
Furthermore, we'll need the `LinkAhead Advanced User Tools
<https://gitlab.com/caosdb/caosdb-advanced-user-tools>`_ for loading the
<https://gitlab.com/linkahead/linkahead-advanced-user-tools>`_ for loading the
metadata schemata from the json files, so install them via
.. code:: console
......@@ -76,7 +76,7 @@ Users with the ``curator`` role should be able to have any permission for all
entities by default. The exceptions for the core data model entities will be set
with the script below. These default settings are best done via the
``global_entities_permissions.xml`` config file (see the `server documentation
<https://docs.indiscale.com/caosdb-server/permissions.html#how-to-set-permissions>`_). Simply
<https://docs.linkahead.org/linkahead-server/permissions.html#how-to-set-permissions>`_). Simply
add the following line to the file
.. code:: xml
......@@ -89,7 +89,7 @@ beginning) **with priority**. This ensures, that no normal user is allowed to
overrule these permissions (since it is granted with priority), but it can still
be denied for the core data model entities by a **deny** rule with priority. See
the server documentation on `permission
calculation <https://docs.indiscale.com/caosdb-server/permissions.html#permission-calculation>`_
calculation <https://docs.linkahead.org/linkahead-server/permissions.html#permission-calculation>`_
for more information on which permission rules can or can't be overruled.
Your complete ``global_entities_permissions.xml`` might then look like
......
......@@ -23,9 +23,9 @@
import os
import sys
import caosdb as db
import linkahead as db
from caosadvancedtools.models.parser import parse_model_from_json_schema
from caosdb import administration as admin
from linkahead import administration as admin
CURATOR = "curator"
......
......@@ -8,11 +8,11 @@ These distances resulted in small x,y, values:
import numpy as np
import scipy.integrate
import caosdb as db
import linkahead as db
from caosadvancedtools.table_converter import to_table
def setup_caosdb():
def setup_linkahead():
"""Create the data model and insert it into LinkAhead
The data model consists of the following RecordTypes:
......@@ -121,7 +121,7 @@ def analyze():
def main():
# 1. Set up the data model
setup_caosdb()
setup_linkahead()
# 2. Run simulations
simulations(n=200, t_max=5)
......
......@@ -8,7 +8,7 @@ access easier.
Or to spell it out directly in Python:
#+BEGIN_SRC python
import caosdb as db
import linkahead as db
# Old API:
r = db.Record()
r.add_parent("Experiment")
......@@ -16,7 +16,7 @@ Or to spell it out directly in Python:
r.get_property("alpha").value = 25 # setting properties (old api)
print(r.get_property("alpha").value + 25) # getting properties (old api)
from caosdb.high_level_api import convert_to_python_entity
from linkahead.high_level_api import convert_to_python_entity
obj = convert_to_python_object(r) # create a high level entity
obj.r = 25 # setting properties (new api)
print(obj.r + 25) # getting properties (new api)
......@@ -27,7 +27,7 @@ Or to spell it out directly in Python:
** Quickstart
The module, needed for the high level API is called:
~caosdb.high_level_api~
~linkahead.high_level_api~
There are two functions converting entities between the two representation (old API and new API):
- ~convert_to_python_object~: Convert entities from **old** into **new** representation.
......@@ -42,7 +42,7 @@ Furthermore there are a few utility functions which expose very practical shorth
So as a first example, you could retrieve any record from LinkAhead and use it using its high level representation:
#+BEGIN_SRC python
from caosdb.high_level_api import query
from linkahead.high_level_api import query
res = query("FIND Record Experiment")
experiment = res[0]
......@@ -60,7 +60,7 @@ like the list of output files "output", become immediately available.
**Note** that for the old API you were supposed to run the following series of commands
to achieve the same result:
#+BEGIN_SRC python
import caosdb as db
import linkahead as db
res = db.execute_query("FIND Record Experiment")
output = res.get_property("output")
......@@ -94,7 +94,7 @@ print(str(obj))
As described in the section [[Quickstart]] the two functions ~convert_to_python_object~ and ~convert_to_entity~ convert
entities beetween the high level and the standard representation.
The high level entities are represented using the following classes from the module ~caosdb.high_level_api~:
The high level entities are represented using the following classes from the module ~linkahead.high_level_api~:
- ~LinkAheadPythonEntity~: Base class of the following entity classes.
- ~LinkAheadPythonRecord~
- ~LinkAheadPythonRecordType~
......@@ -141,7 +141,7 @@ First, the data model will be filled with the parameter values for this specific
Records are created by the `create_record` function. Parameter values can be set at record creation and also after creation as python properties of the corresponding record instance. The following example shows how to create a record, how to set the parameter at creation and how to set them as python properties
#+BEGIN_SRC python
from caosdb.high_level_api import create_record
from linkahead.high_level_api import create_record
MonodomainRecord = create_record("MonodomainTissueSimulation")
MonodomainRecord.LocalModel = create_record("MitchellSchaefferModel")
......
......@@ -10,7 +10,7 @@ Or to speak it out directly in Python:
.. code:: python
import caosdb as db
import linkahead as db
# Old API:
r = db.Record()
r.add_parent("Experiment")
......@@ -18,7 +18,7 @@ Or to speak it out directly in Python:
r.get_property("alpha").value = 25 # setting properties (old api)
print(r.get_property("alpha").value + 25) # getting properties (old api)
from caosdb.high_level_api import convert_to_python_entity
from linkahead.high_level_api import convert_to_python_entity
obj = convert_to_python_object(r) # create a high level entity
obj.r = 25 # setting properties (new api)
print(obj.r + 25) # getting properties (new api)
......@@ -27,7 +27,7 @@ Quickstart
----------
The module, needed for the high level API is called:
``caosdb.high_level_api``
``linkahead.high_level_api``
There are two functions converting entities between the two
representation (old API and new API):
......@@ -57,7 +57,7 @@ it using its high level representation:
.. code:: python
from caosdb.high_level_api import query
from linkahead.high_level_api import query
res = query("FIND Experiment")
experiment = res[0]
......@@ -77,7 +77,7 @@ series of commands to achieve the same result:
.. code:: python
import caosdb as db
import linkahead as db
res = db.execute_query("FIND Experiment")
output = res.get_property("output")
......@@ -122,7 +122,7 @@ As described in the section Quickstart the two functions
beetween the high level and the standard representation.
The high level entities are represented using the following classes from
the module ``caosdb.high_level_api``:
the module ``linkahead.high_level_api``:
- ``LinkAheadPythonEntity``: Base class of the following entity classes.
- ``LinkAheadPythonRecord``
......
......@@ -14,7 +14,7 @@ Welcome to PyLinkAhead's documentation!
Administration <administration>
High Level API <high_level_api>
Code gallery <gallery/index>
API documentation<_apidoc/caosdb>
API documentation<_apidoc/linkahead>
This is the documentation for the Python client library for LinkAhead, ``PyLinkAhead``.
......
......@@ -6,7 +6,7 @@ Data Models
Data is stored and structured in LinkAhead using a concept of RecordTypes, Properties, Records etc.
If you do not know what these are, please look at the chapter :doc:`Data
Model<caosdb-server:Data-Model>` in the LinkAhead server documentation.
Model<linkahead-server:Data-Model>` in the LinkAhead server documentation.
In order to insert some actual data, we need to create a data model
using RecordTypes and Properties (You may skip this if you use a LinkAhead
......@@ -20,7 +20,7 @@ Property called “a” of datatype double. This is very easy in pylib:
There are a few basic datatypes like db.INTEGER, db.DOUBLE, or db.TEXT. See the
`data types
<https://docs.indiscale.com/caosdb-server/specification/Datatype.html>`_ for a
<https://docs.linkahead.org/linkahead-server/specification/Datatype.html>`_ for a
full list.
We can create our own small data model for e.g. a simulation by adding
......@@ -60,11 +60,11 @@ resolution, but we'll omit this for the sake of brevity for now.
print(rt.get_property(name="epsilon").importance) ### rt has a "epsilon" property with the same importance as "BarkleySimulation"
The parameter ``inheritance=(obligatory|recommended|fix|all|none)`` of
:py:meth:`Entity.add_parent()<caosdb.common.models.Entity.add_parent>` tells the server to assign
:py:meth:`Entity.add_parent()<linkahead.common.models.Entity.add_parent>` tells the server to assign
all properties of the parent RecordType with the chosen importance (and properties with a higher
importance) to the child RecordType
automatically upon insertion. See the chapter on `importance
<https://docs.indiscale.com/caosdb-server/specification/RecordType.html#importance>`_ in the
<https://docs.linkahead.org/linkahead-server/specification/RecordType.html#importance>`_ in the
documentation of the LinkAhead server for more information on the importance and inheritance of
properties.
......@@ -209,7 +209,7 @@ list-valued attribute in Python, as the following example illustrates.
.. code:: python
import caosdb as db
import linkahead as db
db.Property(name="TestList", datatype=db.LIST(db.DOUBLE)).insert()
db.RecordType(name="TestType").add_property(name="TestList").insert()
db.Record(name="TestRec").add_parent("TestType").add_property(
......@@ -254,7 +254,7 @@ Updating an existing file by uploading a new version.
.. code:: python
import caosdb as db
import linkahead as db
file_upd = db.File(id=174).retrieve()
......
......@@ -4,7 +4,7 @@ Basic Analysis
If you have not yet, configure a connection with the demo instance. E.g.:
>>> import caosdb as db
>>> import linkahead as db
>>> _ = db.configure_connection(
... url="https://demo.indiscale.com/",
... password_method="plain",
......
......@@ -21,12 +21,12 @@ function, easily created from ``get_entity_by_name`` using Python's ``lru_cache`
# reset the cache with
cached_get_by_name.cache_clear()
For convenience, PyLinkAhead provides the ``caosdb.cached`` module that defines the functions
For convenience, PyLinkAhead provides the ``linkahead.cached`` module that defines the functions
``cached_query`` and ``cached_get_entity_by``, they use a shared cache. Let's have a look:
.. code:: python
from caosdb.cached import cached_query, cached_get_entity_by, cache_clear, cache_info, cache_initialize
from linkahead.cached import cached_query, cached_get_entity_by, cache_clear, cache_info, cache_initialize
rt1 = cached_get_entity_by(name='RT1')
qresult = cached_query('FIND Experiment WITH parameter=1')
# you can inspect the cache
......@@ -45,7 +45,7 @@ have entities on hand from previous queries that you want to add.
.. code:: python
from caosdb.cached import cache_fill, AccessType
from linkahead.cached import cache_fill, AccessType
# Here, items must be a dict with Entity IDs as keys and the Entities as values.
cache_fill(items, AccessType.EID, unique=True)
# If you now use IDs that were in items, they are taken from the cache.
......
......@@ -17,7 +17,7 @@ Examples
.. code-block:: python3
import caosdb as db
import linkahead as db
# Create two record types with descriptions:
rt1 = db.RecordType(name="TypeA", description="The first type")
......
......@@ -17,7 +17,7 @@ cd LinkAhead/data_models
```
There are "data models" defined in
```bash
caosdb_models
linkahead_models
```
having an ending like "_model.py"
A set of data models is also considered to be a model
......
......@@ -12,7 +12,7 @@ The errors and exceptions are ordered hierarchically form the most
general exceptions to specific transaction or connection problems. The
most important error types and the hierarchy will be explained in the
following. For more information on specific error types, see also the
:doc:`source code<../_apidoc/caosdb.exceptions>`.
:doc:`source code<../_apidoc/linkahead.exceptions>`.
.. note::
......@@ -132,7 +132,7 @@ Other Errors
There are further subclasses of ``LinkAheadException`` that are raised in
case of faulty configurations or other problems. They should be rather
self-explanatory from their names; see the :doc:`source code<../_apidoc/caosdb.exceptions>`
self-explanatory from their names; see the :doc:`source code<../_apidoc/linkahead.exceptions>`
for further information.
* ``ConfigurationError``
......@@ -148,7 +148,7 @@ Examples
.. code-block:: python3
import caosdb as db
import linkahead as db
def link_and_insert(entity, linked, link=True):
"""Link the ENTITY to LINKED and insert it."""
......
......@@ -7,12 +7,12 @@ You should have a working connection to a LinkAhead instance now. If not, please
If you are not yet familiar with Records, RecordTypes and Properties used in LinkAhead,
please check out the respective part in the `Web Interface tutorial`_.
You should also know the basics of the LinkAhead Query Language (a tutorial is
`here <https://docs.indiscale.com/caosdb-webui/tutorials/query.html>`_).
`here <https://docs.linkahead.org/linkahead-webui/tutorials/query.html>`_).
We recommend that you connect to the `demo instance`_ (hosted by `Indiscale`_) in order to try out
the following examples. You can do this with
>>> import caosdb as db
>>> import linkahead as db
>>> _ = db.configure_connection(
... url="https://demo.indiscale.com/",
... password_method="plain",
......@@ -34,7 +34,7 @@ data is the strength of the web interface while the automated processing of
data is the strength of the Python client.
>>> type(response)
<class 'caosdb.common.models.Container'>
<class 'linkahead.common.models.Container'>
As you can see the type of the returned object is Container. Containers are
simply lists of LinkAhead objects with useful functions to interact with LinkAhead.
......@@ -47,7 +47,7 @@ Let's look at the first element:
>>> firstguitar = response[0]
>>> print(type(firstguitar))
<class 'caosdb.common.models.Record'>
<class 'linkahead.common.models.Record'>
>>> print(firstguitar)
<Record ...
......@@ -93,7 +93,7 @@ Ids can also come in handy when searching. Suppose you have some complicated con
>>> # thrown if the number of results is unequal to 1 and the resulting object will be
>>> # an Entity and not a Container
>>> print(type(record))
<class 'caosdb.common.models.Record'>
<class 'linkahead.common.models.Record'>
>>> print(record.id)
123
......@@ -128,4 +128,4 @@ The next tutorial shows how to make some meaningful use of this.
.. _`demo instance`: https://demo.indiscale.com
.. _`IndiScale`: https://indiscale.com
.. _`Web Interface tutorial`: https://docs.indiscale.com/caosdb-webui/tutorials/first_steps.html
.. _`Web Interface tutorial`: https://docs.linkahead.org/linkahead-webui/tutorials/first_steps.html
......@@ -17,7 +17,7 @@ execution is fairly simple:
.. code:: python
from caosdb.utils.server_side_scripting import run_server_side_script
from linkahead.utils.server_side_scripting import run_server_side_script
response = run_server_side_script('scriptname.py')
print(response.stderr,response.stdout)
......@@ -38,7 +38,7 @@ Testing it
You can try this out using for example the ``diagnostics.py`` script (it is part
of the `LinkAhead server repository
<https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/blob/main/scripting/bin/administration/diagnostics.py>`_
<https://gitlab.com/linkahead/linkahead-server/-/blob/main/scripting/bin/administration/diagnostics.py>`_
and is also available on https://demo.indiscale.com). The script returns
information about the server in JSON format. You can do for example the
following:
......@@ -46,7 +46,7 @@ following:
.. code:: python
import json
from caosdb.utils.server_side_scripting import run_server_side_script
from linkahead.utils.server_side_scripting import run_server_side_script
response = run_server_side_script('administration/diagnostics.py')
print("JSON content:")
print(json.loads(response.stdout))
......@@ -58,4 +58,4 @@ Further Information
~~~~~~~~~~~~~~~~~~~
Additionally, you might want to have a look at
https://docs.indiscale.com/caosdb-server/specification/Server-side-scripting.html
https://docs.linkahead.org/linkahead-server/specification/Server-side-scripting.html
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment