python-graphblas 2025.2.0a0__tar.gz → 2026.11.0a0__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 (140) hide show
  1. {python_graphblas-2025.2.0a0/python_graphblas.egg-info → python_graphblas-2026.11.0a0}/PKG-INFO +21 -223
  2. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/README.md +5 -6
  3. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/__init__.py +76 -1
  4. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/agg/__init__.py +3 -1
  5. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/binary/__init__.py +3 -1
  6. python_graphblas-2026.11.0a0/graphblas/binary/ss.py +20 -0
  7. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/automethods.py +36 -1
  8. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/base.py +106 -34
  9. python_graphblas-2026.11.0a0/graphblas/core/dtypes.py +853 -0
  10. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/expr.py +26 -1
  11. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/formatting.py +50 -25
  12. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/infix.py +101 -17
  13. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/infixmethods.py +26 -17
  14. python_graphblas-2026.11.0a0/graphblas/core/literals.py +860 -0
  15. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/mask.py +27 -6
  16. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/matrix.py +339 -97
  17. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/__init__.py +1 -0
  18. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/agg.py +81 -3
  19. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/base.py +162 -73
  20. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/binary.py +376 -184
  21. python_graphblas-2026.11.0a0/graphblas/core/operator/indexbinary.py +712 -0
  22. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/indexunary.py +38 -66
  23. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/monoid.py +197 -21
  24. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/select.py +163 -62
  25. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/semiring.py +89 -11
  26. python_graphblas-2026.11.0a0/graphblas/core/operator/udf.py +682 -0
  27. python_graphblas-2026.11.0a0/graphblas/core/operator/udt_codegen.py +1757 -0
  28. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/unary.py +98 -51
  29. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/operator/utils.py +62 -2
  30. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/recorder.py +1 -1
  31. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/scalar.py +267 -117
  32. python_graphblas-2026.11.0a0/graphblas/core/ss/__init__.py +17 -0
  33. python_graphblas-2026.11.0a0/graphblas/core/ss/_utils.py +130 -0
  34. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/binary.py +27 -14
  35. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/config.py +31 -1
  36. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/context.py +12 -6
  37. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/descriptor.py +6 -3
  38. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/dtypes.py +32 -11
  39. python_graphblas-2026.11.0a0/graphblas/core/ss/indexbinary.py +151 -0
  40. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/indexunary.py +28 -14
  41. python_graphblas-2026.11.0a0/graphblas/core/ss/jit_config.py +575 -0
  42. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/matrix.py +285 -125
  43. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/prefix_scan.py +5 -1
  44. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/select.py +8 -1
  45. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/unary.py +26 -13
  46. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/ss/vector.py +120 -67
  47. python_graphblas-2026.11.0a0/graphblas/core/udt.py +936 -0
  48. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/utils.py +184 -18
  49. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/vector.py +248 -97
  50. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/exceptions.py +50 -2
  51. python_graphblas-2026.11.0a0/graphblas/graphblas.yaml +8 -0
  52. python_graphblas-2026.11.0a0/graphblas/indexbinary/__init__.py +33 -0
  53. python_graphblas-2026.11.0a0/graphblas/indexbinary/ss.py +6 -0
  54. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/indexunary/__init__.py +3 -1
  55. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/_awkward.py +5 -14
  56. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/_matrixmarket.py +50 -1
  57. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/_networkx.py +32 -2
  58. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/_scipy.py +7 -1
  59. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/_sparse.py +11 -2
  60. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/monoid/__init__.py +3 -1
  61. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/monoid/numpy.py +8 -6
  62. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/op/__init__.py +3 -1
  63. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/select/__init__.py +53 -17
  64. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/semiring/__init__.py +3 -1
  65. python_graphblas-2026.11.0a0/graphblas/ss/__init__.py +24 -0
  66. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/ss/_core.py +49 -9
  67. python_graphblas-2026.11.0a0/graphblas/tests/conftest.py +273 -0
  68. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_core.py +67 -1
  69. python_graphblas-2026.11.0a0/graphblas/tests/test_dtype.py +700 -0
  70. python_graphblas-2026.11.0a0/graphblas/tests/test_fastpath_parity.py +1075 -0
  71. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_formatting.py +75 -2
  72. python_graphblas-2026.11.0a0/graphblas/tests/test_indexbinary.py +1004 -0
  73. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_infix.py +248 -43
  74. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_io.py +184 -3
  75. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_matrix.py +627 -9
  76. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_numpyops.py +137 -4
  77. python_graphblas-2026.11.0a0/graphblas/tests/test_op.py +7057 -0
  78. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_operator_types.py +2 -0
  79. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_pickle.py +194 -0
  80. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_recorder.py +7 -8
  81. python_graphblas-2026.11.0a0/graphblas/tests/test_scalar.py +1061 -0
  82. python_graphblas-2026.11.0a0/graphblas/tests/test_ss_refcount.py +144 -0
  83. python_graphblas-2026.11.0a0/graphblas/tests/test_ss_utils.py +833 -0
  84. python_graphblas-2026.11.0a0/graphblas/tests/test_ssjit.py +2771 -0
  85. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_vector.py +569 -9
  86. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/unary/__init__.py +3 -1
  87. python_graphblas-2026.11.0a0/graphblas/unary/ss.py +20 -0
  88. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/viz.py +2 -2
  89. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/pyproject.toml +84 -70
  90. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0/python_graphblas.egg-info}/PKG-INFO +21 -223
  91. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/python_graphblas.egg-info/SOURCES.txt +13 -0
  92. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/python_graphblas.egg-info/requires.txt +10 -13
  93. python_graphblas-2025.2.0a0/graphblas/binary/ss.py +0 -6
  94. python_graphblas-2025.2.0a0/graphblas/core/dtypes.py +0 -463
  95. python_graphblas-2025.2.0a0/graphblas/core/ss/__init__.py +0 -5
  96. python_graphblas-2025.2.0a0/graphblas/graphblas.yaml +0 -2
  97. python_graphblas-2025.2.0a0/graphblas/ss/__init__.py +0 -7
  98. python_graphblas-2025.2.0a0/graphblas/tests/conftest.py +0 -166
  99. python_graphblas-2025.2.0a0/graphblas/tests/test_dtype.py +0 -276
  100. python_graphblas-2025.2.0a0/graphblas/tests/test_op.py +0 -1479
  101. python_graphblas-2025.2.0a0/graphblas/tests/test_scalar.py +0 -635
  102. python_graphblas-2025.2.0a0/graphblas/tests/test_ss_utils.py +0 -296
  103. python_graphblas-2025.2.0a0/graphblas/tests/test_ssjit.py +0 -438
  104. python_graphblas-2025.2.0a0/graphblas/unary/ss.py +0 -6
  105. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/LICENSE +0 -0
  106. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/MANIFEST.in +0 -0
  107. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/conftest.py +0 -0
  108. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/agg/ss.py +0 -0
  109. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/binary/numpy.py +0 -0
  110. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/__init__.py +0 -0
  111. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/descriptor.py +0 -0
  112. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/core/slice.py +0 -0
  113. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/dtypes/__init__.py +0 -0
  114. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/dtypes/ss.py +0 -0
  115. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/indexunary/ss.py +0 -0
  116. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/io/__init__.py +0 -0
  117. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/monoid/ss.py +0 -0
  118. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/op/numpy.py +0 -0
  119. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/op/ss.py +0 -0
  120. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/select/ss.py +0 -0
  121. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/semiring/numpy.py +0 -0
  122. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/semiring/ss.py +0 -0
  123. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/__init__.py +0 -0
  124. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle1-vanilla.pkl +0 -0
  125. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle1.pkl +0 -0
  126. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle2-vanilla.pkl +0 -0
  127. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle2.pkl +0 -0
  128. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle3-vanilla.pkl +0 -0
  129. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/pickle3.pkl +0 -0
  130. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_auto_init.py +0 -0
  131. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_descriptor.py +0 -0
  132. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_external_init.py +0 -0
  133. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_mask.py +0 -0
  134. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_prefix_scan.py +0 -0
  135. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/tests/test_resolving.py +0 -0
  136. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/graphblas/unary/numpy.py +0 -0
  137. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/python_graphblas.egg-info/dependency_links.txt +0 -0
  138. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/python_graphblas.egg-info/top_level.txt +0 -0
  139. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/setup.cfg +0 -0
  140. {python_graphblas-2025.2.0a0 → python_graphblas-2026.11.0a0}/setup.py +0 -0
@@ -1,228 +1,27 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: python-graphblas
3
- Version: 2025.2.0a0
3
+ Version: 2026.11.0a0
4
4
  Summary: Python library for GraphBLAS: high-performance sparse linear algebra for scalable graph analytics
5
5
  Author: Jim Kitchen, Python-graphblas contributors
6
6
  Author-email: Erik Welch <erik.n.welch@gmail.com>
7
7
  Maintainer-email: Erik Welch <erik.n.welch@gmail.com>, Jim Kitchen <jim22k@gmail.com>, Sultan Orazbayev <contact@econpoint.com>
8
- License: Apache License
9
- Version 2.0, January 2004
10
- https://www.apache.org/licenses/
11
-
12
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
13
-
14
- 1. Definitions.
15
-
16
- "License" shall mean the terms and conditions for use, reproduction,
17
- and distribution as defined by Sections 1 through 9 of this document.
18
-
19
- "Licensor" shall mean the copyright owner or entity authorized by
20
- the copyright owner that is granting the License.
21
-
22
- "Legal Entity" shall mean the union of the acting entity and all
23
- other entities that control, are controlled by, or are under common
24
- control with that entity. For the purposes of this definition,
25
- "control" means (i) the power, direct or indirect, to cause the
26
- direction or management of such entity, whether by contract or
27
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
28
- outstanding shares, or (iii) beneficial ownership of such entity.
29
-
30
- "You" (or "Your") shall mean an individual or Legal Entity
31
- exercising permissions granted by this License.
32
-
33
- "Source" form shall mean the preferred form for making modifications,
34
- including but not limited to software source code, documentation
35
- source, and configuration files.
36
-
37
- "Object" form shall mean any form resulting from mechanical
38
- transformation or translation of a Source form, including but
39
- not limited to compiled object code, generated documentation,
40
- and conversions to other media types.
41
-
42
- "Work" shall mean the work of authorship, whether in Source or
43
- Object form, made available under the License, as indicated by a
44
- copyright notice that is included in or attached to the work
45
- (an example is provided in the Appendix below).
46
-
47
- "Derivative Works" shall mean any work, whether in Source or Object
48
- form, that is based on (or derived from) the Work and for which the
49
- editorial revisions, annotations, elaborations, or other modifications
50
- represent, as a whole, an original work of authorship. For the purposes
51
- of this License, Derivative Works shall not include works that remain
52
- separable from, or merely link (or bind by name) to the interfaces of,
53
- the Work and Derivative Works thereof.
54
-
55
- "Contribution" shall mean any work of authorship, including
56
- the original version of the Work and any modifications or additions
57
- to that Work or Derivative Works thereof, that is intentionally
58
- submitted to Licensor for inclusion in the Work by the copyright owner
59
- or by an individual or Legal Entity authorized to submit on behalf of
60
- the copyright owner. For the purposes of this definition, "submitted"
61
- means any form of electronic, verbal, or written communication sent
62
- to the Licensor or its representatives, including but not limited to
63
- communication on electronic mailing lists, source code control systems,
64
- and issue tracking systems that are managed by, or on behalf of, the
65
- Licensor for the purpose of discussing and improving the Work, but
66
- excluding communication that is conspicuously marked or otherwise
67
- designated in writing by the copyright owner as "Not a Contribution."
68
-
69
- "Contributor" shall mean Licensor and any individual or Legal Entity
70
- on behalf of whom a Contribution has been received by Licensor and
71
- subsequently incorporated within the Work.
72
-
73
- 2. Grant of Copyright License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- copyright license to reproduce, prepare Derivative Works of,
77
- publicly display, publicly perform, sublicense, and distribute the
78
- Work and such Derivative Works in Source or Object form.
79
-
80
- 3. Grant of Patent License. Subject to the terms and conditions of
81
- this License, each Contributor hereby grants to You a perpetual,
82
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
83
- (except as stated in this section) patent license to make, have made,
84
- use, offer to sell, sell, import, and otherwise transfer the Work,
85
- where such license applies only to those patent claims licensable
86
- by such Contributor that are necessarily infringed by their
87
- Contribution(s) alone or by combination of their Contribution(s)
88
- with the Work to which such Contribution(s) was submitted. If You
89
- institute patent litigation against any entity (including a
90
- cross-claim or counterclaim in a lawsuit) alleging that the Work
91
- or a Contribution incorporated within the Work constitutes direct
92
- or contributory patent infringement, then any patent licenses
93
- granted to You under this License for that Work shall terminate
94
- as of the date such litigation is filed.
95
-
96
- 4. Redistribution. You may reproduce and distribute copies of the
97
- Work or Derivative Works thereof in any medium, with or without
98
- modifications, and in Source or Object form, provided that You
99
- meet the following conditions:
100
-
101
- (a) You must give any other recipients of the Work or
102
- Derivative Works a copy of this License; and
103
-
104
- (b) You must cause any modified files to carry prominent notices
105
- stating that You changed the files; and
106
-
107
- (c) You must retain, in the Source form of any Derivative Works
108
- that You distribute, all copyright, patent, trademark, and
109
- attribution notices from the Source form of the Work,
110
- excluding those notices that do not pertain to any part of
111
- the Derivative Works; and
112
-
113
- (d) If the Work includes a "NOTICE" text file as part of its
114
- distribution, then any Derivative Works that You distribute must
115
- include a readable copy of the attribution notices contained
116
- within such NOTICE file, excluding those notices that do not
117
- pertain to any part of the Derivative Works, in at least one
118
- of the following places: within a NOTICE text file distributed
119
- as part of the Derivative Works; within the Source form or
120
- documentation, if provided along with the Derivative Works; or,
121
- within a display generated by the Derivative Works, if and
122
- wherever such third-party notices normally appear. The contents
123
- of the NOTICE file are for informational purposes only and
124
- do not modify the License. You may add Your own attribution
125
- notices within Derivative Works that You distribute, alongside
126
- or as an addendum to the NOTICE text from the Work, provided
127
- that such additional attribution notices cannot be construed
128
- as modifying the License.
129
-
130
- You may add Your own copyright statement to Your modifications and
131
- may provide additional or different license terms and conditions
132
- for use, reproduction, or distribution of Your modifications, or
133
- for any such Derivative Works as a whole, provided Your use,
134
- reproduction, and distribution of the Work otherwise complies with
135
- the conditions stated in this License.
136
-
137
- 5. Submission of Contributions. Unless You explicitly state otherwise,
138
- any Contribution intentionally submitted for inclusion in the Work
139
- by You to the Licensor shall be under the terms and conditions of
140
- this License, without any additional terms or conditions.
141
- Notwithstanding the above, nothing herein shall supersede or modify
142
- the terms of any separate license agreement you may have executed
143
- with Licensor regarding such Contributions.
144
-
145
- 6. Trademarks. This License does not grant permission to use the trade
146
- names, trademarks, service marks, or product names of the Licensor,
147
- except as required for reasonable and customary use in describing the
148
- origin of the Work and reproducing the content of the NOTICE file.
149
-
150
- 7. Disclaimer of Warranty. Unless required by applicable law or
151
- agreed to in writing, Licensor provides the Work (and each
152
- Contributor provides its Contributions) on an "AS IS" BASIS,
153
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
154
- implied, including, without limitation, any warranties or conditions
155
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
156
- PARTICULAR PURPOSE. You are solely responsible for determining the
157
- appropriateness of using or redistributing the Work and assume any
158
- risks associated with Your exercise of permissions under this License.
159
-
160
- 8. Limitation of Liability. In no event and under no legal theory,
161
- whether in tort (including negligence), contract, or otherwise,
162
- unless required by applicable law (such as deliberate and grossly
163
- negligent acts) or agreed to in writing, shall any Contributor be
164
- liable to You for damages, including any direct, indirect, special,
165
- incidental, or consequential damages of any character arising as a
166
- result of this License or out of the use or inability to use the
167
- Work (including but not limited to damages for loss of goodwill,
168
- work stoppage, computer failure or malfunction, or any and all
169
- other commercial damages or losses), even if such Contributor
170
- has been advised of the possibility of such damages.
171
-
172
- 9. Accepting Warranty or Additional Liability. While redistributing
173
- the Work or Derivative Works thereof, You may choose to offer,
174
- and charge a fee for, acceptance of support, warranty, indemnity,
175
- or other liability obligations and/or rights consistent with this
176
- License. However, in accepting such obligations, You may act only
177
- on Your own behalf and on Your sole responsibility, not on behalf
178
- of any other Contributor, and only if You agree to indemnify,
179
- defend, and hold each Contributor harmless for any liability
180
- incurred by, or claims asserted against, such Contributor by reason
181
- of your accepting any such warranty or additional liability.
182
-
183
- END OF TERMS AND CONDITIONS
184
-
185
- APPENDIX: How to apply the Apache License to your work.
186
-
187
- To apply the Apache License to your work, attach the following
188
- boilerplate notice, with the fields enclosed by brackets "[]"
189
- replaced with your own identifying information. (Don't include
190
- the brackets!) The text should be enclosed in the appropriate
191
- comment syntax for the file format. We also recommend that a
192
- file or class name and description of purpose be included on the
193
- same "printed page" as the copyright notice for easier
194
- identification within third-party archives.
195
-
196
- Copyright 2020-2023 Anaconda, Inc. and contributors
197
-
198
- Licensed under the Apache License, Version 2.0 (the "License");
199
- you may not use this file except in compliance with the License.
200
- You may obtain a copy of the License at
201
-
202
- https://www.apache.org/licenses/LICENSE-2.0
203
-
204
- Unless required by applicable law or agreed to in writing, software
205
- distributed under the License is distributed on an "AS IS" BASIS,
206
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
207
- See the License for the specific language governing permissions and
208
- limitations under the License.
209
-
8
+ License-Expression: Apache-2.0
210
9
  Project-URL: homepage, https://github.com/python-graphblas/python-graphblas
211
10
  Project-URL: documentation, https://python-graphblas.readthedocs.io
212
11
  Project-URL: repository, https://github.com/python-graphblas/python-graphblas
213
12
  Project-URL: changelog, https://github.com/python-graphblas/python-graphblas/releases
214
13
  Keywords: graphblas,graph,sparse,matrix,lagraph,suitesparse,Networks,Graph Theory,Mathematics,network,discrete mathematics,math
215
14
  Classifier: Development Status :: 5 - Production/Stable
216
- Classifier: License :: OSI Approved :: Apache Software License
217
15
  Classifier: Operating System :: MacOS :: MacOS X
218
16
  Classifier: Operating System :: POSIX :: Linux
219
17
  Classifier: Operating System :: Microsoft :: Windows
220
18
  Classifier: Programming Language :: Python
221
19
  Classifier: Programming Language :: Python :: 3
222
- Classifier: Programming Language :: Python :: 3.10
223
20
  Classifier: Programming Language :: Python :: 3.11
224
21
  Classifier: Programming Language :: Python :: 3.12
225
22
  Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
226
25
  Classifier: Programming Language :: Python :: 3 :: Only
227
26
  Classifier: Intended Audience :: Developers
228
27
  Classifier: Intended Audience :: Other Audience
@@ -231,20 +30,20 @@ Classifier: Topic :: Scientific/Engineering
231
30
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
232
31
  Classifier: Topic :: Scientific/Engineering :: Mathematics
233
32
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
234
- Requires-Python: >=3.10
33
+ Requires-Python: >=3.11
235
34
  Description-Content-Type: text/markdown
236
35
  License-File: LICENSE
237
- Requires-Dist: numpy>=1.23
36
+ Requires-Dist: numpy>=1.24
238
37
  Requires-Dist: donfig>=0.6
239
38
  Requires-Dist: pyyaml>=5.4
240
- Requires-Dist: suitesparse-graphblas<10,>=7.4.0.0
241
- Requires-Dist: numba>=0.55; python_version < "3.14"
39
+ Requires-Dist: suitesparse-graphblas>=7.4.0.0
40
+ Requires-Dist: numba>=0.57; python_version < "3.16"
242
41
  Provides-Extra: suitesparse
243
- Requires-Dist: suitesparse-graphblas<10,>=7.4.0.0; extra == "suitesparse"
42
+ Requires-Dist: suitesparse-graphblas>=7.4.0.0; extra == "suitesparse"
244
43
  Provides-Extra: networkx
245
44
  Requires-Dist: networkx>=2.8; extra == "networkx"
246
45
  Provides-Extra: numba
247
- Requires-Dist: numba>=0.55; extra == "numba"
46
+ Requires-Dist: numba>=0.57; extra == "numba"
248
47
  Provides-Extra: pandas
249
48
  Requires-Dist: pandas>=1.5; extra == "pandas"
250
49
  Provides-Extra: scipy
@@ -255,10 +54,9 @@ Provides-Extra: repr
255
54
  Requires-Dist: python-graphblas[pandas]; extra == "repr"
256
55
  Provides-Extra: io
257
56
  Requires-Dist: python-graphblas[networkx,scipy]; extra == "io"
258
- Requires-Dist: python-graphblas[numba]; python_version < "3.14" and extra == "io"
57
+ Requires-Dist: python-graphblas[numba]; python_version < "3.16" and extra == "io"
259
58
  Requires-Dist: awkward>=2.0; extra == "io"
260
- Requires-Dist: sparse>=0.14; python_version < "3.13" and extra == "io"
261
- Requires-Dist: fast-matrix-market>=1.4.5; python_version < "3.13" and extra == "io"
59
+ Requires-Dist: sparse>=0.14; python_version < "3.16" and extra == "io"
262
60
  Provides-Extra: viz
263
61
  Requires-Dist: python-graphblas[networkx,scipy]; extra == "viz"
264
62
  Requires-Dist: matplotlib>=3.6; extra == "viz"
@@ -273,10 +71,11 @@ Requires-Dist: pytest>=6.2; extra == "test"
273
71
  Requires-Dist: tomli>=1; extra == "test"
274
72
  Provides-Extra: default
275
73
  Requires-Dist: python-graphblas[pandas,scipy,suitesparse]; extra == "default"
276
- Requires-Dist: python-graphblas[numba]; python_version < "3.14" and extra == "default"
74
+ Requires-Dist: python-graphblas[numba]; python_version < "3.16" and extra == "default"
277
75
  Provides-Extra: all
278
76
  Requires-Dist: python-graphblas[default,io,test,viz]; extra == "all"
279
- Requires-Dist: python-graphblas[datashade]; python_version < "3.14" and extra == "all"
77
+ Requires-Dist: python-graphblas[datashade]; python_version < "3.16" and extra == "all"
78
+ Dynamic: license-file
280
79
 
281
80
  ![Python-graphblas](https://raw.githubusercontent.com/python-graphblas/python-graphblas/main/docs/_static/img/logo-horizontal-medium-big.svg)
282
81
 
@@ -305,7 +104,7 @@ For algorithms, see
305
104
  - **SuiteSparse:GraphBLAS User Guide:** [https://github.com/DrTimothyAldenDavis/GraphBLAS/raw/stable/Doc/GraphBLAS_UserGuide.pdf](https://github.com/DrTimothyAldenDavis/GraphBLAS/raw/stable/Doc/GraphBLAS_UserGuide.pdf)
306
105
  - **Source:** [https://github.com/python-graphblas/python-graphblas](https://github.com/python-graphblas/python-graphblas)
307
106
  - **Bug reports:** [https://github.com/python-graphblas/python-graphblas/issues](https://github.com/python-graphblas/python-graphblas/issues)
308
- - **Github discussions:** [https://github.com/python-graphblas/python-graphblas/discussions](https://github.com/python-graphblas/python-graphblas/discussions)
107
+ - **GitHub discussions:** [https://github.com/python-graphblas/python-graphblas/discussions](https://github.com/python-graphblas/python-graphblas/discussions)
309
108
  - **Weekly community call:** [python-graphblas#247](https://github.com/python-graphblas/python-graphblas/issues/247) or [https://scientific-python.org/calendars/](https://scientific-python.org/calendars/)
310
109
  - **Chat via Discord:** [https://discord.com/invite/vur45CbwMz](https://discord.com/invite/vur45CbwMz) in the [#graphblas channel](https://discord.com/channels/786703927705862175/1024732940233605190)
311
110
 
@@ -338,8 +137,7 @@ The following are not required by python-graphblas, but may be needed for certai
338
137
  - `pandas` – required for nicer `__repr__`;
339
138
  - `matplotlib` – required for basic plotting of graphs;
340
139
  - `scipy` – used in `io` module to read/write `scipy.sparse` format;
341
- - `networkx` – used in `io` module to interface with `networkx` graphs;
342
- - `fast-matrix-market` - for faster read/write of Matrix Market files with `gb.io.mmread` and `gb.io.mmwrite`.
140
+ - `networkx` – used in `io` module to interface with `networkx` graphs.
343
141
 
344
142
  ## Description
345
143
 
@@ -459,7 +257,7 @@ s(accum) << v.reduce(op)
459
257
  ## Creating new Vectors / Matrices
460
258
 
461
259
  ```python
462
- A = Matrix.new(dtype, num_rows, num_cols) # new_type
260
+ A = Matrix(dtype, num_rows, num_cols) # new_type
463
261
  B = A.dup() # dup
464
262
  A = Matrix.from_coo([row_indices], [col_indices], [values]) # build
465
263
  ```
@@ -506,7 +304,7 @@ Python-graphblas requires `numba` which enables compiling user-defined Python fu
506
304
  Example customized UnaryOp:
507
305
 
508
306
  ```python
509
- from graphblas import unary
307
+ from graphblas import unary, Vector
510
308
 
511
309
  def force_odd_func(x):
512
310
  if x % 2 == 0:
@@ -548,7 +346,7 @@ import graphblas as gb
548
346
 
549
347
  # scipy.sparse matrices
550
348
  A = gb.io.from_scipy_sparse(m)
551
- m = gb.io.to_scipy_sparse(m, format="csr")
349
+ m = gb.io.to_scipy_sparse(A, format="csr")
552
350
 
553
351
  # networkx graphs
554
352
  A = gb.io.from_networkx(g)
@@ -25,7 +25,7 @@ For algorithms, see
25
25
  - **SuiteSparse:GraphBLAS User Guide:** [https://github.com/DrTimothyAldenDavis/GraphBLAS/raw/stable/Doc/GraphBLAS_UserGuide.pdf](https://github.com/DrTimothyAldenDavis/GraphBLAS/raw/stable/Doc/GraphBLAS_UserGuide.pdf)
26
26
  - **Source:** [https://github.com/python-graphblas/python-graphblas](https://github.com/python-graphblas/python-graphblas)
27
27
  - **Bug reports:** [https://github.com/python-graphblas/python-graphblas/issues](https://github.com/python-graphblas/python-graphblas/issues)
28
- - **Github discussions:** [https://github.com/python-graphblas/python-graphblas/discussions](https://github.com/python-graphblas/python-graphblas/discussions)
28
+ - **GitHub discussions:** [https://github.com/python-graphblas/python-graphblas/discussions](https://github.com/python-graphblas/python-graphblas/discussions)
29
29
  - **Weekly community call:** [python-graphblas#247](https://github.com/python-graphblas/python-graphblas/issues/247) or [https://scientific-python.org/calendars/](https://scientific-python.org/calendars/)
30
30
  - **Chat via Discord:** [https://discord.com/invite/vur45CbwMz](https://discord.com/invite/vur45CbwMz) in the [#graphblas channel](https://discord.com/channels/786703927705862175/1024732940233605190)
31
31
 
@@ -58,8 +58,7 @@ The following are not required by python-graphblas, but may be needed for certai
58
58
  - `pandas` – required for nicer `__repr__`;
59
59
  - `matplotlib` – required for basic plotting of graphs;
60
60
  - `scipy` – used in `io` module to read/write `scipy.sparse` format;
61
- - `networkx` – used in `io` module to interface with `networkx` graphs;
62
- - `fast-matrix-market` - for faster read/write of Matrix Market files with `gb.io.mmread` and `gb.io.mmwrite`.
61
+ - `networkx` – used in `io` module to interface with `networkx` graphs.
63
62
 
64
63
  ## Description
65
64
 
@@ -179,7 +178,7 @@ s(accum) << v.reduce(op)
179
178
  ## Creating new Vectors / Matrices
180
179
 
181
180
  ```python
182
- A = Matrix.new(dtype, num_rows, num_cols) # new_type
181
+ A = Matrix(dtype, num_rows, num_cols) # new_type
183
182
  B = A.dup() # dup
184
183
  A = Matrix.from_coo([row_indices], [col_indices], [values]) # build
185
184
  ```
@@ -226,7 +225,7 @@ Python-graphblas requires `numba` which enables compiling user-defined Python fu
226
225
  Example customized UnaryOp:
227
226
 
228
227
  ```python
229
- from graphblas import unary
228
+ from graphblas import unary, Vector
230
229
 
231
230
  def force_odd_func(x):
232
231
  if x % 2 == 0:
@@ -268,7 +267,7 @@ import graphblas as gb
268
267
 
269
268
  # scipy.sparse matrices
270
269
  A = gb.io.from_scipy_sparse(m)
271
- m = gb.io.to_scipy_sparse(m, format="csr")
270
+ m = gb.io.to_scipy_sparse(A, format="csr")
272
271
 
273
272
  # networkx graphs
274
273
  A = gb.io.from_networkx(g)
@@ -25,7 +25,45 @@ def get_config():
25
25
  import donfig
26
26
  import yaml
27
27
 
28
- config = donfig.Config("graphblas")
28
+ class Config(donfig.Config):
29
+ """donfig Config that rejects silent attribute writes.
30
+
31
+ Options are set with ``config.set(name=value)`` (optionally as a
32
+ ``with config.set(name=value):`` block) and read with ``config[name]``.
33
+ Plain attribute assignment (``config.name = value``) would otherwise
34
+ create a dead instance attribute and leave the real option unchanged,
35
+ so we raise instead.
36
+ """
37
+
38
+ def __init__(self, *args, **kwargs):
39
+ # Writes are unrestricted until donfig's own __init__ finishes, and
40
+ # the attributes it set there become the allowlist. Deriving that
41
+ # list beats hardcoding donfig's internals: a donfig release that
42
+ # adds or renames a field can't then break attribute access here.
43
+ object.__setattr__(self, "_initializing", True)
44
+ super().__init__(*args, **kwargs)
45
+ object.__setattr__(self, "_donfig_attrs", frozenset(self.__dict__) - {"_initializing"})
46
+ object.__setattr__(self, "_initializing", False)
47
+
48
+ def __setattr__(self, key, value):
49
+ # An instance built without running __init__ has no allowlist yet,
50
+ # so stay permissive rather than raising a confusing AttributeError
51
+ # from the guard.
52
+ if self.__dict__.get("_initializing", True) or key in self._donfig_attrs:
53
+ object.__setattr__(self, key, value)
54
+ return
55
+ if key in self.config:
56
+ raise AttributeError(
57
+ f"Cannot set config option {key!r} by attribute assignment. "
58
+ f"Use `graphblas.config.set({key}=...)` to change it (optionally "
59
+ f"in a `with` block for a scoped change) and "
60
+ f"`graphblas.config[{key!r}]` to read it."
61
+ )
62
+ raise AttributeError(
63
+ f"Unknown config option {key!r}; known options are {sorted(self.config)}."
64
+ )
65
+
66
+ config = Config("graphblas")
29
67
  path = Path(__file__).parent / "graphblas.yaml"
30
68
  with path.open() as f:
31
69
  defaults = yaml.safe_load(f)
@@ -36,6 +74,10 @@ def get_config():
36
74
  config = get_config()
37
75
  del get_config
38
76
 
77
+ # None until a backend is initialized. Touching a special attribute such as
78
+ # gb.Matrix auto-initializes, as does an explicit init(), and sets this to
79
+ # "suitesparse" or "suitesparse-vanilla". Reading gb.backend is not itself a
80
+ # special-attribute access, so it never triggers initialization.
39
81
  backend = None
40
82
  _init_params = None
41
83
  _SPECIAL_ATTRS = {
@@ -49,6 +91,7 @@ _SPECIAL_ATTRS = {
49
91
  "core",
50
92
  "dtypes",
51
93
  "exceptions",
94
+ "indexbinary",
52
95
  "indexunary",
53
96
  "io",
54
97
  "monoid",
@@ -136,6 +179,9 @@ def _init(backend_arg, blocking, automatic=False):
136
179
  # Already initialized with these parameters; nothing more to do
137
180
  return
138
181
 
182
+ if backend_arg == "suitesparse":
183
+ # Checked before anything is initialized, so a bad value changes nothing
184
+ jit_c_control = _jit_c_control_config()
139
185
  backend = backend_arg
140
186
  if backend in {"suitesparse", "suitesparse-vanilla"}:
141
187
  try:
@@ -196,6 +242,35 @@ def _init(backend_arg, blocking, automatic=False):
196
242
  core.ffi = ffi
197
243
  core.lib = lib
198
244
  core.NULL = ffi.NULL
245
+ if backend == "suitesparse":
246
+ from .core.ss.jit_config import _set_jit_c_control_at_init
247
+
248
+ _set_jit_c_control_at_init(jit_c_control)
249
+
250
+
251
+ _JIT_C_CONTROLS = ("on", "load", "run", "pause", "off")
252
+
253
+
254
+ def _jit_c_control_config():
255
+ """``config["jit_c_control"]``, the SuiteSparse JIT control set at init (see graphblas.yaml).
256
+
257
+ None when it is not set, which is the default: ``'run'``, raised by UDT work.
258
+ """
259
+ val = config.get("jit_c_control")
260
+ if val is None:
261
+ return None
262
+ # YAML 1.1 reads an unquoted on/off as a bool, so a config file saying
263
+ # ``jit_c_control: off`` arrives here as False.
264
+ if val is True or val is False:
265
+ return "on" if val else "off"
266
+ if isinstance(val, str) and val.lower() in _JIT_C_CONTROLS:
267
+ return val.lower()
268
+ raise ValueError(
269
+ "Bad value for graphblas.config['jit_c_control'] (or the GRAPHBLAS_JIT_C_CONTROL "
270
+ f"environment variable): {val!r}. Must be one of: "
271
+ + ", ".join(repr(x) for x in _JIT_C_CONTROLS)
272
+ + ", or unset"
273
+ )
199
274
 
200
275
 
201
276
  # Ideally this is in operator.py, but lives here to avoid circular references
@@ -109,7 +109,9 @@ def __getattr__(key):
109
109
  ss = import_module(".ss", __name__)
110
110
  globals()["ss"] = ss
111
111
  return ss
112
- raise AttributeError(f"module {__name__!r} has no attribute {key!r}")
112
+ from ..core.utils import _module_attr_error
113
+
114
+ raise _module_attr_error(__name__, key, __dir__())
113
115
 
114
116
 
115
117
  from ..core import operator # noqa: E402 isort:skip
@@ -66,7 +66,9 @@ def __getattr__(key):
66
66
  f"module {__name__!r} unable to compile UDF for {key!r}; "
67
67
  "install numba for UDF support"
68
68
  )
69
- raise AttributeError(f"module {__name__!r} has no attribute {key!r}")
69
+ from ..core.utils import _module_attr_error
70
+
71
+ raise _module_attr_error(__name__, key, __dir__())
70
72
 
71
73
 
72
74
  from ..core import operator # noqa: E402 isort:skip
@@ -0,0 +1,20 @@
1
+ from ..core import operator
2
+
3
+ _delayed = {}
4
+
5
+ del operator
6
+
7
+
8
+ # core.ss.binary imports the operators, whose setup imports this module, so
9
+ # register_new is imported on first use: that lets core.ss.binary be imported first.
10
+ def __getattr__(name):
11
+ if name == "register_new":
12
+ from ..core.ss.binary import register_new
13
+
14
+ globals()[name] = register_new
15
+ return register_new
16
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
17
+
18
+
19
+ def __dir__():
20
+ return sorted({*globals(), "register_new"})
@@ -10,11 +10,46 @@ $ python -m graphblas.core.automethods
10
10
 
11
11
  from .. import config
12
12
 
13
+ # Scalar read-only attributes whose value is a plain read of the underlying C
14
+ # scalar. For an index-extract expression (v[i], A[i, j]) these resolve with a
15
+ # single extractElement straight into a cscalar via ScalarIndexExpr._extract_fast,
16
+ # skipping the extra GrB_Scalar round-trip that `.new()` + Scalar.value performs.
17
+ # Only ScalarIndexExpr defines the hook, and no Vector/Matrix expression routes
18
+ # these attrs through _get_value, so their resolution short-circuits on the
19
+ # membership test.
20
+ _fast_scalar_attrs = frozenset(
21
+ {
22
+ "value",
23
+ "__float__",
24
+ "__int__",
25
+ "__complex__",
26
+ "__index__",
27
+ "__bool__",
28
+ "__array__",
29
+ "is_empty",
30
+ "_is_empty",
31
+ }
32
+ )
33
+
13
34
 
14
35
  def _get_value(self, attr=None, default=None):
15
36
  if config.get("autocompute"):
16
37
  if self._value is None:
17
- self._value = self.new()
38
+ if (
39
+ attr in _fast_scalar_attrs
40
+ and (extract_fast := getattr(self, "_extract_fast", None)) is not None
41
+ ):
42
+ self._value = extract_fast()
43
+ else:
44
+ self._value = self.new()
45
+ elif (
46
+ attr not in _fast_scalar_attrs
47
+ and getattr(self, "_extract_fast", None) is not None
48
+ and self._value._is_cscalar != self._is_cscalar
49
+ ):
50
+ # A value read cached a C scalar (_extract_fast); give the other attributes
51
+ # the kind of Scalar this expression reports, holding the same value.
52
+ self._value = self._value.dup(is_cscalar=self._is_cscalar, name=self._value.name)
18
53
  if attr is None:
19
54
  return self._value
20
55
  return getattr(self._value, attr)