maxframe 1.1.0__cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl → 1.1.1__cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.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.

@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from .config import AttributeDict, option_context, options
15
+ from .config import AttributeDict, option_context, options, update_wlm_quota_settings
maxframe/config/config.py CHANGED
@@ -28,6 +28,8 @@ except ImportError:
28
28
 
29
29
  available_timezones = lambda: all_timezones
30
30
 
31
+ import logging
32
+
31
33
  from ..utils import get_python_tag
32
34
  from .validators import (
33
35
  ValidatorType,
@@ -43,6 +45,8 @@ from .validators import (
43
45
  is_valid_cache_path,
44
46
  )
45
47
 
48
+ logger = logging.getLogger(__name__)
49
+
46
50
  _DEFAULT_REDIRECT_WARN = "Option {source} has been replaced by {target} and might be removed in a future release."
47
51
  _DEFAULT_MAX_ALIVE_SECONDS = 3 * 24 * 3600
48
52
  _DEFAULT_MAX_IDLE_SECONDS = 3600
@@ -499,3 +503,22 @@ class OptionsProxy:
499
503
 
500
504
 
501
505
  options = OptionsProxy()
506
+
507
+
508
+ def update_wlm_quota_settings(session_id: str, engine_settings: Dict[str, Any]):
509
+ engine_quota = engine_settings.get("odps.task.wlm.quota", None)
510
+ session_quota = options.session.quota_name or None
511
+ if engine_quota != session_quota and engine_quota:
512
+ logger.warning(
513
+ "[Session=%s] Session quota (%s) is different to SubDag engine quota (%s)",
514
+ session_id,
515
+ session_quota,
516
+ engine_quota,
517
+ )
518
+ # TODO(renxiang): overwrite or not overwrite
519
+ return
520
+
521
+ if session_quota:
522
+ engine_settings["odps.task.wlm.quota"] = session_quota
523
+ elif "odps.task.wlm.quota" in engine_settings:
524
+ engine_settings.pop("odps.task.wlm.quota")
@@ -18,7 +18,14 @@ import threading
18
18
 
19
19
  import pytest
20
20
 
21
- from ..config import Config, is_integer, is_string, option_context, options
21
+ from ..config import (
22
+ Config,
23
+ is_integer,
24
+ is_string,
25
+ option_context,
26
+ options,
27
+ update_wlm_quota_settings,
28
+ )
22
29
 
23
30
 
24
31
  def test_config_context():
@@ -101,3 +108,15 @@ def test_config_copy():
101
108
 
102
109
  target_cfg.update(src_cfg_dict)
103
110
  assert target_cfg.a.b.c == 1
111
+
112
+
113
+ def test_update_wlm_quota_settings():
114
+ with option_context({}):
115
+ options.session.quota_name = "quota1"
116
+ engine_settings = {}
117
+ update_wlm_quota_settings("session_id", engine_settings)
118
+ assert engine_settings["odps.task.wlm.quota"] == "quota1"
119
+ options.session.quota_name = None
120
+ update_wlm_quota_settings("session_id", engine_settings)
121
+ # TODO(renxiang): overwrite or not overwrite
122
+ assert "odps.task.wlm.quota" in engine_settings
maxframe/conftest.py CHANGED
@@ -40,10 +40,14 @@ def _get_odps_env(test_config: ConfigParser, section_name: str) -> ODPS:
40
40
  access_id = test_config.get(section_name, "access_id")
41
41
  except NoOptionError:
42
42
  access_id = test_config.get("odps", "access_id")
43
+ if not access_id:
44
+ access_id = os.getenv("ACCESS_ID")
43
45
  try:
44
46
  secret_access_key = test_config.get(section_name, "secret_access_key")
45
47
  except NoOptionError:
46
48
  secret_access_key = test_config.get("odps", "secret_access_key")
49
+ if not secret_access_key:
50
+ secret_access_key = os.getenv("SECRET_ACCESS_KEY")
47
51
  try:
48
52
  project = test_config.get(section_name, "project")
49
53
  except NoOptionError:
@@ -119,8 +123,10 @@ def oss_config():
119
123
  old_cache_url = options.object_cache_url
120
124
 
121
125
  try:
122
- oss_access_id = config.get("oss", "access_id")
123
- oss_secret_access_key = config.get("oss", "secret_access_key")
126
+ oss_access_id = config.get("oss", "access_id") or os.getenv("ACCESS_ID")
127
+ oss_secret_access_key = config.get("oss", "secret_access_key") or os.getenv(
128
+ "SECRET_ACCESS_KEY"
129
+ )
124
130
  oss_bucket_name = config.get("oss", "bucket_name")
125
131
  oss_endpoint = config.get("oss", "endpoint")
126
132
  oss_rolearn = config.get("oss", "rolearn")
@@ -37,6 +37,7 @@ from ...serialization.serializables import (
37
37
  SeriesField,
38
38
  StringField,
39
39
  )
40
+ from ...utils import is_empty
40
41
  from ..utils import parse_index
41
42
  from .core import ColumnPruneSupportedDataSourceMixin, IncrementalIndexDatasource
42
43
 
@@ -250,7 +251,7 @@ class DataFrameReadODPSQuery(
250
251
  self.columns = columns
251
252
 
252
253
  def __call__(self, chunk_bytes=None, chunk_size=None):
253
- if not self.index_columns:
254
+ if is_empty(self.index_columns):
254
255
  index_value = parse_index(pd.RangeIndex(0))
255
256
  elif len(self.index_columns) == 1:
256
257
  index_value = parse_index(
@@ -34,6 +34,7 @@ from ...serialization.serializables import (
34
34
  SeriesField,
35
35
  StringField,
36
36
  )
37
+ from ...utils import is_empty
37
38
  from ..core import DataFrame # noqa: F401
38
39
  from ..utils import parse_index
39
40
  from .core import ColumnPruneSupportedDataSourceMixin, IncrementalIndexDatasource
@@ -76,7 +77,7 @@ class DataFrameReadODPSTable(
76
77
  self.columns = columns
77
78
 
78
79
  def __call__(self, shape, chunk_bytes=None, chunk_size=None):
79
- if not self.index_columns:
80
+ if is_empty(self.index_columns):
80
81
  if np.isnan(shape[0]):
81
82
  index_value = parse_index(pd.RangeIndex(0))
82
83
  else:
@@ -238,7 +239,8 @@ def read_odps_table(
238
239
  partitions = [partitions]
239
240
 
240
241
  append_partitions = append_partitions or any(
241
- pt.name in (columns or ()) for pt in (table.table_schema.partitions or ())
242
+ pt.name in (columns if not is_empty(columns) else ())
243
+ for pt in (table.table_schema.partitions or ())
242
244
  )
243
245
  op = DataFrameReadODPSTable(
244
246
  table_name=table.full_table_name,
@@ -19,5 +19,5 @@ from .schema import (
19
19
  odps_schema_to_pandas_dtypes,
20
20
  pandas_to_odps_schema,
21
21
  )
22
- from .tableio import HaloTableIO, ODPSTableIO
22
+ from .tableio import HaloTableIO, ODPSTableIO, TunnelTableIO
23
23
  from .volumeio import ODPSVolumeReader, ODPSVolumeWriter
@@ -14,10 +14,12 @@
14
14
 
15
15
  from typing import Any, Tuple, Union
16
16
 
17
+ import numpy as np
17
18
  import pandas as pd
18
19
  import pyarrow as pa
19
20
 
20
21
  from ...core import OutputType
22
+ from ...lib.version import parse as parse_version
21
23
  from ...protocol import DataFrameTableMeta
22
24
  from ...tensor.core import TENSOR_TYPE
23
25
  from ...typing_ import ArrowTableType, PandasObjectTypes
@@ -109,7 +111,26 @@ def pandas_to_arrow(
109
111
  df = pd.DataFrame([[df]], columns=names)
110
112
  else: # this could never happen # pragma: no cover
111
113
  raise ValueError(f"Does not support meta type {table_meta.type!r}")
112
- pa_table = pa.Table.from_pandas(df, nthreads=nthreads, preserve_index=False)
114
+
115
+ try:
116
+ pa_table = pa.Table.from_pandas(df, nthreads=nthreads, preserve_index=False)
117
+ except pa.ArrowTypeError as ex: # pragma: no cover
118
+ late_np_version = parse_version(np.__version__) >= parse_version("1.20")
119
+ early_pa_version = parse_version(pa.__version__) <= parse_version("4.0")
120
+ if (
121
+ late_np_version
122
+ and early_pa_version
123
+ and "Did not pass numpy.dtype object" in str(ex)
124
+ ):
125
+ raise TypeError(
126
+ "Potential dependency conflict. Try update to pyarrow>4.0 "
127
+ "or downgrade to numpy<1.20. Details can be seen at "
128
+ "https://github.com/numpy/numpy/issues/17913. "
129
+ f"Raw error message: {ex!r}"
130
+ ).with_traceback(ex.__traceback__) from None
131
+ else:
132
+ raise
133
+
113
134
  if table_datetime_cols:
114
135
  col_names = pa_table.schema.names
115
136
  col_datas = []
@@ -15,6 +15,7 @@
15
15
  import os
16
16
  import time
17
17
  from abc import ABC, abstractmethod
18
+ from collections import OrderedDict
18
19
  from contextlib import contextmanager
19
20
  from typing import Dict, List, Optional, Union
20
21
 
@@ -25,7 +26,7 @@ from odps.apis.storage_api import (
25
26
  TableBatchScanResponse,
26
27
  TableBatchWriteResponse,
27
28
  )
28
- from odps.tunnel import TableTunnel
29
+ from odps.tunnel import TableDownloadSession, TableDownloadStatus, TableTunnel
29
30
  from odps.types import OdpsSchema, PartitionSpec, timestamp_ntz
30
31
  from odps.utils import call_with_retry
31
32
 
@@ -36,12 +37,13 @@ except ImportError:
36
37
 
37
38
  from ...config import options
38
39
  from ...env import ODPS_STORAGE_API_ENDPOINT
39
- from ...utils import sync_pyodps_options
40
+ from ...utils import is_empty, sync_pyodps_options
40
41
  from .schema import odps_schema_to_arrow_schema
41
42
 
42
43
  PartitionsType = Union[List[str], str, None]
43
44
 
44
45
  _DEFAULT_ROW_BATCH_SIZE = 4096
46
+ _DOWNLOAD_ID_CACHE_SIZE = 100
45
47
 
46
48
 
47
49
  class ODPSTableIO(ABC):
@@ -65,7 +67,11 @@ class ODPSTableIO(ABC):
65
67
  ) -> OdpsSchema:
66
68
  final_cols = []
67
69
 
68
- columns = columns or [col.name for col in table_schema.simple_columns]
70
+ columns = (
71
+ columns
72
+ if not is_empty(columns)
73
+ else [col.name for col in table_schema.simple_columns]
74
+ )
69
75
  if partition_columns is True:
70
76
  partition_columns = [c.name for c in table_schema.partitions]
71
77
  else:
@@ -215,6 +221,46 @@ class TunnelMultiPartitionReader:
215
221
 
216
222
 
217
223
  class TunnelTableIO(ODPSTableIO):
224
+ _down_session_ids = OrderedDict()
225
+
226
+ @classmethod
227
+ def create_download_sessions(
228
+ cls,
229
+ odps_entry: ODPS,
230
+ full_table_name: str,
231
+ partitions: List[Optional[str]] = None,
232
+ ) -> Dict[Optional[str], TableDownloadSession]:
233
+ table = odps_entry.get_table(full_table_name)
234
+ tunnel = TableTunnel(odps_entry)
235
+ parts = (
236
+ [partitions]
237
+ if partitions is None or isinstance(partitions, str)
238
+ else partitions
239
+ )
240
+ part_to_session = dict()
241
+ for part in parts:
242
+ part_key = (full_table_name, part)
243
+ down_session = None
244
+
245
+ if part_key in cls._down_session_ids:
246
+ down_id = cls._down_session_ids[part_key]
247
+ down_session = tunnel.create_download_session(
248
+ table, async_mode=True, partition_spec=part, download_id=down_id
249
+ )
250
+ if down_session.status != TableDownloadStatus.Normal:
251
+ down_session = None
252
+
253
+ if down_session is None:
254
+ down_session = tunnel.create_download_session(
255
+ table, async_mode=True, partition_spec=part
256
+ )
257
+
258
+ while len(cls._down_session_ids) >= _DOWNLOAD_ID_CACHE_SIZE:
259
+ cls._down_session_ids.popitem(False)
260
+ cls._down_session_ids[part_key] = down_session.id
261
+ part_to_session[part] = down_session
262
+ return part_to_session
263
+
218
264
  @contextmanager
219
265
  def open_reader(
220
266
  self,
@@ -241,21 +287,15 @@ class TunnelTableIO(ODPSTableIO):
241
287
  or (reverse_range and start is None)
242
288
  ):
243
289
  with sync_pyodps_options():
244
- table = self._odps.get_table(full_table_name)
245
- tunnel = TableTunnel(self._odps)
246
- parts = (
247
- [partitions]
248
- if partitions is None or isinstance(partitions, str)
249
- else partitions
290
+ tunnel_sessions = self.create_download_sessions(
291
+ self._odps, full_table_name, partitions
292
+ )
293
+ part_to_down_id = {
294
+ pt: session.id for (pt, session) in tunnel_sessions.items()
295
+ }
296
+ total_records = sum(
297
+ session.count for session in tunnel_sessions.values()
250
298
  )
251
- part_to_down_id = dict()
252
- total_records = 0
253
- for part in parts:
254
- down_session = tunnel.create_download_session(
255
- table, async_mode=True, partition_spec=part
256
- )
257
- part_to_down_id[part] = down_session.id
258
- total_records += down_session.count
259
299
 
260
300
  count = None
261
301
  if start is not None or stop is not None:
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import weakref
16
- from collections import defaultdict
16
+ from collections import OrderedDict
17
17
  from typing import Any, Dict, List, Optional, Tuple, Type
18
18
 
19
19
  import msgpack
@@ -98,14 +98,18 @@ class SerializableMeta(type):
98
98
  non_primitive_fields.append(v)
99
99
 
100
100
  # count number of fields for every base class
101
- cls_to_primitive_field_count = defaultdict(lambda: 0)
102
- cls_to_non_primitive_field_count = defaultdict(lambda: 0)
101
+ cls_to_primitive_field_count = OrderedDict()
102
+ cls_to_non_primitive_field_count = OrderedDict()
103
103
  for field_name in field_order:
104
104
  cls_hash = field_to_cls_hash[field_name]
105
105
  if field_name in primitive_field_names:
106
- cls_to_primitive_field_count[cls_hash] += 1
106
+ cls_to_primitive_field_count[cls_hash] = (
107
+ cls_to_primitive_field_count.get(cls_hash, 0) + 1
108
+ )
107
109
  else:
108
- cls_to_non_primitive_field_count[cls_hash] += 1
110
+ cls_to_non_primitive_field_count[cls_hash] = (
111
+ cls_to_non_primitive_field_count.get(cls_hash, 0) + 1
112
+ )
109
113
 
110
114
  slots = set(properties.pop("__slots__", set()))
111
115
  slots.update(properties_field_slot_names)
@@ -120,9 +124,11 @@ class SerializableMeta(type):
120
124
  properties["_FIELD_ORDER"] = field_order
121
125
  properties["_FIELD_TO_NAME_HASH"] = field_to_cls_hash
122
126
  properties["_PRIMITIVE_FIELDS"] = primitive_fields
123
- properties["_CLS_TO_PRIMITIVE_FIELD_COUNT"] = dict(cls_to_primitive_field_count)
127
+ properties["_CLS_TO_PRIMITIVE_FIELD_COUNT"] = OrderedDict(
128
+ cls_to_primitive_field_count
129
+ )
124
130
  properties["_NON_PRIMITIVE_FIELDS"] = non_primitive_fields
125
- properties["_CLS_TO_NON_PRIMITIVE_FIELD_COUNT"] = dict(
131
+ properties["_CLS_TO_NON_PRIMITIVE_FIELD_COUNT"] = OrderedDict(
126
132
  cls_to_non_primitive_field_count
127
133
  )
128
134
  properties["__slots__"] = tuple(slots)
@@ -296,21 +302,51 @@ class SerializableSerializer(Serializer):
296
302
  else:
297
303
  field.set(obj, value)
298
304
 
305
+ @classmethod
306
+ def _prune_server_fields(
307
+ cls,
308
+ client_cls_to_field_count: Optional[Dict[int, int]],
309
+ server_cls_to_field_count: Dict[int, int],
310
+ server_fields: list,
311
+ ) -> list:
312
+ if not client_cls_to_field_count: # pragma: no cover
313
+ # todo remove this branch when all versions below v0.1.0b5 is eliminated
314
+ return server_fields
315
+ if set(client_cls_to_field_count.keys()) == set(
316
+ server_cls_to_field_count.keys()
317
+ ):
318
+ return server_fields
319
+ ret_server_fields = []
320
+ server_pos = 0
321
+ for cls_hash, count in server_cls_to_field_count.items():
322
+ if cls_hash in client_cls_to_field_count:
323
+ ret_server_fields.extend(server_fields[server_pos : server_pos + count])
324
+ server_pos += count
325
+ return ret_server_fields
326
+
299
327
  @classmethod
300
328
  def _set_field_values(
301
329
  cls,
302
330
  obj: Serializable,
303
331
  values: List[Any],
304
- client_cls_to_field_count: Optional[Dict[str, int]],
332
+ client_cls_to_field_count: Optional[Dict[int, int]],
305
333
  is_primitive: bool = True,
306
334
  ):
307
335
  obj_class = type(obj)
308
336
  if is_primitive:
309
337
  server_cls_to_field_count = obj_class._CLS_TO_PRIMITIVE_FIELD_COUNT
310
- server_fields = obj_class._PRIMITIVE_FIELDS
338
+ server_fields = cls._prune_server_fields(
339
+ client_cls_to_field_count,
340
+ server_cls_to_field_count,
341
+ obj_class._PRIMITIVE_FIELDS,
342
+ )
311
343
  else:
312
344
  server_cls_to_field_count = obj_class._CLS_TO_NON_PRIMITIVE_FIELD_COUNT
313
- server_fields = obj_class._NON_PRIMITIVE_FIELDS
345
+ server_fields = cls._prune_server_fields(
346
+ client_cls_to_field_count,
347
+ server_cls_to_field_count,
348
+ obj_class._NON_PRIMITIVE_FIELDS,
349
+ )
314
350
 
315
351
  legacy_to_new_hash = {
316
352
  c._LEGACY_NAME_HASH: c._NAME_HASH
@@ -221,7 +221,10 @@ def test_compatible_serializable(set_is_ci):
221
221
  _ref_val = ReferenceField("ref_val", "MySimpleSerializable")
222
222
  _dict_val = DictField("dict_val")
223
223
 
224
- class MySubSerializable(MySimpleSerializable):
224
+ class MyMidSerializable(MySimpleSerializable):
225
+ _i_bool_val = Int64Field("i_bool_val", default=True)
226
+
227
+ class MySubSerializable(MyMidSerializable):
225
228
  _m_int_val = Int64Field("m_int_val", default=250)
226
229
  _m_str_val = StringField("m_str_val", default="SUB_STR")
227
230
 
@@ -48,7 +48,7 @@ def vstack(tup):
48
48
 
49
49
  Examples
50
50
  --------
51
- >>> import mars.tensor as mt
51
+ >>> import maxframe.tensor as mt
52
52
 
53
53
  >>> a = mt.array([1, 2, 3])
54
54
  >>> b = mt.array([2, 3, 4])
maxframe/utils.py CHANGED
@@ -1127,3 +1127,9 @@ def sync_pyodps_options():
1127
1127
 
1128
1128
  def str_to_bool(s: Optional[str]) -> Optional[bool]:
1129
1129
  return s.lower().strip() in ("true", "1") if s is not None else None
1130
+
1131
+
1132
+ def is_empty(val):
1133
+ if isinstance(val, (pd.DataFrame, pd.Series, pd.Index)):
1134
+ return val.empty
1135
+ return not bool(val)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: maxframe
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: MaxFrame operator-based data analyze framework
5
5
  Requires-Dist: numpy<2.0.0,>=1.19.0
6
6
  Requires-Dist: pandas>=1.0.0
@@ -1,33 +1,33 @@
1
- maxframe_client/fetcher.py,sha256=HTp7U2bv9jj-lc67jH2R0QG7MD1LygvfZi1Tg9nlefs,9203
1
+ maxframe_client/fetcher.py,sha256=6gAKBI23GpkrgKyveHZlABYMWbzgiKwE7W4UWKhrzAI,9172
2
2
  maxframe_client/conftest.py,sha256=7cwy2sFy5snEaxvtMvxfYFUnG6WtYC_9XxVrwJxOpcU,643
3
3
  maxframe_client/__init__.py,sha256=0_6MYIqksNc-B0hORLb0yqNQUhtqdFD7TGg39bQ-_NI,689
4
4
  maxframe_client/tests/test_session.py,sha256=XdbWE3jzmzphsPmbAk5L8xYVUnAXarDDzVhVYIWwnjE,11196
5
5
  maxframe_client/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
6
6
  maxframe_client/tests/test_fetcher.py,sha256=7mVDO456wcUMajguTJ4FWkSpuonLfinFfiz31ZYnHNs,4158
7
- maxframe_client/session/odps.py,sha256=QbOvlQ57xog-EGZM9nXpzdZjNUUKsYOSto54Edgfv2A,24161
7
+ maxframe_client/session/odps.py,sha256=8PbU-5jNhFO2psLQ0X_kiiqKcZXwgeshxZkoh6poMvA,24928
8
8
  maxframe_client/session/consts.py,sha256=kQv67i4wyhV2ZQXwJf_5k4PRXhN811LmYoo2C3NB7tk,1391
9
9
  maxframe_client/session/__init__.py,sha256=KPqhSlAJiuUz8TC-z5o7mHDVXzLSqWwrZ33zNni7piY,832
10
10
  maxframe_client/session/graph.py,sha256=rRilIWsiVfj_N160s8uv2s7mi_nhx7JxSa9BkhyLRnE,4376
11
- maxframe_client/session/task.py,sha256=qjCy-2jsLSDdy1_9T23RgYLD-JLEmu36eV-9FWEaPkM,11858
12
- maxframe_client/session/tests/test_task.py,sha256=jtUBLyZYDedpe_ZSUGWs4_WFIdWBwYvP9ywmvd3N1jw,3142
11
+ maxframe_client/session/task.py,sha256=eL_bQShBAtUttz13JyBbDkMv9UIpnL6wSk9qtwmUNqk,12027
12
+ maxframe_client/session/tests/test_task.py,sha256=L1t8IPy9p60vuLgjdQym2ADSa9LI6cQArJ0pnXxtvS0,4701
13
13
  maxframe_client/session/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
14
14
  maxframe_client/clients/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
15
15
  maxframe_client/clients/framedriver.py,sha256=-Ux7Q_bWuUSG8r14u84-1UVT9V08q_z4jGxV8kvPQaI,4557
16
16
  maxframe/codegen.py,sha256=yxrKeRynJiQ3fN88BPFn5oHPKemEpESz20GI8ghDgv8,17733
17
17
  maxframe/opcodes.py,sha256=Ef_CJvPvMi_JO4CYQfWRc_eZnMKtoiJWnO7eC-xNAOg,10348
18
18
  maxframe/errors.py,sha256=vHcpVrKRHmoZPa6IwsdDT-jOZUTlhCp8c0e8F2C-5uU,966
19
- maxframe/utils.py,sha256=f4iDtyZG7Wamm7jPU5Tse2RwguXJz5KOIiDAgycyW0o,34550
19
+ maxframe/utils.py,sha256=eubuRneXZ_fedIwMDLChgAq0WAXMuFjjyLtc4r_7zjg,34682
20
20
  maxframe/env.py,sha256=_K499f7giN7Iu9f39iI9p_naaEDoJ0rx8dInbzqFOVI,1402
21
21
  maxframe/_utils.pyx,sha256=I4kmfhNr-xXK2ak22dr4Vwahzn-JmTaYctbL3y9_UBQ,17017
22
22
  maxframe/session.py,sha256=FFciufr4jyKKWBDfbd_OwHGGT8zpRz_8rkZHrGhJMNM,36393
23
23
  maxframe/_utils.pxd,sha256=AhJ4vA_UqZqPshi5nvIZq1xgr80fhIVQ9dm5-UdkYJ8,1154
24
24
  maxframe/extension.py,sha256=F5XTYzW5hNw0AIQz3d6u6Yk7adDdiV4c-HD7bF0X1FI,2659
25
25
  maxframe/udf.py,sha256=HrZzDSNHmv63lCt4bMoPPPVV0HdzIKPL89khmj5yAAc,5157
26
- maxframe/conftest.py,sha256=H6KND9MzHGR7WKlP35SeFE9BNafXxK7XtUUpQPN28BE,6057
26
+ maxframe/conftest.py,sha256=s0GB7iP-m8UTSrYF0P1TH-kffzhZsch7EaV2KObVZ8k,6293
27
27
  maxframe/__init__.py,sha256=SqTFS_1o2HDuVY1mhS0ELlqDuM-biwM_MN0EYGkJLf0,1004
28
28
  maxframe/mixin.py,sha256=HBAeWYGb7N6ZIgkA-YpkKiSY1GetcEVNTuMb0ieznBs,3524
29
29
  maxframe/protocol.py,sha256=kP8dnBhQEI6BcVFn2uuZZTmvr4xJA-R-SZi9ZJ_iqtY,18984
30
- maxframe/_utils.cpython-38-aarch64-linux-gnu.so,sha256=1Qc4sPf6hz8F_ogHBYRp9UqH0qxwBEqphX9lolwYJ98,3349728
30
+ maxframe/_utils.cpython-38-aarch64-linux-gnu.so,sha256=65mGOXf_vqvGYxfSpm2AHbcDfEOC4PRAT69oWOprxg0,3349760
31
31
  maxframe/typing_.py,sha256=iYzgThxTu38yLRtyH5xFhMrurfFj7awMGytfObhvvcs,1180
32
32
  maxframe/remote/run_script.py,sha256=Z1j662AwDF9sr-z1xnPTlrfSTixi2RBZjccXEilfpGA,3556
33
33
  maxframe/remote/__init__.py,sha256=D1nfsnjU_cTzwpo_0icFvEPgkFJeCsqv3IOg6_Ho68k,729
@@ -38,10 +38,10 @@ maxframe/io/objects/core.py,sha256=r9X1Cu9FNUdarMFiTPWX_MPcE8AW5e_d_AsFWjdZDP8,4
38
38
  maxframe/io/objects/tensor.py,sha256=F0aObDLIi_2ND5x-uVogi2A29kIuyhKtZLyZqxI13iM,2673
39
39
  maxframe/io/objects/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
40
40
  maxframe/io/objects/tests/test_object_io.py,sha256=LXPwKX7XYDKPy6AZeLdnfGuW-wfNb5rJunY4MPU8aiY,3775
41
- maxframe/io/odpsio/__init__.py,sha256=VD_mvxljDKDfJHYuN3OpjJWzHqFT5DKykIvECahGu0w,902
42
- maxframe/io/odpsio/tableio.py,sha256=zgk7v_Dcq66u0mtBnF7J9ZoeGurEajsXaxgkRF4u9-o,21055
41
+ maxframe/io/odpsio/__init__.py,sha256=GVR_nKbpwG7DTEp2oOoNb2lMWudIJBIAQfdQQ_2Meh4,917
42
+ maxframe/io/odpsio/tableio.py,sha256=Imt5_o53Lg0kqJwv0rdIkIDkhimU4BPYoyHzFKXfTS8,22452
43
43
  maxframe/io/odpsio/schema.py,sha256=U6kHDkRnp3uluMN36ojPQ1SzfiErfdcphJvxUYejQZQ,12980
44
- maxframe/io/odpsio/arrow.py,sha256=L7b6opJok-tM2t9KQS3iQX-WRnbCJZUNnSUQkHR7KkQ,5108
44
+ maxframe/io/odpsio/arrow.py,sha256=Fq5LFyiu8zprCoRs8ITWEn8pIFCZzoYZrL4IDreYURQ,5929
45
45
  maxframe/io/odpsio/volumeio.py,sha256=y3JwUgBryoBFrkPppT7hCf6VGyJDADM0MUlBXmcia5w,2948
46
46
  maxframe/io/odpsio/tests/test_volumeio.py,sha256=1nsYzEbRAwHJitaOPmCEd5k5vmTPEM_UMRY32VTEH-Y,3572
47
47
  maxframe/io/odpsio/tests/test_tableio.py,sha256=2yuQnzmgDZpDlhSrLjOcOWnnnRZrTfYcCMhvCQOoa7Q,5746
@@ -54,17 +54,17 @@ maxframe/tests/test_utils.py,sha256=imfe7sN1_4EjWuT4qMYMwjOjgL0t5oewyhebBGPDBhY,
54
54
  maxframe/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
55
55
  maxframe/tests/test_codegen.py,sha256=GMrnpSb2eyB_nmuv8-_p47Kw877ElKS3BP52SpqZNIQ,2208
56
56
  maxframe/config/validators.py,sha256=UjbxMKZcDG98-9uCQESm_V56d-VUD7kQGV0KJghVbj8,2511
57
- maxframe/config/__init__.py,sha256=g5lN3nP2HTAXa6ExGxU1NwU1M9ulYPmAcsV-gU7nIW8,656
58
- maxframe/config/config.py,sha256=xFJWljdDYZpTGixRn58NWKXKzaXvm-OPF2QONYPHns0,15510
57
+ maxframe/config/__init__.py,sha256=mkW-3nDoNFlRIECv2WbZBv71of2X4KmTUpXK2zuUFjg,683
58
+ maxframe/config/config.py,sha256=3E7VsRV-IVJ8lu0SDU4NMdizuJBVEu0uh_uUFIFOzBU,16280
59
59
  maxframe/config/tests/test_validators.py,sha256=U_7yKSl0FdVdDwKU1EsnCzNWaOXi8xrIC08x7hb_O4c,1240
60
60
  maxframe/config/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
61
- maxframe/config/tests/test_config.py,sha256=Cx3buKli4F77zwJaB-vnUSlE9LUbt3ObHW38cIE2dDs,2736
61
+ maxframe/config/tests/test_config.py,sha256=iddxMP_OfRtcgVtXi42VanLF7CkDy_IwASDVZA9PHds,3283
62
62
  maxframe/lib/compression.py,sha256=k9DSrl_dNBsn5azLjBdL5B4WZ6eNvmCrdMbcF1G7JSc,1442
63
63
  maxframe/lib/mmh3.pyi,sha256=AOp_XqbA5-NwepeeBeG0OFJj5tjEAFLzcViyRNZ0eVI,1494
64
64
  maxframe/lib/__init__.py,sha256=CzfbLNqqm1yR1i6fDwCd4h1ptuKVDbURFVCb0ra7QNc,642
65
65
  maxframe/lib/version.py,sha256=yQ6HkDOvU9X1rpI49auh-qku2g7gIiztgEH6v1urOrk,18321
66
66
  maxframe/lib/functools_compat.py,sha256=PMSkct9GIbzq-aBwTnggrOLNfLh4xQnYTIFMPblzCUA,2616
67
- maxframe/lib/mmh3.cpython-38-aarch64-linux-gnu.so,sha256=MmBsSCfZIkDbKF80zQa8Xp1WouvirroO3zXHkPX9fnU,145536
67
+ maxframe/lib/mmh3.cpython-38-aarch64-linux-gnu.so,sha256=WjIHbCPookTGdYmfVPydo8beBrpTbnlrtYYu4XIRx94,145560
68
68
  maxframe/lib/wrapped_pickle.py,sha256=HJCb8ERK6clUVgPe529vduMmbMVqBlrQ3W8mH3tYcaE,3836
69
69
  maxframe/lib/tests/test_wrapped_pickle.py,sha256=oz1RLwHSZstXgw4caNeaD0ZgQZvkzDLsx7hFN-NvP7U,1524
70
70
  maxframe/lib/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
@@ -167,7 +167,7 @@ maxframe/tensor/random/tests/__init__.py,sha256=CzfbLNqqm1yR1i6fDwCd4h1ptuKVDbUR
167
167
  maxframe/tensor/rechunk/rechunk.py,sha256=ltvGlUQxzoHSE7bC6J6uQ8sO-YhuFpxmj8-ArJJXIoY,1392
168
168
  maxframe/tensor/rechunk/__init__.py,sha256=pQ4vh6rNzxjIkxrWTxXjAcTDmUw3961-H1f__-lJl6A,797
169
169
  maxframe/tensor/merge/stack.py,sha256=4ZMVqtJQ0nQtbtnJKTX0Z_fSUn8slLLSO56mFT-b0gE,4145
170
- maxframe/tensor/merge/vstack.py,sha256=FzuynVGKkNiOXbzp4Jkde0VMxzs_FfxkxO7J0UU9nhs,2264
170
+ maxframe/tensor/merge/vstack.py,sha256=XGyubfPwkauUQ2zw4D9qd5uLLSRw5LgadHBpEQH71V8,2268
171
171
  maxframe/tensor/merge/concatenate.py,sha256=q0qVpizcU7E6op6D54bF4bl2eMLIJOOwb8AkG1jrDCE,3213
172
172
  maxframe/tensor/merge/__init__.py,sha256=NCuoHVwBtVUQnl8-0ph9cT5ARRn3pTdqZt76-XSvpvs,686
173
173
  maxframe/tensor/merge/tests/test_merge.py,sha256=PfZ883l7xHURs7F1PQl-jg3Kf8IN4qzBMlYv3K5_440,2210
@@ -528,9 +528,9 @@ maxframe/dataframe/datasource/from_tensor.py,sha256=4viuN5SLLye7Xeb8kouOpm-osoQ2
528
528
  maxframe/dataframe/datasource/from_index.py,sha256=2061zsQn-BhyHTT0X9tE0JK8vLxQU8RMb16XsMye9c4,1857
529
529
  maxframe/dataframe/datasource/read_csv.py,sha256=cpp6kX0DVrqY0KticL1h11tckobSzz1gyK4Sf2puUjo,24140
530
530
  maxframe/dataframe/datasource/series.py,sha256=QcYiBNcR8jjH6vdO6l6H9F46KHmlBqVCTI2tv9eyZ9w,1909
531
- maxframe/dataframe/datasource/read_odps_table.py,sha256=T44rPm2-2plSCghTGX0U9mnTrQgpjczHt0DPt2H5HM8,9338
531
+ maxframe/dataframe/datasource/read_odps_table.py,sha256=E2hv-9CxpXlxf0r_lc_G6Cs-voYQ1BunuC9A28K5Sx4,9409
532
532
  maxframe/dataframe/datasource/from_records.py,sha256=WBYouYyg7m_8NJdN-yUWSfJlIpm6DVP3IMfLXZFugyI,3442
533
- maxframe/dataframe/datasource/read_odps_query.py,sha256=vA95FxGZHAKE7KmEespmOEF6wFP9fWeXxle2zQ77PF0,13468
533
+ maxframe/dataframe/datasource/read_odps_query.py,sha256=eOYQdYEIdfQ9SqHkNbY_OxBdUVuH-KZNLDA7fxp8erk,13504
534
534
  maxframe/dataframe/datasource/date_range.py,sha256=8JMr_Ife5pKCS_ca7W50Fyoc1JigOJirVzdVaPDzeFo,17227
535
535
  maxframe/dataframe/datasource/index.py,sha256=D7PcfIWS-6Hv1-8o6adNesditOAa9kb4JOQK1WlqNDQ,4401
536
536
  maxframe/dataframe/datasource/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
@@ -630,7 +630,7 @@ maxframe/core/entity/tests/test_objects.py,sha256=-HS2dux6OdmwtMY6GRxwASq2gPSRY5
630
630
  maxframe/core/entity/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
631
631
  maxframe/core/tests/test_mode.py,sha256=2QYqkPl-sW1LKlJF1pxiuMpnAYrbGibZRXHrNcZTO3M,2432
632
632
  maxframe/core/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
633
- maxframe/core/graph/core.cpython-38-aarch64-linux-gnu.so,sha256=DhChIQGdSQlN80aKXgbuAsYft1xlDULwtVTijFWNGOU,2911744
633
+ maxframe/core/graph/core.cpython-38-aarch64-linux-gnu.so,sha256=eGzOySwNULtX50MTu11KPoaV5SKpmmXEaC5qpi63iIY,2911768
634
634
  maxframe/core/graph/core.pyx,sha256=kyqE5-X9Tc82wU4N_zsf8jNthAHWHTVRNFQWNNbzgpM,15923
635
635
  maxframe/core/graph/__init__.py,sha256=tqUUWDOXp2KFjO7zv1dN_-ttE-ef09-S1GNt8EQ35Bk,765
636
636
  maxframe/core/graph/entity.py,sha256=3ifzsEDIxzDjeM9MhlSwgz92GuaEEoCVWxEkEu2xIgE,4863
@@ -650,7 +650,7 @@ maxframe/core/operator/base.py,sha256=IXBJ0Nd8JAcnwN8FQ1H-QXiMRKAz2_LUZstku7Msv1
650
650
  maxframe/core/operator/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
651
651
  maxframe/core/operator/tests/test_core.py,sha256=57aICnc5VLqdVK7icAORTWC81bSjBxeeVWIJcha9J_0,1691
652
652
  maxframe/serialization/core.pyi,sha256=a3CQxlJv5aYyy__VNKEq5XsaHE-n0MPKE_9CcWu8Q34,2142
653
- maxframe/serialization/core.cpython-38-aarch64-linux-gnu.so,sha256=-24w1vj-t2nu_Iwt-OfKMEiLkDMH7q3CArla4yR1bfs,4558232
653
+ maxframe/serialization/core.cpython-38-aarch64-linux-gnu.so,sha256=BEBkWwkvTvYp-emiCZdzhuL5SxzWa7asjBFVtKEgne0,4558256
654
654
  maxframe/serialization/core.pyx,sha256=mqfb7YUd-Vop8wmGJTjziDP59YX2tr1iN6puRmFI7dg,35551
655
655
  maxframe/serialization/maxframe_objects.py,sha256=R9WEjbHL0Kr56OGkYDU9fcGi7gII6fGlXhi6IyihTsM,1365
656
656
  maxframe/serialization/__init__.py,sha256=LrwesIKJ6MR_mhxW7qRXJXohH9waubZMR9-YicGDMUs,936
@@ -663,13 +663,13 @@ maxframe/serialization/numpy.py,sha256=8_GSo45l_eNoMn4NAGEb9NLXY_9i4tf9KK4EzG0mK
663
663
  maxframe/serialization/serializables/field_type.py,sha256=tgaLzbJ9RmzPOkL_iOfl9E8njZ5J7MtRkGLDnY0lRz8,14933
664
664
  maxframe/serialization/serializables/field.py,sha256=atVgX-9rsVG1fTev7vjQArVwIEaCRjXoSEjpQ3mh6bA,16015
665
665
  maxframe/serialization/serializables/__init__.py,sha256=_wyFZF5QzSP32wSXlXHEPl98DN658I66WamP8XPJy0c,1351
666
- maxframe/serialization/serializables/core.py,sha256=gP83bHStfjJf9zuBVBCl40k6wAGAyQ4rLuFdUiLvbxA,16156
667
- maxframe/serialization/serializables/tests/test_serializable.py,sha256=Yu_38DYeGlm7AH8BnkJzddFtmBfTt7OV8DcFMEfFrI8,10148
666
+ maxframe/serialization/serializables/core.py,sha256=drZB6nSOi7P-W-bbZpH2PirlSJNreq44PdlKI6qSEFQ,17509
667
+ maxframe/serialization/serializables/tests/test_serializable.py,sha256=wpdqiKnMYpQm0ztbJqMF7-vFnjYe4zWiSMXJnAFGt3I,10266
668
668
  maxframe/serialization/serializables/tests/test_field_type.py,sha256=T3ebXbUkKveC9Pq1nIl85e4eYascFeJ52d0REHbz5jo,4381
669
669
  maxframe/serialization/serializables/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
670
670
  maxframe/serialization/tests/__init__.py,sha256=FEFOVLi3o2GpZoedTtLYvbie0eQBehJIjtCrWca2ZHw,596
671
671
  maxframe/serialization/tests/test_serial.py,sha256=fL1ufMU7Lf1fgQ4fwJ0QrKWGQIsw_zHtAQ9zkRfFrOI,12543
672
- maxframe-1.1.0.dist-info/top_level.txt,sha256=64x-fc2q59c_vXwNUkehyjF1vb8JWqFSdYmUqIFqoTM,31
673
- maxframe-1.1.0.dist-info/RECORD,,
674
- maxframe-1.1.0.dist-info/METADATA,sha256=n6x3IidqbCnXPjnT-Q0Mtso0YWC4O5ndKVdbt_n-wEg,3022
675
- maxframe-1.1.0.dist-info/WHEEL,sha256=A1542qG9Hh35LUy4yTbKpcQMALG0t1jdSk2N1aHrAlo,150
672
+ maxframe-1.1.1.dist-info/top_level.txt,sha256=64x-fc2q59c_vXwNUkehyjF1vb8JWqFSdYmUqIFqoTM,31
673
+ maxframe-1.1.1.dist-info/RECORD,,
674
+ maxframe-1.1.1.dist-info/METADATA,sha256=60wD4nznnB6yrVVu8gxYTTT7lOABz5hz-yR1GQwejfs,3022
675
+ maxframe-1.1.1.dist-info/WHEEL,sha256=kXl2s4Qckbq-p8Z4uiL35quKbwl-GQoXbtqNVM-5MKM,149
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.45.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp38-cp38-manylinux_2_17_aarch64
5
5
  Tag: cp38-cp38-manylinux2014_aarch64
@@ -20,7 +20,6 @@ import pandas as pd
20
20
  import pyarrow as pa
21
21
  from odps import ODPS
22
22
  from odps.models import ExternalVolume
23
- from odps.tunnel import TableTunnel
24
23
 
25
24
  from maxframe.core import OBJECT_TYPE
26
25
  from maxframe.dataframe.core import DATAFRAME_TYPE
@@ -28,6 +27,7 @@ from maxframe.io.objects import get_object_io_handler
28
27
  from maxframe.io.odpsio import (
29
28
  ODPSTableIO,
30
29
  ODPSVolumeReader,
30
+ TunnelTableIO,
31
31
  arrow_to_pandas,
32
32
  build_dataframe_table_meta,
33
33
  odps_schema_to_pandas_dtypes,
@@ -136,11 +136,10 @@ class ODPSTableFetcher(ToThreadMixin, ResultFetcher):
136
136
  dtypes = odps_schema_to_pandas_dtypes(table.table_schema)
137
137
  tileable.refresh_from_dtypes(dtypes)
138
138
 
139
- tunnel = TableTunnel(self._odps_entry)
140
- total_records = 0
141
- for part_spec in part_specs:
142
- session = tunnel.create_download_session(table, part_spec)
143
- total_records += session.count
139
+ part_sessions = TunnelTableIO.create_download_sessions(
140
+ self._odps_entry, info.full_table_name, part_specs
141
+ )
142
+ total_records = sum(session.count for session in part_sessions.values())
144
143
 
145
144
  new_shape_list = list(tileable.shape)
146
145
  new_shape_list[0] = total_records
@@ -84,10 +84,21 @@ class MaxFrameServiceCaller(metaclass=abc.ABCMeta):
84
84
  def get_settings_to_upload(self) -> Dict[str, Any]:
85
85
  sql_settings = (odps_options.sql.settings or {}).copy()
86
86
  sql_settings.update(options.sql.settings or {})
87
-
88
87
  quota_name = options.session.quota_name or getattr(
89
88
  odps_options, "quota_name", None
90
89
  )
90
+ quota_settings = {
91
+ sql_settings.get("odps.task.wlm.quota", None),
92
+ options.spe.task.settings.get("odps.task.wlm.quota", None),
93
+ options.pythonpack.task.settings.get("odps.task.wlm.quota", None),
94
+ quota_name,
95
+ }.difference([None])
96
+ if len(quota_settings) >= 2:
97
+ raise ValueError(
98
+ "Quota settings are conflicting: %s" % ", ".join(sorted(quota_settings))
99
+ )
100
+ elif len(quota_settings) == 1:
101
+ quota_name = quota_settings.pop()
91
102
  lifecycle = options.session.table_lifecycle or odps_options.lifecycle
92
103
  temp_lifecycle = (
93
104
  options.session.temp_table_lifecycle or odps_options.temp_lifecycle
@@ -332,6 +343,11 @@ class MaxFrameSession(ToThreadMixin, IsolatedAsyncSession):
332
343
  self._last_settings = copy.deepcopy(new_settings)
333
344
  return new_settings
334
345
 
346
+ if self._last_settings.get("session.quota_name", None) != new_settings.get(
347
+ "session.quota_name", None
348
+ ):
349
+ raise ValueError("Quota name cannot be changed after sessions are created")
350
+
335
351
  update = dict()
336
352
  for k in new_settings.keys():
337
353
  old_item = self._last_settings.get(k)
@@ -126,10 +126,13 @@ class MaxFrameInstanceCaller(MaxFrameServiceCaller):
126
126
 
127
127
  def _create_maxframe_task(self) -> MaxFrameTask:
128
128
  task = MaxFrameTask(name=self._task_name, major_version=self._major_version)
129
+ mf_settings = self.get_settings_to_upload()
129
130
  mf_opts = {
130
- "odps.maxframe.settings": json.dumps(self.get_settings_to_upload()),
131
+ "odps.maxframe.settings": json.dumps(mf_settings),
131
132
  "odps.maxframe.output_format": self._output_format,
132
133
  }
134
+ if mf_settings.get("session.quota_name", None):
135
+ mf_opts["odps.task.wlm.quota"] = mf_settings["session.quota_name"]
133
136
  if mf_version:
134
137
  mf_opts["odps.maxframe.client_version"] = mf_version
135
138
  task.update_settings(mf_opts)
@@ -11,17 +11,20 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
14
  import json
16
15
  import os
17
16
 
18
17
  import mock
18
+ import pytest
19
19
  from defusedxml import ElementTree
20
20
  from odps import ODPS
21
21
  from odps import options as odps_options
22
22
 
23
+ from maxframe import options
24
+ from maxframe.config import option_context
25
+
23
26
  from ...session.consts import MAXFRAME_OUTPUT_JSON_FORMAT
24
- from ...session.task import MaxFrameInstanceCaller, MaxFrameTask
27
+ from ...session.task import MaxFrameInstanceCaller, MaxFrameTask, MaxFrameTaskSession
25
28
 
26
29
  expected_file_dir = os.path.join(os.path.dirname(__file__), "expected-data")
27
30
 
@@ -79,3 +82,33 @@ def test_maxframe_instance_caller_creating_session():
79
82
  finally:
80
83
  odps_options.priority = old_priority
81
84
  odps_options.get_priority = old_get_priority
85
+
86
+
87
+ @pytest.mark.asyncio
88
+ async def test_session_quota_flag_valid():
89
+ def mock_create(self, task: MaxFrameTask, **kwargs):
90
+ assert task.properties["settings"]
91
+ task_settings = json.loads(task.properties["settings"])
92
+ assert task_settings["odps.task.wlm.quota"] == "session_quota"
93
+
94
+ with mock.patch.multiple(
95
+ target="maxframe_client.session.task.MaxFrameInstanceCaller",
96
+ _wait_instance_task_ready=mock.DEFAULT,
97
+ get_session=mock.DEFAULT,
98
+ get_logview_address=mock.DEFAULT,
99
+ ), mock.patch("odps.models.instances.BaseInstances.create", mock_create):
100
+ with option_context({"session.quota_name": "session_quota"}):
101
+ with pytest.raises(ValueError):
102
+ options.sql.settings["odps.task.wlm.quota"] = "session_quota2"
103
+ await MaxFrameTaskSession.init(
104
+ address="test", odps_entry=ODPS.from_environments()
105
+ )
106
+ options.sql.settings["odps.task.wlm.quota"] = "session_quota"
107
+ mf_task_session = await MaxFrameTaskSession.init(
108
+ address="test", odps_entry=ODPS.from_environments()
109
+ )
110
+ with pytest.raises(ValueError):
111
+ options.sql.settings["odps.task.wlm.quota"] = "session_quota2"
112
+ mf_task_session._get_diff_settings()
113
+ options.sql.settings["odps.task.wlm.quota"] = "session_quota"
114
+ mf_task_session._get_diff_settings()