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.
Files changed (46) hide show
  1. pygrafito/__about__.py +6 -0
  2. pygrafito/__init__.py +71 -0
  3. pygrafito/__main__.py +9 -0
  4. pygrafito/cli/__init__.py +4 -0
  5. pygrafito/cli/app.py +184 -0
  6. pygrafito/cli/commands.py +927 -0
  7. pygrafito/cli/formatting.py +529 -0
  8. pygrafito/cli/reader.py +170 -0
  9. pygrafito/cli/session.py +667 -0
  10. pygrafito/cli/shell.py +219 -0
  11. pygrafito/engine/__init__.py +4 -0
  12. pygrafito/engine/graph.py +1265 -0
  13. pygrafito/engine/importing.py +644 -0
  14. pygrafito/engine/interop.py +973 -0
  15. pygrafito/engine/query/__init__.py +4 -0
  16. pygrafito/engine/query/ast.py +623 -0
  17. pygrafito/engine/query/compiler.py +1186 -0
  18. pygrafito/engine/query/executor.py +1657 -0
  19. pygrafito/engine/query/lexer.py +591 -0
  20. pygrafito/engine/query/mutation.py +768 -0
  21. pygrafito/engine/query/parser.py +1524 -0
  22. pygrafito/engine/query/pattern.py +608 -0
  23. pygrafito/engine/query/plan.py +278 -0
  24. pygrafito/engine/query/prepared.py +96 -0
  25. pygrafito/engine/query/results.py +186 -0
  26. pygrafito/engine/query/semantic.py +1470 -0
  27. pygrafito/engine/query/tokens.py +155 -0
  28. pygrafito/engine/query/values.py +1764 -0
  29. pygrafito/engine/transaction.py +547 -0
  30. pygrafito/engine/traversal.py +995 -0
  31. pygrafito/model.py +480 -0
  32. pygrafito/py.typed +0 -0
  33. pygrafito/storage/__init__.py +4 -0
  34. pygrafito/storage/codec.py +362 -0
  35. pygrafito/storage/connection.py +378 -0
  36. pygrafito/storage/constraints.py +854 -0
  37. pygrafito/storage/indexes.py +162 -0
  38. pygrafito/storage/nodes.py +617 -0
  39. pygrafito/storage/relationships.py +514 -0
  40. pygrafito/storage/schema.py +232 -0
  41. pygrafito/storage/views.py +203 -0
  42. pygrafito-0.8.0.dist-info/METADATA +99 -0
  43. pygrafito-0.8.0.dist-info/RECORD +46 -0
  44. pygrafito-0.8.0.dist-info/WHEEL +4 -0
  45. pygrafito-0.8.0.dist-info/entry_points.txt +2 -0
  46. pygrafito-0.8.0.dist-info/licenses/LICENSE.txt +18 -0
pygrafito/__about__.py ADDED
@@ -0,0 +1,6 @@
1
+ # SPDX-FileCopyrightText: 2026-present Mario Abarca <knkillname@gmail.com>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Package version metadata."""
5
+
6
+ __version__ = "0.8.0"
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())
@@ -0,0 +1,4 @@
1
+ # SPDX-FileCopyrightText: 2026-present Mario Abarca <knkillname@gmail.com>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Command-line shell for an embedded property graph."""
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