kraph 3.0.1__tar.gz → 4.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kraph-4.1.0/PKG-INFO ADDED
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.5
2
+ Name: kraph
3
+ Version: 4.1.0
4
+ Summary: the arkitekt knowledge graph
5
+ Author-email: jhnnsrs <jhnnsrs@gmail.com>
6
+ License-Expression: GPL-3.0-or-later
7
+ Requires-Python: <4.0,>=3.11
8
+ Requires-Dist: arkitekt-spec>=1.4
9
+ Requires-Dist: dokker>=2.8
10
+ Requires-Dist: fakts>=4
11
+ Requires-Dist: rath>=4.1.1
12
+ Requires-Dist: websockets>=15.0.1
13
+ Description-Content-Type: text/markdown
14
+
15
+ # kraph
16
+
17
+ [![PyPI version](https://badge.fury.io/py/kraph.svg)](https://pypi.org/project/kraph/)
18
+ [![PyPI pyversions](https://img.shields.io/pypi/pyversions/kraph.svg)](https://pypi.python.org/pypi/kraph/)
19
+
20
+ The python client for kraph, the [Arkitekt](https://arkitekt.live) knowledge graph service built
21
+ around Apache AGE: recording claims about entities, events, measurements and metrics, backed by the
22
+ structures (images, tables, …) that are evidence for them, and drawing them into graphs.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install kraph
28
+ ```
29
+
30
+ With arkitekt, `pip install "arkitekt[rekuest,kraph]"` brings it in.
31
+
32
+ ## Concepts
33
+
34
+ - **Claims** — an entity exists, a structure measures it, two things are related — are recorded
35
+ under a *term*, a word your organization owns, never under a graph. Retracting a claim records a
36
+ position rather than deleting anything.
37
+ - **Graphs** are views. A graph declares *categories* (entity, relation, measurement, event, …)
38
+ that say what its words mean, and draws the claims made under those words.
39
+
40
+ ## Usage
41
+
42
+ Every kraph operation is a method of the `Kraph` client, in a blocking and an `a`-prefixed async
43
+ flavour (`kraph.create_graph(...)`, `await kraph.acreate_graph(...)`). What a call returns remembers
44
+ the client, so follow-ups from a result go through the same client.
45
+
46
+ ### In an arkitekt app
47
+
48
+ Add the service to your app and ask for `kraph: Kraph`; the client is injected by annotation.
49
+ Graphs, categories, structures, metrics, terms and more travel between actions by id
50
+ (`@kraph/graph`, `@kraph/entitycategory`, `@kraph/structure`, `@kraph/term`, …), so an action can
51
+ take and return them directly:
52
+
53
+ ```python
54
+ from arkitekt import App, run
55
+ from kraph import Kraph, kraph_service
56
+
57
+ app = App("neuron-claims", "0.1.0", services=[kraph_service])
58
+
59
+
60
+ @app.action
61
+ def claim_neuron(kraph: Kraph) -> str:
62
+ """Claim Neuron
63
+
64
+ Records that a neuron exists.
65
+ """
66
+ asserted = kraph.assert_entity_exists(
67
+ term="Neuron", supporting_evidence=[], derived_from=[], same_as=[]
68
+ )
69
+ return asserted.instance.id
70
+
71
+
72
+ if __name__ == "__main__":
73
+ run(app)
74
+ ```
75
+
76
+ ### From a script
77
+
78
+ ```python
79
+ from arkitekt import easy
80
+ from kraph import kraph_service
81
+
82
+ with easy("my-script", kraph_service) as kraph:
83
+ graph = kraph.create_graph(name="Neurons", backfill=False)
84
+ kraph.create_entity_category(
85
+ key="Neuron",
86
+ ontology_references=[],
87
+ property_definitions=[],
88
+ graph=graph.id,
89
+ backfill=True,
90
+ )
91
+
92
+ asserted = kraph.assert_entity_exists(
93
+ term="Neuron", supporting_evidence=[], derived_from=[], same_as=[]
94
+ )
95
+ print(asserted.is_drawn) # True: the graph declares "Neuron", so it draws the claim
96
+ ```
97
+
98
+ ## Testing
99
+
100
+ ```bash
101
+ uv run pytest -m "not integration" # no server needed
102
+ uv run pytest -m integration # a real kraph via dokker
103
+ ```
104
+
105
+ See [RELEASING.md](RELEASING.md) for how versions are cut.
kraph-4.1.0/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # kraph
2
+
3
+ [![PyPI version](https://badge.fury.io/py/kraph.svg)](https://pypi.org/project/kraph/)
4
+ [![PyPI pyversions](https://img.shields.io/pypi/pyversions/kraph.svg)](https://pypi.python.org/pypi/kraph/)
5
+
6
+ The python client for kraph, the [Arkitekt](https://arkitekt.live) knowledge graph service built
7
+ around Apache AGE: recording claims about entities, events, measurements and metrics, backed by the
8
+ structures (images, tables, …) that are evidence for them, and drawing them into graphs.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pip install kraph
14
+ ```
15
+
16
+ With arkitekt, `pip install "arkitekt[rekuest,kraph]"` brings it in.
17
+
18
+ ## Concepts
19
+
20
+ - **Claims** — an entity exists, a structure measures it, two things are related — are recorded
21
+ under a *term*, a word your organization owns, never under a graph. Retracting a claim records a
22
+ position rather than deleting anything.
23
+ - **Graphs** are views. A graph declares *categories* (entity, relation, measurement, event, …)
24
+ that say what its words mean, and draws the claims made under those words.
25
+
26
+ ## Usage
27
+
28
+ Every kraph operation is a method of the `Kraph` client, in a blocking and an `a`-prefixed async
29
+ flavour (`kraph.create_graph(...)`, `await kraph.acreate_graph(...)`). What a call returns remembers
30
+ the client, so follow-ups from a result go through the same client.
31
+
32
+ ### In an arkitekt app
33
+
34
+ Add the service to your app and ask for `kraph: Kraph`; the client is injected by annotation.
35
+ Graphs, categories, structures, metrics, terms and more travel between actions by id
36
+ (`@kraph/graph`, `@kraph/entitycategory`, `@kraph/structure`, `@kraph/term`, …), so an action can
37
+ take and return them directly:
38
+
39
+ ```python
40
+ from arkitekt import App, run
41
+ from kraph import Kraph, kraph_service
42
+
43
+ app = App("neuron-claims", "0.1.0", services=[kraph_service])
44
+
45
+
46
+ @app.action
47
+ def claim_neuron(kraph: Kraph) -> str:
48
+ """Claim Neuron
49
+
50
+ Records that a neuron exists.
51
+ """
52
+ asserted = kraph.assert_entity_exists(
53
+ term="Neuron", supporting_evidence=[], derived_from=[], same_as=[]
54
+ )
55
+ return asserted.instance.id
56
+
57
+
58
+ if __name__ == "__main__":
59
+ run(app)
60
+ ```
61
+
62
+ ### From a script
63
+
64
+ ```python
65
+ from arkitekt import easy
66
+ from kraph import kraph_service
67
+
68
+ with easy("my-script", kraph_service) as kraph:
69
+ graph = kraph.create_graph(name="Neurons", backfill=False)
70
+ kraph.create_entity_category(
71
+ key="Neuron",
72
+ ontology_references=[],
73
+ property_definitions=[],
74
+ graph=graph.id,
75
+ backfill=True,
76
+ )
77
+
78
+ asserted = kraph.assert_entity_exists(
79
+ term="Neuron", supporting_evidence=[], derived_from=[], same_as=[]
80
+ )
81
+ print(asserted.is_drawn) # True: the graph declares "Neuron", so it draws the claim
82
+ ```
83
+
84
+ ## Testing
85
+
86
+ ```bash
87
+ uv run pytest -m "not integration" # no server needed
88
+ uv run pytest -m integration # a real kraph via dokker
89
+ ```
90
+
91
+ See [RELEASING.md](RELEASING.md) for how versions are cut.
@@ -0,0 +1,7 @@
1
+ from .kraph import Kraph
2
+
3
+
4
+ # The service is declared with arkitekt-spec, a core dependency: it is always there.
5
+ from .arkitekt import kraph as kraph_service
6
+
7
+ __all__ = ["Kraph", "kraph_service"]
@@ -35,8 +35,8 @@ from rath.links.graphql_ws import GraphQLWSLink
35
35
  from rath.links.shrink import ShrinkingLink
36
36
  from rath.links.split import SplitLink
37
37
 
38
- from rekuest.app import AppRegistry
39
- from rekuest.widgets import SearchWidget
38
+ from arkitekt_spec.declare.app import AppRegistry
39
+ from arkitekt_spec.declare.widgets import SearchWidget
40
40
 
41
41
  from kraph.api.schema import (
42
42
  EntityCategory,
@@ -111,8 +111,8 @@ def kraph(
111
111
  FaktsAuthLink(token_loader=tokens),
112
112
  UploadLink(datalayer=store),
113
113
  SplitLink(
114
- left=AIOHttpLink(endpoint_url=kraph.to_http_path("graphql")),
115
- right=GraphQLWSLink(ws_endpoint_url=kraph.to_ws_path("graphql")),
114
+ left=AIOHttpLink(endpoint_url=kraph.to_http_path("graphql"), proxy=kraph.proxy),
115
+ right=GraphQLWSLink(ws_endpoint_url=kraph.to_ws_path("graphql"), proxy=kraph.proxy),
116
116
  split=lambda o: o.node.operation != OperationType.SUBSCRIPTION,
117
117
  ),
118
118
  )
@@ -52,6 +52,9 @@ class DataLayer(KoiledModel):
52
52
  """
53
53
 
54
54
  endpoint_url: str = ""
55
+ proxy: str | None = None
56
+ """The HTTP forward proxy (``http://host:port``) the store is only reachable
57
+ through, when it sits on a private mesh. ``None`` connects directly."""
55
58
 
56
59
 
57
60
  @classmethod
@@ -64,7 +67,7 @@ class DataLayer(KoiledModel):
64
67
  Returns:
65
68
  The datalayer, ready to use.
66
69
  """
67
- return cls(endpoint_url=alias.to_http_path())
70
+ return cls(endpoint_url=alias.to_http_path(), proxy=alias.proxy)
68
71
 
69
72
  async def get_endpoint_url(self):
70
73
  return self.endpoint_url
@@ -12,7 +12,10 @@ async def adownload_file(datalayer: "DataLayer", presigned_url: str, file_name:
12
12
  endpoint_url = await datalayer.get_endpoint_url()
13
13
 
14
14
  async with aiohttp.ClientSession() as session:
15
- async with session.get(endpoint_url + presigned_url) as response:
15
+ # ``proxy=None`` is aiohttp's own default, so an unproxied datalayer is unchanged.
16
+ async with session.get(
17
+ endpoint_url + presigned_url, proxy=datalayer.proxy
18
+ ) as response:
16
19
  with open(file_name, "wb") as file:
17
20
  while True:
18
21
  chunk = await response.content.read(
@@ -32,7 +32,7 @@ from rath.turms.utils import get_attributes_or_error
32
32
  from kraph.client import client_of
33
33
 
34
34
  if TYPE_CHECKING:
35
- from rekuest.structures.registry import StructureRegistry
35
+ from arkitekt_spec.declare.structures.registry import StructureRegistry
36
36
 
37
37
  from kraph.kraph import Kraph
38
38
 
@@ -10,9 +10,12 @@ requires-python = ">=3.11, <4.0"
10
10
  license = "GPL-3.0-or-later"
11
11
  dependencies = [
12
12
  "dokker>=2.8",
13
- "rath>=4",
14
- "rekuest>=4",
13
+ "rath>=4.1.1",
15
14
  "websockets>=15.0.1",
15
+ # The service and structures are declared with arkitekt-spec.
16
+ "arkitekt-spec>=1.4",
17
+ # The service wiring (Alias, Require, FaktsAuthLink); it came through rekuest before.
18
+ "fakts>=4",
16
19
  ]
17
20
 
18
21
  [project.optional-dependencies]
kraph-3.0.1/PKG-INFO DELETED
@@ -1,30 +0,0 @@
1
- Metadata-Version: 2.5
2
- Name: kraph
3
- Version: 3.0.1
4
- Summary: the arkitekt knowledge graph
5
- Author-email: jhnnsrs <jhnnsrs@gmail.com>
6
- License-Expression: GPL-3.0-or-later
7
- Requires-Python: <4.0,>=3.11
8
- Requires-Dist: dokker>=2.8
9
- Requires-Dist: rath>=4
10
- Requires-Dist: rekuest>=4
11
- Requires-Dist: websockets>=15.0.1
12
- Description-Content-Type: text/markdown
13
-
14
- # kraph
15
-
16
- Kraph is a Python library for creating and manipulating knowledge graphs build around apache AGE.
17
-
18
- ## Features
19
-
20
- - Create and manipulate knowledge graphs
21
- - Query knowledge graphs using Cypher
22
- - Ontology support (custom entities and relationships)
23
- - GraphQL API for adding and querying data
24
-
25
-
26
- ## Installation
27
-
28
- ```bash
29
- pip install kraph
30
- ```
kraph-3.0.1/README.md DELETED
@@ -1,17 +0,0 @@
1
- # kraph
2
-
3
- Kraph is a Python library for creating and manipulating knowledge graphs build around apache AGE.
4
-
5
- ## Features
6
-
7
- - Create and manipulate knowledge graphs
8
- - Query knowledge graphs using Cypher
9
- - Ontology support (custom entities and relationships)
10
- - GraphQL API for adding and querying data
11
-
12
-
13
- ## Installation
14
-
15
- ```bash
16
- pip install kraph
17
- ```
@@ -1,18 +0,0 @@
1
- from .kraph import Kraph
2
-
3
-
4
- try:
5
- from .arkitekt import kraph as kraph_service
6
- except ImportError as e:
7
- # Only "rekuest is not installed" may pass silently. Anything else that fails
8
- # to import here (a renamed query, a rekuest too old for what the module
9
- # needs) is a bug, and hiding it makes this package's service vanish
10
- # without a word. Whether it is installed is asked the plain way.
11
- try:
12
- import rekuest # noqa: F401 -- presence is the question
13
- except ImportError:
14
- pass
15
- else:
16
- raise e
17
-
18
- __all__ = ["Kraph", "kraph_service"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes