Skip to content

Commit 65b5497

Browse files
docs(codecs): teach context as part of the signature, not an option
Every place the library shows a codec now declares `context`, and the prose says to declare it rather than describing it as something implementations "may also accept". A codec written from today's documentation therefore survives the 2.4 removal of the legacy key path without changing. The compatibility guarantee is unchanged and stated where it belongs: the underscore keys still work and are still populated, so codecs written before 2.3.4 keep running until 2.4. Covers the module and class examples in codecs.py, the protocol sketches in heading.py and spark.py, the builtin_codecs package example, and the SchemaCodec guidance the two third-party config bugs were copied from.
1 parent a4028f6 commit 65b5497

5 files changed

Lines changed: 28 additions & 19 deletions

File tree

‎src/datajoint/builtin_codecs/__init__.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ class GraphCodec(dj.Codec):
2929
def get_dtype(self, is_store: bool) -> str:
3030
return "<blob>" # Compose with blob for serialization
3131
32-
def encode(self, graph, *, key=None, store_name=None):
32+
def encode(self, graph, *, key=None, context=None, store_name=None):
3333
# Convert graph to a serializable format
3434
return {
3535
'nodes': list(graph.nodes(data=True)),
3636
'edges': list(graph.edges(data=True)),
3737
}
3838
39-
def decode(self, stored, *, key=None):
39+
def decode(self, stored, *, key=None, context=None):
4040
# Reconstruct graph from stored format
4141
G = nx.Graph()
4242
G.add_nodes_from(stored['nodes'])

‎src/datajoint/builtin_codecs/schema.py‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ class SchemaCodec(Codec, register=False):
3838
silently rather than raising.
3939
4040
Since 2.3.4 that config arrives in an explicit ``context`` argument rather
41-
than hidden among the primary key values. Accept ``context=None`` in
42-
``encode``/``decode`` and pass it to the helpers. The old underscore keys in
43-
``key`` still work and are still populated, with a ``DeprecationWarning``
44-
when ``_extract_context`` has to fall back to them; they are removed in 2.4.
41+
than hidden among the primary key values. **Declare ``context=None`` in
42+
``encode`` and ``decode`` and pass it to the helpers**, as the example below
43+
does.
44+
45+
The old underscore keys in ``key`` still work and are still populated, so a
46+
codec written before 2.3.4 keeps running — but reading them raises a
47+
``DeprecationWarning`` and they are removed in 2.4.
4548
4649
Comparison with Hash-addressed:
4750
- **Schema-addressed** (this): Path from schema structure, no dedup

‎src/datajoint/codecs.py‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ class GraphCodec(dj.Codec):
1616
def get_dtype(self, is_store: bool) -> str:
1717
return "<blob>"
1818
19-
def encode(self, graph, *, key=None, store_name=None):
19+
def encode(self, graph, *, key=None, context=None, store_name=None):
2020
return {'nodes': list(graph.nodes()), 'edges': list(graph.edges())}
2121
22-
def decode(self, stored, *, key=None):
22+
def decode(self, stored, *, key=None, context=None):
2323
import networkx as nx
2424
G = nx.Graph()
2525
G.add_nodes_from(stored['nodes'])
@@ -81,10 +81,10 @@ class Codec(ABC):
8181
... def get_dtype(self, is_store: bool) -> str:
8282
... return "<blob>"
8383
...
84-
... def encode(self, graph, *, key=None, store_name=None):
84+
... def encode(self, graph, *, key=None, context=None, store_name=None):
8585
... return {'nodes': list(graph.nodes()), 'edges': list(graph.edges())}
8686
...
87-
... def decode(self, stored, *, key=None):
87+
... def decode(self, stored, *, key=None, context=None):
8888
... import networkx as nx
8989
... G = nx.Graph()
9090
... G.add_nodes_from(stored['nodes'])
@@ -181,10 +181,15 @@ def encode(self, value: Any, *, key: dict | None = None, store_name: str | None
181181
182182
Notes
183183
-----
184-
Implementations may also accept ``context`` (a dict carrying ``schema``,
185-
``table``, ``field`` and ``config``); DataJoint passes it only to codecs
186-
whose signature declares it, so adding it is optional and omitting it
187-
keeps a codec working unchanged. See :meth:`_codec_config`.
184+
**Declare ``context`` as well**: ``encode(self, value, *, key=None,
185+
context=None, store_name=None)``. It carries ``schema``, ``table``,
186+
``field`` and ``config`` — the calling connection's configuration, which
187+
:meth:`_codec_config` reads and which store resolution needs.
188+
189+
Before 2.3.4 those four arrived inside ``key`` under underscore-prefixed
190+
names. That path still works and DataJoint still populates it, so a codec
191+
written against it keeps running — but it is deprecated and removed in
192+
2.4. Write new codecs against ``context``.
188193
"""
189194
...
190195

@@ -207,7 +212,8 @@ def decode(self, stored: Any, *, key: dict | None = None) -> Any:
207212
208213
Notes
209214
-----
210-
Implementations may also accept ``context``; see :meth:`encode`.
215+
**Declare ``context`` as well**: ``decode(self, stored, *, key=None,
216+
context=None)``. See :meth:`encode`.
211217
"""
212218
...
213219

‎src/datajoint/heading.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ def get_dtype(self, is_store: bool) -> str:
4444
f"Codec <{self._codec_name}> is not registered. Define a Codec subclass with name='{self._codec_name}'."
4545
)
4646

47-
def encode(self, value, *, key=None, store_name=None):
47+
def encode(self, value, *, key=None, context=None, store_name=None):
4848
raise DataJointError(
4949
f"Codec <{self._codec_name}> is not registered. Define a Codec subclass with name='{self._codec_name}'."
5050
)
5151

52-
def decode(self, stored, *, key=None):
52+
def decode(self, stored, *, key=None, context=None):
5353
raise DataJointError(
5454
f"Codec <{self._codec_name}> is not registered. Define a Codec subclass with name='{self._codec_name}'."
5555
)

‎src/datajoint/spark.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ class SparkAdapter(Protocol):
5959
class FloatArrayCodec(dj.Codec):
6060
name = "float_array"
6161
62-
def encode(self, value, *, key=None, store_name=None): ...
63-
def decode(self, stored, *, key=None) -> np.ndarray: ...
62+
def encode(self, value, *, key=None, context=None, store_name=None): ...
63+
def decode(self, stored, *, key=None, context=None) -> np.ndarray: ...
6464
6565
def to_spark(self, decoded: np.ndarray, *, key=None) -> list[float]:
6666
return decoded.tolist() # → Spark ARRAY<DOUBLE>

0 commit comments

Comments
 (0)