maxframe 1.0.0rc2__cp39-cp39-win32.whl → 1.0.0rc4__cp39-cp39-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of maxframe might be problematic. Click here for more details.

Files changed (134) hide show
  1. maxframe/_utils.cp39-win32.pyd +0 -0
  2. maxframe/codegen.py +4 -2
  3. maxframe/config/config.py +28 -9
  4. maxframe/config/validators.py +42 -12
  5. maxframe/conftest.py +56 -14
  6. maxframe/core/__init__.py +2 -13
  7. maxframe/core/entity/__init__.py +0 -4
  8. maxframe/core/entity/executable.py +1 -1
  9. maxframe/core/entity/objects.py +45 -2
  10. maxframe/core/entity/output_types.py +0 -3
  11. maxframe/core/entity/tests/test_objects.py +43 -0
  12. maxframe/core/entity/tileables.py +5 -78
  13. maxframe/core/graph/__init__.py +2 -2
  14. maxframe/core/graph/builder/__init__.py +0 -1
  15. maxframe/core/graph/builder/base.py +5 -4
  16. maxframe/core/graph/builder/tileable.py +4 -4
  17. maxframe/core/graph/builder/utils.py +4 -8
  18. maxframe/core/graph/core.cp39-win32.pyd +0 -0
  19. maxframe/core/graph/entity.py +9 -33
  20. maxframe/core/operator/__init__.py +2 -9
  21. maxframe/core/operator/base.py +3 -5
  22. maxframe/core/operator/objects.py +0 -9
  23. maxframe/core/operator/utils.py +55 -0
  24. maxframe/dataframe/arithmetic/docstring.py +26 -2
  25. maxframe/dataframe/arithmetic/equal.py +4 -2
  26. maxframe/dataframe/arithmetic/greater.py +4 -2
  27. maxframe/dataframe/arithmetic/greater_equal.py +4 -2
  28. maxframe/dataframe/arithmetic/less.py +2 -2
  29. maxframe/dataframe/arithmetic/less_equal.py +4 -2
  30. maxframe/dataframe/arithmetic/not_equal.py +4 -2
  31. maxframe/dataframe/core.py +2 -0
  32. maxframe/dataframe/datasource/read_odps_query.py +67 -8
  33. maxframe/dataframe/datasource/read_odps_table.py +4 -2
  34. maxframe/dataframe/datasource/tests/test_datasource.py +35 -6
  35. maxframe/dataframe/datastore/to_odps.py +8 -1
  36. maxframe/dataframe/extensions/__init__.py +3 -0
  37. maxframe/dataframe/extensions/flatmap.py +326 -0
  38. maxframe/dataframe/extensions/tests/test_extensions.py +62 -1
  39. maxframe/dataframe/indexing/add_prefix_suffix.py +1 -1
  40. maxframe/dataframe/indexing/rename.py +11 -0
  41. maxframe/dataframe/initializer.py +11 -1
  42. maxframe/dataframe/misc/drop_duplicates.py +18 -1
  43. maxframe/dataframe/operators.py +1 -17
  44. maxframe/dataframe/reduction/core.py +2 -2
  45. maxframe/dataframe/tests/test_initializer.py +33 -2
  46. maxframe/io/objects/__init__.py +24 -0
  47. maxframe/io/objects/core.py +140 -0
  48. maxframe/io/objects/tensor.py +76 -0
  49. maxframe/io/objects/tests/__init__.py +13 -0
  50. maxframe/io/objects/tests/test_object_io.py +97 -0
  51. maxframe/{odpsio → io/odpsio}/__init__.py +2 -0
  52. maxframe/{odpsio → io/odpsio}/arrow.py +4 -4
  53. maxframe/{odpsio → io/odpsio}/schema.py +10 -8
  54. maxframe/{odpsio → io/odpsio}/tableio.py +50 -38
  55. maxframe/io/odpsio/tests/__init__.py +13 -0
  56. maxframe/{odpsio → io/odpsio}/tests/test_schema.py +3 -7
  57. maxframe/{odpsio → io/odpsio}/tests/test_tableio.py +3 -3
  58. maxframe/{odpsio → io/odpsio}/tests/test_volumeio.py +4 -6
  59. maxframe/io/odpsio/volumeio.py +63 -0
  60. maxframe/learn/contrib/__init__.py +2 -1
  61. maxframe/learn/contrib/graph/__init__.py +15 -0
  62. maxframe/learn/contrib/graph/connected_components.py +215 -0
  63. maxframe/learn/contrib/graph/tests/__init__.py +13 -0
  64. maxframe/learn/contrib/graph/tests/test_connected_components.py +53 -0
  65. maxframe/learn/contrib/xgboost/classifier.py +26 -2
  66. maxframe/learn/contrib/xgboost/core.py +87 -2
  67. maxframe/learn/contrib/xgboost/dmatrix.py +1 -4
  68. maxframe/learn/contrib/xgboost/predict.py +27 -44
  69. maxframe/learn/contrib/xgboost/regressor.py +3 -10
  70. maxframe/learn/contrib/xgboost/train.py +27 -16
  71. maxframe/{core/operator/fuse.py → learn/core.py} +7 -10
  72. maxframe/lib/mmh3.cp39-win32.pyd +0 -0
  73. maxframe/opcodes.py +3 -0
  74. maxframe/protocol.py +7 -16
  75. maxframe/remote/core.py +4 -8
  76. maxframe/serialization/__init__.py +1 -0
  77. maxframe/serialization/core.cp39-win32.pyd +0 -0
  78. maxframe/session.py +9 -2
  79. maxframe/tensor/__init__.py +10 -2
  80. maxframe/tensor/arithmetic/isclose.py +1 -0
  81. maxframe/tensor/arithmetic/tests/test_arithmetic.py +21 -17
  82. maxframe/tensor/core.py +5 -136
  83. maxframe/tensor/datasource/array.py +3 -0
  84. maxframe/tensor/datasource/full.py +1 -1
  85. maxframe/tensor/datasource/tests/test_datasource.py +1 -1
  86. maxframe/tensor/indexing/flatnonzero.py +1 -1
  87. maxframe/tensor/indexing/getitem.py +2 -0
  88. maxframe/tensor/merge/__init__.py +2 -0
  89. maxframe/tensor/merge/concatenate.py +101 -0
  90. maxframe/tensor/merge/tests/test_merge.py +30 -1
  91. maxframe/tensor/merge/vstack.py +74 -0
  92. maxframe/tensor/{base → misc}/__init__.py +2 -0
  93. maxframe/tensor/{base → misc}/atleast_1d.py +0 -2
  94. maxframe/tensor/misc/atleast_2d.py +70 -0
  95. maxframe/tensor/misc/atleast_3d.py +85 -0
  96. maxframe/tensor/misc/tests/__init__.py +13 -0
  97. maxframe/tensor/{base → misc}/transpose.py +22 -18
  98. maxframe/tensor/operators.py +1 -7
  99. maxframe/tensor/random/core.py +1 -1
  100. maxframe/tensor/reduction/count_nonzero.py +1 -0
  101. maxframe/tensor/reduction/mean.py +1 -0
  102. maxframe/tensor/reduction/nanmean.py +1 -0
  103. maxframe/tensor/reduction/nanvar.py +2 -0
  104. maxframe/tensor/reduction/tests/test_reduction.py +12 -1
  105. maxframe/tensor/reduction/var.py +2 -0
  106. maxframe/tensor/utils.py +2 -22
  107. maxframe/typing_.py +4 -1
  108. maxframe/udf.py +8 -9
  109. maxframe/utils.py +49 -73
  110. maxframe-1.0.0rc4.dist-info/METADATA +104 -0
  111. {maxframe-1.0.0rc2.dist-info → maxframe-1.0.0rc4.dist-info}/RECORD +129 -114
  112. {maxframe-1.0.0rc2.dist-info → maxframe-1.0.0rc4.dist-info}/WHEEL +1 -1
  113. maxframe_client/fetcher.py +33 -50
  114. maxframe_client/session/consts.py +3 -0
  115. maxframe_client/session/graph.py +8 -2
  116. maxframe_client/session/odps.py +134 -27
  117. maxframe_client/session/task.py +58 -20
  118. maxframe_client/tests/test_fetcher.py +1 -1
  119. maxframe_client/tests/test_session.py +27 -3
  120. maxframe/core/entity/chunks.py +0 -68
  121. maxframe/core/entity/fuse.py +0 -73
  122. maxframe/core/graph/builder/chunk.py +0 -430
  123. maxframe/odpsio/volumeio.py +0 -95
  124. maxframe-1.0.0rc2.dist-info/METADATA +0 -177
  125. /maxframe/{odpsio → core/entity}/tests/__init__.py +0 -0
  126. /maxframe/{tensor/base/tests → io}/__init__.py +0 -0
  127. /maxframe/{odpsio → io/odpsio}/tests/test_arrow.py +0 -0
  128. /maxframe/tensor/{base → misc}/astype.py +0 -0
  129. /maxframe/tensor/{base → misc}/broadcast_to.py +0 -0
  130. /maxframe/tensor/{base → misc}/ravel.py +0 -0
  131. /maxframe/tensor/{base/tests/test_base.py → misc/tests/test_misc.py} +0 -0
  132. /maxframe/tensor/{base → misc}/unique.py +0 -0
  133. /maxframe/tensor/{base → misc}/where.py +0 -0
  134. {maxframe-1.0.0rc2.dist-info → maxframe-1.0.0rc4.dist-info}/top_level.txt +0 -0
@@ -12,18 +12,21 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import pickle
16
15
 
17
16
  import numpy as np
18
- import pandas as pd
19
17
 
20
18
  from .... import opcodes
21
19
  from ....core.entity.output_types import OutputType
22
20
  from ....core.operator.base import Operator
23
21
  from ....core.operator.core import TileableOperatorMixin
24
- from ....dataframe.utils import parse_index
25
- from ....serialization.serializables import BoolField, BytesField, KeyField, TupleField
26
- from ....tensor.core import TENSOR_TYPE, TensorOrder
22
+ from ....serialization.serializables import (
23
+ BoolField,
24
+ KeyField,
25
+ ReferenceField,
26
+ TupleField,
27
+ )
28
+ from ....tensor.core import TensorOrder
29
+ from .core import BoosterData
27
30
  from .dmatrix import check_data
28
31
 
29
32
 
@@ -32,9 +35,7 @@ class XGBPredict(Operator, TileableOperatorMixin):
32
35
  output_dtype = np.dtype(np.float32)
33
36
 
34
37
  data = KeyField("data", default=None)
35
- model = BytesField(
36
- "model", on_serialize=pickle.dumps, on_deserialize=pickle.loads, default=None
37
- )
38
+ model = ReferenceField("model", reference_type=BoosterData, default=None)
38
39
  pred_leaf = BoolField("pred_leaf", default=False)
39
40
  pred_contribs = BoolField("pred_contribs", default=False)
40
41
  approx_contribs = BoolField("approx_contribs", default=False)
@@ -62,35 +63,12 @@ class XGBPredict(Operator, TileableOperatorMixin):
62
63
  else:
63
64
  shape = (self.data.shape[0],)
64
65
  inputs = [self.data, self.model]
65
- if self.output_types[0] == OutputType.tensor:
66
- # tensor
67
- return self.new_tileable(
68
- inputs,
69
- shape=shape,
70
- dtype=self.output_dtype,
71
- order=TensorOrder.C_ORDER,
72
- )
73
- elif self.output_types[0] == OutputType.dataframe:
74
- # dataframe
75
- dtypes = pd.DataFrame(
76
- np.random.rand(0, num_class), dtype=self.output_dtype
77
- ).dtypes
78
- return self.new_tileable(
79
- inputs,
80
- shape=shape,
81
- dtypes=dtypes,
82
- columns_value=parse_index(dtypes.index),
83
- index_value=self.data.index_value,
84
- )
85
- else:
86
- # series
87
- return self.new_tileable(
88
- inputs,
89
- shape=shape,
90
- index_value=self.data.index_value,
91
- name="predictions",
92
- dtype=self.output_dtype,
93
- )
66
+ return self.new_tileable(
67
+ inputs,
68
+ shape=shape,
69
+ dtype=self.output_dtype,
70
+ order=TensorOrder.C_ORDER,
71
+ )
94
72
 
95
73
 
96
74
  def predict(
@@ -107,16 +85,21 @@ def predict(
107
85
  strict_shape=False,
108
86
  flag=False,
109
87
  ):
88
+ """
89
+ Using MaxFrame XGBoost model to predict data.
90
+
91
+ Parameters
92
+ ----------
93
+ Parameters are the same as `xgboost.train`. The predict() is lazy-execution mode.
94
+
95
+ Returns
96
+ -------
97
+ results: Booster
98
+ """
110
99
  data = check_data(data)
111
100
  # TODO: check model datatype
112
101
 
113
- num_class = getattr(model.op, "num_class", None)
114
- if isinstance(data, TENSOR_TYPE):
115
- output_types = [OutputType.tensor]
116
- elif num_class is not None:
117
- output_types = [OutputType.dataframe]
118
- else:
119
- output_types = [OutputType.series]
102
+ output_types = [OutputType.tensor]
120
103
 
121
104
  iteration_range = iteration_range or (0, 0)
122
105
 
@@ -41,11 +41,6 @@ else:
41
41
  ):
42
42
  session = kw.pop("session", None)
43
43
  run_kwargs = kw.pop("run_kwargs", dict())
44
- if kw:
45
- raise TypeError(
46
- f"fit got an unexpected keyword argument '{next(iter(kw))}'"
47
- )
48
-
49
44
  dtrain, evals = wrap_evaluation_matrices(
50
45
  None,
51
46
  X,
@@ -57,6 +52,8 @@ else:
57
52
  base_margin_eval_set,
58
53
  )
59
54
  params = self.get_xgb_params()
55
+ if not params.get("objective"):
56
+ params["objective"] = "reg:squarederror"
60
57
  self.evals_result_ = dict()
61
58
  result = train(
62
59
  params,
@@ -71,8 +68,4 @@ else:
71
68
  return self
72
69
 
73
70
  def predict(self, data, **kw):
74
- session = kw.pop("session", None)
75
- run_kwargs = kw.pop("run_kwargs", None)
76
- return predict(
77
- self.get_booster(), data, session=session, run_kwargs=run_kwargs, **kw
78
- )
71
+ return predict(self.get_booster(), data, **kw)
@@ -29,6 +29,7 @@ from ....serialization.serializables import (
29
29
  KeyField,
30
30
  ListField,
31
31
  )
32
+ from .core import Booster
32
33
  from .dmatrix import ToDMatrix, to_dmatrix
33
34
 
34
35
  logger = logging.getLogger(__name__)
@@ -59,49 +60,59 @@ class XGBTrain(Operator, TileableOperatorMixin):
59
60
  num_boost_round = Int64Field("num_boost_round", default=10)
60
61
  num_class = Int64Field("num_class", default=None)
61
62
 
62
- # Store evals_result in local to store the remote evals_result
63
- evals_result: dict = None
64
-
65
63
  def __init__(self, gpu=None, **kw):
66
64
  super().__init__(gpu=gpu, **kw)
67
65
  if self.output_types is None:
68
66
  self.output_types = [OutputType.object]
67
+ if self.has_evals_result:
68
+ self.output_types.append(OutputType.object)
69
69
 
70
70
  def _set_inputs(self, inputs):
71
71
  super()._set_inputs(inputs)
72
72
  self.dtrain = self._inputs[0]
73
73
  rest = self._inputs[1:]
74
- if self.evals is not None:
74
+ if self.has_evals_result:
75
75
  evals_dict = OrderedDict(self.evals)
76
76
  new_evals_dict = OrderedDict()
77
77
  for new_key, val in zip(rest, evals_dict.values()):
78
78
  new_evals_dict[new_key] = val
79
79
  self.evals = list(new_evals_dict.items())
80
80
 
81
- def __call__(self):
81
+ def __call__(self, evals_result):
82
82
  inputs = [self.dtrain]
83
- if self.evals is not None:
83
+ if self.has_evals_result:
84
84
  inputs.extend(e[0] for e in self.evals)
85
- return self.new_tileable(inputs)
85
+ return self.new_tileables(
86
+ inputs, object_class=Booster, evals_result=evals_result
87
+ )[0]
88
+
89
+ @property
90
+ def output_limit(self):
91
+ return 2 if self.has_evals_result else 1
92
+
93
+ @property
94
+ def has_evals_result(self) -> bool:
95
+ return self.evals
86
96
 
87
97
 
88
98
  def train(params, dtrain, evals=None, evals_result=None, num_class=None, **kwargs):
89
99
  """
90
- Train XGBoost model in Mars manner.
100
+ Train XGBoost model in MaxFrame manner.
91
101
 
92
102
  Parameters
93
103
  ----------
94
- Parameters are the same as `xgboost.train`.
104
+ Parameters are the same as `xgboost.train`. Note that train is an eager-execution
105
+ API if evals is passed, thus the call will be blocked until training finished.
95
106
 
96
107
  Returns
97
108
  -------
98
109
  results: Booster
99
110
  """
100
111
 
101
- evals_result = evals_result or dict()
102
- evals = None or ()
103
-
112
+ evals_result = evals_result if evals_result is not None else dict()
104
113
  processed_evals = []
114
+ session = kwargs.pop("session", None)
115
+ run_kwargs = kwargs.pop("run_kwargs", dict())
105
116
  if evals:
106
117
  for eval_dmatrix, name in evals:
107
118
  if not isinstance(name, str):
@@ -110,12 +121,12 @@ def train(params, dtrain, evals=None, evals_result=None, num_class=None, **kwarg
110
121
  processed_evals.append((eval_dmatrix, name))
111
122
  else:
112
123
  processed_evals.append((to_dmatrix(eval_dmatrix), name))
113
-
114
- return XGBTrain(
124
+ data = XGBTrain(
115
125
  params=params,
116
126
  dtrain=dtrain,
117
127
  evals=processed_evals,
118
128
  evals_result=evals_result,
119
129
  num_class=num_class,
120
- **kwargs
121
- )()
130
+ **kwargs,
131
+ )(evals_result)
132
+ return data.execute(session=session, **run_kwargs) if evals else data
@@ -12,18 +12,15 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from ... import opcodes
16
- from ...serialization.serializables import ReferenceField
17
- from ..graph import ChunkGraph
18
- from .base import Operator
15
+ from ..core.entity.objects import Object, ObjectData
19
16
 
20
17
 
21
- class Fuse(Operator):
22
- __slots__ = ("_fuse_graph",)
23
- _op_type_ = opcodes.FUSE
18
+ class ModelData(ObjectData):
19
+ pass
24
20
 
25
- fuse_graph = ReferenceField("fuse_graph", ChunkGraph)
26
21
 
22
+ class Model(Object):
23
+ pass
27
24
 
28
- class FuseChunkMixin:
29
- __slots__ = ()
25
+
26
+ MODEL_TYPE = (Model, ModelData)
Binary file
maxframe/opcodes.py CHANGED
@@ -532,6 +532,8 @@ STATSMODELS_TRAIN = 3012
532
532
  STATSMODELS_PREDICT = 3013
533
533
 
534
534
  # learn
535
+ CONNECTED_COMPONENTS = 3100
536
+
535
537
  # checks
536
538
  CHECK_NON_NEGATIVE = 3300
537
539
  # classifier check targets
@@ -566,6 +568,7 @@ CHOLESKY_FUSE = 999988
566
568
 
567
569
  # MaxFrame-dedicated functions
568
570
  DATAFRAME_RESHUFFLE = 10001
571
+ FLATMAP = 10002
569
572
 
570
573
  # MaxFrame internal operators
571
574
  DATAFRAME_PROJECTION_SAME_INDEX_MERGE = 100001
maxframe/protocol.py CHANGED
@@ -15,7 +15,7 @@
15
15
  import base64
16
16
  import enum
17
17
  import uuid
18
- from typing import Any, Dict, Generic, List, Optional, Tuple, Type, TypeVar
18
+ from typing import Any, Dict, Generic, List, Optional, Type, TypeVar
19
19
 
20
20
  import pandas as pd
21
21
 
@@ -38,7 +38,6 @@ from .serialization.serializables import (
38
38
  Serializable,
39
39
  SeriesField,
40
40
  StringField,
41
- TupleField,
42
41
  )
43
42
 
44
43
  pickling_support.install()
@@ -92,19 +91,6 @@ class DataSerializeType(enum.Enum):
92
91
  PICKLE = 0
93
92
 
94
93
 
95
- class VolumeDataMeta(Serializable):
96
- output_type: OutputType = EnumField(
97
- "output_type", OutputType, FieldTypes.int8, default=None
98
- )
99
- serial_type: DataSerializeType = EnumField(
100
- "serial_type", DataSerializeType, FieldTypes.int8, default=None
101
- )
102
- shape: Tuple[int, ...] = TupleField("shape", FieldTypes.int64, default=None)
103
- nsplits: Tuple[Tuple[int, ...], ...] = TupleField(
104
- "nsplits", FieldTypes.tuple(FieldTypes.tuple(FieldTypes.int64)), default=None
105
- )
106
-
107
-
108
94
  _result_type_to_info_cls: Dict[ResultType, Type["ResultInfo"]] = dict()
109
95
 
110
96
 
@@ -389,6 +375,11 @@ class ExecuteDagRequest(Serializable):
389
375
  value_type=FieldTypes.reference,
390
376
  default=None,
391
377
  )
378
+ new_settings: Dict[str, Any] = DictField(
379
+ "new_settings",
380
+ key_type=FieldTypes.string,
381
+ default=None,
382
+ )
392
383
 
393
384
 
394
385
  class SubDagSubmitInstanceInfo(JsonSerializable):
@@ -525,7 +516,7 @@ class DataFrameTableMeta(JsonSerializable):
525
516
  return True
526
517
 
527
518
  def to_json(self) -> dict:
528
- b64_pk = lambda x: base64.b64encode(pickle.dumps(x))
519
+ b64_pk = lambda x: base64.b64encode(pickle.dumps(x)).decode()
529
520
  ret = {
530
521
  "table_name": self.table_name,
531
522
  "type": self.type.value,
maxframe/remote/core.py CHANGED
@@ -15,7 +15,7 @@
15
15
  from functools import partial
16
16
 
17
17
  from .. import opcodes
18
- from ..core import ENTITY_TYPE, ChunkData
18
+ from ..core import ENTITY_TYPE
19
19
  from ..core.operator import ObjectOperator, ObjectOperatorMixin
20
20
  from ..dataframe.core import DATAFRAME_TYPE, INDEX_TYPE, SERIES_TYPE
21
21
  from ..serialization.serializables import (
@@ -26,7 +26,7 @@ from ..serialization.serializables import (
26
26
  ListField,
27
27
  )
28
28
  from ..tensor.core import TENSOR_TYPE
29
- from ..utils import build_fetch_tileable, find_objects, replace_objects
29
+ from ..utils import find_objects, replace_objects
30
30
 
31
31
 
32
32
  class RemoteFunction(ObjectOperatorMixin, ObjectOperator):
@@ -63,12 +63,8 @@ class RemoteFunction(ObjectOperatorMixin, ObjectOperator):
63
63
  if raw_inputs is not None:
64
64
  for raw_inp in raw_inputs:
65
65
  if self._no_prepare(raw_inp):
66
- if not isinstance(self._inputs[0], ChunkData):
67
- # not in tile, set_inputs from tileable
68
- mapping[raw_inp] = next(function_inputs)
69
- else:
70
- # in tile, set_inputs from chunk
71
- mapping[raw_inp] = build_fetch_tileable(raw_inp)
66
+ # not in tile, set_inputs from tileable
67
+ mapping[raw_inp] = next(function_inputs)
72
68
  else:
73
69
  mapping[raw_inp] = next(function_inputs)
74
70
  self.function_args = replace_objects(self.function_args, mapping)
@@ -17,6 +17,7 @@ from .core import (
17
17
  PickleContainer,
18
18
  Serializer,
19
19
  deserialize,
20
+ load_type,
20
21
  pickle_buffers,
21
22
  serialize,
22
23
  serialize_with_spawn,
Binary file
maxframe/session.py CHANGED
@@ -150,6 +150,10 @@ class AbstractSession(ABC):
150
150
  def session_id(self):
151
151
  return self._session_id
152
152
 
153
+ @property
154
+ def closed(self) -> bool:
155
+ return self._closed
156
+
153
157
  def __eq__(self, other):
154
158
  return (
155
159
  isinstance(other, AbstractSession)
@@ -1283,9 +1287,12 @@ def get_default_or_create(**kwargs):
1283
1287
  if session is None:
1284
1288
  # no session attached, try to create one
1285
1289
  warnings.warn(warning_msg)
1286
- session = new_session(
1287
- ODPS.from_global() or ODPS.from_environments(), **kwargs
1290
+ odps_entry = (
1291
+ kwargs.pop("odps_entry", None)
1292
+ or ODPS.from_global()
1293
+ or ODPS.from_environments()
1288
1294
  )
1295
+ session = new_session(odps_entry=odps_entry, **kwargs)
1289
1296
  session.as_default()
1290
1297
  if isinstance(session, IsolatedAsyncSession):
1291
1298
  session = SyncSession.from_isolated_session(session)
@@ -114,7 +114,6 @@ from .arithmetic import (
114
114
  )
115
115
  from .arithmetic import truediv as true_divide
116
116
  from .arithmetic import trunc
117
- from .base import broadcast_to, transpose, unique, where
118
117
  from .core import Tensor
119
118
  from .datasource import (
120
119
  arange,
@@ -143,7 +142,16 @@ from .indexing import (
143
142
  take,
144
143
  unravel_index,
145
144
  )
146
- from .merge import stack
145
+ from .merge import concatenate, stack, vstack
146
+ from .misc import (
147
+ atleast_1d,
148
+ atleast_2d,
149
+ atleast_3d,
150
+ broadcast_to,
151
+ transpose,
152
+ unique,
153
+ where,
154
+ )
147
155
  from .rechunk import rechunk
148
156
  from .reduction import (
149
157
  all,
@@ -23,6 +23,7 @@ from .core import TensorBinOp
23
23
 
24
24
  class TensorIsclose(TensorBinOp):
25
25
  _op_type_ = opcodes.ISCLOSE
26
+ _func_name = "isclose"
26
27
 
27
28
  rtol = Float64Field("rtol", default=None)
28
29
  atol = Float64Field("atol", default=None)
@@ -17,26 +17,13 @@
17
17
  import numpy as np
18
18
  import pytest
19
19
 
20
+ from maxframe.tensor.arithmetic.core import TensorBinOp, TensorUnaryOp
21
+ from maxframe.utils import collect_leaf_operators
22
+
20
23
  from ....core import enter_mode
21
24
  from ...core import SparseTensor, Tensor
22
25
  from ...datasource import array, empty, ones, tensor
23
- from .. import (
24
- TensorAdd,
25
- TensorGreaterThan,
26
- TensorIsclose,
27
- TensorLog,
28
- TensorSubtract,
29
- add,
30
- around,
31
- cos,
32
- frexp,
33
- isclose,
34
- isfinite,
35
- log,
36
- negative,
37
- subtract,
38
- truediv,
39
- )
26
+ from .. import * # noqa: F401
40
27
 
41
28
 
42
29
  def test_add():
@@ -412,3 +399,20 @@ def test_build_mode():
412
399
 
413
400
  with enter_mode(build=True):
414
401
  assert t1 != 2
402
+
403
+
404
+ def test_unary_op_func_name():
405
+ # make sure all the unary op has defined the func name.
406
+
407
+ results = collect_leaf_operators(TensorUnaryOp)
408
+ for op_type in results:
409
+ assert hasattr(op_type, "_func_name")
410
+
411
+
412
+ def test_binary_op_func_name():
413
+ # make sure all the binary op has defined the func name.
414
+
415
+ results = collect_leaf_operators(TensorBinOp)
416
+ for op_type in results:
417
+ if op_type not in (TensorSetImag, TensorSetReal):
418
+ assert hasattr(op_type, "_func_name")