maxframe 0.1.0b5__cp38-cp38-macosx_11_0_arm64.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.
- maxframe/__init__.py +32 -0
- maxframe/_utils.cpython-38-darwin.so +0 -0
- maxframe/_utils.pxd +33 -0
- maxframe/_utils.pyx +547 -0
- maxframe/codegen.py +528 -0
- maxframe/config/__init__.py +15 -0
- maxframe/config/config.py +443 -0
- maxframe/config/tests/__init__.py +13 -0
- maxframe/config/tests/test_config.py +103 -0
- maxframe/config/tests/test_validators.py +34 -0
- maxframe/config/validators.py +57 -0
- maxframe/conftest.py +139 -0
- maxframe/core/__init__.py +65 -0
- maxframe/core/base.py +156 -0
- maxframe/core/entity/__init__.py +44 -0
- maxframe/core/entity/chunks.py +68 -0
- maxframe/core/entity/core.py +152 -0
- maxframe/core/entity/executable.py +337 -0
- maxframe/core/entity/fuse.py +73 -0
- maxframe/core/entity/objects.py +100 -0
- maxframe/core/entity/output_types.py +90 -0
- maxframe/core/entity/tileables.py +438 -0
- maxframe/core/entity/utils.py +24 -0
- maxframe/core/graph/__init__.py +17 -0
- maxframe/core/graph/builder/__init__.py +16 -0
- maxframe/core/graph/builder/base.py +86 -0
- maxframe/core/graph/builder/chunk.py +430 -0
- maxframe/core/graph/builder/tileable.py +34 -0
- maxframe/core/graph/builder/utils.py +41 -0
- maxframe/core/graph/core.cpython-38-darwin.so +0 -0
- maxframe/core/graph/core.pyx +467 -0
- maxframe/core/graph/entity.py +171 -0
- maxframe/core/graph/tests/__init__.py +13 -0
- maxframe/core/graph/tests/test_graph.py +205 -0
- maxframe/core/mode.py +96 -0
- maxframe/core/operator/__init__.py +34 -0
- maxframe/core/operator/base.py +450 -0
- maxframe/core/operator/core.py +276 -0
- maxframe/core/operator/fetch.py +53 -0
- maxframe/core/operator/fuse.py +29 -0
- maxframe/core/operator/objects.py +72 -0
- maxframe/core/operator/shuffle.py +111 -0
- maxframe/core/operator/tests/__init__.py +13 -0
- maxframe/core/operator/tests/test_core.py +64 -0
- maxframe/core/tests/__init__.py +13 -0
- maxframe/core/tests/test_mode.py +75 -0
- maxframe/dataframe/__init__.py +81 -0
- maxframe/dataframe/arithmetic/__init__.py +359 -0
- maxframe/dataframe/arithmetic/abs.py +33 -0
- maxframe/dataframe/arithmetic/add.py +60 -0
- maxframe/dataframe/arithmetic/arccos.py +28 -0
- maxframe/dataframe/arithmetic/arccosh.py +28 -0
- maxframe/dataframe/arithmetic/arcsin.py +28 -0
- maxframe/dataframe/arithmetic/arcsinh.py +28 -0
- maxframe/dataframe/arithmetic/arctan.py +28 -0
- maxframe/dataframe/arithmetic/arctanh.py +28 -0
- maxframe/dataframe/arithmetic/around.py +152 -0
- maxframe/dataframe/arithmetic/bitwise_and.py +46 -0
- maxframe/dataframe/arithmetic/bitwise_or.py +50 -0
- maxframe/dataframe/arithmetic/bitwise_xor.py +46 -0
- maxframe/dataframe/arithmetic/ceil.py +28 -0
- maxframe/dataframe/arithmetic/core.py +342 -0
- maxframe/dataframe/arithmetic/cos.py +28 -0
- maxframe/dataframe/arithmetic/cosh.py +28 -0
- maxframe/dataframe/arithmetic/degrees.py +28 -0
- maxframe/dataframe/arithmetic/docstring.py +442 -0
- maxframe/dataframe/arithmetic/equal.py +56 -0
- maxframe/dataframe/arithmetic/exp.py +28 -0
- maxframe/dataframe/arithmetic/exp2.py +28 -0
- maxframe/dataframe/arithmetic/expm1.py +28 -0
- maxframe/dataframe/arithmetic/floor.py +28 -0
- maxframe/dataframe/arithmetic/floordiv.py +64 -0
- maxframe/dataframe/arithmetic/greater.py +57 -0
- maxframe/dataframe/arithmetic/greater_equal.py +57 -0
- maxframe/dataframe/arithmetic/invert.py +33 -0
- maxframe/dataframe/arithmetic/is_ufuncs.py +62 -0
- maxframe/dataframe/arithmetic/less.py +57 -0
- maxframe/dataframe/arithmetic/less_equal.py +57 -0
- maxframe/dataframe/arithmetic/log.py +28 -0
- maxframe/dataframe/arithmetic/log10.py +28 -0
- maxframe/dataframe/arithmetic/log2.py +28 -0
- maxframe/dataframe/arithmetic/mod.py +60 -0
- maxframe/dataframe/arithmetic/multiply.py +60 -0
- maxframe/dataframe/arithmetic/negative.py +33 -0
- maxframe/dataframe/arithmetic/not_equal.py +56 -0
- maxframe/dataframe/arithmetic/power.py +68 -0
- maxframe/dataframe/arithmetic/radians.py +28 -0
- maxframe/dataframe/arithmetic/sin.py +28 -0
- maxframe/dataframe/arithmetic/sinh.py +28 -0
- maxframe/dataframe/arithmetic/sqrt.py +28 -0
- maxframe/dataframe/arithmetic/subtract.py +64 -0
- maxframe/dataframe/arithmetic/tan.py +28 -0
- maxframe/dataframe/arithmetic/tanh.py +28 -0
- maxframe/dataframe/arithmetic/tests/__init__.py +13 -0
- maxframe/dataframe/arithmetic/tests/test_arithmetic.py +695 -0
- maxframe/dataframe/arithmetic/truediv.py +64 -0
- maxframe/dataframe/arithmetic/trunc.py +28 -0
- maxframe/dataframe/arrays.py +864 -0
- maxframe/dataframe/core.py +2417 -0
- maxframe/dataframe/datasource/__init__.py +15 -0
- maxframe/dataframe/datasource/core.py +81 -0
- maxframe/dataframe/datasource/dataframe.py +59 -0
- maxframe/dataframe/datasource/date_range.py +504 -0
- maxframe/dataframe/datasource/from_index.py +54 -0
- maxframe/dataframe/datasource/from_records.py +107 -0
- maxframe/dataframe/datasource/from_tensor.py +419 -0
- maxframe/dataframe/datasource/index.py +117 -0
- maxframe/dataframe/datasource/read_csv.py +528 -0
- maxframe/dataframe/datasource/read_odps_query.py +299 -0
- maxframe/dataframe/datasource/read_odps_table.py +253 -0
- maxframe/dataframe/datasource/read_parquet.py +421 -0
- maxframe/dataframe/datasource/series.py +55 -0
- maxframe/dataframe/datasource/tests/__init__.py +13 -0
- maxframe/dataframe/datasource/tests/test_datasource.py +401 -0
- maxframe/dataframe/datastore/__init__.py +26 -0
- maxframe/dataframe/datastore/core.py +19 -0
- maxframe/dataframe/datastore/to_csv.py +227 -0
- maxframe/dataframe/datastore/to_odps.py +162 -0
- maxframe/dataframe/extensions/__init__.py +41 -0
- maxframe/dataframe/extensions/accessor.py +50 -0
- maxframe/dataframe/extensions/reshuffle.py +83 -0
- maxframe/dataframe/extensions/tests/__init__.py +13 -0
- maxframe/dataframe/extensions/tests/test_extensions.py +38 -0
- maxframe/dataframe/fetch/__init__.py +15 -0
- maxframe/dataframe/fetch/core.py +86 -0
- maxframe/dataframe/groupby/__init__.py +82 -0
- maxframe/dataframe/groupby/aggregation.py +350 -0
- maxframe/dataframe/groupby/apply.py +251 -0
- maxframe/dataframe/groupby/core.py +179 -0
- maxframe/dataframe/groupby/cum.py +124 -0
- maxframe/dataframe/groupby/fill.py +141 -0
- maxframe/dataframe/groupby/getitem.py +92 -0
- maxframe/dataframe/groupby/head.py +105 -0
- maxframe/dataframe/groupby/sample.py +214 -0
- maxframe/dataframe/groupby/tests/__init__.py +13 -0
- maxframe/dataframe/groupby/tests/test_groupby.py +374 -0
- maxframe/dataframe/groupby/transform.py +255 -0
- maxframe/dataframe/indexing/__init__.py +84 -0
- maxframe/dataframe/indexing/add_prefix_suffix.py +110 -0
- maxframe/dataframe/indexing/align.py +349 -0
- maxframe/dataframe/indexing/at.py +83 -0
- maxframe/dataframe/indexing/getitem.py +204 -0
- maxframe/dataframe/indexing/iat.py +37 -0
- maxframe/dataframe/indexing/iloc.py +566 -0
- maxframe/dataframe/indexing/insert.py +86 -0
- maxframe/dataframe/indexing/loc.py +411 -0
- maxframe/dataframe/indexing/reindex.py +526 -0
- maxframe/dataframe/indexing/rename.py +462 -0
- maxframe/dataframe/indexing/rename_axis.py +209 -0
- maxframe/dataframe/indexing/reset_index.py +402 -0
- maxframe/dataframe/indexing/sample.py +221 -0
- maxframe/dataframe/indexing/set_axis.py +194 -0
- maxframe/dataframe/indexing/set_index.py +61 -0
- maxframe/dataframe/indexing/setitem.py +130 -0
- maxframe/dataframe/indexing/tests/__init__.py +13 -0
- maxframe/dataframe/indexing/tests/test_indexing.py +488 -0
- maxframe/dataframe/indexing/where.py +308 -0
- maxframe/dataframe/initializer.py +288 -0
- maxframe/dataframe/merge/__init__.py +32 -0
- maxframe/dataframe/merge/append.py +121 -0
- maxframe/dataframe/merge/concat.py +325 -0
- maxframe/dataframe/merge/merge.py +593 -0
- maxframe/dataframe/merge/tests/__init__.py +13 -0
- maxframe/dataframe/merge/tests/test_merge.py +215 -0
- maxframe/dataframe/misc/__init__.py +134 -0
- maxframe/dataframe/misc/_duplicate.py +46 -0
- maxframe/dataframe/misc/accessor.py +276 -0
- maxframe/dataframe/misc/apply.py +692 -0
- maxframe/dataframe/misc/astype.py +236 -0
- maxframe/dataframe/misc/case_when.py +141 -0
- maxframe/dataframe/misc/check_monotonic.py +84 -0
- maxframe/dataframe/misc/cut.py +383 -0
- maxframe/dataframe/misc/datetimes.py +79 -0
- maxframe/dataframe/misc/describe.py +108 -0
- maxframe/dataframe/misc/diff.py +210 -0
- maxframe/dataframe/misc/drop.py +440 -0
- maxframe/dataframe/misc/drop_duplicates.py +248 -0
- maxframe/dataframe/misc/duplicated.py +292 -0
- maxframe/dataframe/misc/eval.py +728 -0
- maxframe/dataframe/misc/explode.py +171 -0
- maxframe/dataframe/misc/get_dummies.py +208 -0
- maxframe/dataframe/misc/isin.py +217 -0
- maxframe/dataframe/misc/map.py +236 -0
- maxframe/dataframe/misc/melt.py +162 -0
- maxframe/dataframe/misc/memory_usage.py +248 -0
- maxframe/dataframe/misc/pct_change.py +150 -0
- maxframe/dataframe/misc/pivot_table.py +262 -0
- maxframe/dataframe/misc/qcut.py +104 -0
- maxframe/dataframe/misc/select_dtypes.py +104 -0
- maxframe/dataframe/misc/shift.py +256 -0
- maxframe/dataframe/misc/stack.py +238 -0
- maxframe/dataframe/misc/string_.py +221 -0
- maxframe/dataframe/misc/tests/__init__.py +13 -0
- maxframe/dataframe/misc/tests/test_misc.py +468 -0
- maxframe/dataframe/misc/to_numeric.py +178 -0
- maxframe/dataframe/misc/transform.py +361 -0
- maxframe/dataframe/misc/transpose.py +136 -0
- maxframe/dataframe/misc/value_counts.py +182 -0
- maxframe/dataframe/missing/__init__.py +53 -0
- maxframe/dataframe/missing/checkna.py +223 -0
- maxframe/dataframe/missing/dropna.py +280 -0
- maxframe/dataframe/missing/fillna.py +275 -0
- maxframe/dataframe/missing/replace.py +439 -0
- maxframe/dataframe/missing/tests/__init__.py +13 -0
- maxframe/dataframe/missing/tests/test_missing.py +89 -0
- maxframe/dataframe/operators.py +273 -0
- maxframe/dataframe/plotting/__init__.py +40 -0
- maxframe/dataframe/plotting/core.py +78 -0
- maxframe/dataframe/plotting/tests/__init__.py +13 -0
- maxframe/dataframe/plotting/tests/test_plotting.py +136 -0
- maxframe/dataframe/reduction/__init__.py +107 -0
- maxframe/dataframe/reduction/aggregation.py +344 -0
- maxframe/dataframe/reduction/all.py +78 -0
- maxframe/dataframe/reduction/any.py +78 -0
- maxframe/dataframe/reduction/core.py +837 -0
- maxframe/dataframe/reduction/count.py +59 -0
- maxframe/dataframe/reduction/cummax.py +30 -0
- maxframe/dataframe/reduction/cummin.py +30 -0
- maxframe/dataframe/reduction/cumprod.py +30 -0
- maxframe/dataframe/reduction/cumsum.py +30 -0
- maxframe/dataframe/reduction/custom_reduction.py +42 -0
- maxframe/dataframe/reduction/kurtosis.py +104 -0
- maxframe/dataframe/reduction/max.py +65 -0
- maxframe/dataframe/reduction/mean.py +61 -0
- maxframe/dataframe/reduction/min.py +65 -0
- maxframe/dataframe/reduction/nunique.py +141 -0
- maxframe/dataframe/reduction/prod.py +76 -0
- maxframe/dataframe/reduction/reduction_size.py +36 -0
- maxframe/dataframe/reduction/sem.py +69 -0
- maxframe/dataframe/reduction/skew.py +89 -0
- maxframe/dataframe/reduction/std.py +53 -0
- maxframe/dataframe/reduction/str_concat.py +48 -0
- maxframe/dataframe/reduction/sum.py +77 -0
- maxframe/dataframe/reduction/tests/__init__.py +13 -0
- maxframe/dataframe/reduction/tests/test_reduction.py +486 -0
- maxframe/dataframe/reduction/unique.py +90 -0
- maxframe/dataframe/reduction/var.py +72 -0
- maxframe/dataframe/sort/__init__.py +34 -0
- maxframe/dataframe/sort/core.py +36 -0
- maxframe/dataframe/sort/sort_index.py +153 -0
- maxframe/dataframe/sort/sort_values.py +311 -0
- maxframe/dataframe/sort/tests/__init__.py +13 -0
- maxframe/dataframe/sort/tests/test_sort.py +81 -0
- maxframe/dataframe/statistics/__init__.py +33 -0
- maxframe/dataframe/statistics/corr.py +280 -0
- maxframe/dataframe/statistics/quantile.py +341 -0
- maxframe/dataframe/statistics/tests/__init__.py +13 -0
- maxframe/dataframe/statistics/tests/test_statistics.py +82 -0
- maxframe/dataframe/tests/__init__.py +13 -0
- maxframe/dataframe/tests/test_initializer.py +29 -0
- maxframe/dataframe/tseries/__init__.py +13 -0
- maxframe/dataframe/tseries/tests/__init__.py +13 -0
- maxframe/dataframe/tseries/tests/test_tseries.py +30 -0
- maxframe/dataframe/tseries/to_datetime.py +297 -0
- maxframe/dataframe/ufunc/__init__.py +27 -0
- maxframe/dataframe/ufunc/tensor.py +54 -0
- maxframe/dataframe/ufunc/ufunc.py +52 -0
- maxframe/dataframe/utils.py +1267 -0
- maxframe/dataframe/window/__init__.py +29 -0
- maxframe/dataframe/window/aggregation.py +96 -0
- maxframe/dataframe/window/core.py +69 -0
- maxframe/dataframe/window/ewm.py +249 -0
- maxframe/dataframe/window/expanding.py +147 -0
- maxframe/dataframe/window/rolling.py +376 -0
- maxframe/dataframe/window/tests/__init__.py +13 -0
- maxframe/dataframe/window/tests/test_ewm.py +70 -0
- maxframe/dataframe/window/tests/test_expanding.py +66 -0
- maxframe/dataframe/window/tests/test_rolling.py +57 -0
- maxframe/env.py +33 -0
- maxframe/errors.py +21 -0
- maxframe/extension.py +81 -0
- maxframe/learn/__init__.py +17 -0
- maxframe/learn/contrib/__init__.py +17 -0
- maxframe/learn/contrib/pytorch/__init__.py +16 -0
- maxframe/learn/contrib/pytorch/run_function.py +110 -0
- maxframe/learn/contrib/pytorch/run_script.py +102 -0
- maxframe/learn/contrib/pytorch/tests/__init__.py +13 -0
- maxframe/learn/contrib/pytorch/tests/test_pytorch.py +42 -0
- maxframe/learn/contrib/utils.py +52 -0
- maxframe/learn/contrib/xgboost/__init__.py +26 -0
- maxframe/learn/contrib/xgboost/classifier.py +86 -0
- maxframe/learn/contrib/xgboost/core.py +156 -0
- maxframe/learn/contrib/xgboost/dmatrix.py +150 -0
- maxframe/learn/contrib/xgboost/predict.py +138 -0
- maxframe/learn/contrib/xgboost/regressor.py +78 -0
- maxframe/learn/contrib/xgboost/tests/__init__.py +13 -0
- maxframe/learn/contrib/xgboost/tests/test_core.py +43 -0
- maxframe/learn/contrib/xgboost/train.py +121 -0
- maxframe/learn/utils/__init__.py +15 -0
- maxframe/learn/utils/core.py +29 -0
- maxframe/lib/__init__.py +15 -0
- maxframe/lib/aio/__init__.py +27 -0
- maxframe/lib/aio/_runners.py +162 -0
- maxframe/lib/aio/_threads.py +35 -0
- maxframe/lib/aio/base.py +82 -0
- maxframe/lib/aio/file.py +85 -0
- maxframe/lib/aio/isolation.py +100 -0
- maxframe/lib/aio/lru.py +242 -0
- maxframe/lib/aio/parallelism.py +37 -0
- maxframe/lib/aio/tests/__init__.py +13 -0
- maxframe/lib/aio/tests/test_aio_file.py +55 -0
- maxframe/lib/compression.py +55 -0
- maxframe/lib/cython/__init__.py +13 -0
- maxframe/lib/cython/libcpp.pxd +30 -0
- maxframe/lib/filesystem/__init__.py +21 -0
- maxframe/lib/filesystem/_glob.py +173 -0
- maxframe/lib/filesystem/_oss_lib/__init__.py +13 -0
- maxframe/lib/filesystem/_oss_lib/common.py +198 -0
- maxframe/lib/filesystem/_oss_lib/glob.py +147 -0
- maxframe/lib/filesystem/_oss_lib/handle.py +156 -0
- maxframe/lib/filesystem/arrow.py +236 -0
- maxframe/lib/filesystem/base.py +263 -0
- maxframe/lib/filesystem/core.py +95 -0
- maxframe/lib/filesystem/fsmap.py +164 -0
- maxframe/lib/filesystem/hdfs.py +31 -0
- maxframe/lib/filesystem/local.py +112 -0
- maxframe/lib/filesystem/oss.py +157 -0
- maxframe/lib/filesystem/tests/__init__.py +13 -0
- maxframe/lib/filesystem/tests/test_filesystem.py +223 -0
- maxframe/lib/filesystem/tests/test_oss.py +182 -0
- maxframe/lib/functools_compat.py +81 -0
- maxframe/lib/mmh3.cpython-38-darwin.so +0 -0
- maxframe/lib/mmh3_src/MurmurHash3.cpp +339 -0
- maxframe/lib/mmh3_src/MurmurHash3.h +43 -0
- maxframe/lib/mmh3_src/mmh3module.cpp +387 -0
- maxframe/lib/sparse/__init__.py +861 -0
- maxframe/lib/sparse/array.py +1604 -0
- maxframe/lib/sparse/core.py +92 -0
- maxframe/lib/sparse/matrix.py +241 -0
- maxframe/lib/sparse/tests/__init__.py +15 -0
- maxframe/lib/sparse/tests/test_sparse.py +476 -0
- maxframe/lib/sparse/vector.py +150 -0
- maxframe/lib/tblib/LICENSE +20 -0
- maxframe/lib/tblib/__init__.py +327 -0
- maxframe/lib/tblib/cpython.py +83 -0
- maxframe/lib/tblib/decorators.py +44 -0
- maxframe/lib/tblib/pickling_support.py +90 -0
- maxframe/lib/tests/__init__.py +13 -0
- maxframe/lib/tests/test_wrapped_pickle.py +51 -0
- maxframe/lib/version.py +620 -0
- maxframe/lib/wrapped_pickle.py +139 -0
- maxframe/mixin.py +100 -0
- maxframe/odpsio/__init__.py +21 -0
- maxframe/odpsio/arrow.py +91 -0
- maxframe/odpsio/schema.py +364 -0
- maxframe/odpsio/tableio.py +322 -0
- maxframe/odpsio/tests/__init__.py +13 -0
- maxframe/odpsio/tests/test_arrow.py +88 -0
- maxframe/odpsio/tests/test_schema.py +297 -0
- maxframe/odpsio/tests/test_tableio.py +136 -0
- maxframe/odpsio/tests/test_volumeio.py +90 -0
- maxframe/odpsio/volumeio.py +95 -0
- maxframe/opcodes.py +590 -0
- maxframe/protocol.py +415 -0
- maxframe/remote/__init__.py +18 -0
- maxframe/remote/core.py +210 -0
- maxframe/remote/run_script.py +121 -0
- maxframe/serialization/__init__.py +26 -0
- maxframe/serialization/arrow.py +95 -0
- maxframe/serialization/core.cpython-38-darwin.so +0 -0
- maxframe/serialization/core.pxd +44 -0
- maxframe/serialization/core.pyi +61 -0
- maxframe/serialization/core.pyx +1094 -0
- maxframe/serialization/exception.py +86 -0
- maxframe/serialization/maxframe_objects.py +39 -0
- maxframe/serialization/numpy.py +91 -0
- maxframe/serialization/pandas.py +202 -0
- maxframe/serialization/scipy.py +71 -0
- maxframe/serialization/serializables/__init__.py +55 -0
- maxframe/serialization/serializables/core.py +262 -0
- maxframe/serialization/serializables/field.py +624 -0
- maxframe/serialization/serializables/field_type.py +589 -0
- maxframe/serialization/serializables/tests/__init__.py +13 -0
- maxframe/serialization/serializables/tests/test_field_type.py +121 -0
- maxframe/serialization/serializables/tests/test_serializable.py +250 -0
- maxframe/serialization/tests/__init__.py +13 -0
- maxframe/serialization/tests/test_serial.py +412 -0
- maxframe/session.py +1310 -0
- maxframe/tensor/__init__.py +183 -0
- maxframe/tensor/arithmetic/__init__.py +315 -0
- maxframe/tensor/arithmetic/abs.py +68 -0
- maxframe/tensor/arithmetic/absolute.py +68 -0
- maxframe/tensor/arithmetic/add.py +82 -0
- maxframe/tensor/arithmetic/angle.py +72 -0
- maxframe/tensor/arithmetic/arccos.py +104 -0
- maxframe/tensor/arithmetic/arccosh.py +91 -0
- maxframe/tensor/arithmetic/arcsin.py +94 -0
- maxframe/tensor/arithmetic/arcsinh.py +86 -0
- maxframe/tensor/arithmetic/arctan.py +106 -0
- maxframe/tensor/arithmetic/arctan2.py +128 -0
- maxframe/tensor/arithmetic/arctanh.py +86 -0
- maxframe/tensor/arithmetic/around.py +114 -0
- maxframe/tensor/arithmetic/bitand.py +95 -0
- maxframe/tensor/arithmetic/bitor.py +102 -0
- maxframe/tensor/arithmetic/bitxor.py +95 -0
- maxframe/tensor/arithmetic/cbrt.py +66 -0
- maxframe/tensor/arithmetic/ceil.py +71 -0
- maxframe/tensor/arithmetic/clip.py +165 -0
- maxframe/tensor/arithmetic/conj.py +74 -0
- maxframe/tensor/arithmetic/copysign.py +78 -0
- maxframe/tensor/arithmetic/core.py +544 -0
- maxframe/tensor/arithmetic/cos.py +85 -0
- maxframe/tensor/arithmetic/cosh.py +72 -0
- maxframe/tensor/arithmetic/deg2rad.py +72 -0
- maxframe/tensor/arithmetic/degrees.py +77 -0
- maxframe/tensor/arithmetic/divide.py +114 -0
- maxframe/tensor/arithmetic/equal.py +76 -0
- maxframe/tensor/arithmetic/exp.py +106 -0
- maxframe/tensor/arithmetic/exp2.py +67 -0
- maxframe/tensor/arithmetic/expm1.py +79 -0
- maxframe/tensor/arithmetic/fabs.py +74 -0
- maxframe/tensor/arithmetic/fix.py +69 -0
- maxframe/tensor/arithmetic/float_power.py +103 -0
- maxframe/tensor/arithmetic/floor.py +77 -0
- maxframe/tensor/arithmetic/floordiv.py +94 -0
- maxframe/tensor/arithmetic/fmax.py +105 -0
- maxframe/tensor/arithmetic/fmin.py +106 -0
- maxframe/tensor/arithmetic/fmod.py +99 -0
- maxframe/tensor/arithmetic/frexp.py +92 -0
- maxframe/tensor/arithmetic/greater.py +77 -0
- maxframe/tensor/arithmetic/greater_equal.py +69 -0
- maxframe/tensor/arithmetic/hypot.py +77 -0
- maxframe/tensor/arithmetic/i0.py +89 -0
- maxframe/tensor/arithmetic/imag.py +67 -0
- maxframe/tensor/arithmetic/invert.py +110 -0
- maxframe/tensor/arithmetic/isclose.py +115 -0
- maxframe/tensor/arithmetic/iscomplex.py +64 -0
- maxframe/tensor/arithmetic/isfinite.py +106 -0
- maxframe/tensor/arithmetic/isinf.py +103 -0
- maxframe/tensor/arithmetic/isnan.py +82 -0
- maxframe/tensor/arithmetic/isreal.py +63 -0
- maxframe/tensor/arithmetic/ldexp.py +99 -0
- maxframe/tensor/arithmetic/less.py +69 -0
- maxframe/tensor/arithmetic/less_equal.py +69 -0
- maxframe/tensor/arithmetic/log.py +92 -0
- maxframe/tensor/arithmetic/log10.py +85 -0
- maxframe/tensor/arithmetic/log1p.py +95 -0
- maxframe/tensor/arithmetic/log2.py +85 -0
- maxframe/tensor/arithmetic/logaddexp.py +80 -0
- maxframe/tensor/arithmetic/logaddexp2.py +78 -0
- maxframe/tensor/arithmetic/logical_and.py +81 -0
- maxframe/tensor/arithmetic/logical_not.py +74 -0
- maxframe/tensor/arithmetic/logical_or.py +82 -0
- maxframe/tensor/arithmetic/logical_xor.py +88 -0
- maxframe/tensor/arithmetic/lshift.py +82 -0
- maxframe/tensor/arithmetic/maximum.py +108 -0
- maxframe/tensor/arithmetic/minimum.py +108 -0
- maxframe/tensor/arithmetic/mod.py +104 -0
- maxframe/tensor/arithmetic/modf.py +83 -0
- maxframe/tensor/arithmetic/multiply.py +81 -0
- maxframe/tensor/arithmetic/nan_to_num.py +99 -0
- maxframe/tensor/arithmetic/negative.py +65 -0
- maxframe/tensor/arithmetic/nextafter.py +68 -0
- maxframe/tensor/arithmetic/not_equal.py +72 -0
- maxframe/tensor/arithmetic/positive.py +47 -0
- maxframe/tensor/arithmetic/power.py +106 -0
- maxframe/tensor/arithmetic/rad2deg.py +71 -0
- maxframe/tensor/arithmetic/radians.py +77 -0
- maxframe/tensor/arithmetic/real.py +70 -0
- maxframe/tensor/arithmetic/reciprocal.py +76 -0
- maxframe/tensor/arithmetic/rint.py +68 -0
- maxframe/tensor/arithmetic/rshift.py +81 -0
- maxframe/tensor/arithmetic/setimag.py +29 -0
- maxframe/tensor/arithmetic/setreal.py +29 -0
- maxframe/tensor/arithmetic/sign.py +81 -0
- maxframe/tensor/arithmetic/signbit.py +65 -0
- maxframe/tensor/arithmetic/sin.py +98 -0
- maxframe/tensor/arithmetic/sinc.py +102 -0
- maxframe/tensor/arithmetic/sinh.py +93 -0
- maxframe/tensor/arithmetic/spacing.py +72 -0
- maxframe/tensor/arithmetic/sqrt.py +81 -0
- maxframe/tensor/arithmetic/square.py +69 -0
- maxframe/tensor/arithmetic/subtract.py +81 -0
- maxframe/tensor/arithmetic/tan.py +88 -0
- maxframe/tensor/arithmetic/tanh.py +92 -0
- maxframe/tensor/arithmetic/tests/__init__.py +15 -0
- maxframe/tensor/arithmetic/tests/test_arithmetic.py +414 -0
- maxframe/tensor/arithmetic/truediv.py +104 -0
- maxframe/tensor/arithmetic/trunc.py +72 -0
- maxframe/tensor/arithmetic/utils.py +65 -0
- maxframe/tensor/array_utils.py +186 -0
- maxframe/tensor/base/__init__.py +34 -0
- maxframe/tensor/base/astype.py +119 -0
- maxframe/tensor/base/atleast_1d.py +74 -0
- maxframe/tensor/base/broadcast_to.py +89 -0
- maxframe/tensor/base/ravel.py +92 -0
- maxframe/tensor/base/tests/__init__.py +13 -0
- maxframe/tensor/base/tests/test_base.py +114 -0
- maxframe/tensor/base/transpose.py +125 -0
- maxframe/tensor/base/unique.py +205 -0
- maxframe/tensor/base/where.py +127 -0
- maxframe/tensor/core.py +724 -0
- maxframe/tensor/datasource/__init__.py +32 -0
- maxframe/tensor/datasource/arange.py +156 -0
- maxframe/tensor/datasource/array.py +415 -0
- maxframe/tensor/datasource/core.py +109 -0
- maxframe/tensor/datasource/empty.py +169 -0
- maxframe/tensor/datasource/from_dataframe.py +70 -0
- maxframe/tensor/datasource/from_dense.py +54 -0
- maxframe/tensor/datasource/from_sparse.py +47 -0
- maxframe/tensor/datasource/full.py +186 -0
- maxframe/tensor/datasource/ones.py +173 -0
- maxframe/tensor/datasource/scalar.py +40 -0
- maxframe/tensor/datasource/tests/__init__.py +13 -0
- maxframe/tensor/datasource/tests/test_datasource.py +278 -0
- maxframe/tensor/datasource/zeros.py +188 -0
- maxframe/tensor/fetch/__init__.py +15 -0
- maxframe/tensor/fetch/core.py +54 -0
- maxframe/tensor/indexing/__init__.py +47 -0
- maxframe/tensor/indexing/choose.py +196 -0
- maxframe/tensor/indexing/compress.py +124 -0
- maxframe/tensor/indexing/core.py +190 -0
- maxframe/tensor/indexing/extract.py +71 -0
- maxframe/tensor/indexing/fill_diagonal.py +183 -0
- maxframe/tensor/indexing/flatnonzero.py +60 -0
- maxframe/tensor/indexing/getitem.py +175 -0
- maxframe/tensor/indexing/nonzero.py +120 -0
- maxframe/tensor/indexing/setitem.py +132 -0
- maxframe/tensor/indexing/slice.py +29 -0
- maxframe/tensor/indexing/take.py +130 -0
- maxframe/tensor/indexing/tests/__init__.py +15 -0
- maxframe/tensor/indexing/tests/test_indexing.py +234 -0
- maxframe/tensor/indexing/unravel_index.py +103 -0
- maxframe/tensor/merge/__init__.py +15 -0
- maxframe/tensor/merge/stack.py +132 -0
- maxframe/tensor/merge/tests/__init__.py +13 -0
- maxframe/tensor/merge/tests/test_merge.py +52 -0
- maxframe/tensor/operators.py +123 -0
- maxframe/tensor/random/__init__.py +168 -0
- maxframe/tensor/random/beta.py +87 -0
- maxframe/tensor/random/binomial.py +137 -0
- maxframe/tensor/random/bytes.py +39 -0
- maxframe/tensor/random/chisquare.py +110 -0
- maxframe/tensor/random/choice.py +186 -0
- maxframe/tensor/random/core.py +234 -0
- maxframe/tensor/random/dirichlet.py +123 -0
- maxframe/tensor/random/exponential.py +94 -0
- maxframe/tensor/random/f.py +135 -0
- maxframe/tensor/random/gamma.py +128 -0
- maxframe/tensor/random/geometric.py +93 -0
- maxframe/tensor/random/gumbel.py +167 -0
- maxframe/tensor/random/hypergeometric.py +148 -0
- maxframe/tensor/random/laplace.py +133 -0
- maxframe/tensor/random/logistic.py +129 -0
- maxframe/tensor/random/lognormal.py +159 -0
- maxframe/tensor/random/logseries.py +122 -0
- maxframe/tensor/random/multinomial.py +133 -0
- maxframe/tensor/random/multivariate_normal.py +192 -0
- maxframe/tensor/random/negative_binomial.py +125 -0
- maxframe/tensor/random/noncentral_chisquare.py +132 -0
- maxframe/tensor/random/noncentral_f.py +126 -0
- maxframe/tensor/random/normal.py +143 -0
- maxframe/tensor/random/pareto.py +140 -0
- maxframe/tensor/random/permutation.py +104 -0
- maxframe/tensor/random/poisson.py +111 -0
- maxframe/tensor/random/power.py +142 -0
- maxframe/tensor/random/rand.py +82 -0
- maxframe/tensor/random/randint.py +121 -0
- maxframe/tensor/random/randn.py +96 -0
- maxframe/tensor/random/random_integers.py +123 -0
- maxframe/tensor/random/random_sample.py +86 -0
- maxframe/tensor/random/rayleigh.py +110 -0
- maxframe/tensor/random/shuffle.py +61 -0
- maxframe/tensor/random/standard_cauchy.py +105 -0
- maxframe/tensor/random/standard_exponential.py +72 -0
- maxframe/tensor/random/standard_gamma.py +120 -0
- maxframe/tensor/random/standard_normal.py +74 -0
- maxframe/tensor/random/standard_t.py +135 -0
- maxframe/tensor/random/tests/__init__.py +15 -0
- maxframe/tensor/random/tests/test_random.py +167 -0
- maxframe/tensor/random/triangular.py +119 -0
- maxframe/tensor/random/uniform.py +131 -0
- maxframe/tensor/random/vonmises.py +131 -0
- maxframe/tensor/random/wald.py +114 -0
- maxframe/tensor/random/weibull.py +140 -0
- maxframe/tensor/random/zipf.py +122 -0
- maxframe/tensor/rechunk/__init__.py +26 -0
- maxframe/tensor/rechunk/rechunk.py +43 -0
- maxframe/tensor/reduction/__init__.py +66 -0
- maxframe/tensor/reduction/all.py +103 -0
- maxframe/tensor/reduction/allclose.py +88 -0
- maxframe/tensor/reduction/any.py +105 -0
- maxframe/tensor/reduction/argmax.py +103 -0
- maxframe/tensor/reduction/argmin.py +103 -0
- maxframe/tensor/reduction/array_equal.py +64 -0
- maxframe/tensor/reduction/core.py +168 -0
- maxframe/tensor/reduction/count_nonzero.py +81 -0
- maxframe/tensor/reduction/cumprod.py +97 -0
- maxframe/tensor/reduction/cumsum.py +101 -0
- maxframe/tensor/reduction/max.py +120 -0
- maxframe/tensor/reduction/mean.py +123 -0
- maxframe/tensor/reduction/min.py +120 -0
- maxframe/tensor/reduction/nanargmax.py +82 -0
- maxframe/tensor/reduction/nanargmin.py +76 -0
- maxframe/tensor/reduction/nancumprod.py +91 -0
- maxframe/tensor/reduction/nancumsum.py +94 -0
- maxframe/tensor/reduction/nanmax.py +111 -0
- maxframe/tensor/reduction/nanmean.py +106 -0
- maxframe/tensor/reduction/nanmin.py +111 -0
- maxframe/tensor/reduction/nanprod.py +94 -0
- maxframe/tensor/reduction/nanstd.py +126 -0
- maxframe/tensor/reduction/nansum.py +115 -0
- maxframe/tensor/reduction/nanvar.py +149 -0
- maxframe/tensor/reduction/prod.py +130 -0
- maxframe/tensor/reduction/std.py +134 -0
- maxframe/tensor/reduction/sum.py +125 -0
- maxframe/tensor/reduction/tests/__init__.py +13 -0
- maxframe/tensor/reduction/tests/test_reduction.py +181 -0
- maxframe/tensor/reduction/var.py +176 -0
- maxframe/tensor/reshape/__init__.py +17 -0
- maxframe/tensor/reshape/reshape.py +188 -0
- maxframe/tensor/reshape/tests/__init__.py +15 -0
- maxframe/tensor/reshape/tests/test_reshape.py +37 -0
- maxframe/tensor/statistics/__init__.py +13 -0
- maxframe/tensor/statistics/percentile.py +175 -0
- maxframe/tensor/statistics/quantile.py +288 -0
- maxframe/tensor/ufunc/__init__.py +26 -0
- maxframe/tensor/ufunc/ufunc.py +200 -0
- maxframe/tensor/utils.py +718 -0
- maxframe/tests/__init__.py +13 -0
- maxframe/tests/test_codegen.py +69 -0
- maxframe/tests/test_protocol.py +144 -0
- maxframe/tests/test_utils.py +376 -0
- maxframe/tests/utils.py +164 -0
- maxframe/typing_.py +37 -0
- maxframe/udf.py +134 -0
- maxframe/utils.py +1114 -0
- maxframe-0.1.0b5.dist-info/METADATA +104 -0
- maxframe-0.1.0b5.dist-info/RECORD +647 -0
- maxframe-0.1.0b5.dist-info/WHEEL +5 -0
- maxframe-0.1.0b5.dist-info/top_level.txt +2 -0
- maxframe_client/__init__.py +17 -0
- maxframe_client/clients/__init__.py +13 -0
- maxframe_client/clients/framedriver.py +118 -0
- maxframe_client/clients/spe.py +104 -0
- maxframe_client/conftest.py +15 -0
- maxframe_client/fetcher.py +264 -0
- maxframe_client/session/__init__.py +22 -0
- maxframe_client/session/consts.py +36 -0
- maxframe_client/session/graph.py +119 -0
- maxframe_client/session/odps.py +482 -0
- maxframe_client/session/task.py +280 -0
- maxframe_client/session/tests/__init__.py +13 -0
- maxframe_client/session/tests/test_task.py +85 -0
- maxframe_client/tests/__init__.py +13 -0
- maxframe_client/tests/test_fetcher.py +89 -0
- maxframe_client/tests/test_session.py +255 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
from typing import Any, Callable, Dict, List, Type
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from numpy.core._exceptions import UFuncTypeError
|
|
22
|
+
except ImportError: # pragma: no cover
|
|
23
|
+
UFuncTypeError = None
|
|
24
|
+
|
|
25
|
+
from ...typing_ import ChunkType, OperatorType, TileableType
|
|
26
|
+
from ..entity import (
|
|
27
|
+
ExecutableTuple,
|
|
28
|
+
OutputType,
|
|
29
|
+
get_fetch_class,
|
|
30
|
+
get_output_types,
|
|
31
|
+
get_tileable_types,
|
|
32
|
+
)
|
|
33
|
+
from ..mode import is_eager_mode
|
|
34
|
+
|
|
35
|
+
_op_type_to_executor: Dict[Type[OperatorType], Callable] = dict()
|
|
36
|
+
_op_type_to_size_estimator: Dict[Type[OperatorType], Callable] = dict()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TileableOperatorMixin:
|
|
40
|
+
__slots__ = ()
|
|
41
|
+
|
|
42
|
+
def check_inputs(self, inputs: List[TileableType]):
|
|
43
|
+
if not inputs:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
for inp in inputs:
|
|
47
|
+
if inp is not None and inp._need_execution():
|
|
48
|
+
raise ValueError(
|
|
49
|
+
f"{inp} has unknown dtypes, "
|
|
50
|
+
f"it must be executed first before {str(type(self))}"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def _check_if_gpu(cls, inputs: List[TileableType]):
|
|
55
|
+
if not inputs:
|
|
56
|
+
return None
|
|
57
|
+
true_num = 0
|
|
58
|
+
for inp in inputs:
|
|
59
|
+
op = getattr(inp, "op", None)
|
|
60
|
+
if op is None or op.gpu is None:
|
|
61
|
+
return None
|
|
62
|
+
true_num += int(op.gpu)
|
|
63
|
+
if true_num == len(inputs):
|
|
64
|
+
return True
|
|
65
|
+
elif true_num == 0:
|
|
66
|
+
return False
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
def _tokenize_output(self, output_idx: int, **kw):
|
|
70
|
+
return f"{self._key}_{output_idx}"
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def _fill_nan_shape(kw: dict):
|
|
74
|
+
nsplits = kw.get("nsplits")
|
|
75
|
+
shape = kw.get("shape")
|
|
76
|
+
if nsplits is not None and shape is not None:
|
|
77
|
+
nsplits = tuple(nsplits)
|
|
78
|
+
shape = list(shape)
|
|
79
|
+
for idx, (s, sp) in enumerate(zip(shape, nsplits)):
|
|
80
|
+
if not np.isnan(s):
|
|
81
|
+
continue
|
|
82
|
+
s = sum(sp)
|
|
83
|
+
if not np.isnan(s):
|
|
84
|
+
shape[idx] = s
|
|
85
|
+
kw["shape"] = tuple(shape)
|
|
86
|
+
kw["nsplits"] = nsplits
|
|
87
|
+
return kw
|
|
88
|
+
|
|
89
|
+
def _create_tileable(self, output_idx: int, **kw) -> TileableType:
|
|
90
|
+
output_type = kw.pop("output_type", self._get_output_type(output_idx))
|
|
91
|
+
if output_type is None:
|
|
92
|
+
raise ValueError("output_type should be specified")
|
|
93
|
+
|
|
94
|
+
if isinstance(output_type, (list, tuple)):
|
|
95
|
+
output_type = output_type[output_idx]
|
|
96
|
+
|
|
97
|
+
tileable_type, tileable_data_type = get_tileable_types(output_type)
|
|
98
|
+
kw["_i"] = output_idx
|
|
99
|
+
kw["op"] = self
|
|
100
|
+
if output_type == OutputType.scalar:
|
|
101
|
+
# tensor
|
|
102
|
+
kw["order"] = "C_ORDER"
|
|
103
|
+
|
|
104
|
+
kw = self._fill_nan_shape(kw)
|
|
105
|
+
|
|
106
|
+
# key of output chunks may only contain keys for its output ids
|
|
107
|
+
if "_key" not in kw:
|
|
108
|
+
kw["_key"] = self._tokenize_output(output_idx, **kw)
|
|
109
|
+
|
|
110
|
+
data = tileable_data_type(**kw)
|
|
111
|
+
return tileable_type(data)
|
|
112
|
+
|
|
113
|
+
def _new_tileables(
|
|
114
|
+
self, inputs: List[TileableType], kws: List[dict] = None, **kw
|
|
115
|
+
) -> List[TileableType]:
|
|
116
|
+
output_limit = kw.pop("output_limit", None)
|
|
117
|
+
if output_limit is None:
|
|
118
|
+
output_limit = getattr(self, "output_limit")
|
|
119
|
+
|
|
120
|
+
self._set_inputs(inputs)
|
|
121
|
+
if self.gpu is None:
|
|
122
|
+
self.gpu = self._check_if_gpu(self._inputs)
|
|
123
|
+
if getattr(self, "_key", None) is None:
|
|
124
|
+
self._update_key() # update key when inputs are set
|
|
125
|
+
|
|
126
|
+
tileables = []
|
|
127
|
+
for j in range(output_limit):
|
|
128
|
+
create_tensor_kw = kw.copy()
|
|
129
|
+
if kws:
|
|
130
|
+
create_tensor_kw.update(kws[j])
|
|
131
|
+
tileable = self._create_tileable(j, **create_tensor_kw)
|
|
132
|
+
tileables.append(tileable)
|
|
133
|
+
|
|
134
|
+
self.outputs = tileables
|
|
135
|
+
if len(tileables) > 1:
|
|
136
|
+
# for each output tileable, hold the reference to the other outputs
|
|
137
|
+
# so that either no one or everyone are gc collected
|
|
138
|
+
for j, t in enumerate(tileables):
|
|
139
|
+
t.data._siblings = [
|
|
140
|
+
tileable.data for tileable in tileables[:j] + tileables[j + 1 :]
|
|
141
|
+
]
|
|
142
|
+
return tileables
|
|
143
|
+
|
|
144
|
+
def new_tileables(
|
|
145
|
+
self, inputs: List[TileableType], kws: List[dict] = None, **kw
|
|
146
|
+
) -> List[TileableType]:
|
|
147
|
+
"""
|
|
148
|
+
Create tileable objects(Tensors or DataFrames).
|
|
149
|
+
|
|
150
|
+
This is a misc function for create tileable objects like tensors or dataframes,
|
|
151
|
+
it will be called inside the `new_tensors` and `new_dataframes`.
|
|
152
|
+
If eager mode is on, it will trigger the execution after tileable objects are created.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
inputs : list
|
|
157
|
+
Input tileables
|
|
158
|
+
kws : List[dict]
|
|
159
|
+
Kwargs for each output.
|
|
160
|
+
kw : dict
|
|
161
|
+
Common kwargs for all outputs.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
tileables : list
|
|
166
|
+
Output tileables.
|
|
167
|
+
|
|
168
|
+
.. note::
|
|
169
|
+
It's a final method, do not override.
|
|
170
|
+
Override the method `_new_tileables` if needed.
|
|
171
|
+
"""
|
|
172
|
+
tileables = self._new_tileables(inputs, kws=kws, **kw)
|
|
173
|
+
if is_eager_mode():
|
|
174
|
+
ExecutableTuple(tileables).execute()
|
|
175
|
+
return tileables
|
|
176
|
+
|
|
177
|
+
def new_tileable(
|
|
178
|
+
self, inputs: List[TileableType], kws: List[Dict] = None, **kw
|
|
179
|
+
) -> TileableType:
|
|
180
|
+
if getattr(self, "output_limit") != 1:
|
|
181
|
+
raise TypeError("cannot new chunk with more than 1 outputs")
|
|
182
|
+
|
|
183
|
+
return self.new_tileables(inputs, kws=kws, **kw)[0]
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def concat_tileable_chunks(cls, tileable: TileableType):
|
|
187
|
+
raise NotImplementedError
|
|
188
|
+
|
|
189
|
+
@classmethod
|
|
190
|
+
def create_tileable_from_chunks(
|
|
191
|
+
cls, chunks: List[ChunkType], inputs: List[TileableType] = None, **kw
|
|
192
|
+
) -> TileableType:
|
|
193
|
+
raise NotImplementedError
|
|
194
|
+
|
|
195
|
+
def get_fetch_op_cls(self, obj: ChunkType):
|
|
196
|
+
from .shuffle import ShuffleProxy
|
|
197
|
+
|
|
198
|
+
output_types = get_output_types(obj, unknown_as=OutputType.object)
|
|
199
|
+
fetch_cls, fetch_shuffle_cls = get_fetch_class(output_types[0])
|
|
200
|
+
if isinstance(self, ShuffleProxy):
|
|
201
|
+
cls = fetch_shuffle_cls
|
|
202
|
+
else:
|
|
203
|
+
cls = fetch_cls
|
|
204
|
+
|
|
205
|
+
def _inner(**kw):
|
|
206
|
+
return cls(output_types=output_types, **kw)
|
|
207
|
+
|
|
208
|
+
return _inner
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def register_executor(cls, executor: Callable):
|
|
212
|
+
_op_type_to_executor[cls] = executor
|
|
213
|
+
|
|
214
|
+
@classmethod
|
|
215
|
+
def unregister_executor(cls):
|
|
216
|
+
del _op_type_to_executor[cls]
|
|
217
|
+
|
|
218
|
+
@classmethod
|
|
219
|
+
def register_size_estimator(cls, size_estimator: Callable):
|
|
220
|
+
_op_type_to_size_estimator[cls] = size_estimator
|
|
221
|
+
|
|
222
|
+
@classmethod
|
|
223
|
+
def unregister_size_estimator(cls):
|
|
224
|
+
del _op_type_to_size_estimator[cls]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def execute(results: Dict[str, Any], op: OperatorType):
|
|
228
|
+
try:
|
|
229
|
+
executor = _op_type_to_executor[type(op)]
|
|
230
|
+
except KeyError:
|
|
231
|
+
executor = type(op).execute
|
|
232
|
+
|
|
233
|
+
# pre execute
|
|
234
|
+
op.pre_execute(results, op)
|
|
235
|
+
succeeded = False
|
|
236
|
+
try:
|
|
237
|
+
if UFuncTypeError is None: # pragma: no cover
|
|
238
|
+
return executor(results, op)
|
|
239
|
+
else:
|
|
240
|
+
# Cast `UFuncTypeError` to `TypeError` since subclasses of the former is unpickleable.
|
|
241
|
+
# The `UFuncTypeError` was introduced by numpy#12593 since v1.17.0.
|
|
242
|
+
try:
|
|
243
|
+
result = executor(results, op)
|
|
244
|
+
succeeded = True
|
|
245
|
+
return result
|
|
246
|
+
except UFuncTypeError as e: # pragma: no cover
|
|
247
|
+
raise TypeError(str(e)).with_traceback(sys.exc_info()[2]) from None
|
|
248
|
+
except NotImplementedError:
|
|
249
|
+
for op_cls in type(op).__mro__:
|
|
250
|
+
if op_cls in _op_type_to_executor:
|
|
251
|
+
executor = _op_type_to_executor[op_cls]
|
|
252
|
+
_op_type_to_executor[type(op)] = executor
|
|
253
|
+
result = executor(results, op)
|
|
254
|
+
succeeded = True
|
|
255
|
+
return result
|
|
256
|
+
raise KeyError(f"No handler found for op: {op}")
|
|
257
|
+
finally:
|
|
258
|
+
if succeeded:
|
|
259
|
+
op.post_execute(results, op)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def estimate_size(results: Dict[str, Any], op: OperatorType):
|
|
263
|
+
try:
|
|
264
|
+
size_estimator = _op_type_to_size_estimator[type(op)]
|
|
265
|
+
except KeyError:
|
|
266
|
+
size_estimator = type(op).estimate_size
|
|
267
|
+
|
|
268
|
+
try:
|
|
269
|
+
return size_estimator(results, op)
|
|
270
|
+
except NotImplementedError:
|
|
271
|
+
for op_cls in type(op).__mro__:
|
|
272
|
+
if op_cls in _op_type_to_size_estimator:
|
|
273
|
+
size_estimator = _op_type_to_size_estimator[op_cls]
|
|
274
|
+
_op_type_to_size_estimator[type(op)] = size_estimator
|
|
275
|
+
return size_estimator(results, op)
|
|
276
|
+
raise KeyError(f"No handler found for op: {op} to estimate size")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import enum
|
|
16
|
+
|
|
17
|
+
from ... import opcodes
|
|
18
|
+
from ...serialization.serializables import (
|
|
19
|
+
FieldTypes,
|
|
20
|
+
Int32Field,
|
|
21
|
+
ListField,
|
|
22
|
+
ReferenceField,
|
|
23
|
+
StringField,
|
|
24
|
+
)
|
|
25
|
+
from .base import Operator
|
|
26
|
+
from .core import TileableOperatorMixin
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Fetch(Operator):
|
|
30
|
+
_op_type_ = opcodes.FETCH
|
|
31
|
+
|
|
32
|
+
source_key = StringField("source_key", default=None)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class FetchMixin(TileableOperatorMixin):
|
|
36
|
+
def check_inputs(self, inputs):
|
|
37
|
+
# no inputs
|
|
38
|
+
if inputs and len(inputs) > 0:
|
|
39
|
+
raise ValueError(f"{type(self).__name__} has no inputs")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class FetchShuffle(Operator):
|
|
43
|
+
_op_type_ = opcodes.FETCH_SHUFFLE
|
|
44
|
+
|
|
45
|
+
source_keys = ListField("source_keys", FieldTypes.string)
|
|
46
|
+
n_mappers = Int32Field("n_mappers")
|
|
47
|
+
n_reducers = Int32Field("n_reducers")
|
|
48
|
+
shuffle_fetch_type = ReferenceField("shuffle_fetch_type")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ShuffleFetchType(enum.Enum):
|
|
52
|
+
FETCH_BY_KEY = 0
|
|
53
|
+
FETCH_BY_INDEX = 1
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from ... import opcodes
|
|
16
|
+
from ...serialization.serializables import ReferenceField
|
|
17
|
+
from ..graph import ChunkGraph
|
|
18
|
+
from .base import Operator
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Fuse(Operator):
|
|
22
|
+
__slots__ = ("_fuse_graph",)
|
|
23
|
+
_op_type_ = opcodes.FUSE
|
|
24
|
+
|
|
25
|
+
fuse_graph = ReferenceField("fuse_graph", ChunkGraph)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FuseChunkMixin:
|
|
29
|
+
__slots__ = ()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from ...serialization.serializables import BoolField
|
|
16
|
+
from ..entity import OutputType, register_fetch_class
|
|
17
|
+
from .base import Operator
|
|
18
|
+
from .core import TileableOperatorMixin
|
|
19
|
+
from .fetch import Fetch, FetchMixin
|
|
20
|
+
from .fuse import Fuse, FuseChunkMixin
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ObjectOperator(Operator):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ObjectOperatorMixin(TileableOperatorMixin):
|
|
28
|
+
_output_type_ = OutputType.object
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ObjectFuseChunkMixin(FuseChunkMixin, ObjectOperatorMixin):
|
|
32
|
+
__slots__ = ()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ObjectFuseChunk(ObjectFuseChunkMixin, Fuse):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ObjectFetch(FetchMixin, ObjectOperatorMixin, Fetch):
|
|
40
|
+
_output_type_ = OutputType.object
|
|
41
|
+
|
|
42
|
+
def __init__(self, **kw):
|
|
43
|
+
kw.pop("output_types", None)
|
|
44
|
+
kw.pop("_output_types", None)
|
|
45
|
+
super().__init__(**kw)
|
|
46
|
+
|
|
47
|
+
def _new_tileables(self, inputs, kws=None, **kw):
|
|
48
|
+
if "_key" in kw and self.source_key is None:
|
|
49
|
+
self.source_key = kw["_key"]
|
|
50
|
+
return super()._new_tileables(inputs, kws=kws, **kw)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
register_fetch_class(OutputType.object, ObjectFetch, None)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MergeDictOperator(ObjectOperator, ObjectOperatorMixin):
|
|
57
|
+
_merge = BoolField("merge")
|
|
58
|
+
|
|
59
|
+
def __init__(self, merge=None, **kw):
|
|
60
|
+
super().__init__(_merge=merge, **kw)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def merge(self):
|
|
64
|
+
return self._merge
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def concat_tileable_chunks(cls, tileable):
|
|
68
|
+
assert not tileable.is_coarse()
|
|
69
|
+
|
|
70
|
+
op = cls(merge=True)
|
|
71
|
+
chunk = cls(merge=True).new_chunk(tileable.chunks)
|
|
72
|
+
return op.new_tileable([tileable], chunks=[chunk], nsplits=((1,),))
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from ... import opcodes
|
|
16
|
+
from ...serialization.serializables import (
|
|
17
|
+
FieldTypes,
|
|
18
|
+
Int32Field,
|
|
19
|
+
StringField,
|
|
20
|
+
TupleField,
|
|
21
|
+
)
|
|
22
|
+
from . import FetchShuffle, ShuffleFetchType
|
|
23
|
+
from .base import Operator, OperatorStage, VirtualOperator
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ShuffleProxy(VirtualOperator):
|
|
27
|
+
_op_type_ = opcodes.SHUFFLE_PROXY
|
|
28
|
+
n_mappers = Int32Field("n_mappers", default=0)
|
|
29
|
+
# `n_reducers` will be updated in `MapReduceOperator._new_chunks`
|
|
30
|
+
n_reducers = Int32Field("n_reducers", default=0)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MapReduceOperator(Operator):
|
|
34
|
+
"""
|
|
35
|
+
An operator for shuffle execution which partitions data by the value in each record’s partition key, and
|
|
36
|
+
send the partitioned data from all mappers to all reducers.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# for reducer
|
|
40
|
+
reducer_index = TupleField("reducer_index", FieldTypes.uint64)
|
|
41
|
+
# Total reducer nums, which also be shuffle blocks for single mapper.
|
|
42
|
+
n_reducers = Int32Field("n_reducers")
|
|
43
|
+
# The reducer ordinal in all reducers. It's different from reducer_index,
|
|
44
|
+
# which might be a tuple.
|
|
45
|
+
# `reducer_ordinal` will be set in `_new_chunks`.
|
|
46
|
+
reducer_ordinal = Int32Field("reducer_ordinal")
|
|
47
|
+
reducer_phase = StringField("reducer_phase", default=None)
|
|
48
|
+
|
|
49
|
+
def __init__(self, *args, **kwargs):
|
|
50
|
+
super().__init__(*args, **kwargs)
|
|
51
|
+
if self.stage == OperatorStage.reduce:
|
|
52
|
+
# for reducer, we assign worker at first
|
|
53
|
+
self.scheduling_hint.reassign_worker = True
|
|
54
|
+
|
|
55
|
+
def get_dependent_data_keys(self):
|
|
56
|
+
from .fetch import FetchShuffle
|
|
57
|
+
|
|
58
|
+
if self.stage == OperatorStage.reduce:
|
|
59
|
+
inputs = self.inputs or ()
|
|
60
|
+
deps = []
|
|
61
|
+
for inp in inputs:
|
|
62
|
+
if isinstance(inp.op, ShuffleProxy):
|
|
63
|
+
deps.extend(
|
|
64
|
+
[(chunk.key, self.reducer_index) for chunk in inp.inputs or ()]
|
|
65
|
+
)
|
|
66
|
+
elif isinstance(inp.op, FetchShuffle):
|
|
67
|
+
# fetch shuffle by index doesn't store data keys, so it won't run into this function.
|
|
68
|
+
assert inp.op.shuffle_fetch_type == ShuffleFetchType.FETCH_BY_KEY
|
|
69
|
+
deps.extend([(k, self.reducer_index) for k in inp.op.source_keys])
|
|
70
|
+
else:
|
|
71
|
+
deps.append(inp.key)
|
|
72
|
+
return deps
|
|
73
|
+
return super().get_dependent_data_keys()
|
|
74
|
+
|
|
75
|
+
def iter_mapper_keys(self, input_id=0):
|
|
76
|
+
# key is mapper chunk key, index is mapper chunk index.
|
|
77
|
+
input_chunk = self.inputs[input_id]
|
|
78
|
+
if isinstance(input_chunk.op, ShuffleProxy):
|
|
79
|
+
keys = [inp.key for inp in input_chunk.inputs]
|
|
80
|
+
else:
|
|
81
|
+
assert isinstance(input_chunk.op, FetchShuffle), input_chunk.op
|
|
82
|
+
if input_chunk.op.shuffle_fetch_type == ShuffleFetchType.FETCH_BY_INDEX:
|
|
83
|
+
# For fetch shuffle by index, all shuffle block of same reducers are
|
|
84
|
+
# identified by their index. chunk key are not needed any more.
|
|
85
|
+
# so just mock key here.
|
|
86
|
+
# keep this in sync with ray executor `execute_subtask`.
|
|
87
|
+
return list(range(input_chunk.op.n_mappers))
|
|
88
|
+
keys = input_chunk.op.source_keys
|
|
89
|
+
return keys
|
|
90
|
+
|
|
91
|
+
def iter_mapper_data(self, ctx, input_id=0, pop=False, skip_none=False):
|
|
92
|
+
for key in self.iter_mapper_keys(input_id):
|
|
93
|
+
try:
|
|
94
|
+
if pop:
|
|
95
|
+
yield ctx.pop((key, self.reducer_index))
|
|
96
|
+
else:
|
|
97
|
+
yield ctx[key, self.reducer_index]
|
|
98
|
+
except KeyError:
|
|
99
|
+
if not skip_none: # pragma: no cover
|
|
100
|
+
raise
|
|
101
|
+
if not pop:
|
|
102
|
+
ctx[key, self.reducer_index] = None
|
|
103
|
+
|
|
104
|
+
def execute(self, ctx, op):
|
|
105
|
+
"""The mapper stage must ensure all mapper blocks are inserted into ctx
|
|
106
|
+
and no blocks for some reducers are missing. This is needed by shuffle
|
|
107
|
+
fetch by index, which shuffle block are identified by the index instead
|
|
108
|
+
of data keys. For operators implementation simplicity, we can sort the
|
|
109
|
+
`ctx` by key which are (chunk key, reducer index) tuple and relax the
|
|
110
|
+
insert order requirements.
|
|
111
|
+
"""
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
|
|
17
|
+
from ....dataframe import core # noqa: F401 # pylint: disable=unused-variable
|
|
18
|
+
from ... import OutputType
|
|
19
|
+
from .. import Operator, TileableOperatorMixin
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MyOperator(Operator, TileableOperatorMixin):
|
|
23
|
+
@classmethod
|
|
24
|
+
def execute(cls, ctx, op):
|
|
25
|
+
return 1
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def estimate_size(cls, ctx, op):
|
|
29
|
+
return 1
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MyOperator2(MyOperator):
|
|
33
|
+
@classmethod
|
|
34
|
+
def execute(cls, ctx, op):
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def estimate_size(cls, ctx, op):
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class _OperatorMixin(TileableOperatorMixin):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class MyOperator3(Operator, _OperatorMixin):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MyOperator4(Operator, _OperatorMixin):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class MyOperator5(MyOperator4):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_unknown_dtypes():
|
|
59
|
+
op = MyOperator(_output_types=[OutputType.dataframe])
|
|
60
|
+
df = op.new_tileable(None, dtypes=None)
|
|
61
|
+
op2 = MyOperator(_output_types=[OutputType.scalar])
|
|
62
|
+
with pytest.raises(ValueError) as exc_info:
|
|
63
|
+
op2.new_tileable([df])
|
|
64
|
+
assert "executed first" in exc_info.value.args[0]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|