Skip to content
Open
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
2 changes: 1 addition & 1 deletion converters/ontology/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ htmlcov/
.idea/
*.iml
*.iws
*.ipr
*.ipr
107 changes: 101 additions & 6 deletions converters/ontology/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,108 @@

# Ossie Ontology Converters

Converters between Ossie, Palantir, and Spec ontology formats.
Converters between Ossie, Palantir, Spec, and RelationalAI ontology formats.

| Converter | Direction |
|-------------------------|-----------|
| `palantir_to_ossie` | Palantir ontology → Ossie model |
| `ossie_to_spec` | Ossie model → Spec YAML |
| `spec_to_ossie` | Spec YAML → Ossie model |
| `ossie_to_relationalai` | Ossie model → RelationalAI (PyRel) |

### The `relationalai` extra

> **`relationalai` is proprietary and declares no license.** Its PyPI
> distribution carries no `License` field, no license classifier and no
> `LICENSE` file, and the [project page](https://pypi.org/project/relationalai/)
> lists none either — so it grants no use or redistribution rights by default.
> Get the applicable terms from RelationalAI (`support@relational.ai`) before
> installing it. Ossie is Apache-2.0 and neither bundles nor depends on it.
>
> Installing the package is also not enough to *run* what this converter emits.
> That needs a Snowflake account with the RelationalAI Native App installed from
> the [Marketplace](https://app.snowflake.com/marketplace/listing/GZTYZOOIX8H/relationalai-relationalai),
> and access enabled by RelationalAI on request — see the
> [setup guide](https://docs.relational.ai/manage/get-started/install/). Ossie
> never executes the generated source: it converts and compiles in-process,
> offline, against no engine.

`ossie_to_relationalai` is the only converter that needs a vendor SDK. Because
that SDK is non-free, it is kept out of the base install entirely and gated
behind an opt-in extra, so nobody acquires it without asking for it:

| Converter | Direction |
|---------------------|-----------|
| `palantir_to_ossie` | Palantir ontology → Ossie model |
| `ossie_to_spec` | Ossie model → Spec YAML |
| `spec_to_ossie` | Spec YAML → Ossie model |
```bash
pip install "apache-ossie-ontology[relationalai]" # opt in, having read the above
pip install apache-ossie-ontology # everything else, no vendor SDK
```

Nothing reachable from `ossie_ontology/__init__.py` imports `relationalai`, so
everything else — parsing Ossie, converting Palantir, reading and writing the
spec — installs and runs without it. `tests/test_optional_extra.py` asserts that
boundary in a subprocess with the SDK masked, so the base install cannot start
depending on it by accident. The converter's own tests skip themselves when it
is absent.

The PyRel-side model it targets — `OntologyModel` and its bindings, roles and
CSV plumbing — lives under `ossie_ontology/vendor/relationalai/`,
next to `ossie_ontology/vendor/palantir/`. The converter package itself holds
only the translation. The one piece that sits elsewhere is the formula emitter,
`ossie_ontology/expr/formula/visitor/converter.py`, which stays with the other
formula visitors it is a variant of.

It converts an `OssieOntology` into an in-memory `OntologyModel`, which can then
be serialized to PyRel source:

```python
from pathlib import Path

from relationalai.semantics.metamodel.pyrel_codegen import to_pyrel

from ossie_ontology.parser import OssieParser
from ossie_ontology.converter.ossie_to_relationalai import OssieToRelationalAIConverter

ontology = OssieParser().parse(Path("model.yaml"))

model = OssieToRelationalAIConverter.convert(ontology)
Path("model_pyrel.py").write_text(to_pyrel(model.base_model().to_metamodel()))
```

`OssieParser` parses and validates `derived_by` and `requires` expressions into
an AST by default, which is what the conversion needs — an unparsed formula is
skipped and never reaches PyRel. To keep formulas as raw text instead, pass the
plain `FormulaFactory` and `MappingFormulaFactory` from `ossie_ontology.model`.
`SpecToOssieConverter` and `PalantirToOssieConverter` take the same argument and
default the same way.

Two things about the environment this needs. Constructing a model makes
`relationalai` resolve its configuration, so a `raiconfig.yaml` must be present.
And each dataset's `source` is read from the configured connection to get its
column types, so the call above needs one that can reach those tables.

To convert without a warehouse, pass a different `table_provider`. The default,
`warehouse_table`, resolves each dataset's `source` against the connection —
which is what gets the column identifiers right, since Snowflake folds an
unquoted name to upper case. The alternative, `declared_table`, declares the
columns from the Ossie spec instead and reads nothing:

```python
from ossie_ontology.converter.ossie_to_relationalai import declared_table

model = OssieToRelationalAIConverter.convert(ontology, table_provider=declared_table)
```

Nothing leaves the process, so the tables the generated source names need not
exist. The tradeoff is the one `warehouse_table` avoids: the declared
identifiers have to match how the table was actually created.

That is how the test suite runs — see `tests/conftest.py` for the offline config
it pins and the network guard it installs, and `tests/relationalai/test_converter.py`
for the rest of the offline setup.

`table_provider` is also the extension point for reading rows from somewhere
else entirely — from inline CSV, for example, so a test corpus needs no
warehouse. This package ships no such provider and has no CSV handling at all,
because reading rows is not part of converting an ontology.

## Prerequisites

Expand Down
18 changes: 17 additions & 1 deletion converters/ontology/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,24 @@ keywords = [
]
dependencies = [
"pydantic",
"ply",
"pyyaml",
]

# Opt-in extra: `pip install "apache-ossie-ontology[relationalai]"`.
#
# WARNING: `relationalai` is proprietary and declares no license, and running
# what this converter emits needs a RelationalAI deployment in Snowflake. Read
# README.md, "The `relationalai` extra", before installing it.
#
# It is an extra rather than a dependency because nothing reachable from
# `ossie_ontology/__init__.py` imports it: everything but this one converter
# works without the SDK.
[project.optional-dependencies]
relationalai = [
"relationalai==1.27.1",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This package is non-free. This may require PMC approval (please see the PR checklist that you get when you open a new PR).

In my opinion, at the very least it should be clearly stated in the README that this is a fully proprietary package and what is its license (the PyPI listing does not say that). That matters because the license can be arbitrarily restrictive, so people installing this may unknowingly get into trouble.

Disclaimer: I'm not a lawyer, nor a PMC member.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Ostrzyciel, this is a good point. I will update the README file and add links and additional information about RelationalAI.

]

[project.urls]
homepage = "https://ossie.apache.org/"
repository = "https://github.com/apache/ossie/"
Expand All @@ -55,9 +70,10 @@ testpaths = ["tests"]

[tool.pyright]
pythonVersion = "3.11"
exclude = ["tests/snapshots", "build", "venv"]

[tool.uv]
required-version = ">=0.9.0"
default-groups = [
"dev"
]
]
2 changes: 1 addition & 1 deletion converters/ontology/scripts/palantir_to_ossie.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
from ossie_ontology.converter.palantir_to_ossie.converter import PalantirToOssieConverter
from ossie_ontology.converter.ossie_to_spec.converter import OssieToSpecConverter

from ossie_ontology.external.palantir.parser import PalantirParser
from ossie_ontology.vendor.palantir.parser import PalantirParser

if __name__ == "__main__":
db_name = os.environ.get("SNOWFLAKE_DATABASE_NAME", "PALANTIR")
Expand Down
10 changes: 9 additions & 1 deletion converters/ontology/src/ossie_ontology/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@
SemanticModel,
)
from ossie_ontology.spec import OssieSpec
from ossie_ontology.reasoner import OntologyReasoner
from ossie_ontology.parser import OssieParser
from ossie_ontology.external.palantir.parser import PalantirParser
from ossie_ontology.expr.factory import FormulaParserFactory, MappingFormulaParserFactory
from ossie_ontology.vendor.palantir.parser import PalantirParser
from ossie_ontology.converter.spec_to_ossie.converter import SpecToOssieConverter
from ossie_ontology.converter.ossie_to_spec.converter import OssieToSpecConverter
from ossie_ontology.converter.palantir_to_ossie.converter import PalantirToOssieConverter
Expand Down Expand Up @@ -81,9 +83,15 @@
"FormulaFactory",
# Spec DTO
"OssieSpec",
# Reasoner
"OntologyReasoner",
# Parsers
"OssieParser",
"PalantirParser",
# Formula parsing — plug these into OssieParser/PalantirParser to get
# formulas parsed into an AST rather than kept as raw strings.
"FormulaParserFactory",
"MappingFormulaParserFactory",
# Converters
"SpecToOssieConverter",
"OssieToSpecConverter",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

"""Ossie -> RelationalAI (PyRel) conversion.

Importing anything from this package imports `relationalai`, which ships as the
optional `relationalai` extra. Nothing under `ossie_ontology` imports this
package at module scope, so the rest of the library stays installable — and
importable — without the SDK present.

The model this converter targets is not here: `OntologyModel` and the rest of
the PyRel-side types live under `ossie_ontology.vendor.relationalai`, the same
way the Palantir model lives under `ossie_ontology.vendor.palantir`. What is
left here is the translation itself.
"""

from ossie_ontology.converter.ossie_to_relationalai.converter import (
OssieToRelationalAIConverter,
TableProvider,
declared_table,
warehouse_table,
)
from ossie_ontology.vendor.relationalai.ontology import OntologyModel

__all__ = [
"OssieToRelationalAIConverter",
"OntologyModel",
# The dataset extension point: swap `table_provider` to read datasets from
# somewhere other than the warehouse their `source` names.
"TableProvider",
"warehouse_table",
"declared_table",
]
Loading