cobra-array 0.1.1__tar.gz → 0.1.3__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 (31) hide show
  1. {cobra_array-0.1.1/src/cobra_array.egg-info → cobra_array-0.1.3}/PKG-INFO +3 -11
  2. {cobra_array-0.1.1 → cobra_array-0.1.3}/README.md +2 -10
  3. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/__init__.py +8 -15
  4. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/_core.py +79 -1
  5. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/_utils.py +1 -1
  6. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/array_api.py +67 -1
  7. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/__init__.py +18 -0
  8. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/_array.py +55 -0
  9. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/_namespace.py +25 -0
  10. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/convert.py +53 -0
  11. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/default.py +20 -1
  12. {cobra_array-0.1.1 → cobra_array-0.1.3/src/cobra_array.egg-info}/PKG-INFO +3 -11
  13. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_default.py +1 -1
  14. {cobra_array-0.1.1 → cobra_array-0.1.3}/LICENSE +0 -0
  15. {cobra_array-0.1.1 → cobra_array-0.1.3}/pyproject.toml +0 -0
  16. {cobra_array-0.1.1 → cobra_array-0.1.3}/setup.cfg +0 -0
  17. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/_array.pyi +0 -0
  18. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/_base.py +0 -0
  19. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/compat/_namespace.pyi +0 -0
  20. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/convert.pyi +0 -0
  21. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/exceptions.py +0 -0
  22. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array/types.py +0 -0
  23. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array.egg-info/SOURCES.txt +0 -0
  24. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array.egg-info/dependency_links.txt +0 -0
  25. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array.egg-info/requires.txt +0 -0
  26. {cobra_array-0.1.1 → cobra_array-0.1.3}/src/cobra_array.egg-info/top_level.txt +0 -0
  27. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_backend.py +0 -0
  28. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_compat.py +0 -0
  29. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_compat_namespace.py +0 -0
  30. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_convert.py +0 -0
  31. {cobra_array-0.1.1 → cobra_array-0.1.3}/tests/test_wrap.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cobra-array
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: A backend-agnostic array utility library that unifies array conversion, context control, and cross-library operations across `NumPy`/`PyTorch`-style ecosystems.
5
5
  Author-email: Zhen Tian <zhen.tian.cs@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/tinchen777/cobra-array.git
@@ -71,14 +71,11 @@ pip install cobra-array
71
71
 
72
72
  data = [[1, 2], [3, 4]]
73
73
 
74
- arr_np = to_numpy(data, dtype=np.float32)
75
- print(type(arr_np), arr_np.dtype) # numpy.ndarray float32
74
+ arr_np = to_numpy(data, dtype=np.float32) # numpy.ndarray float32
76
75
 
77
76
  arr_torch = to_tensor(data, device="cpu")
78
- print(type(arr_torch), arr_torch.device)
79
77
 
80
- back_to_list = to_list(arr_np)
81
- print(back_to_list) # [[1.0, 2.0], [3.0, 4.0]]
78
+ back_to_list = to_list(arr_np) # [[1.0, 2.0], [3.0, 4.0]]
82
79
  ```
83
80
 
84
81
  - Context-based conversion:
@@ -91,8 +88,6 @@ pip install cobra-array
91
88
  x = as_context([1, 2, 3])
92
89
  y = as_context(np.array([4, 5]))
93
90
  spec = context_spec()
94
- print(spec.cxp.xp_name, spec.dtype, spec.device)
95
- print(x, y)
96
91
  ```
97
92
 
98
93
  - Auto-unify function arguments:
@@ -107,7 +102,6 @@ pip install cobra-array
107
102
  return c.mean()
108
103
 
109
104
  out = add_and_mean(np.array([1, 2, 3]), [4, 5, 6])
110
- print(out)
111
105
  ```
112
106
 
113
107
  - Default backend strategy:
@@ -116,10 +110,8 @@ pip install cobra-array
116
110
  from cobra_array.default import as_default, default_spec
117
111
 
118
112
  spec = default_spec()
119
- print(spec.cxp.xp_name, spec.dtype, spec.device)
120
113
 
121
114
  x = as_default([1, 2, 3], unify_dtype=True, unify_device=True)
122
- print(x, x.dtype)
123
115
  ```
124
116
 
125
117
  ## Requirements
@@ -46,14 +46,11 @@ pip install cobra-array
46
46
 
47
47
  data = [[1, 2], [3, 4]]
48
48
 
49
- arr_np = to_numpy(data, dtype=np.float32)
50
- print(type(arr_np), arr_np.dtype) # numpy.ndarray float32
49
+ arr_np = to_numpy(data, dtype=np.float32) # numpy.ndarray float32
51
50
 
52
51
  arr_torch = to_tensor(data, device="cpu")
53
- print(type(arr_torch), arr_torch.device)
54
52
 
55
- back_to_list = to_list(arr_np)
56
- print(back_to_list) # [[1.0, 2.0], [3.0, 4.0]]
53
+ back_to_list = to_list(arr_np) # [[1.0, 2.0], [3.0, 4.0]]
57
54
  ```
58
55
 
59
56
  - Context-based conversion:
@@ -66,8 +63,6 @@ pip install cobra-array
66
63
  x = as_context([1, 2, 3])
67
64
  y = as_context(np.array([4, 5]))
68
65
  spec = context_spec()
69
- print(spec.cxp.xp_name, spec.dtype, spec.device)
70
- print(x, y)
71
66
  ```
72
67
 
73
68
  - Auto-unify function arguments:
@@ -82,7 +77,6 @@ pip install cobra-array
82
77
  return c.mean()
83
78
 
84
79
  out = add_and_mean(np.array([1, 2, 3]), [4, 5, 6])
85
- print(out)
86
80
  ```
87
81
 
88
82
  - Default backend strategy:
@@ -91,10 +85,8 @@ pip install cobra-array
91
85
  from cobra_array.default import as_default, default_spec
92
86
 
93
87
  spec = default_spec()
94
- print(spec.cxp.xp_name, spec.dtype, spec.device)
95
88
 
96
89
  x = as_default([1, 2, 3], unify_dtype=True, unify_device=True)
97
- print(x, x.dtype)
98
90
  ```
99
91
 
100
92
  ## Requirements
@@ -12,6 +12,7 @@ Modules
12
12
  - :mod:`cobra_array.convert`: Utilities for converting between different array types and namespaces.
13
13
  - :mod:`cobra_array.default`: Default utilities for array specifications and namespaces.
14
14
  - :mod:`cobra_array.array_api`: Utilities for working with array namespaces and devices.
15
+
15
16
  Functions
16
17
  ---------
17
18
  - :func:`array_spec`: Get the array specification of an object.
@@ -25,23 +26,20 @@ Functions
25
26
 
26
27
  Examples
27
28
  --------
28
- Basic conversions::
29
+ - Basic conversions::
29
30
 
30
31
  import numpy as np
31
32
  from cobra_array.convert import to_numpy, to_tensor, to_list
32
33
 
33
34
  data = [[1, 2], [3, 4]]
34
35
 
35
- arr_np = to_numpy(data, dtype=np.float32)
36
- print(type(arr_np), arr_np.dtype) # numpy.ndarray float32
36
+ arr_np = to_numpy(data, dtype=np.float32) # numpy.ndarray float32
37
37
 
38
38
  arr_torch = to_tensor(data, device="cpu")
39
- print(type(arr_torch), arr_torch.device)
40
39
 
41
- back_to_list = to_list(arr_np)
42
- print(back_to_list) # [[1.0, 2.0], [3.0, 4.0]]
40
+ back_to_list = to_list(arr_np) # [[1.0, 2.0], [3.0, 4.0]]
43
41
 
44
- Context-based conversion::
42
+ - Context-based conversion::
45
43
 
46
44
  import numpy as np
47
45
  from cobra_array import array_context, as_context, context_spec
@@ -50,10 +48,8 @@ Context-based conversion::
50
48
  x = as_context([1, 2, 3])
51
49
  y = as_context(np.array([4, 5]))
52
50
  spec = context_spec()
53
- print(spec.cxp.xp_name, spec.dtype, spec.device)
54
- print(x, y)
55
51
 
56
- Auto-unify function arguments::
52
+ - Auto-unify function arguments::
57
53
 
58
54
  import numpy as np
59
55
  from cobra_array import unify_args
@@ -64,17 +60,14 @@ Auto-unify function arguments::
64
60
  return c.mean()
65
61
 
66
62
  out = add_and_mean(np.array([1, 2, 3]), [4, 5, 6])
67
- print(out)
68
63
 
69
- Default backend strategy::
64
+ - Default backend strategy::
70
65
 
71
66
  from cobra_array.default import as_default, default_spec
72
67
 
73
68
  spec = default_spec()
74
- print(spec.cxp.xp_name, spec.dtype, spec.device)
75
69
 
76
70
  x = as_default([1, 2, 3], unify_dtype=True, unify_device=True)
77
- print(x, x.dtype)
78
71
  """
79
72
 
80
73
  from ._core import (
@@ -91,7 +84,7 @@ from ._utils import (
91
84
  )
92
85
 
93
86
  __author__ = "Zhen Tian"
94
- __version__ = "0.1.1"
87
+ __version__ = "0.1.3"
95
88
 
96
89
  __all__ = [
97
90
  "array_spec",
@@ -85,6 +85,32 @@ def array_spec(
85
85
  If `ref` is not `None`, a string, or an integer.
86
86
  NotArrayAPIObjectError
87
87
  If the reference array determined by `ref` is not an array API compatible array object.
88
+
89
+ Examples
90
+ --------
91
+ Infer namespace from positional arrays:
92
+
93
+ >>> import numpy as np
94
+ >>> spec = array_spec(np.asarray([1, 2]), np.asarray([3, 4]))
95
+ >>> spec.cxp.xp_name
96
+ 'NumPy'
97
+ >>> spec.dtype is None and spec.device is None
98
+ True
99
+
100
+ Use a keyword argument as reference to carry dtype and device:
101
+
102
+ >>> ref_arr = np.asarray([1, 2], dtype=np.float32)
103
+ >>> spec = array_spec(kw_arrays={"x": ref_arr}, ref="x")
104
+ >>> str(spec.dtype)
105
+ 'float32'
106
+ >>> str(spec.device)
107
+ 'cpu'
108
+
109
+ Filter non-array-like inputs when selecting reference by index:
110
+
111
+ >>> spec = array_spec("skip", np.asarray([1, 2]), ref=0, filter_arraylike=True)
112
+ >>> spec.cxp.xp_name
113
+ 'NumPy'
88
114
  """
89
115
  kw_arrays = kw_arrays or {}
90
116
 
@@ -240,6 +266,12 @@ def as_context(
240
266
  Raises
241
267
  ------
242
268
  Refer to :func:`convert.as_array`, :func:`context_spec` for possible exceptions.
269
+
270
+ Examples
271
+ --------
272
+ >>> from cobra_array import as_context
273
+ >>> as_context([1, 2, 3])
274
+ PyTorch_Array(tensor([1., 2., 3.], dtype=torch.float64))
243
275
  """
244
276
  spec = context_spec()
245
277
  return wrap_arraylike(as_array(
@@ -254,6 +286,40 @@ def as_context(
254
286
  class array_context:
255
287
  """
256
288
  **Context Manager** to set the context `compatibility namespace`, `dtype` and `device` for the enclosed block of code.
289
+
290
+ Examples
291
+ --------
292
+ Set a temporary context explicitly:
293
+
294
+ >>> from cobra_array import array_context
295
+ >>> with array_context(xp="numpy", dtype=None, device="cpu") as spec:
296
+ ... spec.cxp.xp_name
297
+ 'NumPy'
298
+
299
+ Convert data in the active context:
300
+
301
+ >>> with array_context(xp="numpy", dtype=None, device="cpu"):
302
+ ... as_context([1, 2, 3], unify_dtype=False)
303
+ NumPy_Array([1 2 3])
304
+
305
+ Build a context from :class:`ArraySpec`:
306
+
307
+ >>> import numpy as np
308
+ >>> spec = array_spec(np.asarray([1, 2], dtype=np.float32), ref=0)
309
+ >>> with array_context.from_array_spec(spec) as cur:
310
+ ... str(cur.dtype)
311
+ 'float32'
312
+
313
+ Nested contexts override temporarily and then restore outer context:
314
+
315
+ >>> from cobra_array import context_spec
316
+ >>> with array_context(xp="numpy", dtype=None, device="cpu"):
317
+ ... before = context_spec().dtype
318
+ ... with array_context(dtype=float):
319
+ ... middle = context_spec().dtype
320
+ ... after = context_spec().dtype
321
+ ... (before is None, middle is float, after is None)
322
+ (True, True, True)
257
323
  """
258
324
  @classmethod
259
325
  def from_array_spec(cls, arr_spec: ArraySpec, /):
@@ -309,7 +375,7 @@ class array_context:
309
375
 
310
376
  def unify_args(
311
377
  ref: Optional[Union[str, int]] = 0,
312
- /,
378
+ /, *,
313
379
  filter_arraylike: bool = True,
314
380
  api_version: Optional[str] = None,
315
381
  use_compat: Optional[bool] = None,
@@ -353,6 +419,18 @@ def unify_args(
353
419
  Raises
354
420
  ------
355
421
  Refer to :func:`default.default_spec`, :func:`as_context` for possible exceptions.
422
+
423
+ Examples
424
+ --------
425
+ Use `unify_args` as a decorator to normalize array arguments before the function body runs:
426
+
427
+ >>> import numpy as np
428
+ >>> from cobra_array import unify_args
429
+ >>> @unify_args(ref=0, unify_dtype=False, unify_device=False)
430
+ ... def add(x, y):
431
+ ... return x + y
432
+ >>> add(np.asarray([1, 2]), y=np.asarray([3, 4]))
433
+ NumPy_Array([4 6])
356
434
  """
357
435
  def decorator(func):
358
436
  @wraps(func)
@@ -43,7 +43,7 @@ def array_namespace_alias(xp: object) -> str:
43
43
  Raises
44
44
  ------
45
45
  UnsupportedNameSpaceError
46
- If the input object is not a supported namespace.
46
+ If the input object is not a supported `array namespace`.
47
47
  """
48
48
  if isinstance(xp, ModuleType):
49
49
  if api.is_numpy_namespace(xp):
@@ -15,6 +15,24 @@ Attributes
15
15
  Functions
16
16
  ---------
17
17
  - :func:`resolve_device`: Get the device string from an object or a device specification string, and check if it is compatible with the specified `array namespace` if provided.
18
+
19
+ Examples
20
+ --------
21
+ - Basic usage::
22
+
23
+ from cobra_array.array_api import resolve_device, torch_xp, numpy_xp
24
+
25
+ r = resolve_device("cpu") # "cpu"
26
+ r = resolve_device("cuda:0") # "cuda:0"
27
+
28
+ if numpy_xp is not None:
29
+ r = resolve_device("cpu", xp="numpy")
30
+
31
+ if torch_xp is not None:
32
+ r = resolve_device("cpu", xp="torch")
33
+
34
+ if torch_xp is not None:
35
+ r = resolve_device("cpu", xp=torch_xp)
18
36
  """
19
37
 
20
38
  from __future__ import annotations
@@ -61,7 +79,7 @@ def resolve_device(
61
79
  obj : object
62
80
  The input object or device specification string to extract the device information from.
63
81
 
64
- xp : Optional[Union[Namespace, CompatNamespace, ArrayLibraryName]], default is `None`
82
+ xp : Optional[Union[Any, ArrayLibraryName]], default is `None`
65
83
  The `array namespace` to check the device compatibility against.
66
84
  - `None`: No compatibility check will be performed.
67
85
 
@@ -80,6 +98,54 @@ def resolve_device(
80
98
  If the extracted device is not compatible with the specified `array namespace`.
81
99
  CUDAUnavailableError
82
100
  If a CUDA device is specified but CUDA is not available for `PyTorch`.
101
+
102
+ Examples
103
+ --------
104
+ Basic parsing and normalization:
105
+
106
+ >>> resolve_device("cpu")
107
+ 'cpu'
108
+ >>> resolve_device(" CUDA:0 ")
109
+ 'cuda:0'
110
+ >>> resolve_device(None)
111
+ None
112
+
113
+ Namespace compatibility checks:
114
+
115
+ >>> resolve_device("cpu")
116
+ 'cpu'
117
+ >>> resolve_device("cpu", xp="numpy")
118
+ 'cpu'
119
+ >>> resolve_device("cpu", xp="torch")
120
+ 'cpu'
121
+
122
+ Unsupported device for NumPy:
123
+
124
+ >>> resolve_device("cuda:0", xp="numpy")
125
+ Traceback (most recent call last):
126
+ ...
127
+ cobra_array.exceptions.DeviceNotSupportedError: ...
128
+
129
+ Unsupported device type for PyTorch:
130
+
131
+ >>> resolve_device("quantum", xp="torch")
132
+ Traceback (most recent call last):
133
+ ...
134
+ cobra_array.exceptions.DeviceNotSupportedError: ...
135
+
136
+ CUDA path for PyTorch (works with or without CUDA runtime):
137
+
138
+ >>> from cobra_array.array_api import CUDA_AVAILABLE
139
+ >>> result = None
140
+ >>> if not CUDA_AVAILABLE:
141
+ ... try:
142
+ ... resolve_device("cuda:0", xp="torch")
143
+ ... except CUDAUnavailableError:
144
+ ... result = "CUDAUnavailableError"
145
+ ... else:
146
+ ... result = resolve_device("cuda:0", xp="torch")
147
+ >>> result in {"cuda:0", "CUDAUnavailableError"}
148
+ True
83
149
  """
84
150
  # source
85
151
  if obj is None:
@@ -6,10 +6,28 @@ Functions
6
6
  ---------
7
7
  - :func:`wrap_arraylike`: Wraps an array-like object in a :class:`CompatArray` array if it is an array API object.
8
8
  - :func:`unwrap`: Unwraps a :class:`CompatArray` array to get the backend-specific array instance, or returns the object itself if it is not a :class:`CompatArray` array.
9
+
9
10
  Classes
10
11
  -------
11
12
  - :class:`CompatArray`: A backend-agnostic array abstraction compliant with the `Python Array API standard`.
12
13
  - :class:`CompatNamespace`: A wrapper around an `array namespace` providing a unified, backend-agnostic functional interface.
14
+
15
+ Examples
16
+ --------
17
+ - Basic usage::
18
+
19
+ import numpy as np
20
+ from cobra_array.compat import CompatArray, CompatNamespace, wrap_arraylike, unwrap
21
+
22
+ cxp = CompatNamespace(np)
23
+ a = CompatArray(np.asarray([1, 2, 3]))
24
+ b = cxp.asarray([10, 20, 30])
25
+
26
+ r = (a + b).to_list() # [11, 22, 33]
27
+ r = cxp.add(a, b).to_list() # [11, 22, 33]
28
+
29
+ wrapped = wrap_arraylike(np.asarray([4, 5]))
30
+ unwrap(wrapped).tolist() # [4, 5]
13
31
  """
14
32
 
15
33
  from ._array import (CompatArray, wrap_arraylike, unwrap)
@@ -26,6 +26,61 @@ class CompatArray(Compat):
26
26
  - All operations follow the semantics defined by the `Python Array API standard`.
27
27
  - Methods correspond directly to standard functions, but are exposed in an object-oriented form.
28
28
  - All methods guarantee that any array-like objects in the returned value are automatically wrapped as :class:`CompatArray`. This applies recursively to arrays contained in Python containers (e.g., `tuple`, `list`, `dict`). Non-array objects remain unchanged.
29
+
30
+ Examples
31
+ --------
32
+ Create a :class:`CompatArray` from a backend array object:
33
+
34
+ >>> xp = to_xp("numpy")
35
+ >>> a = CompatArray(xp.asarray([1, 2, 3]))
36
+ >>> a
37
+ NumPy_Array([1 2 3])
38
+ >>> a.to_list()
39
+ [1, 2, 3]
40
+ >>> a.shape
41
+ (3,)
42
+ >>> a.xp_name
43
+ 'NumPy'
44
+
45
+ Convert Python data with an explicit backend:
46
+
47
+ >>> b = CompatArray.from_other([10, 20], xp="numpy")
48
+ >>> isinstance(b, CompatArray)
49
+ True
50
+ >>> b.to_tensor()
51
+ tensor([10, 20])
52
+
53
+ Re-wrapping behavior for existing :class:`CompatArray`:
54
+
55
+ >>> CompatArray(b) is b
56
+ True
57
+ >>> CompatArray(b, copy=True) is b
58
+ False
59
+
60
+ Call elementwise functions directly:
61
+
62
+ >>> x = CompatArray.from_other([1, 2, 3], xp="numpy")
63
+ >>> y = CompatArray.from_other([10, 20, 30], xp="numpy")
64
+ >>> x.add(y)
65
+ NumPy_Array([11 22 33])
66
+ >>> x.multiply(2)
67
+ NumPy_Array([2 4 6])
68
+
69
+ Use Python operators:
70
+
71
+ >>> x + y
72
+ NumPy_Array([11 22 33])
73
+ >>> y - x
74
+ NumPy_Array([ 9 18 27])
75
+ >>> x * 2
76
+ NumPy_Array([2 4 6])
77
+
78
+ Invalid input raises an exception:
79
+
80
+ >>> CompatArray("not-array")
81
+ Traceback (most recent call last):
82
+ ...
83
+ cobra_array.exceptions.NotArrayAPIObjectError: ...
29
84
  """
30
85
  _arr = None
31
86
  _cxp = None
@@ -23,6 +23,31 @@ class CompatNamespace(Compat):
23
23
  - Functions correspond directly to those defined in the underlying `array namespace`, following the `Python Array API standard`.
24
24
  - This namespace complements :class:`CompatArray` by providing a functional interface for operations that are not naturally expressed as methods.
25
25
  - All functions guarantee that any array-like objects in the returned value are automatically wrapped as :class:`CompatArray`. This conversion is applied recursively to arrays contained in Python containers (e.g., `tuple`, `list`, `dict`). Non-array objects remain unchanged.
26
+
27
+ Examples
28
+ --------
29
+ Create a compatibility namespace from a backend namespace:
30
+
31
+ >>> import numpy as np
32
+ >>> cxp = CompatNamespace(np)
33
+ >>> cxp.xp_name
34
+ 'NumPy'
35
+
36
+ Create arrays and call namespace functions:
37
+
38
+ >>> a = cxp.asarray([1, 2, 3])
39
+ >>> b = cxp.asarray([10, 20, 30])
40
+ >>> a
41
+ NumPy_Array([1 2 3])
42
+ >>> cxp.add(a, b).to_list()
43
+ [11, 22, 33]
44
+
45
+ Missing attributes raise an exception:
46
+
47
+ >>> cxp.this_attr_does_not_exist
48
+ Traceback (most recent call last):
49
+ ...
50
+ AttributeError: ...
26
51
  """
27
52
  def __new__(cls, xp, /):
28
53
  if isinstance(xp, CompatNamespace):
@@ -12,6 +12,24 @@ Functions
12
12
  - :func:`to_list`: Convert an object to a built-in `list`.
13
13
  - :func:`to_array_namespace` or :func:`to_xp`: Convert an array library name to a `array namespace` or return the `array namespace` directly if is a supported namespace.
14
14
  - :func:`as_array`: Convert an object to an array in the specified `array namespace`.
15
+
16
+ Examples
17
+ --------
18
+ - Basic usage::
19
+
20
+ import numpy as np
21
+ from cobra_array.convert import to_numpy, to_tensor, to_list, to_xp, as_array
22
+
23
+ r = to_numpy([1, 2, 3]) # array([1, 2, 3])
24
+ r = to_list(np.asarray([1, 2, 3])) # [1, 2, 3]
25
+ r = to_xp("numpy") # NumPy namespace
26
+ r = as_array([1, 2, 3], "numpy") # NumPy array
27
+
28
+ - When PyTorch is available, the same helpers can be used with the torch namespace::
29
+
30
+ from cobra_array.convert import as_array
31
+
32
+ r = as_array([1, 2, 3], "torch") # PyTorch tensor
15
33
  """
16
34
 
17
35
  from collections import abc
@@ -304,6 +322,41 @@ def as_array(obj, xp, /, *, dtype=None, device=None, copy=False, arraylike_only=
304
322
  If an unsupported `array namespace` is specified.
305
323
  ArrayConversionError
306
324
  If an error occurs during array conversion in the specified `array namespace`.
325
+
326
+ Examples
327
+ --------
328
+ Convert to NumPy namespace (when available):
329
+
330
+ >>> from cobra_array.array_api import numpy_xp
331
+ >>> if numpy_xp is not None:
332
+ ... as_array([1, 2, 3], "numpy")
333
+ array([1, 2, 3])
334
+ >>> if numpy_xp is not None:
335
+ ... as_array([1, 2, 3], numpy_xp)
336
+ array([1, 2, 3])
337
+
338
+ Convert to PyTorch namespace (when available):
339
+
340
+ >>> from cobra_array.array_api import torch_xp
341
+ >>> if torch_xp is not None:
342
+ ... as_array([1, 2, 3], "torch")
343
+ tensor([1, 2, 3])
344
+ >>> if torch_xp is not None:
345
+ ... as_array([1, 2, 3], torch_xp)
346
+ tensor([1, 2, 3])
347
+
348
+ Pass through non-array-like objects with `arraylike_only=True`:
349
+
350
+ >>> marker = object()
351
+ >>> as_array(marker, "numpy", arraylike_only=True) is marker
352
+ True
353
+
354
+ Unsupported namespace name raises an error:
355
+
356
+ >>> as_array([1, 2, 3], "unknown")
357
+ Traceback (most recent call last):
358
+ ...
359
+ cobra_array.exceptions.UnsupportedArrayLibraryNameError: ...
307
360
  """
308
361
  if arraylike_only and not api.is_array_api_obj(obj):
309
362
  return obj
@@ -15,6 +15,19 @@ Functions
15
15
  ---------
16
16
  - :func:`default_spec`: Get the default array specification.
17
17
  - :func:`as_default`: Convert an array-like object to a :class:`CompatArray` array in the default context.
18
+
19
+ Examples
20
+ --------
21
+ - Basic usage::
22
+
23
+ from cobra_array.default import default_spec, as_default
24
+
25
+ spec = default_spec()
26
+ spec.cxp.xp_name # "PyTorch" or "NumPy"
27
+ spec.dtype # default dtype, e.g. float
28
+ spec.device # default device, e.g. "cpu"
29
+
30
+ arr = as_default([1, 2, 3]) # PyTorch_Array(tensor([1., 2., 3.], dtype=torch.float64)) or CompatArray([1. 2. 3.])
18
31
  """
19
32
 
20
33
  from __future__ import annotations
@@ -53,7 +66,7 @@ class ArraySpec(NamedTuple):
53
66
 
54
67
 
55
68
  # get defaults
56
- DEFAULT_DTYPE = float
69
+ DEFAULT_DTYPE = None
57
70
  DEFAULT_DEVICE = "cpu"
58
71
  NUMPY_COMPAT_NAMESPACE = CompatNamespace(numpy_xp) if numpy_xp is not None else None
59
72
  TORCH_COMPAT_NAMESPACE = CompatNamespace(torch_xp) if torch_xp is not None else None
@@ -131,6 +144,12 @@ def as_default(
131
144
  Raises
132
145
  ------
133
146
  Refer to :func:`convert.as_array`, :func:`default.default_spec` for possible exceptions.
147
+
148
+ Examples
149
+ --------
150
+ >>> from cobra_array.default import as_default
151
+ >>> as_default([1, 2, 3])
152
+ PyTorch_Array(tensor([1., 2., 3.], dtype=torch.float64))
134
153
  """
135
154
  spec = default_spec()
136
155
  return wrap_arraylike(as_array(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cobra-array
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: A backend-agnostic array utility library that unifies array conversion, context control, and cross-library operations across `NumPy`/`PyTorch`-style ecosystems.
5
5
  Author-email: Zhen Tian <zhen.tian.cs@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/tinchen777/cobra-array.git
@@ -71,14 +71,11 @@ pip install cobra-array
71
71
 
72
72
  data = [[1, 2], [3, 4]]
73
73
 
74
- arr_np = to_numpy(data, dtype=np.float32)
75
- print(type(arr_np), arr_np.dtype) # numpy.ndarray float32
74
+ arr_np = to_numpy(data, dtype=np.float32) # numpy.ndarray float32
76
75
 
77
76
  arr_torch = to_tensor(data, device="cpu")
78
- print(type(arr_torch), arr_torch.device)
79
77
 
80
- back_to_list = to_list(arr_np)
81
- print(back_to_list) # [[1.0, 2.0], [3.0, 4.0]]
78
+ back_to_list = to_list(arr_np) # [[1.0, 2.0], [3.0, 4.0]]
82
79
  ```
83
80
 
84
81
  - Context-based conversion:
@@ -91,8 +88,6 @@ pip install cobra-array
91
88
  x = as_context([1, 2, 3])
92
89
  y = as_context(np.array([4, 5]))
93
90
  spec = context_spec()
94
- print(spec.cxp.xp_name, spec.dtype, spec.device)
95
- print(x, y)
96
91
  ```
97
92
 
98
93
  - Auto-unify function arguments:
@@ -107,7 +102,6 @@ pip install cobra-array
107
102
  return c.mean()
108
103
 
109
104
  out = add_and_mean(np.array([1, 2, 3]), [4, 5, 6])
110
- print(out)
111
105
  ```
112
106
 
113
107
  - Default backend strategy:
@@ -116,10 +110,8 @@ pip install cobra-array
116
110
  from cobra_array.default import as_default, default_spec
117
111
 
118
112
  spec = default_spec()
119
- print(spec.cxp.xp_name, spec.dtype, spec.device)
120
113
 
121
114
  x = as_default([1, 2, 3], unify_dtype=True, unify_device=True)
122
- print(x, x.dtype)
123
115
  ```
124
116
 
125
117
  ## Requirements
@@ -19,7 +19,7 @@ def test_default_spec_returns_valid_defaults():
19
19
  spec = default_spec()
20
20
  assert isinstance(spec, ArraySpec)
21
21
  assert isinstance(spec.cxp, CompatNamespace)
22
- assert spec.dtype is float
22
+ assert spec.dtype is None
23
23
  assert spec.device == "cpu"
24
24
 
25
25
 
File without changes
File without changes
File without changes