haliax 1.4.dev400__tar.gz → 1.4.dev402__tar.gz

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 (120) hide show
  1. {haliax-1.4.dev400 → haliax-1.4.dev402}/PKG-INFO +1 -1
  2. haliax-1.4.dev402/src/haliax/__about__.py +1 -0
  3. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/__init__.py +2 -0
  4. haliax-1.4.dev402/src/haliax/field.py +38 -0
  5. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/partitioning.py +57 -29
  6. haliax-1.4.dev402/tests/test_field.py +19 -0
  7. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_partitioning.py +20 -1
  8. haliax-1.4.dev400/src/haliax/__about__.py +0 -1
  9. {haliax-1.4.dev400 → haliax-1.4.dev402}/.coveragerc +0 -0
  10. {haliax-1.4.dev400 → haliax-1.4.dev402}/.flake8 +0 -0
  11. {haliax-1.4.dev400 → haliax-1.4.dev402}/.github/workflows/publish_dev.yaml +0 -0
  12. {haliax-1.4.dev400 → haliax-1.4.dev402}/.github/workflows/run_pre_commit.yaml +0 -0
  13. {haliax-1.4.dev400 → haliax-1.4.dev402}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
  14. {haliax-1.4.dev400 → haliax-1.4.dev402}/.github/workflows/run_tests.yaml +0 -0
  15. {haliax-1.4.dev400 → haliax-1.4.dev402}/.gitignore +0 -0
  16. {haliax-1.4.dev400 → haliax-1.4.dev402}/.playbooks/add-types.md +0 -0
  17. {haliax-1.4.dev400 → haliax-1.4.dev402}/.playbooks/wrap-non-named.md +0 -0
  18. {haliax-1.4.dev400 → haliax-1.4.dev402}/.pre-commit-config.yaml +0 -0
  19. {haliax-1.4.dev400 → haliax-1.4.dev402}/.readthedocs.yaml +0 -0
  20. {haliax-1.4.dev400 → haliax-1.4.dev402}/AGENTS.md +0 -0
  21. {haliax-1.4.dev400 → haliax-1.4.dev402}/CONTRIBUTING.md +0 -0
  22. {haliax-1.4.dev400 → haliax-1.4.dev402}/LICENSE +0 -0
  23. {haliax-1.4.dev400 → haliax-1.4.dev402}/README.md +0 -0
  24. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/api.md +0 -0
  25. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/broadcasting.md +0 -0
  26. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/cheatsheet.md +0 -0
  27. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/css/material.css +0 -0
  28. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/css/mkdocstrings.css +0 -0
  29. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/faq.md +0 -0
  30. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/data_parallel_mesh.png +0 -0
  31. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/data_parallel_mesh_replicated.png +0 -0
  32. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_1d.png +0 -0
  33. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_1d_zero.png +0 -0
  34. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d.png +0 -0
  35. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
  36. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
  37. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
  38. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
  39. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/figures/device_mesh_2d_zero.png +0 -0
  40. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/fp8.md +0 -0
  41. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/index.md +0 -0
  42. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/indexing.md +0 -0
  43. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/matmul.md +0 -0
  44. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/nn.md +0 -0
  45. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/partitioning.md +0 -0
  46. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/primer.md +0 -0
  47. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/rearrange.ipynb +0 -0
  48. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/rearrange.md +0 -0
  49. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/requirements.txt +0 -0
  50. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/scan.md +0 -0
  51. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/state-dict.md +0 -0
  52. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/tutorial.md +0 -0
  53. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/typing.md +0 -0
  54. {haliax-1.4.dev400 → haliax-1.4.dev402}/docs/vmap.md +0 -0
  55. {haliax-1.4.dev400 → haliax-1.4.dev402}/mkdocs.yml +0 -0
  56. {haliax-1.4.dev400 → haliax-1.4.dev402}/pyproject.toml +0 -0
  57. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/__init__.py +0 -0
  58. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/compile_utils.py +0 -0
  59. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/dot.py +0 -0
  60. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/einsum.py +0 -0
  61. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/fp8.py +0 -0
  62. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/parsing.py +0 -0
  63. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/rearrange.py +0 -0
  64. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/scan.py +0 -0
  65. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/state_dict.py +0 -0
  66. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/_src/util.py +0 -0
  67. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/axis.py +0 -0
  68. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/core.py +0 -0
  69. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/debug.py +0 -0
  70. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/haxtyping.py +0 -0
  71. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/hof.py +0 -0
  72. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/jax_utils.py +0 -0
  73. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/__init__.py +0 -0
  74. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/activations.py +0 -0
  75. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/attention.py +0 -0
  76. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/conv.py +0 -0
  77. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/dropout.py +0 -0
  78. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/embedding.py +0 -0
  79. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/linear.py +0 -0
  80. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/loss.py +0 -0
  81. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/mlp.py +0 -0
  82. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/normalization.py +0 -0
  83. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/pool.py +0 -0
  84. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/nn/scan.py +0 -0
  85. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/ops.py +0 -0
  86. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/quantization.py +0 -0
  87. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/random.py +0 -0
  88. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/specialized_fns.py +0 -0
  89. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/state_dict.py +0 -0
  90. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/tree_util.py +0 -0
  91. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/types.py +0 -0
  92. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/util.py +0 -0
  93. {haliax-1.4.dev400 → haliax-1.4.dev402}/src/haliax/wrap.py +0 -0
  94. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/core_test.py +0 -0
  95. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_attention.py +0 -0
  96. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_axis.py +0 -0
  97. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_conv.py +0 -0
  98. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_debug.py +0 -0
  99. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_dot.py +0 -0
  100. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_dtype_typing.py +0 -0
  101. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_einsum.py +0 -0
  102. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_fp8.py +0 -0
  103. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_hof.py +0 -0
  104. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_int8.py +0 -0
  105. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_moe_linear.py +0 -0
  106. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_namedarray_typing.py +0 -0
  107. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_nn.py +0 -0
  108. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_ops.py +0 -0
  109. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_parsing.py +0 -0
  110. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_pool.py +0 -0
  111. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_random.py +0 -0
  112. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_rearrange.py +0 -0
  113. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_scan.py +0 -0
  114. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_scatter_gather.py +0 -0
  115. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_specialized_fns.py +0 -0
  116. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_state_dict.py +0 -0
  117. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_tree_util.py +0 -0
  118. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_utils.py +0 -0
  119. {haliax-1.4.dev400 → haliax-1.4.dev402}/tests/test_visualize_sharding.py +0 -0
  120. {haliax-1.4.dev400 → haliax-1.4.dev402}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haliax
3
- Version: 1.4.dev400
3
+ Version: 1.4.dev402
4
4
  Summary: Named Tensors for Legible Deep Learning in JAX
5
5
  Project-URL: Homepage, https://github.com/stanford-crfm/haliax
6
6
  Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
@@ -0,0 +1 @@
1
+ __version__ = "1.4.dev402"
@@ -17,6 +17,7 @@ import haliax.random as random
17
17
  import haliax.state_dict as state_dict
18
18
  import haliax.tree_util as tree_util
19
19
  import haliax.util as util
20
+ from .field import field
20
21
 
21
22
  from ._src.dot import dot
22
23
  from ._src.einsum import einsum
@@ -932,6 +933,7 @@ __all__ = [
932
933
  "tree_util",
933
934
  "nn",
934
935
  "state_dict",
936
+ "field",
935
937
  "Axis",
936
938
  "AxisSpec",
937
939
  "AxisSelection",
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Callable
4
+
5
+ import equinox as eqx
6
+
7
+
8
+ def field(
9
+ *,
10
+ converter: Callable[[Any], Any] | None = None,
11
+ static: bool = False,
12
+ axis_names: tuple[str, ...] | None = None,
13
+ **kwargs,
14
+ ):
15
+ """Wrapper around :func:`equinox.field` with optional ``axis_names`` metadata.
16
+
17
+ Args:
18
+ converter: Optional function applied to the value during dataclass initialisation.
19
+ static: Whether the field is static in the PyTree.
20
+ axis_names: Optional axis names associated with array fields. Cannot be
21
+ specified together with ``static=True``.
22
+ **kwargs: Additional keyword arguments forwarded to :func:`dataclasses.field`.
23
+
24
+ Returns:
25
+ A dataclasses field configured like :func:`equinox.field` with additional
26
+ ``axis_names`` metadata.
27
+ """
28
+ if static and axis_names is not None:
29
+ raise ValueError("axis_names cannot be specified together with static=True")
30
+
31
+ metadata = dict(kwargs.pop("metadata", {}))
32
+ metadata["axis_names"] = axis_names
33
+
34
+ field_kwargs = {}
35
+ if converter is not None:
36
+ field_kwargs["converter"] = converter
37
+
38
+ return eqx.field(static=static, metadata=metadata, **field_kwargs, **kwargs)
@@ -177,24 +177,21 @@ def shard_with_axis_mapping(x: T, mapping: ResourceMapping, mesh: Optional[Mesh]
177
177
  return shard(x, mapping, mesh)
178
178
 
179
179
 
180
- def infer_resource_partitions(
180
+ def pspec_for(
181
181
  tree: PyTree,
182
182
  resource_mapping: Optional[ResourceMapping] = None,
183
183
  preserve_existing_shardings: bool = True,
184
184
  use_auto_sharding: bool = True,
185
- mesh: Optional[Mesh] = None,
186
185
  ) -> PyTree:
187
- """
188
- Infer the sharding for a module, to be used with named_jit.
189
- The basic idea is to tree all NamedArrays as leaves for the purposes of this function,
190
- and to create NamedShardings from those names plus the resource_mapping.
191
- If preserve_existing_shardings is True, then NamedArrays that are already sharded are left alone.
186
+ """Infer the :class:`PartitionSpec` for a module.
192
187
 
193
- If resource_mapping is not provided, this function attempts to use the global resource mapping.
188
+ This behaves like :func:`infer_resource_partitions` but returns ``PartitionSpec``
189
+ objects instead of :class:`~jax.sharding.NamedSharding`. It is primarily a helper
190
+ for :func:`infer_resource_partitions` but may be useful when only the partition
191
+ specification is required.
194
192
 
195
- If use_auto_sharding is True, then we use the new experimental AUTO-sharding feature, which is not yet
196
- fully supported by JAX. If it is False, then we will guess fully replicated for any unnamed arrays that
197
- don't have a sharding.
193
+ If ``preserve_existing_shardings`` is ``True``, then arrays that already have a
194
+ sharding are left untouched and ``None`` is returned for those leaves.
198
195
  """
199
196
  if resource_mapping is None:
200
197
  resource_mapping = current_thread_local_mapping()
@@ -202,35 +199,26 @@ def infer_resource_partitions(
202
199
  if resource_mapping is None:
203
200
  raise ValueError("No resource mapping found")
204
201
 
205
- mesh = mesh or _get_mesh()
206
- assert not isinstance(mesh, dict)
207
-
208
202
  def partition_spec(node: typing.Any):
209
203
  if isinstance(node, NamedArray):
210
204
  # If our NamedArray doesn't have an array (or a shapedtypestruct), we can't shard it
211
- # so better to not try
212
205
  if not is_jax_array_like(node.array):
213
206
  return None
214
207
 
215
- if preserve_existing_shardings:
216
- current_sharding = getattr(node.array, "sharding", None)
217
- else:
218
- current_sharding = None
219
-
208
+ current_sharding = getattr(node.array, "sharding", None) if preserve_existing_shardings else None
220
209
  if current_sharding is not None:
221
- return current_sharding
210
+ return None
222
211
  else:
223
- sharding = NamedSharding(mesh, pspec_for_axis(node.axes, resource_mapping))
224
- return sharding
212
+ return pspec_for_axis(node.axes, resource_mapping)
225
213
  elif is_jax_array_like(node):
226
214
  sharding = getattr(node, "sharding", None)
227
215
  # TODO: these are usually replicated. Is there a better way to tell?
228
216
  if node.shape == ():
229
- return NamedSharding(mesh, PartitionSpec())
217
+ return PartitionSpec()
230
218
  elif isinstance(sharding, SingleDeviceSharding):
231
- return NamedSharding(mesh, PartitionSpec(None))
232
- elif sharding is not None:
233
- return sharding
219
+ return PartitionSpec(None)
220
+ elif sharding is not None and preserve_existing_shardings:
221
+ return None
234
222
  # elif use_auto_sharding:
235
223
  # TODO: auto doesn't seem to really work reliably yet
236
224
  # compat between 0.4.10 and 0.4.11
@@ -238,15 +226,54 @@ def infer_resource_partitions(
238
226
  # return AUTO(mesh)
239
227
  # else:
240
228
  # return AUTO
241
- return NamedSharding(mesh, PartitionSpec(None))
229
+ return PartitionSpec(None)
242
230
  elif isinstance(node, (bool, float, complex, int)):
243
- return NamedSharding(mesh, PartitionSpec())
231
+ return PartitionSpec()
244
232
  else:
245
233
  return None
246
234
 
247
235
  return htu.tree_map(partition_spec, tree)
248
236
 
249
237
 
238
+ def infer_resource_partitions(
239
+ tree: PyTree,
240
+ resource_mapping: Optional[ResourceMapping] = None,
241
+ preserve_existing_shardings: bool = True,
242
+ use_auto_sharding: bool = True,
243
+ mesh: Optional[Mesh] = None,
244
+ ) -> PyTree:
245
+ """
246
+ Infer the sharding for a module, to be used with ``named_jit``.
247
+
248
+ This first calls :func:`pspec_for` to compute ``PartitionSpec`` objects and then
249
+ wraps them in :class:`~jax.sharding.NamedSharding` using the provided mesh. If
250
+ ``preserve_existing_shardings`` is ``True``, then arrays that are already sharded
251
+ retain their current sharding.
252
+ """
253
+ pspecs = pspec_for(
254
+ tree,
255
+ resource_mapping=resource_mapping,
256
+ preserve_existing_shardings=preserve_existing_shardings,
257
+ use_auto_sharding=use_auto_sharding,
258
+ )
259
+
260
+ mesh = mesh or _get_mesh()
261
+ assert not isinstance(mesh, dict)
262
+
263
+ def to_sharding(node: typing.Any, spec: typing.Any):
264
+ if spec is None:
265
+ if isinstance(node, NamedArray):
266
+ return getattr(node.array, "sharding", None)
267
+ elif is_jax_array_like(node):
268
+ return getattr(node, "sharding", None)
269
+ else:
270
+ return None
271
+ else:
272
+ return NamedSharding(mesh, spec)
273
+
274
+ return htu.tree_map(to_sharding, tree, pspecs)
275
+
276
+
250
277
  class WrappedCallable(typing.Protocol[Args, R]):
251
278
  """
252
279
  A wrapper for a callable that preserves the original function's name and qualname.
@@ -659,6 +686,7 @@ __all__ = [
659
686
  "auto_sharded",
660
687
  "shard",
661
688
  "shard_with_axis_mapping",
689
+ "pspec_for",
662
690
  "infer_resource_partitions",
663
691
  "named_jit",
664
692
  "fsdp",
@@ -0,0 +1,19 @@
1
+ import jax.numpy as jnp
2
+ import equinox as eqx
3
+ import pytest
4
+
5
+ import haliax as hax
6
+
7
+
8
+ class M(eqx.Module):
9
+ a: jnp.ndarray = hax.field(axis_names=("batch",))
10
+
11
+
12
+ def test_axis_names_metadata():
13
+ field = M.__dataclass_fields__["a"]
14
+ assert field.metadata["axis_names"] == ("batch",)
15
+
16
+
17
+ def test_axis_names_static_exclusive():
18
+ with pytest.raises(ValueError):
19
+ hax.field(static=True, axis_names=("x",))
@@ -7,7 +7,13 @@ from jaxtyping import Array
7
7
 
8
8
  import haliax as hax
9
9
  from haliax import Axis, NamedArray
10
- from haliax.partitioning import ResourceAxis, axis_mapping, infer_resource_partitions, named_jit
10
+ from haliax.partitioning import (
11
+ ResourceAxis,
12
+ axis_mapping,
13
+ infer_resource_partitions,
14
+ named_jit,
15
+ pspec_for,
16
+ )
11
17
  from test_utils import skip_if_not_enough_devices
12
18
 
13
19
 
@@ -40,6 +46,19 @@ def test_infer_named_axes():
40
46
  assert axes.unnamed1.is_fully_replicated
41
47
 
42
48
 
49
+ def test_pspec_for_named_axes():
50
+ mesh = Mesh(np.array(jax.devices()).reshape(-1, 1), (ResourceAxis.DATA, ResourceAxis.MODEL))
51
+ with axis_mapping(resource_map), mesh:
52
+ mod = MyModule(named=hax.ones((Dim1, Dim2, Dim3)), unnamed1=jnp.ones(Dim2.size), static_field=1)
53
+
54
+ specs: MyModule = pspec_for(mod, preserve_existing_shardings=False)
55
+
56
+ spec = PartitionSpec(None, ResourceAxis.DATA, ResourceAxis.MODEL)
57
+
58
+ assert specs.named == spec
59
+ assert specs.unnamed1 == PartitionSpec(None)
60
+
61
+
43
62
  class MyModuleInit(eqx.Module):
44
63
  named: NamedArray
45
64
  unnamed1: Array
@@ -1 +0,0 @@
1
- __version__ = "1.4.dev400"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes