smartcomment 0.1.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.
- smartcomment/__init__.py +49 -0
- smartcomment/analysis/__init__.py +1 -0
- smartcomment/analysis/visualization/__init__.py +43 -0
- smartcomment/analysis/visualization/_utils.py +103 -0
- smartcomment/analysis/visualization/graphviz.py +201 -0
- smartcomment/analysis/visualization/pyvis.py +155 -0
- smartcomment/api/__init__.py +18 -0
- smartcomment/api/_helpers.py +440 -0
- smartcomment/api/_mutation.py +318 -0
- smartcomment/api/public.py +971 -0
- smartcomment/debugging.py +69 -0
- smartcomment/drivers/__init__.py +12 -0
- smartcomment/drivers/base.py +309 -0
- smartcomment/drivers/in_memory.py +323 -0
- smartcomment/identity/__init__.py +6 -0
- smartcomment/identity/registry.py +214 -0
- smartcomment/logging.py +80 -0
- smartcomment/runtime/__init__.py +44 -0
- smartcomment/runtime/context.py +630 -0
- smartcomment/runtime/errors.py +117 -0
- smartcomment/runtime/graph.py +520 -0
- smartcomment/runtime/network.py +1841 -0
- smartcomment/runtime/operation.py +274 -0
- smartcomment/runtime/session.py +133 -0
- smartcomment/runtime/variable.py +237 -0
- smartcomment/schema/__init__.py +1 -0
- smartcomment/schema/base.py +134 -0
- smartcomment/schema/operation.py +96 -0
- smartcomment/schema/session.py +42 -0
- smartcomment/schema/variable.py +126 -0
- smartcomment-0.1.0.dist-info/METADATA +29 -0
- smartcomment-0.1.0.dist-info/RECORD +34 -0
- smartcomment-0.1.0.dist-info/WHEEL +5 -0
- smartcomment-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
"""Internal helpers for the public API."""
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import inspect
|
|
5
|
+
from pydantic import BaseModel, JsonValue
|
|
6
|
+
from ..runtime import (
|
|
7
|
+
ExecNetwork,
|
|
8
|
+
none_session_id,
|
|
9
|
+
current_graph,
|
|
10
|
+
current_session,
|
|
11
|
+
current_context,
|
|
12
|
+
none_identity,
|
|
13
|
+
)
|
|
14
|
+
from ..runtime.variable import RuntimeVariable
|
|
15
|
+
from ..runtime.errors import TraceConsistencyError, _diff_context
|
|
16
|
+
from ..schema.variable import Variable
|
|
17
|
+
from ..identity.registry import IdentityRegistry
|
|
18
|
+
from ..logging import logger
|
|
19
|
+
from typing import (
|
|
20
|
+
Any,
|
|
21
|
+
Callable,
|
|
22
|
+
TypeVar,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
T = TypeVar("T")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _resolve_identity(
|
|
30
|
+
value: Any,
|
|
31
|
+
*,
|
|
32
|
+
id_strategy: Callable[[Any], str] | str | None = None,
|
|
33
|
+
) -> str:
|
|
34
|
+
"""Resolve the identity string for a value.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
value (`Any`):
|
|
38
|
+
The value to resolve the identity for.
|
|
39
|
+
id_strategy (`Callable[[Any], str] | str | None`, optional):
|
|
40
|
+
The identity strategy to use. If not provided, it will be looked up by type.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
`str`:
|
|
44
|
+
The resolved identity string.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
`ValueError`:
|
|
48
|
+
If the identity is the built-in NONE sentinel.
|
|
49
|
+
"""
|
|
50
|
+
fn = IdentityRegistry.resolve(value, override=id_strategy)
|
|
51
|
+
identity = fn(value)
|
|
52
|
+
|
|
53
|
+
none_id = none_identity()
|
|
54
|
+
if identity == none_id:
|
|
55
|
+
raise ValueError(
|
|
56
|
+
f"The identity '{none_id}' is reserved for the built-in "
|
|
57
|
+
"NONE sentinel. Choose a different identity strategy."
|
|
58
|
+
)
|
|
59
|
+
return identity
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _resolve_call_context(
|
|
63
|
+
caller_name: str = "comment_*",
|
|
64
|
+
stack_level: int = 2,
|
|
65
|
+
) -> tuple[ExecNetwork, str, str, int]:
|
|
66
|
+
"""Resolve the active graph, session identifier, and caller location.
|
|
67
|
+
|
|
68
|
+
It obtains the current execution graph, determines the current session
|
|
69
|
+
identifier (falling back to the NONE sentinel session when no session is active),
|
|
70
|
+
and captures the caller's source location for attribution.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
caller_name (`str`, defaults to `"comment_*"`):
|
|
74
|
+
Name of the calling public function, included in the error
|
|
75
|
+
message when no graph context is active.
|
|
76
|
+
stack_level (`int`, defaults to `2`):
|
|
77
|
+
Frame index passed to ``inspect.stack`` to locate the
|
|
78
|
+
original call site.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
`tuple[ExecNetwork, str, str, int]`:
|
|
82
|
+
A 4-tuple including the current execution graph, session identifier,
|
|
83
|
+
caller's source location and line number.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
`RuntimeError`:
|
|
87
|
+
If no graph context is active.
|
|
88
|
+
"""
|
|
89
|
+
graph = current_graph()
|
|
90
|
+
if graph is None:
|
|
91
|
+
raise RuntimeError(
|
|
92
|
+
f"`{caller_name}` requires an active graph context. "
|
|
93
|
+
"Wrap your code in `with comment_graph() as graph:`."
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
session = current_session()
|
|
97
|
+
if session is not None:
|
|
98
|
+
session_id = session.session_id
|
|
99
|
+
else:
|
|
100
|
+
# Check whether the NONE sentinel session has been inserted yet.
|
|
101
|
+
graph._ensure_none_session()
|
|
102
|
+
session_id = none_session_id()
|
|
103
|
+
|
|
104
|
+
frame = inspect.stack()[stack_level]
|
|
105
|
+
filename, lineno = frame.filename, frame.lineno
|
|
106
|
+
return graph, session_id, filename, lineno
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _ensure_variable(
|
|
110
|
+
value: T,
|
|
111
|
+
*,
|
|
112
|
+
graph: ExecNetwork,
|
|
113
|
+
session_id: str,
|
|
114
|
+
filename: str,
|
|
115
|
+
lineno: int,
|
|
116
|
+
id_strategy: Callable[[T], str] | str | None = None,
|
|
117
|
+
encoding_fn: Callable[[T], str] | None = None,
|
|
118
|
+
decoding_fn: Callable[[str], T] | None = None,
|
|
119
|
+
schema: type[BaseModel] | None = None,
|
|
120
|
+
comment: str | None = None,
|
|
121
|
+
category: str = "variable",
|
|
122
|
+
class_name: str | None = None,
|
|
123
|
+
auto_class_name: bool = False,
|
|
124
|
+
variable_name: str | None = None,
|
|
125
|
+
metadata: dict[str, JsonValue] | None = None,
|
|
126
|
+
identity_only: bool = False,
|
|
127
|
+
force_new_version: bool = False,
|
|
128
|
+
) -> RuntimeVariable[T]:
|
|
129
|
+
"""Create or reuse a graph variable node and return a runtime handle.
|
|
130
|
+
|
|
131
|
+
It resolves the variable to a stable identity, encodes it to a string for storage,
|
|
132
|
+
and either reuses the latest matching node (same encoded value) or
|
|
133
|
+
appends a new version. When the variable's name is set and a tracing context
|
|
134
|
+
exists, the handle is registered for lookup by name.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
value (`T`):
|
|
138
|
+
The Python value to record in the graph.
|
|
139
|
+
graph (`ExecNetwork`):
|
|
140
|
+
Target execution graph.
|
|
141
|
+
session_id (`str`):
|
|
142
|
+
Session identifier stored on the variable node.
|
|
143
|
+
filename (`str`):
|
|
144
|
+
Source file recorded on the variable node (call-site attribution).
|
|
145
|
+
lineno (`int`):
|
|
146
|
+
Source line recorded on the variable node.
|
|
147
|
+
id_strategy (`Callable[[T], str] | str | None`, optional):
|
|
148
|
+
An identity strategy. It can be a callable, a registered name.
|
|
149
|
+
If not provided, it will be looked up by type.
|
|
150
|
+
encoding_fn (`Callable[[T], str] | None`, optional):
|
|
151
|
+
Custom encoder from the value to string.
|
|
152
|
+
decoding_fn (`Callable[[str], T] | None`, optional):
|
|
153
|
+
Optional decoder paired with the encoding function for the runtime handle.
|
|
154
|
+
schema (`type[BaseModel] | None`, optional):
|
|
155
|
+
Pydantic schema for auto encoding and decoding.
|
|
156
|
+
comment (`str | None`, optional):
|
|
157
|
+
A comment for the variable.
|
|
158
|
+
category (`str`, defaults to `"variable"`):
|
|
159
|
+
Variable category.
|
|
160
|
+
class_name (`str | None`, optional):
|
|
161
|
+
Namespace prefix for the variable's full name when set.
|
|
162
|
+
auto_class_name (`bool`, defaults to `False`):
|
|
163
|
+
If enabled, it will auto-detect the class name from the value.
|
|
164
|
+
variable_name (`str | None`, optional):
|
|
165
|
+
If provided, it registers the returned handle on the current
|
|
166
|
+
tracing context under this name (overwriting any prior registration).
|
|
167
|
+
metadata (`dict[str, JsonValue] | None`, optional):
|
|
168
|
+
Extra metadata for the variable.
|
|
169
|
+
identity_only (`bool`, defaults to `False`):
|
|
170
|
+
When enabled, the snapshot consistency check is bypassed for this
|
|
171
|
+
variable. If a node with the same identity already exists in the
|
|
172
|
+
graph but has a different encoded value, the existing node is
|
|
173
|
+
returned as-is instead of raising error or creating a new version.
|
|
174
|
+
This is useful when the caller holds a lightweight representation
|
|
175
|
+
(e.g. only an identifier) of a variable that was previously recorded
|
|
176
|
+
with a richer snapshot.
|
|
177
|
+
force_new_version (`bool`, defaults to `False`):
|
|
178
|
+
When enabled, it always creates a new version even if the encoded
|
|
179
|
+
value matches the latest node. It is used by ``comment_op`` to avoid
|
|
180
|
+
self-loop edges when the same value appears in both inputs and outputs.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
`RuntimeVariable[T]`:
|
|
184
|
+
A handle for the latest or newly created variable version.
|
|
185
|
+
|
|
186
|
+
Raises:
|
|
187
|
+
ValueError:
|
|
188
|
+
If identity resolution yields the reserved NONE sentinel identity.
|
|
189
|
+
TraceConsistencyError:
|
|
190
|
+
If the graph is in strict mode, an existing node for this identity
|
|
191
|
+
has a different encoded value, ``identity_only`` is not set, and
|
|
192
|
+
the change was not recorded via ``comment_mutation``.
|
|
193
|
+
"""
|
|
194
|
+
if auto_class_name and class_name is None:
|
|
195
|
+
class_name = type(value).__qualname__
|
|
196
|
+
|
|
197
|
+
# Determine the string representation.
|
|
198
|
+
if schema is not None and encoding_fn is None:
|
|
199
|
+
value_str = value.model_dump_json()
|
|
200
|
+
elif encoding_fn is not None:
|
|
201
|
+
value_str = encoding_fn(value)
|
|
202
|
+
else:
|
|
203
|
+
logger.debug(
|
|
204
|
+
"No encoding function is provided. `repr` is used to encode the value.",
|
|
205
|
+
)
|
|
206
|
+
value_str = repr(value)
|
|
207
|
+
|
|
208
|
+
name = _resolve_identity(value, id_strategy=id_strategy)
|
|
209
|
+
full_name = f"{class_name}:{name}" if class_name is not None else name
|
|
210
|
+
|
|
211
|
+
# Acquire the driver lock (if present) to make the read-modify-write
|
|
212
|
+
# sequence atomic.
|
|
213
|
+
# Drivers without a lock are assumed to handle concurrency internally.
|
|
214
|
+
driver_lock = getattr(graph._driver, "_lock", None)
|
|
215
|
+
lock_ctx = driver_lock if driver_lock is not None else contextlib.nullcontext()
|
|
216
|
+
|
|
217
|
+
with lock_ctx:
|
|
218
|
+
# Check if this variable already exists in the graph.
|
|
219
|
+
raw = graph._driver.get_latest_node(full_name)
|
|
220
|
+
if raw is None:
|
|
221
|
+
existing = None
|
|
222
|
+
else:
|
|
223
|
+
existing = RuntimeVariable(variable=raw)
|
|
224
|
+
|
|
225
|
+
if existing is not None and existing.raw_value == value_str and not force_new_version:
|
|
226
|
+
rv_existing = RuntimeVariable(
|
|
227
|
+
variable=existing._variable,
|
|
228
|
+
encoding_fn=encoding_fn,
|
|
229
|
+
decoding_fn=decoding_fn,
|
|
230
|
+
schema=schema,
|
|
231
|
+
)
|
|
232
|
+
if variable_name is not None:
|
|
233
|
+
ctx = current_context()
|
|
234
|
+
assert ctx is not None, (
|
|
235
|
+
"The current tracing context is not active."
|
|
236
|
+
)
|
|
237
|
+
ctx.register_variable(variable_name, rv_existing, overwrite=True)
|
|
238
|
+
return rv_existing
|
|
239
|
+
|
|
240
|
+
if existing is not None and existing.raw_value != value_str and identity_only:
|
|
241
|
+
logger.debug(
|
|
242
|
+
"For the variable with the identity '{full_name}', "
|
|
243
|
+
"a snapshot mismatch is detected. "
|
|
244
|
+
"However, the caller explicitly opts out of snapshot consistency. "
|
|
245
|
+
"Therefore, the existing node will be returned instead of raising "
|
|
246
|
+
"an error or creating a new version.",
|
|
247
|
+
full_name=full_name,
|
|
248
|
+
)
|
|
249
|
+
rv_existing = RuntimeVariable(
|
|
250
|
+
variable=existing._variable,
|
|
251
|
+
encoding_fn=encoding_fn,
|
|
252
|
+
decoding_fn=decoding_fn,
|
|
253
|
+
schema=schema,
|
|
254
|
+
)
|
|
255
|
+
if variable_name is not None:
|
|
256
|
+
ctx = current_context()
|
|
257
|
+
assert ctx is not None, (
|
|
258
|
+
"The current tracing context is not active."
|
|
259
|
+
)
|
|
260
|
+
ctx.register_variable(variable_name, rv_existing, overwrite=True)
|
|
261
|
+
return rv_existing
|
|
262
|
+
|
|
263
|
+
# Strict mode check whether the value changed for an existing identity.
|
|
264
|
+
if existing is not None and existing.raw_value != value_str:
|
|
265
|
+
if graph.strict:
|
|
266
|
+
raise TraceConsistencyError(
|
|
267
|
+
user_value=value,
|
|
268
|
+
user_value_encoded=value_str,
|
|
269
|
+
existing_variable=existing,
|
|
270
|
+
identity_name=name,
|
|
271
|
+
)
|
|
272
|
+
else:
|
|
273
|
+
old_snippet, new_snippet = _diff_context(existing.raw_value, value_str)
|
|
274
|
+
logger.info(
|
|
275
|
+
"A value changed for an existing identity (identity_name={name}) "
|
|
276
|
+
"but strict mode is disabled. A new version will be created. "
|
|
277
|
+
"The first difference between the recorded and provided values is:\n"
|
|
278
|
+
" Recorded: {old}\n"
|
|
279
|
+
" Provided: {new}",
|
|
280
|
+
name=name,
|
|
281
|
+
old=old_snippet,
|
|
282
|
+
new=new_snippet,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Determine the version.
|
|
286
|
+
version = 1
|
|
287
|
+
if existing is not None:
|
|
288
|
+
version = existing.version + 1
|
|
289
|
+
|
|
290
|
+
var = Variable(
|
|
291
|
+
name=name,
|
|
292
|
+
version=version,
|
|
293
|
+
value=value_str,
|
|
294
|
+
comment=comment,
|
|
295
|
+
category=category,
|
|
296
|
+
class_name=class_name,
|
|
297
|
+
graph_id=graph.graph_id,
|
|
298
|
+
user_id=graph.user_id,
|
|
299
|
+
project_id=graph.project_id,
|
|
300
|
+
session_id=session_id,
|
|
301
|
+
filename=filename,
|
|
302
|
+
lineno=lineno,
|
|
303
|
+
)
|
|
304
|
+
if metadata:
|
|
305
|
+
var.update_metadata(metadata)
|
|
306
|
+
|
|
307
|
+
# Propagate context metadata.
|
|
308
|
+
ctx = current_context()
|
|
309
|
+
assert ctx is not None, (
|
|
310
|
+
"The current tracing context is not active."
|
|
311
|
+
)
|
|
312
|
+
ctx_meta = ctx.metadata
|
|
313
|
+
if ctx_meta:
|
|
314
|
+
var.update_metadata(ctx_meta)
|
|
315
|
+
|
|
316
|
+
# Add the raw variable to the driver and build one runtime variable handle.
|
|
317
|
+
graph._driver.add_node(var)
|
|
318
|
+
|
|
319
|
+
rv_full = RuntimeVariable(
|
|
320
|
+
variable=var,
|
|
321
|
+
encoding_fn=encoding_fn,
|
|
322
|
+
decoding_fn=decoding_fn,
|
|
323
|
+
schema=schema,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# Register in context if a variable name is provided.
|
|
327
|
+
if variable_name is not None:
|
|
328
|
+
ctx.register_variable(variable_name, rv_full, overwrite=True)
|
|
329
|
+
|
|
330
|
+
return rv_full
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _resolve_item(
|
|
334
|
+
item: Any,
|
|
335
|
+
*,
|
|
336
|
+
shared_id_strategy: Callable[[Any], str] | str | None,
|
|
337
|
+
shared_encoding_fn: Callable[[Any], str] | None,
|
|
338
|
+
shared_decoding_fn: Callable[[str], Any] | None,
|
|
339
|
+
shared_schema: type[BaseModel] | None,
|
|
340
|
+
shared_auto_class_name: bool,
|
|
341
|
+
shared_category: str,
|
|
342
|
+
shared_metadata: dict[str, JsonValue] | None,
|
|
343
|
+
graph: ExecNetwork,
|
|
344
|
+
session_id: str,
|
|
345
|
+
filename: str,
|
|
346
|
+
lineno: int,
|
|
347
|
+
force_new_version: bool = False,
|
|
348
|
+
) -> RuntimeVariable[Any]:
|
|
349
|
+
"""Resolve a single ``comment_op`` or ``comment_fn`` slot to a runtime variable.
|
|
350
|
+
|
|
351
|
+
If ``item`` is already a ``RuntimeVariable``, it is returned unchanged.
|
|
352
|
+
If ``item`` is a plain Python value, it is passed to :func:`_ensure_variable`
|
|
353
|
+
with the shared keyword defaults from the caller. If ``item`` is a length-2
|
|
354
|
+
tuple ``(value, options)`` and ``options`` is a ``dict``, keys in that dict
|
|
355
|
+
override the shared defaults for that slot only (for example
|
|
356
|
+
``id_strategy``, ``encoding_fn``, ``metadata``). At debug level, tuple
|
|
357
|
+
items log a truncated ``repr`` of ``value`` and the full options dict.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
item (`Any`):
|
|
361
|
+
A runtime handle, a raw value, or ``(value, options_dict)``.
|
|
362
|
+
shared_id_strategy (`Callable[[Any], str] | str | None`):
|
|
363
|
+
Default identity strategy when the item does not override it.
|
|
364
|
+
shared_encoding_fn (`Callable[[Any], str] | None`):
|
|
365
|
+
Default encoder when the item does not override it.
|
|
366
|
+
shared_decoding_fn (`Callable[[str], Any] | None`):
|
|
367
|
+
Default decoder when the item does not override it.
|
|
368
|
+
shared_schema (`type[BaseModel] | None`):
|
|
369
|
+
Default Pydantic schema when the item does not override it.
|
|
370
|
+
shared_auto_class_name (`bool`):
|
|
371
|
+
Default flag for auto class name detection.
|
|
372
|
+
shared_category (`str`):
|
|
373
|
+
Default variable category for newly created nodes.
|
|
374
|
+
shared_metadata (`dict[str, JsonValue] | None`):
|
|
375
|
+
Default metadata merged into new variable nodes when not overridden
|
|
376
|
+
per item.
|
|
377
|
+
graph (`ExecNetwork`):
|
|
378
|
+
Target execution graph.
|
|
379
|
+
session_id (`str`):
|
|
380
|
+
Session identifier for new variable nodes.
|
|
381
|
+
filename (`str`):
|
|
382
|
+
Call-site file path for new variable nodes.
|
|
383
|
+
lineno (`int`):
|
|
384
|
+
Call-site line number for new variable nodes.
|
|
385
|
+
force_new_version (`bool`, defaults to ``False``):
|
|
386
|
+
When enabled, forwarded to :func:`_ensure_variable` so a new
|
|
387
|
+
version is always created even if the encoded value matches the
|
|
388
|
+
latest node.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
`RuntimeVariable[Any]`:
|
|
392
|
+
The existing handle or a handle for the latest or newly created node.
|
|
393
|
+
|
|
394
|
+
Raises:
|
|
395
|
+
`ValueError`:
|
|
396
|
+
If identity resolution yields the reserved NONE sentinel identity.
|
|
397
|
+
`TraceConsistencyError`:
|
|
398
|
+
If the graph is in strict mode and an existing identity's encoded
|
|
399
|
+
value changed without ``comment_mutation``.
|
|
400
|
+
"""
|
|
401
|
+
if isinstance(item, RuntimeVariable):
|
|
402
|
+
return item
|
|
403
|
+
|
|
404
|
+
config = {}
|
|
405
|
+
value = item
|
|
406
|
+
|
|
407
|
+
if isinstance(item, tuple) and len(item) == 2 and isinstance(item[1], dict):
|
|
408
|
+
value, config = item
|
|
409
|
+
|
|
410
|
+
value_str = repr(value)
|
|
411
|
+
if len(value_str) > 30:
|
|
412
|
+
value_str = value_str[:27] + "..."
|
|
413
|
+
logger.debug(
|
|
414
|
+
"A value-option tuple is provided for an input or output item. "
|
|
415
|
+
"The options will override the shared defaults.\n"
|
|
416
|
+
" Value: {value!r}\n"
|
|
417
|
+
" Options: {config!r}",
|
|
418
|
+
value=value_str,
|
|
419
|
+
config=config,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
return _ensure_variable(
|
|
423
|
+
value,
|
|
424
|
+
id_strategy=config.get("id_strategy", shared_id_strategy),
|
|
425
|
+
encoding_fn=config.get("encoding_fn", shared_encoding_fn),
|
|
426
|
+
decoding_fn=config.get("decoding_fn", shared_decoding_fn),
|
|
427
|
+
schema=config.get("schema", shared_schema),
|
|
428
|
+
comment=config.get("comment"),
|
|
429
|
+
category=config.get("category", shared_category),
|
|
430
|
+
class_name=config.get("class_name"),
|
|
431
|
+
auto_class_name=config.get("auto_class_name", shared_auto_class_name),
|
|
432
|
+
variable_name=config.get("variable_name"),
|
|
433
|
+
metadata=config.get("metadata", shared_metadata),
|
|
434
|
+
identity_only=config.get("identity_only", False),
|
|
435
|
+
graph=graph,
|
|
436
|
+
session_id=session_id,
|
|
437
|
+
filename=filename,
|
|
438
|
+
lineno=lineno,
|
|
439
|
+
force_new_version=force_new_version,
|
|
440
|
+
)
|