pygrafito 0.8.0__py3-none-any.whl
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.
- pygrafito/__about__.py +6 -0
- pygrafito/__init__.py +71 -0
- pygrafito/__main__.py +9 -0
- pygrafito/cli/__init__.py +4 -0
- pygrafito/cli/app.py +184 -0
- pygrafito/cli/commands.py +927 -0
- pygrafito/cli/formatting.py +529 -0
- pygrafito/cli/reader.py +170 -0
- pygrafito/cli/session.py +667 -0
- pygrafito/cli/shell.py +219 -0
- pygrafito/engine/__init__.py +4 -0
- pygrafito/engine/graph.py +1265 -0
- pygrafito/engine/importing.py +644 -0
- pygrafito/engine/interop.py +973 -0
- pygrafito/engine/query/__init__.py +4 -0
- pygrafito/engine/query/ast.py +623 -0
- pygrafito/engine/query/compiler.py +1186 -0
- pygrafito/engine/query/executor.py +1657 -0
- pygrafito/engine/query/lexer.py +591 -0
- pygrafito/engine/query/mutation.py +768 -0
- pygrafito/engine/query/parser.py +1524 -0
- pygrafito/engine/query/pattern.py +608 -0
- pygrafito/engine/query/plan.py +278 -0
- pygrafito/engine/query/prepared.py +96 -0
- pygrafito/engine/query/results.py +186 -0
- pygrafito/engine/query/semantic.py +1470 -0
- pygrafito/engine/query/tokens.py +155 -0
- pygrafito/engine/query/values.py +1764 -0
- pygrafito/engine/transaction.py +547 -0
- pygrafito/engine/traversal.py +995 -0
- pygrafito/model.py +480 -0
- pygrafito/py.typed +0 -0
- pygrafito/storage/__init__.py +4 -0
- pygrafito/storage/codec.py +362 -0
- pygrafito/storage/connection.py +378 -0
- pygrafito/storage/constraints.py +854 -0
- pygrafito/storage/indexes.py +162 -0
- pygrafito/storage/nodes.py +617 -0
- pygrafito/storage/relationships.py +514 -0
- pygrafito/storage/schema.py +232 -0
- pygrafito/storage/views.py +203 -0
- pygrafito-0.8.0.dist-info/METADATA +99 -0
- pygrafito-0.8.0.dist-info/RECORD +46 -0
- pygrafito-0.8.0.dist-info/WHEEL +4 -0
- pygrafito-0.8.0.dist-info/entry_points.txt +2 -0
- pygrafito-0.8.0.dist-info/licenses/LICENSE.txt +18 -0
pygrafito/__about__.py
ADDED
pygrafito/__init__.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026-present Mario Abarca <knkillname@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Public package surface for the embedded property graph."""
|
|
5
|
+
|
|
6
|
+
from pygrafito.engine.graph import Graph
|
|
7
|
+
from pygrafito.engine.interop import InteropSummary
|
|
8
|
+
from pygrafito.engine.query.prepared import PreparedQuery
|
|
9
|
+
from pygrafito.engine.query.results import ImportSummary, MutationSummary, QueryResult, Row
|
|
10
|
+
from pygrafito.engine.transaction import Transaction
|
|
11
|
+
from pygrafito.model import (
|
|
12
|
+
ConnectedNodeError,
|
|
13
|
+
Constraint,
|
|
14
|
+
ConstraintViolationError,
|
|
15
|
+
Direction,
|
|
16
|
+
ElementKind,
|
|
17
|
+
GraphClosedError,
|
|
18
|
+
HandleAffinityError,
|
|
19
|
+
Index,
|
|
20
|
+
IndexKind,
|
|
21
|
+
LockTimeoutError,
|
|
22
|
+
Node,
|
|
23
|
+
NotFoundError,
|
|
24
|
+
Path,
|
|
25
|
+
PygrafitoError,
|
|
26
|
+
QueryError,
|
|
27
|
+
QueryExecutionError,
|
|
28
|
+
QuerySemanticError,
|
|
29
|
+
QuerySyntaxError,
|
|
30
|
+
ReadOnlyError,
|
|
31
|
+
Relationship,
|
|
32
|
+
TransactionError,
|
|
33
|
+
TraversalStep,
|
|
34
|
+
UnsupportedSqliteError,
|
|
35
|
+
ValidationError,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"ConnectedNodeError",
|
|
40
|
+
"Constraint",
|
|
41
|
+
"ConstraintViolationError",
|
|
42
|
+
"Direction",
|
|
43
|
+
"ElementKind",
|
|
44
|
+
"Graph",
|
|
45
|
+
"GraphClosedError",
|
|
46
|
+
"HandleAffinityError",
|
|
47
|
+
"ImportSummary",
|
|
48
|
+
"Index",
|
|
49
|
+
"IndexKind",
|
|
50
|
+
"InteropSummary",
|
|
51
|
+
"LockTimeoutError",
|
|
52
|
+
"MutationSummary",
|
|
53
|
+
"Node",
|
|
54
|
+
"NotFoundError",
|
|
55
|
+
"Path",
|
|
56
|
+
"PreparedQuery",
|
|
57
|
+
"PygrafitoError",
|
|
58
|
+
"QueryError",
|
|
59
|
+
"QueryExecutionError",
|
|
60
|
+
"QueryResult",
|
|
61
|
+
"QuerySemanticError",
|
|
62
|
+
"QuerySyntaxError",
|
|
63
|
+
"ReadOnlyError",
|
|
64
|
+
"Relationship",
|
|
65
|
+
"Row",
|
|
66
|
+
"Transaction",
|
|
67
|
+
"TransactionError",
|
|
68
|
+
"TraversalStep",
|
|
69
|
+
"UnsupportedSqliteError",
|
|
70
|
+
"ValidationError",
|
|
71
|
+
]
|
pygrafito/__main__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026-present Mario Abarca <knkillname@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Module entry point for ``python -m pygrafito``."""
|
|
5
|
+
|
|
6
|
+
from pygrafito.cli.app import App
|
|
7
|
+
|
|
8
|
+
if __name__ == "__main__":
|
|
9
|
+
raise SystemExit(App.main())
|
pygrafito/cli/app.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026-present Mario Abarca <knkillname@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Process entry point for the graph shell."""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import sys
|
|
8
|
+
import typing
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from pygrafito import PygrafitoError, ValidationError
|
|
12
|
+
from pygrafito.cli.formatting import OutputMode
|
|
13
|
+
from pygrafito.cli.session import ParameterDecoder, Session
|
|
14
|
+
from pygrafito.cli.shell import Shell
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class App:
|
|
18
|
+
"""Wire arguments, streams, and a session into one process run."""
|
|
19
|
+
|
|
20
|
+
DESCRIPTION: typing.ClassVar[str] = (
|
|
21
|
+
"Interactive and scripted shell for an embedded property graph."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def main(argv: typing.Sequence[str] | None = None) -> int:
|
|
26
|
+
"""Run the shell.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
argv : typing.Sequence[str] | None, optional
|
|
31
|
+
Argument list, by default the process arguments.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
int
|
|
36
|
+
Process exit code.
|
|
37
|
+
"""
|
|
38
|
+
parser = App._parser()
|
|
39
|
+
arguments = parser.parse_args(argv)
|
|
40
|
+
if arguments.readonly and arguments.database is None:
|
|
41
|
+
parser.error("--readonly requires a database path")
|
|
42
|
+
parameters: dict[str, object] = {}
|
|
43
|
+
for item in typing.cast(list[str], arguments.param):
|
|
44
|
+
try:
|
|
45
|
+
name, value = ParameterDecoder.decode(item)
|
|
46
|
+
except ValidationError as error:
|
|
47
|
+
parser.error(str(error))
|
|
48
|
+
parameters[name] = value
|
|
49
|
+
interactive = arguments.command is None and arguments.file is None and sys.stdin.isatty()
|
|
50
|
+
session = Session(
|
|
51
|
+
mode=OutputMode.from_name(arguments.format),
|
|
52
|
+
headers=True,
|
|
53
|
+
timer=False,
|
|
54
|
+
quiet=arguments.quiet,
|
|
55
|
+
interactive=interactive,
|
|
56
|
+
readonly=arguments.readonly,
|
|
57
|
+
output=sys.stdout,
|
|
58
|
+
error=sys.stderr,
|
|
59
|
+
)
|
|
60
|
+
for name, value in parameters.items():
|
|
61
|
+
session.set_parameter(name, value)
|
|
62
|
+
try:
|
|
63
|
+
session.open_database(arguments.database)
|
|
64
|
+
except (PygrafitoError, OSError) as error:
|
|
65
|
+
session.report_error(error)
|
|
66
|
+
return 1
|
|
67
|
+
shell = Shell(session, input=sys.stdin, error=sys.stderr)
|
|
68
|
+
try:
|
|
69
|
+
return App._run(shell, session, arguments)
|
|
70
|
+
except KeyboardInterrupt:
|
|
71
|
+
session.warn("interrupted")
|
|
72
|
+
return 130
|
|
73
|
+
finally:
|
|
74
|
+
session.finish()
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def _run(
|
|
78
|
+
cls,
|
|
79
|
+
shell: Shell,
|
|
80
|
+
session: Session,
|
|
81
|
+
arguments: argparse.Namespace,
|
|
82
|
+
) -> int:
|
|
83
|
+
"""Select the input mode and run it.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
shell : Shell
|
|
88
|
+
Shell bound to the session.
|
|
89
|
+
session : Session
|
|
90
|
+
Session under test.
|
|
91
|
+
arguments : argparse.Namespace
|
|
92
|
+
Parsed arguments.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
int
|
|
97
|
+
Process exit code.
|
|
98
|
+
"""
|
|
99
|
+
if arguments.command is not None:
|
|
100
|
+
return shell.run_script(arguments.command)
|
|
101
|
+
if arguments.file is not None:
|
|
102
|
+
return cls._run_file(shell, session, arguments.file)
|
|
103
|
+
if not session.interactive:
|
|
104
|
+
return shell.run_script(sys.stdin.read())
|
|
105
|
+
return shell.run()
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def _run_file(cls, shell: Shell, session: Session, path: str) -> int:
|
|
109
|
+
"""Run a script file.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
shell : Shell
|
|
114
|
+
Shell bound to the session.
|
|
115
|
+
session : Session
|
|
116
|
+
Session under test.
|
|
117
|
+
path : str
|
|
118
|
+
Script path.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
int
|
|
123
|
+
Process exit code.
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
text = Path(path).read_text(encoding="utf-8")
|
|
127
|
+
except OSError as error:
|
|
128
|
+
session.report_error(error)
|
|
129
|
+
return 1
|
|
130
|
+
return shell.run_script(text)
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def _parser(cls) -> argparse.ArgumentParser:
|
|
134
|
+
"""Build the argument parser.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
argparse.ArgumentParser
|
|
139
|
+
Configured parser.
|
|
140
|
+
"""
|
|
141
|
+
parser = argparse.ArgumentParser(prog="pygrafito", description=cls.DESCRIPTION)
|
|
142
|
+
parser.add_argument(
|
|
143
|
+
"database",
|
|
144
|
+
nargs="?",
|
|
145
|
+
help="database file; omit for a transient in-memory graph",
|
|
146
|
+
)
|
|
147
|
+
source = parser.add_mutually_exclusive_group()
|
|
148
|
+
source.add_argument(
|
|
149
|
+
"-c",
|
|
150
|
+
"--command",
|
|
151
|
+
metavar="TEXT",
|
|
152
|
+
help="run statements and exit",
|
|
153
|
+
)
|
|
154
|
+
source.add_argument(
|
|
155
|
+
"-f",
|
|
156
|
+
"--file",
|
|
157
|
+
metavar="PATH",
|
|
158
|
+
help="run a script file and exit",
|
|
159
|
+
)
|
|
160
|
+
parser.add_argument(
|
|
161
|
+
"--format",
|
|
162
|
+
choices=[mode.value for mode in OutputMode],
|
|
163
|
+
default=OutputMode.TABLE.value,
|
|
164
|
+
help="result rendering mode (default: table)",
|
|
165
|
+
)
|
|
166
|
+
parser.add_argument(
|
|
167
|
+
"--param",
|
|
168
|
+
action="append",
|
|
169
|
+
default=[],
|
|
170
|
+
metavar="NAME=JSON",
|
|
171
|
+
help="bind a query parameter; repeatable",
|
|
172
|
+
)
|
|
173
|
+
parser.add_argument(
|
|
174
|
+
"--readonly",
|
|
175
|
+
action="store_true",
|
|
176
|
+
help="open the database without write access",
|
|
177
|
+
)
|
|
178
|
+
parser.add_argument(
|
|
179
|
+
"-q",
|
|
180
|
+
"--quiet",
|
|
181
|
+
action="store_true",
|
|
182
|
+
help="suppress the banner and interactive footers",
|
|
183
|
+
)
|
|
184
|
+
return parser
|