Skip to content

Commit 8cdbc77

Browse files
committed
Merge branch 'main' of github.com:jupyter-naas/abi
2 parents 4e499e6 + 5d9ea51 commit 8cdbc77

101 files changed

Lines changed: 13942 additions & 2640 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bandit.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ skips:
1919
# hashlib/md5 — flagged generically; project uses it for non-security hashing (e.g. cache keys)
2020
# Remove this skip once all hashlib usages have been audited and confirmed safe
2121
- B324
22+
# pickle used only with trusted internal storage
23+
- B301

libs/naas-abi-core/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
<!-- version list -->
44

5+
## v1.47.0 (2026-05-26)
6+
7+
### Documentation
8+
9+
- **event**: Add README covering event creation, publish/subscribe, query, and filter DSL
10+
([`64ad241`](https://github.com/jupyter-naas/abi/commit/64ad241d40b77114c7e70eefe52387ec30afe616))
11+
12+
513
## v1.46.0 (2026-05-26)
614

715
### Features

libs/naas-abi-core/naas_abi_core/services/event/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ The contract `EventService` cares about:
2323

2424
### 1. Write a TTL
2525

26-
Create a `.ttl` file in your domain's `ontologies/modules/` directory. The two things that matter: an `owl:imports` pointing at the EventOntology TTL, and a `rdfs:subClassOf abi:LogProcess` on each event class.
26+
Create a `.ttl` file in your domain's `ontologies/modules/` directory. Three things matter:
27+
28+
1. `owl:imports <http://ontology.naas.ai/abi/EventService>` so `LogProcess` is pulled from the canonical EventOntology (not regenerated locally).
29+
2. `rdfs:subClassOf abi:LogProcess` on each event class.
30+
3. The `abi:pythonPackage` / `abi:ontologyResource` / `abi:pythonResource` locator annotations on your own `owl:Ontology` declaration, so any *other* module can in turn `owl:imports` your ontology by its canonical IRI.
2731

2832
```ttl
2933
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@@ -37,7 +41,10 @@ Create a `.ttl` file in your domain's `ontologies/modules/` directory. The two t
3741
3842
mydomain:MyDomainEvents a owl:Ontology ;
3943
dc:title "My domain events"@en ;
40-
owl:imports <python://naas_abi_core.services.event.ontologies.modules/EventOntology.ttl> .
44+
owl:imports <http://ontology.naas.ai/abi/EventService> ;
45+
abi:pythonPackage "my_module" ;
46+
abi:ontologyResource "ontologies/modules/MyDomainEvents.ttl" ;
47+
abi:pythonResource "ontologies/modules/MyDomainEvents.py" .
4148
4249
mydomain:UserRegistered a owl:Class ;
4350
rdfs:label "UserRegistered"@en ;
@@ -55,7 +62,7 @@ mydomain:source a owl:DatatypeProperty ;
5562
rdfs:range xsd:string .
5663
```
5764

58-
**Why `python://`?** It's an `importlib.resources`-based locator that works the same in editable installs, wheels, and zipped packages — it doesn't break the moment your TTL lives inside a `.venv`. Plain relative paths (e.g. `<../other/Foo.ttl>`) also work for intra-package references. Remote HTTP IRIs (BFO, etc.) are deliberately skipped — they're RDF-level references, not codegen inputs.
65+
**Why `<http://ontology.naas.ai/abi/EventService>`?** That's the canonical IRI of the EventOntology — a normal, spec-compliant `owl:imports` target. onto2py keeps an index of every ontology declared by an installed `naas_abi*` package; when an `owl:imports` IRI matches one in the index, the TTL is loaded through `importlib.resources` (via the `abi:pythonPackage` / `abi:ontologyResource` annotations on that ontology), so it works the same in editable installs, wheels, and zipped packages. Plain relative paths (e.g. `<../other/Foo.ttl>`) also work for intra-package references. Remote HTTP IRIs that no installed package declares (BFO, etc.) are skipped — they're RDF-level references, not codegen inputs.
5966

6067
### 2. Generate the Python module
6168

libs/naas-abi-core/naas_abi_core/services/event/ontologies/modules/EventOntology.ttl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,30 @@
88
@prefix bfo: <http://purl.obolibrary.org/obo/> .
99
@prefix abi: <http://ontology.naas.ai/abi/> .
1010

11+
# Locator annotations: tell onto2py where this ontology lives in the Python
12+
# package tree so downstream ontologies can import it by its canonical IRI
13+
# (a spec-compliant owl:imports target) and still resolve correctly inside
14+
# editable installs, wheels, and zipped packages.
15+
abi:pythonPackage a owl:AnnotationProperty ;
16+
rdfs:label "python package"@en ;
17+
rdfs:comment "Dotted Python package used as the importlib.resources root for this ontology's files."@en .
18+
19+
abi:ontologyResource a owl:AnnotationProperty ;
20+
rdfs:label "ontology resource"@en ;
21+
rdfs:comment "Path to this ontology's .ttl file, relative to abi:pythonPackage."@en .
22+
23+
abi:pythonResource a owl:AnnotationProperty ;
24+
rdfs:label "python resource"@en ;
25+
rdfs:comment "Path to this ontology's generated .py file, relative to abi:pythonPackage. Used to build the dotted module for `from <module> import <Class>`."@en .
26+
1127
abi:EventService a owl:Ontology ;
1228
dc:title "Event Service Ontology"@en ;
1329
dc:description "Base ontology for engine events. Defines LogProcess as the root class for all events published through the EventService."@en ;
1430
dc:license <https://creativecommons.org/licenses/by/4.0/> ;
1531
rdfs:comment "All event types published through the EventService must be rdfs:subClassOf abi:LogProcess." ;
32+
abi:pythonPackage "naas_abi_core.services.event" ;
33+
abi:ontologyResource "ontologies/modules/EventOntology.ttl" ;
34+
abi:pythonResource "ontologies/modules/EventOntology.py" ;
1635
dc11:date "2026-05-22"^^xsd:date .
1736

1837
# Reference: BFO Process (parent class — included for the generator to resolve the hierarchy).

libs/naas-abi-core/naas_abi_core/services/object_storage/ontologies/modules/ObjectStorageEventOntology.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515
get_origin,
1616
)
1717

18-
from pydantic import BaseModel, Field, ValidationError
19-
from rdflib import Graph, Literal, Namespace, URIRef
20-
from rdflib.namespace import OWL, RDF, RDFS, XSD
21-
2218
from naas_abi_core.services.event.ontologies.modules.EventOntology import (
2319
LogProcess,
2420
)
21+
from pydantic import BaseModel, Field, ValidationError
22+
from rdflib import Graph, Literal, Namespace, URIRef
23+
from rdflib.namespace import OWL, RDF, RDFS, XSD
2524

2625
BFO = Namespace("http://purl.obolibrary.org/obo/")
2726
ABI = Namespace("http://ontology.naas.ai/abi/")

libs/naas-abi-core/naas_abi_core/services/object_storage/ontologies/modules/ObjectStorageEventOntology.ttl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ os:ObjectStorageEventOntology a owl:Ontology ;
1212
dc:title "Object Storage Event Ontology"@en ;
1313
dc:description "Events emitted by the ObjectStorageService when objects are written to or removed from the store."@en ;
1414
dc:license <https://creativecommons.org/licenses/by/4.0/> ;
15-
owl:imports <python://naas_abi_core.services.event.ontologies.modules/EventOntology.ttl> ;
15+
owl:imports <http://ontology.naas.ai/abi/EventService> ;
16+
abi:pythonPackage "naas_abi_core.services.object_storage" ;
17+
abi:ontologyResource "ontologies/modules/ObjectStorageEventOntology.ttl" ;
18+
abi:pythonResource "ontologies/modules/ObjectStorageEventOntology.py" ;
1619
dc11:date "2026-05-26"^^xsd:date .
1720

1821
# ObjectPut: published after ObjectStorageService.put_object() succeeds.

libs/naas-abi-core/naas_abi_core/utils/StorageUtils.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import json
2+
import pickle
23
from datetime import datetime
34
from io import BytesIO
4-
from typing import Dict, Tuple
5+
from typing import Any, Dict, Tuple
56

67
import pandas as pd
78
import yaml
@@ -465,3 +466,41 @@ def save_powerpoint_presentation(
465466
except Exception as e:
466467
logger.error(f"Error saving PowerPoint presentation to {dir_path}: {e}")
467468
return dir_path, file_name
469+
470+
def get_pickle(self, dir_path: str, file_name: str) -> Any | None:
471+
"""
472+
Get a pickled Python object from storage.
473+
474+
SECURITY: ``pickle.loads`` will execute arbitrary code embedded in
475+
the byte stream. Only call this on objects written by trusted
476+
producers in the same trust boundary.
477+
"""
478+
try:
479+
content = self.__storage_service.get_object(dir_path, file_name)
480+
if content is None:
481+
return None
482+
return pickle.loads(content) # nosec B301 — trusted internal storage only
483+
except Exception as e:
484+
logger.warning(f"Error getting pickle from {dir_path}/{file_name}: {e}")
485+
return None
486+
487+
def save_pickle(
488+
self, obj: Any, dir_path: str, file_name: str, copy: bool = True
489+
) -> Tuple[str, str]:
490+
"""
491+
Pickle a Python object and save it to storage.
492+
"""
493+
try:
494+
content = pickle.dumps(obj)
495+
self.__storage_service.put_object(
496+
prefix=dir_path, key=file_name, content=content
497+
)
498+
if copy:
499+
self.__make_copy(dir_path, file_name, content)
500+
logger.debug(
501+
f"[save_pickle] File successfully written to storage: {dir_path}/{file_name}"
502+
)
503+
return dir_path, file_name
504+
except Exception as e:
505+
logger.error(f"Error saving pickle to {dir_path}: {e}")
506+
return dir_path, file_name

0 commit comments

Comments
 (0)