rbtr-lang-python 2026.7.0.dev0__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.
- rbtr_lang_python/__init__.py +1 -0
- rbtr_lang_python/plugin.py +120 -0
- rbtr_lang_python/py.typed +0 -0
- rbtr_lang_python/python.scm +59 -0
- rbtr_lang_python/tests/__init__.py +0 -0
- rbtr_lang_python/tests/__snapshots__/test_samples/test_edges_match_snapshot.json +3 -0
- rbtr_lang_python/tests/__snapshots__/test_samples/test_extraction_matches_snapshot.json +470 -0
- rbtr_lang_python/tests/cases_docstrings.py +174 -0
- rbtr_lang_python/tests/cases_extraction.py +572 -0
- rbtr_lang_python/tests/samples/python/config.py +3 -0
- rbtr_lang_python/tests/samples/python/python.py +84 -0
- rbtr_lang_python/tests/test_docstrings.py +54 -0
- rbtr_lang_python/tests/test_extraction.py +110 -0
- rbtr_lang_python/tests/test_samples.py +83 -0
- rbtr_lang_python-2026.7.0.dev0.dist-info/METADATA +8 -0
- rbtr_lang_python-2026.7.0.dev0.dist-info/RECORD +18 -0
- rbtr_lang_python-2026.7.0.dev0.dist-info/WHEEL +4 -0
- rbtr_lang_python-2026.7.0.dev0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Python language plugin package."""
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Python language plugin.
|
|
2
|
+
|
|
3
|
+
Provides full support: symbol extraction (functions, classes,
|
|
4
|
+
methods, imports) and structured import metadata.
|
|
5
|
+
|
|
6
|
+
Extracted chunks::
|
|
7
|
+
|
|
8
|
+
def hello(): → function "hello", scope ""
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
class Config: → class "Config", scope ""
|
|
12
|
+
def load(self): → method "load", scope "Config"
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
import os → import, metadata {module: "os"}
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
→ import, metadata {module: "pathlib", names: "Path"}
|
|
18
|
+
from ..core import engine
|
|
19
|
+
→ import, metadata {dots: "2", module: "core",
|
|
20
|
+
names: "engine"}
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
27
|
+
from rbtr.index.models import ImportMeta
|
|
28
|
+
from rbtr.languages.registration import (
|
|
29
|
+
ImportResolver,
|
|
30
|
+
LanguageRegistration,
|
|
31
|
+
ModuleStyle,
|
|
32
|
+
QueryExtraction,
|
|
33
|
+
load_query,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from tree_sitter import Node
|
|
38
|
+
|
|
39
|
+
# ── Query ────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
# The `@_docstring` sub-capture marks the first-statement body
|
|
42
|
+
# docstring for doc-range detection (used by `extract_doc_spans`
|
|
43
|
+
# and the eval query sampler). It is optional in the match
|
|
44
|
+
# (`?`), so functions/classes without a docstring still match.
|
|
45
|
+
|
|
46
|
+
# ── Import extractor ─────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def extract_import_meta(
|
|
50
|
+
resolver: ImportResolver, node: Node, captures: dict[str, list[Node]]
|
|
51
|
+
) -> ImportMeta:
|
|
52
|
+
"""Extract structured import data from a Python import node.
|
|
53
|
+
|
|
54
|
+
Reads query captures (`@_import_module`, `@_import_dots`)
|
|
55
|
+
and walks the node for multi-valued import names (which
|
|
56
|
+
the query can't capture).
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
|
|
60
|
+
`import os.path`:
|
|
61
|
+
module="os.path"
|
|
62
|
+
|
|
63
|
+
`from pathlib import Path`:
|
|
64
|
+
module="pathlib", names="Path"
|
|
65
|
+
|
|
66
|
+
`from ..core import engine`:
|
|
67
|
+
dots="2", module="core", names="engine"
|
|
68
|
+
|
|
69
|
+
`from .models import Chunk as C`:
|
|
70
|
+
dots="1", module="models", names="Chunk"
|
|
71
|
+
|
|
72
|
+
`from . import utils`:
|
|
73
|
+
dots="1", names="utils"
|
|
74
|
+
"""
|
|
75
|
+
meta = resolver(node, captures)
|
|
76
|
+
|
|
77
|
+
# Convert @_import_dots from raw import_prefix (e.g. "..")
|
|
78
|
+
# to a count string.
|
|
79
|
+
dots_nodes = captures.get("_import_dots", [])
|
|
80
|
+
if dots_nodes and dots_nodes[0].text:
|
|
81
|
+
meta.dots = str(dots_nodes[0].text.decode().count("."))
|
|
82
|
+
|
|
83
|
+
if node.type == "import_from_statement":
|
|
84
|
+
# Imported names. The `name` field can be dotted_name
|
|
85
|
+
# or aliased_import; there may be multiple `name` fields.
|
|
86
|
+
names: list[str] = []
|
|
87
|
+
for name_node in node.children_by_field_name("name"):
|
|
88
|
+
match name_node.type:
|
|
89
|
+
case "dotted_name":
|
|
90
|
+
if name_node.text:
|
|
91
|
+
names.append(name_node.text.decode())
|
|
92
|
+
case "aliased_import":
|
|
93
|
+
original = name_node.child_by_field_name("name")
|
|
94
|
+
if original and original.text:
|
|
95
|
+
names.append(original.text.decode())
|
|
96
|
+
if names:
|
|
97
|
+
meta.names = ",".join(names)
|
|
98
|
+
|
|
99
|
+
return meta
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# ── Plugin ───────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
python = LanguageRegistration(
|
|
106
|
+
id="python",
|
|
107
|
+
extensions=frozenset({".py", ".pyi"}),
|
|
108
|
+
grammar_module="tree_sitter_python",
|
|
109
|
+
extraction=QueryExtraction(
|
|
110
|
+
query=load_query(__package__, "python"),
|
|
111
|
+
scope_types=frozenset({"class_definition", "function_definition"}),
|
|
112
|
+
class_scope_types=frozenset({"class_definition"}),
|
|
113
|
+
),
|
|
114
|
+
index_files=frozenset({"__init__.py"}),
|
|
115
|
+
source_roots=("", "src"),
|
|
116
|
+
module_style=ModuleStyle.DOTTED,
|
|
117
|
+
extraction_serial=5,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
python.import_extractor(extract_import_meta)
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
; Comments and the module docstring. The engine groups comments into
|
|
2
|
+
; blank-line-delimited blocks and either folds a block into the symbol flush
|
|
3
|
+
; after it (its docstring, possibly nested), drops it if interior, or emits
|
|
4
|
+
; it as a standalone COMMENT chunk.
|
|
5
|
+
(comment) @comment
|
|
6
|
+
(module (expression_statement (string) @comment))
|
|
7
|
+
|
|
8
|
+
(function_definition
|
|
9
|
+
name: (identifier) @_fn_name
|
|
10
|
+
body: (block
|
|
11
|
+
. (expression_statement (string) @_docstring)?)) @function
|
|
12
|
+
|
|
13
|
+
(class_definition
|
|
14
|
+
name: (identifier) @_cls_name
|
|
15
|
+
body: (block
|
|
16
|
+
. (expression_statement (string) @_docstring)?)) @class
|
|
17
|
+
|
|
18
|
+
(type_alias_statement
|
|
19
|
+
. (type (identifier) @_cls_name)) @class
|
|
20
|
+
|
|
21
|
+
(module
|
|
22
|
+
(expression_statement
|
|
23
|
+
(assignment
|
|
24
|
+
left: (identifier) @_var_name) @variable))
|
|
25
|
+
|
|
26
|
+
(module
|
|
27
|
+
(expression_statement
|
|
28
|
+
(assignment
|
|
29
|
+
left: (pattern_list (identifier) @_var_name)) @variable))
|
|
30
|
+
|
|
31
|
+
(module
|
|
32
|
+
(expression_statement
|
|
33
|
+
(assignment
|
|
34
|
+
left: (tuple_pattern (identifier) @_var_name)) @variable))
|
|
35
|
+
|
|
36
|
+
(module
|
|
37
|
+
(expression_statement
|
|
38
|
+
(assignment
|
|
39
|
+
left: (list_pattern (identifier) @_var_name)) @variable))
|
|
40
|
+
|
|
41
|
+
(module
|
|
42
|
+
(expression_statement
|
|
43
|
+
(assignment
|
|
44
|
+
left: (pattern_list (list_splat_pattern (identifier) @_var_name))) @variable))
|
|
45
|
+
|
|
46
|
+
(import_statement
|
|
47
|
+
name: (dotted_name) @_import_module) @import
|
|
48
|
+
|
|
49
|
+
(import_from_statement
|
|
50
|
+
module_name: (dotted_name) @_import_module) @import
|
|
51
|
+
|
|
52
|
+
(import_from_statement
|
|
53
|
+
module_name: (relative_import
|
|
54
|
+
(import_prefix) @_import_dots
|
|
55
|
+
(dotted_name) @_import_module)) @import
|
|
56
|
+
|
|
57
|
+
(import_from_statement
|
|
58
|
+
module_name: (relative_import
|
|
59
|
+
(import_prefix) @_import_dots .)) @import
|
|
File without changes
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "8a4843f093a489a4",
|
|
4
|
+
"blob_sha": "sha1",
|
|
5
|
+
"file_path": "config.py",
|
|
6
|
+
"kind": "comment",
|
|
7
|
+
"name": "<anonymous>",
|
|
8
|
+
"scope": "",
|
|
9
|
+
"language": "python",
|
|
10
|
+
"content": "\"\"\"Configuration values for the greeter.\"\"\"",
|
|
11
|
+
"line_start": 1,
|
|
12
|
+
"line_end": 1,
|
|
13
|
+
"metadata": {
|
|
14
|
+
"module": "",
|
|
15
|
+
"names": "",
|
|
16
|
+
"dots": "",
|
|
17
|
+
"language_hint": ""
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "e03be7d87e70e097",
|
|
22
|
+
"blob_sha": "sha1",
|
|
23
|
+
"file_path": "config.py",
|
|
24
|
+
"kind": "variable",
|
|
25
|
+
"name": "LOCALE",
|
|
26
|
+
"scope": "",
|
|
27
|
+
"language": "python",
|
|
28
|
+
"content": "LOCALE = \"en\"",
|
|
29
|
+
"line_start": 3,
|
|
30
|
+
"line_end": 3,
|
|
31
|
+
"metadata": {
|
|
32
|
+
"module": "",
|
|
33
|
+
"names": "",
|
|
34
|
+
"dots": "",
|
|
35
|
+
"language_hint": ""
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "90a5683217fcbf40",
|
|
40
|
+
"blob_sha": "sha1",
|
|
41
|
+
"file_path": "python.py",
|
|
42
|
+
"kind": "comment",
|
|
43
|
+
"name": "<anonymous>",
|
|
44
|
+
"scope": "",
|
|
45
|
+
"language": "python",
|
|
46
|
+
"content": "# Top-of-file banner comment, attached to nothing.\n# Second banner line, same block.",
|
|
47
|
+
"line_start": 1,
|
|
48
|
+
"line_end": 2,
|
|
49
|
+
"metadata": {
|
|
50
|
+
"module": "",
|
|
51
|
+
"names": "",
|
|
52
|
+
"dots": "",
|
|
53
|
+
"language_hint": ""
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "bcb39bbdc83beb10",
|
|
58
|
+
"blob_sha": "sha1",
|
|
59
|
+
"file_path": "python.py",
|
|
60
|
+
"kind": "comment",
|
|
61
|
+
"name": "<anonymous>",
|
|
62
|
+
"scope": "",
|
|
63
|
+
"language": "python",
|
|
64
|
+
"content": "\"\"\"Greeter — formats greetings for named recipients.\n\nA sample module exercising the constructs the python plugin extracts:\nfunctions (sync, async, decorated), classes, methods (instance, property,\nstatic, class), module-level variables (including tuple unpacking and\nannotated assignments), nested functions (scoped to their parent), PEP 695\n`type` aliases (as classes), the import styles that carry distinct\nmetadata, and standalone / leading comments.\n\"\"\"",
|
|
65
|
+
"line_start": 4,
|
|
66
|
+
"line_end": 12,
|
|
67
|
+
"metadata": {
|
|
68
|
+
"module": "",
|
|
69
|
+
"names": "",
|
|
70
|
+
"dots": "",
|
|
71
|
+
"language_hint": ""
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "86800a35eec519ec",
|
|
76
|
+
"blob_sha": "sha1",
|
|
77
|
+
"file_path": "python.py",
|
|
78
|
+
"kind": "import",
|
|
79
|
+
"name": "import os",
|
|
80
|
+
"scope": "",
|
|
81
|
+
"language": "python",
|
|
82
|
+
"content": "import os",
|
|
83
|
+
"line_start": 16,
|
|
84
|
+
"line_end": 16,
|
|
85
|
+
"metadata": {
|
|
86
|
+
"module": "os",
|
|
87
|
+
"names": "",
|
|
88
|
+
"dots": "",
|
|
89
|
+
"language_hint": ""
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "99f2b46e21fdc9ed",
|
|
94
|
+
"blob_sha": "sha1",
|
|
95
|
+
"file_path": "python.py",
|
|
96
|
+
"kind": "import",
|
|
97
|
+
"name": "from functools import lru_cache",
|
|
98
|
+
"scope": "",
|
|
99
|
+
"language": "python",
|
|
100
|
+
"content": "from functools import lru_cache",
|
|
101
|
+
"line_start": 17,
|
|
102
|
+
"line_end": 17,
|
|
103
|
+
"metadata": {
|
|
104
|
+
"module": "functools",
|
|
105
|
+
"names": "lru_cache",
|
|
106
|
+
"dots": "",
|
|
107
|
+
"language_hint": ""
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "a1111f0d689a9844",
|
|
112
|
+
"blob_sha": "sha1",
|
|
113
|
+
"file_path": "python.py",
|
|
114
|
+
"kind": "import",
|
|
115
|
+
"name": "from pathlib import Path as P",
|
|
116
|
+
"scope": "",
|
|
117
|
+
"language": "python",
|
|
118
|
+
"content": "from pathlib import Path as P",
|
|
119
|
+
"line_start": 18,
|
|
120
|
+
"line_end": 18,
|
|
121
|
+
"metadata": {
|
|
122
|
+
"module": "pathlib",
|
|
123
|
+
"names": "Path",
|
|
124
|
+
"dots": "",
|
|
125
|
+
"language_hint": ""
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"id": "df33b6fad729b242",
|
|
130
|
+
"blob_sha": "sha1",
|
|
131
|
+
"file_path": "python.py",
|
|
132
|
+
"kind": "import",
|
|
133
|
+
"name": "from .config import LOCALE",
|
|
134
|
+
"scope": "",
|
|
135
|
+
"language": "python",
|
|
136
|
+
"content": "from .config import LOCALE",
|
|
137
|
+
"line_start": 20,
|
|
138
|
+
"line_end": 20,
|
|
139
|
+
"metadata": {
|
|
140
|
+
"module": "config",
|
|
141
|
+
"names": "LOCALE",
|
|
142
|
+
"dots": "1",
|
|
143
|
+
"language_hint": ""
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "d81a70db3e82f25a",
|
|
148
|
+
"blob_sha": "sha1",
|
|
149
|
+
"file_path": "python.py",
|
|
150
|
+
"kind": "class",
|
|
151
|
+
"name": "GreetingList",
|
|
152
|
+
"scope": "",
|
|
153
|
+
"language": "python",
|
|
154
|
+
"content": "type GreetingList = list[str]",
|
|
155
|
+
"line_start": 22,
|
|
156
|
+
"line_end": 22,
|
|
157
|
+
"metadata": {
|
|
158
|
+
"module": "",
|
|
159
|
+
"names": "",
|
|
160
|
+
"dots": "",
|
|
161
|
+
"language_hint": ""
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "39b5a904c304c9c9",
|
|
166
|
+
"blob_sha": "sha1",
|
|
167
|
+
"file_path": "python.py",
|
|
168
|
+
"kind": "variable",
|
|
169
|
+
"name": "DEFAULT_GREETING",
|
|
170
|
+
"scope": "",
|
|
171
|
+
"language": "python",
|
|
172
|
+
"content": "DEFAULT_GREETING = \"Hello\"",
|
|
173
|
+
"line_start": 24,
|
|
174
|
+
"line_end": 24,
|
|
175
|
+
"metadata": {
|
|
176
|
+
"module": "",
|
|
177
|
+
"names": "",
|
|
178
|
+
"dots": "",
|
|
179
|
+
"language_hint": ""
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"id": "397202f732684d50",
|
|
184
|
+
"blob_sha": "sha1",
|
|
185
|
+
"file_path": "python.py",
|
|
186
|
+
"kind": "variable",
|
|
187
|
+
"name": "LOCALES",
|
|
188
|
+
"scope": "",
|
|
189
|
+
"language": "python",
|
|
190
|
+
"content": "LOCALES, FALLBACK = (\"en\", \"fr\"), \"en\"",
|
|
191
|
+
"line_start": 25,
|
|
192
|
+
"line_end": 25,
|
|
193
|
+
"metadata": {
|
|
194
|
+
"module": "",
|
|
195
|
+
"names": "",
|
|
196
|
+
"dots": "",
|
|
197
|
+
"language_hint": ""
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"id": "0ed9c20b3fe660be",
|
|
202
|
+
"blob_sha": "sha1",
|
|
203
|
+
"file_path": "python.py",
|
|
204
|
+
"kind": "variable",
|
|
205
|
+
"name": "FALLBACK",
|
|
206
|
+
"scope": "",
|
|
207
|
+
"language": "python",
|
|
208
|
+
"content": "LOCALES, FALLBACK = (\"en\", \"fr\"), \"en\"",
|
|
209
|
+
"line_start": 25,
|
|
210
|
+
"line_end": 25,
|
|
211
|
+
"metadata": {
|
|
212
|
+
"module": "",
|
|
213
|
+
"names": "",
|
|
214
|
+
"dots": "",
|
|
215
|
+
"language_hint": ""
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"id": "9ac255b17801a682",
|
|
220
|
+
"blob_sha": "sha1",
|
|
221
|
+
"file_path": "python.py",
|
|
222
|
+
"kind": "variable",
|
|
223
|
+
"name": "MAX_RECIPIENTS",
|
|
224
|
+
"scope": "",
|
|
225
|
+
"language": "python",
|
|
226
|
+
"content": "MAX_RECIPIENTS: int = 100",
|
|
227
|
+
"line_start": 26,
|
|
228
|
+
"line_end": 26,
|
|
229
|
+
"metadata": {
|
|
230
|
+
"module": "",
|
|
231
|
+
"names": "",
|
|
232
|
+
"dots": "",
|
|
233
|
+
"language_hint": ""
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"id": "7f441b61192c0790",
|
|
238
|
+
"blob_sha": "sha1",
|
|
239
|
+
"file_path": "python.py",
|
|
240
|
+
"kind": "comment",
|
|
241
|
+
"name": "<anonymous>",
|
|
242
|
+
"scope": "",
|
|
243
|
+
"language": "python",
|
|
244
|
+
"content": "# trailing comment: not folded, its own chunk",
|
|
245
|
+
"line_start": 26,
|
|
246
|
+
"line_end": 26,
|
|
247
|
+
"metadata": {
|
|
248
|
+
"module": "",
|
|
249
|
+
"names": "",
|
|
250
|
+
"dots": "",
|
|
251
|
+
"language_hint": ""
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "faa176a42cc8b903",
|
|
256
|
+
"blob_sha": "sha1",
|
|
257
|
+
"file_path": "python.py",
|
|
258
|
+
"kind": "comment",
|
|
259
|
+
"name": "<anonymous>",
|
|
260
|
+
"scope": "",
|
|
261
|
+
"language": "python",
|
|
262
|
+
"content": "# Section: greeting helpers.\n# A standalone block between definitions.",
|
|
263
|
+
"line_start": 28,
|
|
264
|
+
"line_end": 29,
|
|
265
|
+
"metadata": {
|
|
266
|
+
"module": "",
|
|
267
|
+
"names": "",
|
|
268
|
+
"dots": "",
|
|
269
|
+
"language_hint": ""
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"id": "b2c0884b8be95035",
|
|
274
|
+
"blob_sha": "sha1",
|
|
275
|
+
"file_path": "python.py",
|
|
276
|
+
"kind": "function",
|
|
277
|
+
"name": "format_greeting",
|
|
278
|
+
"scope": "",
|
|
279
|
+
"language": "python",
|
|
280
|
+
"content": "# Leading doc comment folded into format_greeting.\ndef format_greeting(name: str) -> str:\n \"\"\"Return a greeting for ``name`` in the configured locale.\"\"\"\n\n def normalise(raw: str) -> str:\n \"\"\"Trim and title-case a raw recipient name.\"\"\"\n return raw.strip().title()\n\n return f\"{DEFAULT_GREETING}, {normalise(name)} ({LOCALE})\"",
|
|
281
|
+
"line_start": 32,
|
|
282
|
+
"line_end": 40,
|
|
283
|
+
"metadata": {
|
|
284
|
+
"module": "",
|
|
285
|
+
"names": "",
|
|
286
|
+
"dots": "",
|
|
287
|
+
"language_hint": ""
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"id": "a7a4d2b076bcecd6",
|
|
292
|
+
"blob_sha": "sha1",
|
|
293
|
+
"file_path": "python.py",
|
|
294
|
+
"kind": "function",
|
|
295
|
+
"name": "normalise",
|
|
296
|
+
"scope": "format_greeting",
|
|
297
|
+
"language": "python",
|
|
298
|
+
"content": "def normalise(raw: str) -> str:\n \"\"\"Trim and title-case a raw recipient name.\"\"\"\n return raw.strip().title()",
|
|
299
|
+
"line_start": 36,
|
|
300
|
+
"line_end": 38,
|
|
301
|
+
"metadata": {
|
|
302
|
+
"module": "",
|
|
303
|
+
"names": "",
|
|
304
|
+
"dots": "",
|
|
305
|
+
"language_hint": ""
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"id": "4781f65b33434b65",
|
|
310
|
+
"blob_sha": "sha1",
|
|
311
|
+
"file_path": "python.py",
|
|
312
|
+
"kind": "function",
|
|
313
|
+
"name": "fetch_remote_greeting",
|
|
314
|
+
"scope": "",
|
|
315
|
+
"language": "python",
|
|
316
|
+
"content": "async def fetch_remote_greeting(url: str) -> str:\n \"\"\"Fetch a greeting template from a remote source.\"\"\"\n return os.environ.get(\"GREETING\", DEFAULT_GREETING)",
|
|
317
|
+
"line_start": 43,
|
|
318
|
+
"line_end": 45,
|
|
319
|
+
"metadata": {
|
|
320
|
+
"module": "",
|
|
321
|
+
"names": "",
|
|
322
|
+
"dots": "",
|
|
323
|
+
"language_hint": ""
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"id": "512e3f71a402f3b7",
|
|
328
|
+
"blob_sha": "sha1",
|
|
329
|
+
"file_path": "python.py",
|
|
330
|
+
"kind": "function",
|
|
331
|
+
"name": "cached_default",
|
|
332
|
+
"scope": "",
|
|
333
|
+
"language": "python",
|
|
334
|
+
"content": "def cached_default() -> str:\n \"\"\"Cache and return the default greeting prefix.\"\"\"\n return DEFAULT_GREETING",
|
|
335
|
+
"line_start": 49,
|
|
336
|
+
"line_end": 51,
|
|
337
|
+
"metadata": {
|
|
338
|
+
"module": "",
|
|
339
|
+
"names": "",
|
|
340
|
+
"dots": "",
|
|
341
|
+
"language_hint": ""
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"id": "c509d883ae06d023",
|
|
346
|
+
"blob_sha": "sha1",
|
|
347
|
+
"file_path": "python.py",
|
|
348
|
+
"kind": "class",
|
|
349
|
+
"name": "Greeter",
|
|
350
|
+
"scope": "",
|
|
351
|
+
"language": "python",
|
|
352
|
+
"content": "class Greeter:\n \"\"\"Stateful greeter holding a prefix and recipient log.\"\"\"\n\n def __init__(self, prefix: str = DEFAULT_GREETING) -> None:\n self.prefix = prefix\n self._seen: list[str] = []\n\n def greet(self, name: str) -> str:\n \"\"\"Greet ``name`` and record the recipient.\"\"\"\n self._seen.append(name)\n return format_greeting(name)\n\n @property\n def seen(self) -> list[str]:\n \"\"\"Recipients greeted so far.\"\"\"\n return list(self._seen)\n\n @staticmethod\n def shout(message: str) -> str:\n \"\"\"Upper-case a message.\"\"\"\n return message.upper()\n\n @classmethod\n def default(cls) -> Greeter:\n \"\"\"Build a greeter with the default prefix.\"\"\"\n return cls(DEFAULT_GREETING)",
|
|
353
|
+
"line_start": 54,
|
|
354
|
+
"line_end": 79,
|
|
355
|
+
"metadata": {
|
|
356
|
+
"module": "",
|
|
357
|
+
"names": "",
|
|
358
|
+
"dots": "",
|
|
359
|
+
"language_hint": ""
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"id": "f5316a1306021dbf",
|
|
364
|
+
"blob_sha": "sha1",
|
|
365
|
+
"file_path": "python.py",
|
|
366
|
+
"kind": "method",
|
|
367
|
+
"name": "__init__",
|
|
368
|
+
"scope": "Greeter",
|
|
369
|
+
"language": "python",
|
|
370
|
+
"content": "def __init__(self, prefix: str = DEFAULT_GREETING) -> None:\n self.prefix = prefix\n self._seen: list[str] = []",
|
|
371
|
+
"line_start": 57,
|
|
372
|
+
"line_end": 59,
|
|
373
|
+
"metadata": {
|
|
374
|
+
"module": "",
|
|
375
|
+
"names": "",
|
|
376
|
+
"dots": "",
|
|
377
|
+
"language_hint": ""
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"id": "04526264daec6180",
|
|
382
|
+
"blob_sha": "sha1",
|
|
383
|
+
"file_path": "python.py",
|
|
384
|
+
"kind": "method",
|
|
385
|
+
"name": "greet",
|
|
386
|
+
"scope": "Greeter",
|
|
387
|
+
"language": "python",
|
|
388
|
+
"content": "def greet(self, name: str) -> str:\n \"\"\"Greet ``name`` and record the recipient.\"\"\"\n self._seen.append(name)\n return format_greeting(name)",
|
|
389
|
+
"line_start": 61,
|
|
390
|
+
"line_end": 64,
|
|
391
|
+
"metadata": {
|
|
392
|
+
"module": "",
|
|
393
|
+
"names": "",
|
|
394
|
+
"dots": "",
|
|
395
|
+
"language_hint": ""
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
"id": "404ed4eb32f154f2",
|
|
400
|
+
"blob_sha": "sha1",
|
|
401
|
+
"file_path": "python.py",
|
|
402
|
+
"kind": "method",
|
|
403
|
+
"name": "seen",
|
|
404
|
+
"scope": "Greeter",
|
|
405
|
+
"language": "python",
|
|
406
|
+
"content": "def seen(self) -> list[str]:\n \"\"\"Recipients greeted so far.\"\"\"\n return list(self._seen)",
|
|
407
|
+
"line_start": 67,
|
|
408
|
+
"line_end": 69,
|
|
409
|
+
"metadata": {
|
|
410
|
+
"module": "",
|
|
411
|
+
"names": "",
|
|
412
|
+
"dots": "",
|
|
413
|
+
"language_hint": ""
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"id": "4174241e8ca95cc9",
|
|
418
|
+
"blob_sha": "sha1",
|
|
419
|
+
"file_path": "python.py",
|
|
420
|
+
"kind": "method",
|
|
421
|
+
"name": "shout",
|
|
422
|
+
"scope": "Greeter",
|
|
423
|
+
"language": "python",
|
|
424
|
+
"content": "def shout(message: str) -> str:\n \"\"\"Upper-case a message.\"\"\"\n return message.upper()",
|
|
425
|
+
"line_start": 72,
|
|
426
|
+
"line_end": 74,
|
|
427
|
+
"metadata": {
|
|
428
|
+
"module": "",
|
|
429
|
+
"names": "",
|
|
430
|
+
"dots": "",
|
|
431
|
+
"language_hint": ""
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
"id": "b4873c720ebf2b3b",
|
|
436
|
+
"blob_sha": "sha1",
|
|
437
|
+
"file_path": "python.py",
|
|
438
|
+
"kind": "method",
|
|
439
|
+
"name": "default",
|
|
440
|
+
"scope": "Greeter",
|
|
441
|
+
"language": "python",
|
|
442
|
+
"content": "def default(cls) -> Greeter:\n \"\"\"Build a greeter with the default prefix.\"\"\"\n return cls(DEFAULT_GREETING)",
|
|
443
|
+
"line_start": 77,
|
|
444
|
+
"line_end": 79,
|
|
445
|
+
"metadata": {
|
|
446
|
+
"module": "",
|
|
447
|
+
"names": "",
|
|
448
|
+
"dots": "",
|
|
449
|
+
"language_hint": ""
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"id": "290aeaf830254689",
|
|
454
|
+
"blob_sha": "sha1",
|
|
455
|
+
"file_path": "python.py",
|
|
456
|
+
"kind": "function",
|
|
457
|
+
"name": "config_path",
|
|
458
|
+
"scope": "",
|
|
459
|
+
"language": "python",
|
|
460
|
+
"content": "def config_path() -> P:\n \"\"\"Return the path to the greeter config file.\"\"\"\n return P.home() / \".greeter\"",
|
|
461
|
+
"line_start": 82,
|
|
462
|
+
"line_end": 84,
|
|
463
|
+
"metadata": {
|
|
464
|
+
"module": "",
|
|
465
|
+
"names": "",
|
|
466
|
+
"dots": "",
|
|
467
|
+
"language_hint": ""
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
]
|